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