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_SECTION_HPP 24 #define ELFIO_SECTION_HPP 25 26 #include <string> 27 #include <iostream> 28 #include <new> 29 30 namespace ELFIO { 31 32 class section 33 { 34 friend class elfio; 35 36 public: ~section()37 virtual ~section(){}; 38 39 ELFIO_GET_ACCESS_DECL( Elf_Half, index ); 40 ELFIO_GET_SET_ACCESS_DECL( std::string, name ); 41 ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type ); 42 ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, flags ); 43 ELFIO_GET_SET_ACCESS_DECL( Elf_Word, info ); 44 ELFIO_GET_SET_ACCESS_DECL( Elf_Word, link ); 45 ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, addr_align ); 46 ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, entry_size ); 47 ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, address ); 48 ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, size ); 49 ELFIO_GET_SET_ACCESS_DECL( Elf_Word, name_string_offset ); 50 ELFIO_GET_ACCESS_DECL( Elf64_Off, offset ); 51 52 virtual const char* get_data() const = 0; 53 virtual void set_data( const char* pData, Elf_Word size ) = 0; 54 virtual void set_data( const std::string& data ) = 0; 55 virtual void append_data( const char* pData, Elf_Word size ) = 0; 56 virtual void append_data( const std::string& data ) = 0; 57 virtual size_t get_stream_size() const = 0; 58 virtual void set_stream_size( size_t value ) = 0; 59 60 protected: 61 ELFIO_SET_ACCESS_DECL( Elf64_Off, offset ); 62 ELFIO_SET_ACCESS_DECL( Elf_Half, index ); 63 64 virtual void load( std::istream& stream, std::streampos header_offset ) = 0; 65 virtual void save( std::ostream& stream, 66 std::streampos header_offset, 67 std::streampos data_offset ) = 0; 68 virtual bool is_address_initialized() const = 0; 69 }; 70 71 template <class T> class section_impl : public section 72 { 73 public: 74 //------------------------------------------------------------------------------ section_impl(const endianess_convertor * convertor)75 section_impl( const endianess_convertor* convertor ) 76 : convertor( convertor ) 77 { 78 std::fill_n( reinterpret_cast<char*>( &header ), sizeof( header ), 79 '\0' ); 80 is_address_set = false; 81 data = 0; 82 data_size = 0; 83 index = 0; 84 stream_size = 0; 85 } 86 87 //------------------------------------------------------------------------------ ~section_impl()88 ~section_impl() { delete[] data; } 89 90 //------------------------------------------------------------------------------ 91 // Section info functions 92 ELFIO_GET_SET_ACCESS( Elf_Word, type, header.sh_type ); 93 ELFIO_GET_SET_ACCESS( Elf_Xword, flags, header.sh_flags ); 94 ELFIO_GET_SET_ACCESS( Elf_Xword, size, header.sh_size ); 95 ELFIO_GET_SET_ACCESS( Elf_Word, link, header.sh_link ); 96 ELFIO_GET_SET_ACCESS( Elf_Word, info, header.sh_info ); 97 ELFIO_GET_SET_ACCESS( Elf_Xword, addr_align, header.sh_addralign ); 98 ELFIO_GET_SET_ACCESS( Elf_Xword, entry_size, header.sh_entsize ); 99 ELFIO_GET_SET_ACCESS( Elf_Word, name_string_offset, header.sh_name ); 100 ELFIO_GET_ACCESS( Elf64_Addr, address, header.sh_addr ); 101 102 //------------------------------------------------------------------------------ get_index() const103 Elf_Half get_index() const { return index; } 104 105 //------------------------------------------------------------------------------ get_name() const106 std::string get_name() const { return name; } 107 108 //------------------------------------------------------------------------------ set_name(std::string name)109 void set_name( std::string name ) { this->name = name; } 110 111 //------------------------------------------------------------------------------ set_address(Elf64_Addr value)112 void set_address( Elf64_Addr value ) 113 { 114 header.sh_addr = value; 115 header.sh_addr = ( *convertor )( header.sh_addr ); 116 is_address_set = true; 117 } 118 119 //------------------------------------------------------------------------------ is_address_initialized() const120 bool is_address_initialized() const { return is_address_set; } 121 122 //------------------------------------------------------------------------------ get_data() const123 const char* get_data() const { return data; } 124 125 //------------------------------------------------------------------------------ set_data(const char * raw_data,Elf_Word size)126 void set_data( const char* raw_data, Elf_Word size ) 127 { 128 if ( get_type() != SHT_NOBITS ) { 129 delete[] data; 130 data = new ( std::nothrow ) char[size]; 131 if ( 0 != data && 0 != raw_data ) { 132 data_size = size; 133 std::copy( raw_data, raw_data + size, data ); 134 } 135 else { 136 data_size = 0; 137 } 138 } 139 140 set_size( data_size ); 141 } 142 143 //------------------------------------------------------------------------------ set_data(const std::string & str_data)144 void set_data( const std::string& str_data ) 145 { 146 return set_data( str_data.c_str(), (Elf_Word)str_data.size() ); 147 } 148 149 //------------------------------------------------------------------------------ append_data(const char * raw_data,Elf_Word size)150 void append_data( const char* raw_data, Elf_Word size ) 151 { 152 if ( get_type() != SHT_NOBITS ) { 153 if ( get_size() + size < data_size ) { 154 std::copy( raw_data, raw_data + size, data + get_size() ); 155 } 156 else { 157 data_size = 2 * ( data_size + size ); 158 char* new_data = new ( std::nothrow ) char[data_size]; 159 160 if ( 0 != new_data ) { 161 std::copy( data, data + get_size(), new_data ); 162 std::copy( raw_data, raw_data + size, 163 new_data + get_size() ); 164 delete[] data; 165 data = new_data; 166 } 167 else { 168 size = 0; 169 } 170 } 171 set_size( get_size() + size ); 172 } 173 } 174 175 //------------------------------------------------------------------------------ append_data(const std::string & str_data)176 void append_data( const std::string& str_data ) 177 { 178 return append_data( str_data.c_str(), (Elf_Word)str_data.size() ); 179 } 180 181 //------------------------------------------------------------------------------ 182 protected: 183 //------------------------------------------------------------------------------ 184 ELFIO_GET_SET_ACCESS( Elf64_Off, offset, header.sh_offset ); 185 186 //------------------------------------------------------------------------------ set_index(Elf_Half value)187 void set_index( Elf_Half value ) { index = value; } 188 189 //------------------------------------------------------------------------------ load(std::istream & stream,std::streampos header_offset)190 void load( std::istream& stream, std::streampos header_offset ) 191 { 192 std::fill_n( reinterpret_cast<char*>( &header ), sizeof( header ), 193 '\0' ); 194 195 stream.seekg( 0, stream.end ); 196 set_stream_size( stream.tellg() ); 197 198 stream.seekg( header_offset ); 199 stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) ); 200 201 Elf_Xword size = get_size(); 202 if ( 0 == data && SHT_NULL != get_type() && SHT_NOBITS != get_type() && 203 size < get_stream_size() ) { 204 data = new ( std::nothrow ) char[size + 1]; 205 206 if ( ( 0 != size ) && ( 0 != data ) ) { 207 stream.seekg( ( *convertor )( header.sh_offset ) ); 208 stream.read( data, size ); 209 data[size] = 0; // Ensure data is ended with 0 to avoid oob read 210 data_size = size; 211 } 212 else { 213 data_size = 0; 214 } 215 } 216 } 217 218 //------------------------------------------------------------------------------ save(std::ostream & stream,std::streampos header_offset,std::streampos data_offset)219 void save( std::ostream& stream, 220 std::streampos header_offset, 221 std::streampos data_offset ) 222 { 223 if ( 0 != get_index() ) { 224 header.sh_offset = data_offset; 225 header.sh_offset = ( *convertor )( header.sh_offset ); 226 } 227 228 save_header( stream, header_offset ); 229 if ( get_type() != SHT_NOBITS && get_type() != SHT_NULL && 230 get_size() != 0 && data != 0 ) { 231 save_data( stream, data_offset ); 232 } 233 } 234 235 //------------------------------------------------------------------------------ 236 private: 237 //------------------------------------------------------------------------------ save_header(std::ostream & stream,std::streampos header_offset) const238 void save_header( std::ostream& stream, std::streampos header_offset ) const 239 { 240 adjust_stream_size( stream, header_offset ); 241 stream.write( reinterpret_cast<const char*>( &header ), 242 sizeof( header ) ); 243 } 244 245 //------------------------------------------------------------------------------ save_data(std::ostream & stream,std::streampos data_offset) const246 void save_data( std::ostream& stream, std::streampos data_offset ) const 247 { 248 adjust_stream_size( stream, data_offset ); 249 stream.write( get_data(), get_size() ); 250 } 251 252 //------------------------------------------------------------------------------ get_stream_size() const253 size_t get_stream_size() const { return stream_size; } 254 255 //------------------------------------------------------------------------------ set_stream_size(size_t value)256 void set_stream_size( size_t value ) { stream_size = value; } 257 258 //------------------------------------------------------------------------------ 259 private: 260 T header; 261 Elf_Half index; 262 std::string name; 263 char* data; 264 Elf_Word data_size; 265 const endianess_convertor* convertor; 266 bool is_address_set; 267 size_t stream_size; 268 }; 269 270 } // namespace ELFIO 271 272 #endif // ELFIO_SECTION_HPP 273