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 #include <limits> 30 31 namespace ELFIO { 32 33 class segment 34 { 35 friend class elfio; 36 37 public: 38 virtual ~segment() = default; 39 40 ELFIO_GET_ACCESS_DECL( Elf_Half, index ); 41 ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type ); 42 ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags ); 43 ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, align ); 44 ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, virtual_address ); 45 ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, physical_address ); 46 ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, file_size ); 47 ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, memory_size ); 48 ELFIO_GET_ACCESS_DECL( Elf64_Off, offset ); 49 50 virtual const char* get_data() const noexcept = 0; 51 52 virtual Elf_Half add_section( section* psec, 53 Elf_Xword addr_align ) noexcept = 0; 54 virtual Elf_Half add_section_index( Elf_Half index, 55 Elf_Xword addr_align ) noexcept = 0; 56 virtual Elf_Half get_sections_num() const noexcept = 0; 57 virtual Elf_Half get_section_index_at( Elf_Half num ) const noexcept = 0; 58 virtual bool is_offset_initialized() const noexcept = 0; 59 60 protected: 61 ELFIO_SET_ACCESS_DECL( Elf64_Off, offset ); 62 ELFIO_SET_ACCESS_DECL( Elf_Half, index ); 63 64 virtual const std::vector<Elf_Half>& get_sections() const noexcept = 0; 65 66 virtual bool load( std::istream& stream, 67 std::streampos header_offset, 68 bool is_lazy ) noexcept = 0; 69 virtual void save( std::ostream& stream, 70 std::streampos header_offset, 71 std::streampos data_offset ) noexcept = 0; 72 }; 73 74 //------------------------------------------------------------------------------ 75 template <class T> class segment_impl : public segment 76 { 77 public: 78 //------------------------------------------------------------------------------ segment_impl(const endianess_convertor * convertor,const address_translator * translator)79 segment_impl( const endianess_convertor* convertor, 80 const address_translator* translator ) 81 : convertor( convertor ), translator( translator ) 82 { 83 } 84 85 //------------------------------------------------------------------------------ 86 // Section info functions 87 ELFIO_GET_SET_ACCESS( Elf_Word, type, ph.p_type ); 88 ELFIO_GET_SET_ACCESS( Elf_Word, flags, ph.p_flags ); 89 ELFIO_GET_SET_ACCESS( Elf_Xword, align, ph.p_align ); 90 ELFIO_GET_SET_ACCESS( Elf64_Addr, virtual_address, ph.p_vaddr ); 91 ELFIO_GET_SET_ACCESS( Elf64_Addr, physical_address, ph.p_paddr ); 92 ELFIO_GET_SET_ACCESS( Elf_Xword, file_size, ph.p_filesz ); 93 ELFIO_GET_SET_ACCESS( Elf_Xword, memory_size, ph.p_memsz ); 94 ELFIO_GET_ACCESS( Elf64_Off, offset, ph.p_offset ); 95 96 //------------------------------------------------------------------------------ get_index() const97 Elf_Half get_index() const noexcept override { return index; } 98 99 //------------------------------------------------------------------------------ get_data() const100 const char* get_data() const noexcept override 101 { 102 if ( is_lazy ) { 103 load_data(); 104 } 105 return data.get(); 106 } 107 108 //------------------------------------------------------------------------------ add_section_index(Elf_Half sec_index,Elf_Xword addr_align)109 Elf_Half add_section_index( Elf_Half sec_index, 110 Elf_Xword addr_align ) noexcept override 111 { 112 sections.emplace_back( sec_index ); 113 if ( addr_align > get_align() ) { 114 set_align( addr_align ); 115 } 116 117 return (Elf_Half)sections.size(); 118 } 119 120 //------------------------------------------------------------------------------ add_section(section * psec,Elf_Xword addr_align)121 Elf_Half add_section( section* psec, 122 Elf_Xword addr_align ) noexcept override 123 { 124 return add_section_index( psec->get_index(), addr_align ); 125 } 126 127 //------------------------------------------------------------------------------ get_sections_num() const128 Elf_Half get_sections_num() const noexcept override 129 { 130 return (Elf_Half)sections.size(); 131 } 132 133 //------------------------------------------------------------------------------ get_section_index_at(Elf_Half num) const134 Elf_Half get_section_index_at( Elf_Half num ) const noexcept override 135 { 136 if ( num < sections.size() ) { 137 return sections[num]; 138 } 139 140 return Elf_Half( -1 ); 141 } 142 143 //------------------------------------------------------------------------------ 144 protected: 145 //------------------------------------------------------------------------------ 146 147 //------------------------------------------------------------------------------ set_offset(const Elf64_Off & value)148 void set_offset( const Elf64_Off& value ) noexcept override 149 { 150 ph.p_offset = decltype( ph.p_offset )( value ); 151 ph.p_offset = ( *convertor )( ph.p_offset ); 152 is_offset_set = true; 153 } 154 155 //------------------------------------------------------------------------------ is_offset_initialized() const156 bool is_offset_initialized() const noexcept override 157 { 158 return is_offset_set; 159 } 160 161 //------------------------------------------------------------------------------ get_sections() const162 const std::vector<Elf_Half>& get_sections() const noexcept override 163 { 164 return sections; 165 } 166 167 //------------------------------------------------------------------------------ set_index(const Elf_Half & value)168 void set_index( const Elf_Half& value ) noexcept override { index = value; } 169 170 //------------------------------------------------------------------------------ load(std::istream & stream,std::streampos header_offset,bool is_lazy_)171 bool load( std::istream& stream, 172 std::streampos header_offset, 173 bool is_lazy_ ) noexcept override 174 { 175 pstream = &stream; 176 is_lazy = is_lazy_; 177 178 if ( translator->empty() ) { 179 stream.seekg( 0, std::istream::end ); 180 set_stream_size( size_t( stream.tellg() ) ); 181 } 182 else { 183 set_stream_size( std::numeric_limits<size_t>::max() ); 184 } 185 186 stream.seekg( ( *translator )[header_offset] ); 187 stream.read( reinterpret_cast<char*>( &ph ), sizeof( ph ) ); 188 is_offset_set = true; 189 190 if ( !is_lazy ) { 191 return load_data(); 192 } 193 194 return true; 195 } 196 197 //------------------------------------------------------------------------------ load_data() const198 bool load_data() const noexcept 199 { 200 is_lazy = false; 201 if ( PT_NULL == get_type() || 0 == get_file_size() ) { 202 return true; 203 } 204 205 pstream->seekg( ( *translator )[( *convertor )( ph.p_offset )] ); 206 Elf_Xword size = get_file_size(); 207 208 if ( size > get_stream_size() ) { 209 data = nullptr; 210 } 211 else { 212 data.reset( new ( std::nothrow ) char[(size_t)size + 1] ); 213 214 if ( nullptr != data.get() && pstream->read( data.get(), size ) ) { 215 data.get()[size] = 0; 216 } 217 else { 218 data = nullptr; 219 return false; 220 } 221 } 222 223 return true; 224 } 225 226 //------------------------------------------------------------------------------ save(std::ostream & stream,std::streampos header_offset,std::streampos data_offset)227 void save( std::ostream& stream, 228 std::streampos header_offset, 229 std::streampos data_offset ) noexcept override 230 { 231 ph.p_offset = decltype( ph.p_offset )( data_offset ); 232 ph.p_offset = ( *convertor )( ph.p_offset ); 233 adjust_stream_size( stream, header_offset ); 234 stream.write( reinterpret_cast<const char*>( &ph ), sizeof( ph ) ); 235 } 236 237 //------------------------------------------------------------------------------ get_stream_size() const238 size_t get_stream_size() const noexcept { return stream_size; } 239 240 //------------------------------------------------------------------------------ set_stream_size(size_t value)241 void set_stream_size( size_t value ) noexcept { stream_size = value; } 242 243 //------------------------------------------------------------------------------ 244 private: 245 mutable std::istream* pstream = nullptr; 246 T ph = {}; 247 Elf_Half index = 0; 248 mutable std::unique_ptr<char[]> data; 249 std::vector<Elf_Half> sections; 250 const endianess_convertor* convertor = nullptr; 251 const address_translator* translator = nullptr; 252 size_t stream_size = 0; 253 bool is_offset_set = false; 254 mutable bool is_lazy = false; 255 }; 256 257 } // namespace ELFIO 258 259 #endif // ELFIO_SEGMENT_HPP 260