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