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_RELOCATION_HPP 24 #define ELFIO_RELOCATION_HPP 25 26 namespace ELFIO { 27 28 template <typename T> struct get_sym_and_type; 29 template <> struct get_sym_and_type<Elf32_Rel> 30 { get_r_symELFIO::get_sym_and_type31 static int get_r_sym( Elf_Xword info ) 32 { 33 return ELF32_R_SYM( (Elf_Word)info ); 34 } get_r_typeELFIO::get_sym_and_type35 static int get_r_type( Elf_Xword info ) 36 { 37 return ELF32_R_TYPE( (Elf_Word)info ); 38 } 39 }; 40 template <> struct get_sym_and_type<Elf32_Rela> 41 { get_r_symELFIO::get_sym_and_type42 static int get_r_sym( Elf_Xword info ) 43 { 44 return ELF32_R_SYM( (Elf_Word)info ); 45 } get_r_typeELFIO::get_sym_and_type46 static int get_r_type( Elf_Xword info ) 47 { 48 return ELF32_R_TYPE( (Elf_Word)info ); 49 } 50 }; 51 template <> struct get_sym_and_type<Elf64_Rel> 52 { get_r_symELFIO::get_sym_and_type53 static int get_r_sym( Elf_Xword info ) { return ELF64_R_SYM( info ); } get_r_typeELFIO::get_sym_and_type54 static int get_r_type( Elf_Xword info ) { return ELF64_R_TYPE( info ); } 55 }; 56 template <> struct get_sym_and_type<Elf64_Rela> 57 { get_r_symELFIO::get_sym_and_type58 static int get_r_sym( Elf_Xword info ) { return ELF64_R_SYM( info ); } get_r_typeELFIO::get_sym_and_type59 static int get_r_type( Elf_Xword info ) { return ELF64_R_TYPE( info ); } 60 }; 61 62 //------------------------------------------------------------------------------ 63 template <class S> class relocation_section_accessor_template 64 { 65 public: 66 //------------------------------------------------------------------------------ relocation_section_accessor_template(const elfio & elf_file,S * section)67 explicit relocation_section_accessor_template( const elfio& elf_file, 68 S* section ) 69 : elf_file( elf_file ), relocation_section( section ) 70 { 71 } 72 73 //------------------------------------------------------------------------------ get_entries_num() const74 Elf_Xword get_entries_num() const 75 { 76 Elf_Xword nRet = 0; 77 78 if ( 0 != relocation_section->get_entry_size() ) { 79 nRet = relocation_section->get_size() / 80 relocation_section->get_entry_size(); 81 } 82 83 return nRet; 84 } 85 86 //------------------------------------------------------------------------------ get_entry(Elf_Xword index,Elf64_Addr & offset,Elf_Word & symbol,unsigned & type,Elf_Sxword & addend) const87 bool get_entry( Elf_Xword index, 88 Elf64_Addr& offset, 89 Elf_Word& symbol, 90 unsigned& type, 91 Elf_Sxword& addend ) const 92 { 93 if ( index >= get_entries_num() ) { // Is index valid 94 return false; 95 } 96 97 if ( elf_file.get_class() == ELFCLASS32 ) { 98 if ( SHT_REL == relocation_section->get_type() ) { 99 generic_get_entry_rel<Elf32_Rel>( index, offset, symbol, type, 100 addend ); 101 } 102 else if ( SHT_RELA == relocation_section->get_type() ) { 103 generic_get_entry_rela<Elf32_Rela>( index, offset, symbol, type, 104 addend ); 105 } 106 } 107 else { 108 if ( SHT_REL == relocation_section->get_type() ) { 109 generic_get_entry_rel<Elf64_Rel>( index, offset, symbol, type, 110 addend ); 111 } 112 else if ( SHT_RELA == relocation_section->get_type() ) { 113 generic_get_entry_rela<Elf64_Rela>( index, offset, symbol, type, 114 addend ); 115 } 116 } 117 118 return true; 119 } 120 121 //------------------------------------------------------------------------------ get_entry(Elf_Xword index,Elf64_Addr & offset,Elf64_Addr & symbolValue,std::string & symbolName,unsigned & type,Elf_Sxword & addend,Elf_Sxword & calcValue) const122 bool get_entry( Elf_Xword index, 123 Elf64_Addr& offset, 124 Elf64_Addr& symbolValue, 125 std::string& symbolName, 126 unsigned& type, 127 Elf_Sxword& addend, 128 Elf_Sxword& calcValue ) const 129 { 130 // Do regular job 131 Elf_Word symbol = 0; 132 bool ret = get_entry( index, offset, symbol, type, addend ); 133 134 // Find the symbol 135 Elf_Xword size; 136 unsigned char bind; 137 unsigned char symbolType; 138 Elf_Half section; 139 unsigned char other; 140 141 symbol_section_accessor symbols( 142 elf_file, elf_file.sections[get_symbol_table_index()] ); 143 ret = ret && symbols.get_symbol( symbol, symbolName, symbolValue, size, 144 bind, symbolType, section, other ); 145 146 if ( ret ) { // Was it successful? 147 switch ( type ) { 148 case R_386_NONE: // none 149 calcValue = 0; 150 break; 151 case R_386_32: // S + A 152 calcValue = symbolValue + addend; 153 break; 154 case R_386_PC32: // S + A - P 155 calcValue = symbolValue + addend - offset; 156 break; 157 case R_386_GOT32: // G + A - P 158 calcValue = 0; 159 break; 160 case R_386_PLT32: // L + A - P 161 calcValue = 0; 162 break; 163 case R_386_COPY: // none 164 calcValue = 0; 165 break; 166 case R_386_GLOB_DAT: // S 167 case R_386_JMP_SLOT: // S 168 calcValue = symbolValue; 169 break; 170 case R_386_RELATIVE: // B + A 171 calcValue = addend; 172 break; 173 case R_386_GOTOFF: // S + A - GOT 174 calcValue = 0; 175 break; 176 case R_386_GOTPC: // GOT + A - P 177 calcValue = 0; 178 break; 179 default: // Not recognized symbol! 180 calcValue = 0; 181 break; 182 } 183 } 184 185 return ret; 186 } 187 188 //------------------------------------------------------------------------------ set_entry(Elf_Xword index,Elf64_Addr offset,Elf_Word symbol,unsigned type,Elf_Sxword addend)189 bool set_entry( Elf_Xword index, 190 Elf64_Addr offset, 191 Elf_Word symbol, 192 unsigned type, 193 Elf_Sxword addend ) 194 { 195 if ( index >= get_entries_num() ) { // Is index valid 196 return false; 197 } 198 199 if ( elf_file.get_class() == ELFCLASS32 ) { 200 if ( SHT_REL == relocation_section->get_type() ) { 201 generic_set_entry_rel<Elf32_Rel>( index, offset, symbol, type, 202 addend ); 203 } 204 else if ( SHT_RELA == relocation_section->get_type() ) { 205 generic_set_entry_rela<Elf32_Rela>( index, offset, symbol, type, 206 addend ); 207 } 208 } 209 else { 210 if ( SHT_REL == relocation_section->get_type() ) { 211 generic_set_entry_rel<Elf64_Rel>( index, offset, symbol, type, 212 addend ); 213 } 214 else if ( SHT_RELA == relocation_section->get_type() ) { 215 generic_set_entry_rela<Elf64_Rela>( index, offset, symbol, type, 216 addend ); 217 } 218 } 219 220 return true; 221 } 222 223 //------------------------------------------------------------------------------ add_entry(Elf64_Addr offset,Elf_Xword info)224 void add_entry( Elf64_Addr offset, Elf_Xword info ) 225 { 226 if ( elf_file.get_class() == ELFCLASS32 ) { 227 generic_add_entry<Elf32_Rel>( offset, info ); 228 } 229 else { 230 generic_add_entry<Elf64_Rel>( offset, info ); 231 } 232 } 233 234 //------------------------------------------------------------------------------ add_entry(Elf64_Addr offset,Elf_Word symbol,unsigned type)235 void add_entry( Elf64_Addr offset, Elf_Word symbol, unsigned type ) 236 { 237 Elf_Xword info; 238 if ( elf_file.get_class() == ELFCLASS32 ) { 239 info = ELF32_R_INFO( (Elf_Xword)symbol, type ); 240 } 241 else { 242 info = ELF64_R_INFO( (Elf_Xword)symbol, type ); 243 } 244 245 add_entry( offset, info ); 246 } 247 248 //------------------------------------------------------------------------------ add_entry(Elf64_Addr offset,Elf_Xword info,Elf_Sxword addend)249 void add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend ) 250 { 251 if ( elf_file.get_class() == ELFCLASS32 ) { 252 generic_add_entry<Elf32_Rela>( offset, info, addend ); 253 } 254 else { 255 generic_add_entry<Elf64_Rela>( offset, info, addend ); 256 } 257 } 258 259 //------------------------------------------------------------------------------ add_entry(Elf64_Addr offset,Elf_Word symbol,unsigned type,Elf_Sxword addend)260 void add_entry( Elf64_Addr offset, 261 Elf_Word symbol, 262 unsigned type, 263 Elf_Sxword addend ) 264 { 265 Elf_Xword info; 266 if ( elf_file.get_class() == ELFCLASS32 ) { 267 info = ELF32_R_INFO( (Elf_Xword)symbol, type ); 268 } 269 else { 270 info = ELF64_R_INFO( (Elf_Xword)symbol, type ); 271 } 272 273 add_entry( offset, info, addend ); 274 } 275 276 //------------------------------------------------------------------------------ add_entry(string_section_accessor str_writer,const char * str,symbol_section_accessor sym_writer,Elf64_Addr value,Elf_Word size,unsigned char sym_info,unsigned char other,Elf_Half shndx,Elf64_Addr offset,unsigned type)277 void add_entry( string_section_accessor str_writer, 278 const char* str, 279 symbol_section_accessor sym_writer, 280 Elf64_Addr value, 281 Elf_Word size, 282 unsigned char sym_info, 283 unsigned char other, 284 Elf_Half shndx, 285 Elf64_Addr offset, 286 unsigned type ) 287 { 288 Elf_Word str_index = str_writer.add_string( str ); 289 Elf_Word sym_index = sym_writer.add_symbol( str_index, value, size, 290 sym_info, other, shndx ); 291 add_entry( offset, sym_index, type ); 292 } 293 294 //------------------------------------------------------------------------------ swap_symbols(Elf_Xword first,Elf_Xword second)295 void swap_symbols( Elf_Xword first, Elf_Xword second ) 296 { 297 Elf64_Addr offset = 0; 298 Elf_Word symbol = 0; 299 unsigned rtype = 0; 300 Elf_Sxword addend = 0; 301 for ( Elf_Word i = 0; i < get_entries_num(); i++ ) { 302 get_entry( i, offset, symbol, rtype, addend ); 303 if ( symbol == first ) { 304 set_entry( i, offset, (Elf_Word)second, rtype, addend ); 305 } 306 if ( symbol == second ) { 307 set_entry( i, offset, (Elf_Word)first, rtype, addend ); 308 } 309 } 310 } 311 312 //------------------------------------------------------------------------------ 313 private: 314 //------------------------------------------------------------------------------ get_symbol_table_index() const315 Elf_Half get_symbol_table_index() const 316 { 317 return (Elf_Half)relocation_section->get_link(); 318 } 319 320 //------------------------------------------------------------------------------ 321 template <class T> generic_get_entry_rel(Elf_Xword index,Elf64_Addr & offset,Elf_Word & symbol,unsigned & type,Elf_Sxword & addend) const322 void generic_get_entry_rel( Elf_Xword index, 323 Elf64_Addr& offset, 324 Elf_Word& symbol, 325 unsigned& type, 326 Elf_Sxword& addend ) const 327 { 328 const endianess_convertor& convertor = elf_file.get_convertor(); 329 330 const T* pEntry = reinterpret_cast<const T*>( 331 relocation_section->get_data() + 332 index * relocation_section->get_entry_size() ); 333 offset = convertor( pEntry->r_offset ); 334 Elf_Xword tmp = convertor( pEntry->r_info ); 335 symbol = get_sym_and_type<T>::get_r_sym( tmp ); 336 type = get_sym_and_type<T>::get_r_type( tmp ); 337 addend = 0; 338 } 339 340 //------------------------------------------------------------------------------ 341 template <class T> generic_get_entry_rela(Elf_Xword index,Elf64_Addr & offset,Elf_Word & symbol,unsigned & type,Elf_Sxword & addend) const342 void generic_get_entry_rela( Elf_Xword index, 343 Elf64_Addr& offset, 344 Elf_Word& symbol, 345 unsigned& type, 346 Elf_Sxword& addend ) const 347 { 348 const endianess_convertor& convertor = elf_file.get_convertor(); 349 350 const T* pEntry = reinterpret_cast<const T*>( 351 relocation_section->get_data() + 352 index * relocation_section->get_entry_size() ); 353 offset = convertor( pEntry->r_offset ); 354 Elf_Xword tmp = convertor( pEntry->r_info ); 355 symbol = get_sym_and_type<T>::get_r_sym( tmp ); 356 type = get_sym_and_type<T>::get_r_type( tmp ); 357 addend = convertor( pEntry->r_addend ); 358 } 359 360 //------------------------------------------------------------------------------ 361 template <class T> generic_set_entry_rel(Elf_Xword index,Elf64_Addr offset,Elf_Word symbol,unsigned type,Elf_Sxword)362 void generic_set_entry_rel( Elf_Xword index, 363 Elf64_Addr offset, 364 Elf_Word symbol, 365 unsigned type, 366 Elf_Sxword ) 367 { 368 const endianess_convertor& convertor = elf_file.get_convertor(); 369 370 T* pEntry = const_cast<T*>( reinterpret_cast<const T*>( 371 relocation_section->get_data() + 372 index * relocation_section->get_entry_size() ) ); 373 374 if ( elf_file.get_class() == ELFCLASS32 ) { 375 pEntry->r_info = ELF32_R_INFO( (Elf_Xword)symbol, type ); 376 } 377 else { 378 pEntry->r_info = ELF64_R_INFO( (Elf_Xword)symbol, type ); 379 } 380 pEntry->r_offset = decltype( pEntry->r_offset )( offset ); 381 pEntry->r_offset = convertor( pEntry->r_offset ); 382 pEntry->r_info = convertor( pEntry->r_info ); 383 } 384 385 //------------------------------------------------------------------------------ 386 template <class T> generic_set_entry_rela(Elf_Xword index,Elf64_Addr offset,Elf_Word symbol,unsigned type,Elf_Sxword addend)387 void generic_set_entry_rela( Elf_Xword index, 388 Elf64_Addr offset, 389 Elf_Word symbol, 390 unsigned type, 391 Elf_Sxword addend ) 392 { 393 const endianess_convertor& convertor = elf_file.get_convertor(); 394 395 T* pEntry = const_cast<T*>( reinterpret_cast<const T*>( 396 relocation_section->get_data() + 397 index * relocation_section->get_entry_size() ) ); 398 399 if ( elf_file.get_class() == ELFCLASS32 ) { 400 pEntry->r_info = ELF32_R_INFO( (Elf_Xword)symbol, type ); 401 } 402 else { 403 pEntry->r_info = ELF64_R_INFO( (Elf_Xword)symbol, type ); 404 } 405 pEntry->r_offset = decltype( pEntry->r_offset )( offset ); 406 pEntry->r_addend = decltype( pEntry->r_addend )( addend ); 407 pEntry->r_offset = convertor( pEntry->r_offset ); 408 pEntry->r_info = convertor( pEntry->r_info ); 409 pEntry->r_addend = convertor( pEntry->r_addend ); 410 } 411 412 //------------------------------------------------------------------------------ 413 template <class T> generic_add_entry(Elf64_Addr offset,Elf_Xword info)414 void generic_add_entry( Elf64_Addr offset, Elf_Xword info ) 415 { 416 const endianess_convertor& convertor = elf_file.get_convertor(); 417 418 T entry; 419 entry.r_offset = decltype( entry.r_offset )( offset ); 420 entry.r_info = decltype( entry.r_info )( info ); 421 entry.r_offset = convertor( entry.r_offset ); 422 entry.r_info = convertor( entry.r_info ); 423 424 relocation_section->append_data( reinterpret_cast<char*>( &entry ), 425 sizeof( entry ) ); 426 } 427 428 //------------------------------------------------------------------------------ 429 template <class T> 430 void generic_add_entry(Elf64_Addr offset,Elf_Xword info,Elf_Sxword addend)431 generic_add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend ) 432 { 433 const endianess_convertor& convertor = elf_file.get_convertor(); 434 435 T entry; 436 entry.r_offset = offset; 437 entry.r_info = info; 438 entry.r_addend = addend; 439 entry.r_offset = convertor( entry.r_offset ); 440 entry.r_info = convertor( entry.r_info ); 441 entry.r_addend = convertor( entry.r_addend ); 442 443 relocation_section->append_data( reinterpret_cast<char*>( &entry ), 444 sizeof( entry ) ); 445 } 446 447 //------------------------------------------------------------------------------ 448 private: 449 const elfio& elf_file; 450 S* relocation_section = nullptr; 451 }; 452 453 using relocation_section_accessor = 454 relocation_section_accessor_template<section>; 455 using const_relocation_section_accessor = 456 relocation_section_accessor_template<const section>; 457 458 } // namespace ELFIO 459 460 #endif // ELFIO_RELOCATION_HPP 461