1 /* 2 Copyright (C) 2001-present by Serge Lamikhov-Center 3 4 Permission is hereby granted, free of charge, to any person obtaining a copy 5 of this software and associated documentation files (the "Software"), to deal 6 in the Software without restriction, including without limitation the rights 7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 copies of the Software, and to permit persons to whom the Software is 9 furnished to do so, subject to the following conditions: 10 11 The above copyright notice and this permission notice shall be included in 12 all copies or substantial portions of the Software. 13 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 THE SOFTWARE. 21 */ 22 23 #ifndef ELFIO_SEGMENT_HPP 24 #define ELFIO_SEGMENT_HPP 25 26 #include <iostream> 27 #include <vector> 28 #include <new> 29 30 namespace ELFIO { 31 32 class segment 33 { 34 friend class elfio; 35 36 public: ~segment()37 virtual ~segment(){}; 38 39 ELFIO_GET_ACCESS_DECL( Elf_Half, index ); 40 ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type ); 41 ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags ); 42 ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, align ); 43 ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, virtual_address ); 44 ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, physical_address ); 45 ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, file_size ); 46 ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, memory_size ); 47 ELFIO_GET_ACCESS_DECL( Elf64_Off, offset ); 48 49 virtual const char* get_data() const = 0; 50 51 virtual Elf_Half add_section_index( Elf_Half index, 52 Elf_Xword addr_align ) = 0; 53 virtual Elf_Half get_sections_num() const = 0; 54 virtual Elf_Half get_section_index_at( Elf_Half num ) const = 0; 55 virtual bool is_offset_initialized() const = 0; 56 57 protected: 58 ELFIO_SET_ACCESS_DECL( Elf64_Off, offset ); 59 ELFIO_SET_ACCESS_DECL( Elf_Half, index ); 60 61 virtual const std::vector<Elf_Half>& get_sections() const = 0; 62 virtual void load( std::istream& stream, std::streampos header_offset ) = 0; 63 virtual void save( std::ostream& stream, 64 std::streampos header_offset, 65 std::streampos data_offset ) = 0; 66 }; 67 68 //------------------------------------------------------------------------------ 69 template <class T> class segment_impl : public segment 70 { 71 public: 72 //------------------------------------------------------------------------------ segment_impl(endianess_convertor * convertor)73 segment_impl( endianess_convertor* convertor ) 74 : stream_size( 0 ), index( 0 ), data( 0 ), convertor( convertor ) 75 { 76 is_offset_set = false; 77 std::fill_n( reinterpret_cast<char*>( &ph ), sizeof( ph ), '\0' ); 78 } 79 80 //------------------------------------------------------------------------------ ~segment_impl()81 virtual ~segment_impl() { delete[] data; } 82 83 //------------------------------------------------------------------------------ 84 // Section info functions 85 ELFIO_GET_SET_ACCESS( Elf_Word, type, ph.p_type ); 86 ELFIO_GET_SET_ACCESS( Elf_Word, flags, ph.p_flags ); 87 ELFIO_GET_SET_ACCESS( Elf_Xword, align, ph.p_align ); 88 ELFIO_GET_SET_ACCESS( Elf64_Addr, virtual_address, ph.p_vaddr ); 89 ELFIO_GET_SET_ACCESS( Elf64_Addr, physical_address, ph.p_paddr ); 90 ELFIO_GET_SET_ACCESS( Elf_Xword, file_size, ph.p_filesz ); 91 ELFIO_GET_SET_ACCESS( Elf_Xword, memory_size, ph.p_memsz ); 92 ELFIO_GET_ACCESS( Elf64_Off, offset, ph.p_offset ); 93 size_t stream_size; 94 95 //------------------------------------------------------------------------------ get_stream_size() const96 size_t get_stream_size() const { return stream_size; } 97 98 //------------------------------------------------------------------------------ set_stream_size(size_t value)99 void set_stream_size( size_t value ) { stream_size = value; } 100 101 //------------------------------------------------------------------------------ get_index() const102 Elf_Half get_index() const { return index; } 103 104 //------------------------------------------------------------------------------ get_data() const105 const char* get_data() const { return data; } 106 107 //------------------------------------------------------------------------------ add_section_index(Elf_Half sec_index,Elf_Xword addr_align)108 Elf_Half add_section_index( Elf_Half sec_index, Elf_Xword addr_align ) 109 { 110 sections.push_back( sec_index ); 111 if ( addr_align > get_align() ) { 112 set_align( addr_align ); 113 } 114 115 return (Elf_Half)sections.size(); 116 } 117 118 //------------------------------------------------------------------------------ get_sections_num() const119 Elf_Half get_sections_num() const { return (Elf_Half)sections.size(); } 120 121 //------------------------------------------------------------------------------ get_section_index_at(Elf_Half num) const122 Elf_Half get_section_index_at( Elf_Half num ) const 123 { 124 if ( num < sections.size() ) { 125 return sections[num]; 126 } 127 128 return Elf_Half( -1 ); 129 } 130 131 //------------------------------------------------------------------------------ 132 protected: 133 //------------------------------------------------------------------------------ 134 135 //------------------------------------------------------------------------------ set_offset(Elf64_Off value)136 void set_offset( Elf64_Off value ) 137 { 138 ph.p_offset = value; 139 ph.p_offset = ( *convertor )( ph.p_offset ); 140 is_offset_set = true; 141 } 142 143 //------------------------------------------------------------------------------ is_offset_initialized() const144 bool is_offset_initialized() const { return is_offset_set; } 145 146 //------------------------------------------------------------------------------ get_sections() const147 const std::vector<Elf_Half>& get_sections() const { return sections; } 148 149 //------------------------------------------------------------------------------ set_index(Elf_Half value)150 void set_index( Elf_Half value ) { index = value; } 151 152 //------------------------------------------------------------------------------ load(std::istream & stream,std::streampos header_offset)153 void load( std::istream& stream, std::streampos header_offset ) 154 { 155 156 stream.seekg( 0, stream.end ); 157 set_stream_size( stream.tellg() ); 158 159 stream.seekg( header_offset ); 160 stream.read( reinterpret_cast<char*>( &ph ), sizeof( ph ) ); 161 is_offset_set = true; 162 163 if ( PT_NULL != get_type() && 0 != get_file_size() ) { 164 stream.seekg( ( *convertor )( ph.p_offset ) ); 165 Elf_Xword size = get_file_size(); 166 167 if ( size > get_stream_size() ) { 168 data = 0; 169 } 170 else { 171 data = new ( std::nothrow ) char[size + 1]; 172 173 if ( 0 != data ) { 174 stream.read( data, size ); 175 data[size] = 0; 176 } 177 } 178 } 179 } 180 181 //------------------------------------------------------------------------------ save(std::ostream & stream,std::streampos header_offset,std::streampos data_offset)182 void save( std::ostream& stream, 183 std::streampos header_offset, 184 std::streampos data_offset ) 185 { 186 ph.p_offset = data_offset; 187 ph.p_offset = ( *convertor )( ph.p_offset ); 188 adjust_stream_size( stream, header_offset ); 189 stream.write( reinterpret_cast<const char*>( &ph ), sizeof( ph ) ); 190 } 191 192 //------------------------------------------------------------------------------ 193 private: 194 T ph; 195 Elf_Half index; 196 char* data; 197 std::vector<Elf_Half> sections; 198 endianess_convertor* convertor; 199 bool is_offset_set; 200 }; 201 202 } // namespace ELFIO 203 204 #endif // ELFIO_SEGMENT_HPP 205