GNU Binutils with patches for OS216
Revisión | 8c13bcd2209cb776aa2cf7e5016b7884b0aecbf6 (tree) |
---|---|
Tiempo | 2017-04-26 12:07:52 |
Autor | Cary Coutant <ccoutant@gmai...> |
Commiter | Cary Coutant |
Experimental implementation of RELR-style relocations.
For x86-64 only. Instead of R_X86_64_RELATIVE relocations, we
write the offsets of the relocation targets to a new section,
.relr.dyn, with section type SHT_RELR.
@@ -358,6 +358,7 @@ enum SHT | ||
358 | 358 | SHT_PREINIT_ARRAY = 16, |
359 | 359 | SHT_GROUP = 17, |
360 | 360 | SHT_SYMTAB_SHNDX = 18, |
361 | + SHT_RELR = 19, // Experimental | |
361 | 362 | SHT_LOOS = 0x60000000, |
362 | 363 | SHT_HIOS = 0x6fffffff, |
363 | 364 | SHT_LOPROC = 0x70000000, |
@@ -719,6 +720,11 @@ enum DT | ||
719 | 720 | |
720 | 721 | DT_PREINIT_ARRAY = 32, |
721 | 722 | DT_PREINIT_ARRAYSZ = 33, |
723 | + DT_SYMTAB_SHNDX = 34, | |
724 | + DT_RELRSZ = 35, // Experimental | |
725 | + DT_RELR = 36, // Experimental | |
726 | + DT_RELRENT = 37, // Experimental | |
727 | + | |
722 | 728 | DT_LOOS = 0x6000000d, |
723 | 729 | DT_HIOS = 0x6ffff000, |
724 | 730 | DT_LOPROC = 0x70000000, |
@@ -1021,6 +1027,7 @@ struct Elf_sizes | ||
1021 | 1027 | // Sizes of ELF reloc entries. |
1022 | 1028 | static const int rel_size = sizeof(internal::Rel_data<size>); |
1023 | 1029 | static const int rela_size = sizeof(internal::Rela_data<size>); |
1030 | + static const int relr_size = sizeof(internal::Relr_data<size>); | |
1024 | 1031 | // Size of ELF dynamic entry. |
1025 | 1032 | static const int dyn_size = sizeof(internal::Dyn_data<size>); |
1026 | 1033 | // Size of ELF version structures. |
@@ -1666,6 +1673,48 @@ class Rela_write | ||
1666 | 1673 | internal::Rela_data<size>* p_; |
1667 | 1674 | }; |
1668 | 1675 | |
1676 | +// Accessor class for an ELF Relr relocation. | |
1677 | + | |
1678 | +template<int size, bool big_endian> | |
1679 | +class Relr | |
1680 | +{ | |
1681 | + public: | |
1682 | + Relr(const unsigned char* p) | |
1683 | + : p_(reinterpret_cast<const internal::Relr_data<size>*>(p)) | |
1684 | + { } | |
1685 | + | |
1686 | + template<typename File> | |
1687 | + Relr(File* file, typename File::Location loc) | |
1688 | + : p_(reinterpret_cast<const internal::Relr_data<size>*>( | |
1689 | + file->view(loc.file_offset, loc.data_size).data())) | |
1690 | + { } | |
1691 | + | |
1692 | + typename Elf_types<size>::Elf_Addr | |
1693 | + get_r_offset() const | |
1694 | + { return Convert<size, big_endian>::convert_host(this->p_->r_offset); } | |
1695 | + | |
1696 | + private: | |
1697 | + const internal::Relr_data<size>* p_; | |
1698 | +}; | |
1699 | + | |
1700 | +// Writer class for an ELF Relr relocation. | |
1701 | + | |
1702 | +template<int size, bool big_endian> | |
1703 | +class Relr_write | |
1704 | +{ | |
1705 | + public: | |
1706 | + Relr_write(unsigned char* p) | |
1707 | + : p_(reinterpret_cast<internal::Relr_data<size>*>(p)) | |
1708 | + { } | |
1709 | + | |
1710 | + void | |
1711 | + put_r_offset(typename Elf_types<size>::Elf_Addr v) | |
1712 | + { this->p_->r_offset = Convert<size, big_endian>::convert_host(v); } | |
1713 | + | |
1714 | + private: | |
1715 | + internal::Relr_data<size>* p_; | |
1716 | +}; | |
1717 | + | |
1669 | 1718 | // MIPS-64 has a non-standard relocation layout. |
1670 | 1719 | |
1671 | 1720 | template<bool big_endian> |
@@ -180,6 +180,12 @@ struct Rela_data | ||
180 | 180 | typename Elf_types<size>::Elf_Swxword r_addend; |
181 | 181 | }; |
182 | 182 | |
183 | +template<int size> | |
184 | +struct Relr_data | |
185 | +{ | |
186 | + typename Elf_types<size>::Elf_Addr r_offset; | |
187 | +}; | |
188 | + | |
183 | 189 | // MIPS-64 has a non-standard layout for relocations. |
184 | 190 | |
185 | 191 | struct Mips64_rel_data |
@@ -4710,7 +4710,8 @@ void | ||
4710 | 4710 | Layout::add_target_dynamic_tags(bool use_rel, const Output_data* plt_got, |
4711 | 4711 | const Output_data* plt_rel, |
4712 | 4712 | const Output_data_reloc_generic* dyn_rel, |
4713 | - bool add_debug, bool dynrel_includes_plt) | |
4713 | + bool add_debug, bool dynrel_includes_plt, | |
4714 | + const Output_data_reloc_generic* dyn_relr) | |
4714 | 4715 | { |
4715 | 4716 | Output_data_dynamic* odyn = this->dynamic_data_; |
4716 | 4717 | if (odyn == NULL) |
@@ -4783,6 +4784,14 @@ Layout::add_target_dynamic_tags(bool use_rel, const Output_data* plt_got, | ||
4783 | 4784 | } |
4784 | 4785 | } |
4785 | 4786 | |
4787 | + if (dyn_relr != NULL && dyn_relr->output_section() != NULL) | |
4788 | + { | |
4789 | + const int size = parameters->target().get_size(); | |
4790 | + odyn->add_section_address(elfcpp::DT_RELR, dyn_relr->output_section()); | |
4791 | + odyn->add_section_size(elfcpp::DT_RELRSZ, dyn_relr->output_section()); | |
4792 | + odyn->add_constant(elfcpp::DT_RELRENT, size / 8); | |
4793 | + } | |
4794 | + | |
4786 | 4795 | if (add_debug && !parameters->options().shared()) |
4787 | 4796 | { |
4788 | 4797 | // The value of the DT_DEBUG tag is filled in by the dynamic |
@@ -900,7 +900,8 @@ class Layout | ||
900 | 900 | add_target_dynamic_tags(bool use_rel, const Output_data* plt_got, |
901 | 901 | const Output_data* plt_rel, |
902 | 902 | const Output_data_reloc_generic* dyn_rel, |
903 | - bool add_debug, bool dynrel_includes_plt); | |
903 | + bool add_debug, bool dynrel_includes_plt, | |
904 | + const Output_data_reloc_generic* dyn_relr = NULL); | |
904 | 905 | |
905 | 906 | // Add a target-specific dynamic tag with constant value. |
906 | 907 | void |
@@ -834,6 +834,10 @@ class General_options | ||
834 | 834 | N_("Exclude libraries from automatic export"), |
835 | 835 | N_(("lib,lib ..."))); |
836 | 836 | |
837 | + DEFINE_bool(experimental_use_relr, options::TWO_DASHES, '\0', false, | |
838 | + N_("(x86-64 only) Generate RELR dynamic relocations"), | |
839 | + N_("Do not generate RELR dynamic relocations")); | |
840 | + | |
837 | 841 | DEFINE_bool(export_dynamic, options::TWO_DASHES, 'E', false, |
838 | 842 | N_("Export all dynamic symbols"), |
839 | 843 | N_("Do not export all dynamic symbols")); |
@@ -1224,6 +1224,17 @@ Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>::write( | ||
1224 | 1224 | orel.put_r_addend(addend); |
1225 | 1225 | } |
1226 | 1226 | |
1227 | +// Write out a Relr relocation. | |
1228 | + | |
1229 | +template<bool dynamic, int size, bool big_endian> | |
1230 | +void | |
1231 | +Output_reloc<elfcpp::SHT_RELR, dynamic, size, big_endian>::write( | |
1232 | + unsigned char* pov) const | |
1233 | +{ | |
1234 | + elfcpp::Relr_write<size, big_endian> orel(pov); | |
1235 | + orel.put_r_offset(this->rel_.get_address()); | |
1236 | +} | |
1237 | + | |
1227 | 1238 | // Output_data_reloc_base methods. |
1228 | 1239 | |
1229 | 1240 | // Adjust the output section. |
@@ -1237,6 +1248,8 @@ Output_data_reloc_base<sh_type, dynamic, size, big_endian> | ||
1237 | 1248 | os->set_entsize(elfcpp::Elf_sizes<size>::rel_size); |
1238 | 1249 | else if (sh_type == elfcpp::SHT_RELA) |
1239 | 1250 | os->set_entsize(elfcpp::Elf_sizes<size>::rela_size); |
1251 | + else if (sh_type == elfcpp::SHT_RELR) | |
1252 | + os->set_entsize(elfcpp::Elf_sizes<size>::relr_size); | |
1240 | 1253 | else |
1241 | 1254 | gold_unreachable(); |
1242 | 1255 |
@@ -5528,6 +5541,26 @@ class Output_data_reloc<elfcpp::SHT_RELA, true, 64, true>; | ||
5528 | 5541 | |
5529 | 5542 | #ifdef HAVE_TARGET_32_LITTLE |
5530 | 5543 | template |
5544 | +class Output_data_reloc<elfcpp::SHT_RELR, true, 32, false>; | |
5545 | +#endif | |
5546 | + | |
5547 | +#ifdef HAVE_TARGET_32_BIG | |
5548 | +template | |
5549 | +class Output_data_reloc<elfcpp::SHT_RELR, true, 32, true>; | |
5550 | +#endif | |
5551 | + | |
5552 | +#ifdef HAVE_TARGET_64_LITTLE | |
5553 | +template | |
5554 | +class Output_data_reloc<elfcpp::SHT_RELR, true, 64, false>; | |
5555 | +#endif | |
5556 | + | |
5557 | +#ifdef HAVE_TARGET_64_BIG | |
5558 | +template | |
5559 | +class Output_data_reloc<elfcpp::SHT_RELR, true, 64, true>; | |
5560 | +#endif | |
5561 | + | |
5562 | +#ifdef HAVE_TARGET_32_LITTLE | |
5563 | +template | |
5531 | 5564 | class Output_relocatable_relocs<elfcpp::SHT_REL, 32, false>; |
5532 | 5565 | #endif |
5533 | 5566 |
@@ -1500,6 +1500,104 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> | ||
1500 | 1500 | Addend addend_; |
1501 | 1501 | }; |
1502 | 1502 | |
1503 | +// The SHT_RELR version of Output_reloc<>. This is a relative reloc, | |
1504 | +// and holds nothing but an offset. Rather than duplicate all the fields | |
1505 | +// of the SHT_REL version except for the symbol and relocation type, we | |
1506 | +// simply use an SHT_REL as a proxy. | |
1507 | + | |
1508 | +template<bool dynamic, int size, bool big_endian> | |
1509 | +class Output_reloc<elfcpp::SHT_RELR, dynamic, size, big_endian> | |
1510 | +{ | |
1511 | + public: | |
1512 | + typedef typename elfcpp::Elf_types<size>::Elf_Addr Address; | |
1513 | + | |
1514 | + // An uninitialized entry. | |
1515 | + Output_reloc() | |
1516 | + : rel_() | |
1517 | + { } | |
1518 | + | |
1519 | + // A reloc against a global symbol. | |
1520 | + | |
1521 | + Output_reloc(Symbol* gsym, Output_data* od, Address address) | |
1522 | + : rel_(gsym, 0, od, address, true, true, false) | |
1523 | + { } | |
1524 | + | |
1525 | + Output_reloc(Symbol* gsym, Sized_relobj<size, big_endian>* relobj, | |
1526 | + unsigned int shndx, Address address) | |
1527 | + : rel_(gsym, 0, relobj, shndx, address, true, true, false) | |
1528 | + { } | |
1529 | + | |
1530 | + // A reloc against a local symbol. | |
1531 | + | |
1532 | + Output_reloc(Sized_relobj<size, big_endian>* relobj, | |
1533 | + unsigned int local_sym_index, Output_data* od, Address address, | |
1534 | + bool is_section_symbol) | |
1535 | + : rel_(relobj, local_sym_index, 0, od, address, true, | |
1536 | + true, is_section_symbol, false) | |
1537 | + { } | |
1538 | + | |
1539 | + Output_reloc(Sized_relobj<size, big_endian>* relobj, | |
1540 | + unsigned int local_sym_index, unsigned int shndx, | |
1541 | + Address address, bool is_section_symbol) | |
1542 | + : rel_(relobj, local_sym_index, 0, shndx, address, true, | |
1543 | + true, is_section_symbol, false) | |
1544 | + { } | |
1545 | + | |
1546 | + // A reloc against the STT_SECTION symbol of an output section. | |
1547 | + | |
1548 | + Output_reloc(Output_section* os, Output_data* od, Address address) | |
1549 | + : rel_(os, 0, od, address, true) | |
1550 | + { } | |
1551 | + | |
1552 | + Output_reloc(Output_section* os, Sized_relobj<size, big_endian>* relobj, | |
1553 | + unsigned int shndx, Address address) | |
1554 | + : rel_(os, 0, relobj, shndx, address, true) | |
1555 | + { } | |
1556 | + | |
1557 | + // A relative relocation with no symbol. | |
1558 | + | |
1559 | + Output_reloc(Output_data* od, Address address) | |
1560 | + : rel_(0, od, address, true) | |
1561 | + { } | |
1562 | + | |
1563 | + Output_reloc(Sized_relobj<size, big_endian>* relobj, | |
1564 | + unsigned int shndx, Address address) | |
1565 | + : rel_(0, relobj, shndx, address, true) | |
1566 | + { } | |
1567 | + | |
1568 | + // Return whether this is a RELATIVE relocation. | |
1569 | + bool | |
1570 | + is_relative() const | |
1571 | + { return true; } | |
1572 | + | |
1573 | + // Return whether this is a relocation which should not use | |
1574 | + // a symbol, but which obtains its addend from a symbol. | |
1575 | + bool | |
1576 | + is_symbolless() const | |
1577 | + { return true; } | |
1578 | + | |
1579 | + // If this relocation is against an input section, return the | |
1580 | + // relocatable object containing the input section. | |
1581 | + Sized_relobj<size, big_endian>* | |
1582 | + get_relobj() const | |
1583 | + { return this->rel_.get_relobj(); } | |
1584 | + | |
1585 | + // Write the reloc entry to an output view. | |
1586 | + void | |
1587 | + write(unsigned char* pov) const; | |
1588 | + | |
1589 | + // Return whether this reloc should be sorted before the argument | |
1590 | + // when sorting dynamic relocs. | |
1591 | + bool | |
1592 | + sort_before(const Output_reloc<elfcpp::SHT_RELR, dynamic, size, big_endian>& | |
1593 | + r2) const | |
1594 | + { return this->rel_.compare(r2.rel_) < 0; } | |
1595 | + | |
1596 | + private: | |
1597 | + // The basic reloc. | |
1598 | + Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> rel_; | |
1599 | +}; | |
1600 | + | |
1503 | 1601 | // Output_data_reloc_generic is a non-template base class for |
1504 | 1602 | // Output_data_reloc_base. This gives the generic code a way to hold |
1505 | 1603 | // a pointer to a reloc section. |
@@ -2344,6 +2442,127 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> | ||
2344 | 2442 | } |
2345 | 2443 | }; |
2346 | 2444 | |
2445 | +// The SHT_RELR version of Output_data_reloc. | |
2446 | + | |
2447 | +template<bool dynamic, int size, bool big_endian> | |
2448 | +class Output_data_reloc<elfcpp::SHT_RELR, dynamic, size, big_endian> | |
2449 | + : public Output_data_reloc_base<elfcpp::SHT_RELR, dynamic, size, big_endian> | |
2450 | +{ | |
2451 | + private: | |
2452 | + typedef Output_data_reloc_base<elfcpp::SHT_RELR, dynamic, size, | |
2453 | + big_endian> Base; | |
2454 | + | |
2455 | + public: | |
2456 | + typedef typename Base::Output_reloc_type Output_reloc_type; | |
2457 | + typedef typename Output_reloc_type::Address Address; | |
2458 | + | |
2459 | + Output_data_reloc() | |
2460 | + : Output_data_reloc_base<elfcpp::SHT_RELR, dynamic, size, big_endian>(false) | |
2461 | + { } | |
2462 | + | |
2463 | + void | |
2464 | + add_global_generic(Symbol*, unsigned int, Output_data*, uint64_t, uint64_t) | |
2465 | + { | |
2466 | + gold_unreachable(); | |
2467 | + } | |
2468 | + | |
2469 | + void | |
2470 | + add_global_generic(Symbol*, unsigned int, Output_data*, Relobj*, | |
2471 | + unsigned int, uint64_t, uint64_t) | |
2472 | + { | |
2473 | + gold_unreachable(); | |
2474 | + } | |
2475 | + | |
2476 | + // Add a RELATIVE reloc against a global symbol. The final relocation | |
2477 | + // will not reference the symbol. | |
2478 | + | |
2479 | + void | |
2480 | + add_global_relative(Symbol* gsym, Output_data* od, Address address) | |
2481 | + { | |
2482 | + this->add(od, Output_reloc_type(gsym, od, address)); | |
2483 | + } | |
2484 | + | |
2485 | + void | |
2486 | + add_global_relative(Symbol* gsym, Output_data* od, | |
2487 | + Sized_relobj<size, big_endian>* relobj, | |
2488 | + unsigned int shndx, Address address) | |
2489 | + { | |
2490 | + this->add(od, Output_reloc_type(gsym, relobj, shndx, address)); | |
2491 | + } | |
2492 | + | |
2493 | + void | |
2494 | + add_local_generic(Relobj*, unsigned int, unsigned int, Output_data*, uint64_t, | |
2495 | + uint64_t) | |
2496 | + { | |
2497 | + gold_unreachable(); | |
2498 | + } | |
2499 | + | |
2500 | + void | |
2501 | + add_local_generic(Relobj*, unsigned int, unsigned int, Output_data*, | |
2502 | + unsigned int, uint64_t, uint64_t) | |
2503 | + { | |
2504 | + gold_unreachable(); | |
2505 | + } | |
2506 | + | |
2507 | + // Add a RELATIVE reloc against a local symbol. | |
2508 | + | |
2509 | + void | |
2510 | + add_local_relative(Sized_relobj<size, big_endian>* relobj, | |
2511 | + unsigned int local_sym_index, Output_data* od, | |
2512 | + Address address) | |
2513 | + { | |
2514 | + this->add(od, Output_reloc_type(relobj, local_sym_index, od, address, | |
2515 | + false)); | |
2516 | + } | |
2517 | + | |
2518 | + void | |
2519 | + add_local_relative(Sized_relobj<size, big_endian>* relobj, | |
2520 | + unsigned int local_sym_index, Output_data* od, | |
2521 | + unsigned int shndx, Address address) | |
2522 | + { | |
2523 | + this->add(od, Output_reloc_type(relobj, local_sym_index, shndx, address, | |
2524 | + false)); | |
2525 | + } | |
2526 | + | |
2527 | + void | |
2528 | + add_output_section_generic(Output_section*, unsigned int, Output_data*, | |
2529 | + uint64_t, uint64_t) | |
2530 | + { | |
2531 | + gold_unreachable(); | |
2532 | + } | |
2533 | + | |
2534 | + void | |
2535 | + add_output_section_generic(Output_section*, unsigned int, Output_data*, | |
2536 | + Relobj*, unsigned int, uint64_t, uint64_t) | |
2537 | + { | |
2538 | + gold_unreachable(); | |
2539 | + } | |
2540 | + | |
2541 | + // Add a RELATIVE reloc against an output section symbol. | |
2542 | + | |
2543 | + void | |
2544 | + add_output_section_relative(Output_section* os, Output_data* od, | |
2545 | + Address address) | |
2546 | + { this->add(od, Output_reloc_type(os, od, address)); } | |
2547 | + | |
2548 | + void | |
2549 | + add_output_section_relative(Output_section* os, Output_data* od, | |
2550 | + Sized_relobj<size, big_endian>* relobj, | |
2551 | + unsigned int shndx, Address address) | |
2552 | + { this->add(od, Output_reloc_type(os, relobj, shndx, address)); } | |
2553 | + | |
2554 | + // Add a relative relocation | |
2555 | + | |
2556 | + void | |
2557 | + add_relative(Output_data* od, Address address) | |
2558 | + { this->add(od, Output_reloc_type(od, address)); } | |
2559 | + | |
2560 | + void | |
2561 | + add_relative(Output_data* od, Sized_relobj<size, big_endian>* relobj, | |
2562 | + unsigned int shndx, Address address) | |
2563 | + { this->add(od, Output_reloc_type(relobj, shndx, address)); } | |
2564 | +}; | |
2565 | + | |
2347 | 2566 | // Output_relocatable_relocs represents a relocation section in a |
2348 | 2567 | // relocatable link. The actual data is written out in the target |
2349 | 2568 | // hook relocate_relocs. This just saves space for it. |
@@ -79,6 +79,27 @@ struct Reloc_types<elfcpp::SHT_RELA, size, big_endian> | ||
79 | 79 | { p->put_r_addend(val); } |
80 | 80 | }; |
81 | 81 | |
82 | +template<int size, bool big_endian> | |
83 | +struct Reloc_types<elfcpp::SHT_RELR, size, big_endian> | |
84 | +{ | |
85 | + typedef typename elfcpp::Relr<size, big_endian> Reloc; | |
86 | + typedef typename elfcpp::Relr_write<size, big_endian> Reloc_write; | |
87 | + static const int reloc_size = elfcpp::Elf_sizes<size>::relr_size; | |
88 | + | |
89 | + static inline typename elfcpp::Elf_types<size>::Elf_Swxword | |
90 | + get_reloc_addend(const Reloc*) | |
91 | + { gold_unreachable(); } | |
92 | + | |
93 | + static inline typename elfcpp::Elf_types<size>::Elf_Swxword | |
94 | + get_reloc_addend_noerror(const Reloc*) | |
95 | + { return 0; } | |
96 | + | |
97 | + static inline void | |
98 | + set_reloc_addend(Reloc_write*, | |
99 | + typename elfcpp::Elf_types<size>::Elf_Swxword) | |
100 | + { gold_unreachable(); } | |
101 | +}; | |
102 | + | |
82 | 103 | }; // End namespace gold. |
83 | 104 | |
84 | 105 | #endif // !defined(GOLD_RELOC_TYPE_SH) |
@@ -584,13 +584,15 @@ class Target_x86_64 : public Sized_target<size, false> | ||
584 | 584 | // uses only Elf64_Rela relocation entries with explicit addends." |
585 | 585 | typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, false> Reloc_section; |
586 | 586 | |
587 | + typedef Output_data_reloc<elfcpp::SHT_RELR, true, size, false> Relr_section; | |
588 | + | |
587 | 589 | Target_x86_64(const Target::Target_info* info = &x86_64_info) |
588 | 590 | : Sized_target<size, false>(info), |
589 | 591 | got_(NULL), plt_(NULL), got_plt_(NULL), got_irelative_(NULL), |
590 | 592 | got_tlsdesc_(NULL), global_offset_table_(NULL), rela_dyn_(NULL), |
591 | - rela_irelative_(NULL), copy_relocs_(elfcpp::R_X86_64_COPY), | |
592 | - got_mod_index_offset_(-1U), tlsdesc_reloc_info_(), | |
593 | - tls_base_symbol_defined_(false) | |
593 | + rela_irelative_(NULL), relr_dyn_(NULL), | |
594 | + copy_relocs_(elfcpp::R_X86_64_COPY), got_mod_index_offset_(-1U), | |
595 | + tlsdesc_reloc_info_(), tls_base_symbol_defined_(false) | |
594 | 596 | { } |
595 | 597 | |
596 | 598 | // Hook for a new output section. |
@@ -1172,6 +1174,10 @@ class Target_x86_64 : public Sized_target<size, false> | ||
1172 | 1174 | Reloc_section* |
1173 | 1175 | rela_irelative_section(Layout*); |
1174 | 1176 | |
1177 | + // Get the RELR dynamic reloc section, creating it if necessary. | |
1178 | + Relr_section* | |
1179 | + relr_dyn_section(Layout*); | |
1180 | + | |
1175 | 1181 | // Add a potential copy relocation. |
1176 | 1182 | void |
1177 | 1183 | copy_reloc(Symbol_table* symtab, Layout* layout, |
@@ -1235,6 +1241,8 @@ class Target_x86_64 : public Sized_target<size, false> | ||
1235 | 1241 | Reloc_section* rela_dyn_; |
1236 | 1242 | // The section to use for IRELATIVE relocs. |
1237 | 1243 | Reloc_section* rela_irelative_; |
1244 | + // The RELR dynamic reloc section. | |
1245 | + Relr_section* relr_dyn_; | |
1238 | 1246 | // Relocs saved to avoid a COPY reloc. |
1239 | 1247 | Copy_relocs<elfcpp::SHT_RELA, size, false> copy_relocs_; |
1240 | 1248 | // Offset of the GOT entry for the TLS module index. |
@@ -1431,6 +1439,23 @@ Target_x86_64<size>::rela_irelative_section(Layout* layout) | ||
1431 | 1439 | return this->rela_irelative_; |
1432 | 1440 | } |
1433 | 1441 | |
1442 | +// Get the RELR dynamic reloc section, creating it if necessary. | |
1443 | + | |
1444 | +template<int size> | |
1445 | +typename Target_x86_64<size>::Relr_section* | |
1446 | +Target_x86_64<size>::relr_dyn_section(Layout* layout) | |
1447 | +{ | |
1448 | + if (this->relr_dyn_ == NULL) | |
1449 | + { | |
1450 | + gold_assert(layout != NULL); | |
1451 | + this->relr_dyn_ = new Relr_section(); | |
1452 | + layout->add_output_section_data(".relr.dyn", elfcpp::SHT_RELR, | |
1453 | + elfcpp::SHF_ALLOC, this->relr_dyn_, | |
1454 | + ORDER_DYNAMIC_RELOCS, false); | |
1455 | + } | |
1456 | + return this->relr_dyn_; | |
1457 | +} | |
1458 | + | |
1434 | 1459 | // Write the first three reserved words of the .got.plt section. |
1435 | 1460 | // The remainder of the section is written while writing the PLT |
1436 | 1461 | // in Output_data_plt_i386::do_write. |
@@ -2966,14 +2991,25 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab, | ||
2966 | 2991 | if (parameters->options().output_is_position_independent()) |
2967 | 2992 | { |
2968 | 2993 | unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info()); |
2969 | - Reloc_section* rela_dyn = target->rela_dyn_section(layout); | |
2970 | - rela_dyn->add_local_relative(object, r_sym, | |
2971 | - (size == 32 | |
2972 | - ? elfcpp::R_X86_64_RELATIVE64 | |
2973 | - : elfcpp::R_X86_64_RELATIVE), | |
2974 | - output_section, data_shndx, | |
2975 | - reloc.get_r_offset(), | |
2976 | - reloc.get_r_addend(), is_ifunc); | |
2994 | + if (size == 64 | |
2995 | + && !is_ifunc | |
2996 | + && parameters->options().experimental_use_relr()) | |
2997 | + { | |
2998 | + Relr_section* relr_dyn = target->relr_dyn_section(layout); | |
2999 | + relr_dyn->add_local_relative(object, r_sym, output_section, | |
3000 | + data_shndx, reloc.get_r_offset()); | |
3001 | + } | |
3002 | + else | |
3003 | + { | |
3004 | + Reloc_section* rela_dyn = target->rela_dyn_section(layout); | |
3005 | + rela_dyn->add_local_relative(object, r_sym, | |
3006 | + (size == 32 | |
3007 | + ? elfcpp::R_X86_64_RELATIVE64 | |
3008 | + : elfcpp::R_X86_64_RELATIVE), | |
3009 | + output_section, data_shndx, | |
3010 | + reloc.get_r_offset(), | |
3011 | + reloc.get_r_addend(), is_ifunc); | |
3012 | + } | |
2977 | 3013 | } |
2978 | 3014 | break; |
2979 | 3015 |
@@ -2991,12 +3027,22 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab, | ||
2991 | 3027 | if (size == 32 && r_type == elfcpp::R_X86_64_32) |
2992 | 3028 | { |
2993 | 3029 | unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info()); |
2994 | - Reloc_section* rela_dyn = target->rela_dyn_section(layout); | |
2995 | - rela_dyn->add_local_relative(object, r_sym, | |
2996 | - elfcpp::R_X86_64_RELATIVE, | |
2997 | - output_section, data_shndx, | |
2998 | - reloc.get_r_offset(), | |
2999 | - reloc.get_r_addend(), is_ifunc); | |
3030 | + if (!is_ifunc && parameters->options().experimental_use_relr()) | |
3031 | + { | |
3032 | + Relr_section* relr_dyn = target->relr_dyn_section(layout); | |
3033 | + relr_dyn->add_local_relative(object, r_sym, output_section, | |
3034 | + data_shndx, | |
3035 | + reloc.get_r_offset()); | |
3036 | + } | |
3037 | + else | |
3038 | + { | |
3039 | + Reloc_section* rela_dyn = target->rela_dyn_section(layout); | |
3040 | + rela_dyn->add_local_relative(object, r_sym, | |
3041 | + elfcpp::R_X86_64_RELATIVE, | |
3042 | + output_section, data_shndx, | |
3043 | + reloc.get_r_offset(), | |
3044 | + reloc.get_r_addend(), is_ifunc); | |
3045 | + } | |
3000 | 3046 | break; |
3001 | 3047 | } |
3002 | 3048 |
@@ -3099,15 +3145,7 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab, | ||
3099 | 3145 | { |
3100 | 3146 | Reloc_section* rela_dyn = target->rela_dyn_section(layout); |
3101 | 3147 | // R_X86_64_RELATIVE assumes a 64-bit relocation. |
3102 | - if (r_type != elfcpp::R_X86_64_GOT32) | |
3103 | - { | |
3104 | - unsigned int got_offset = | |
3105 | - object->local_got_offset(r_sym, GOT_TYPE_STANDARD); | |
3106 | - rela_dyn->add_local_relative(object, r_sym, | |
3107 | - elfcpp::R_X86_64_RELATIVE, | |
3108 | - got, got_offset, 0, is_ifunc); | |
3109 | - } | |
3110 | - else | |
3148 | + if (r_type == elfcpp::R_X86_64_GOT32) | |
3111 | 3149 | { |
3112 | 3150 | this->check_non_pic(object, r_type, NULL); |
3113 | 3151 |
@@ -3116,6 +3154,24 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab, | ||
3116 | 3154 | object, r_sym, r_type, got, |
3117 | 3155 | object->local_got_offset(r_sym, GOT_TYPE_STANDARD), 0); |
3118 | 3156 | } |
3157 | + else if (size == 64 | |
3158 | + && !is_ifunc | |
3159 | + && parameters->options().experimental_use_relr()) | |
3160 | + { | |
3161 | + Relr_section* relr_dyn = target->relr_dyn_section(layout); | |
3162 | + unsigned int got_offset = | |
3163 | + object->local_got_offset(r_sym, GOT_TYPE_STANDARD); | |
3164 | + relr_dyn->add_local_relative(object, r_sym, got, | |
3165 | + got_offset); | |
3166 | + } | |
3167 | + else | |
3168 | + { | |
3169 | + unsigned int got_offset = | |
3170 | + object->local_got_offset(r_sym, GOT_TYPE_STANDARD); | |
3171 | + rela_dyn->add_local_relative(object, r_sym, | |
3172 | + elfcpp::R_X86_64_RELATIVE, | |
3173 | + got, got_offset, 0, is_ifunc); | |
3174 | + } | |
3119 | 3175 | } |
3120 | 3176 | } |
3121 | 3177 | // For GOTPLT64, we'd normally want a PLT section, but since |
@@ -3478,12 +3534,24 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab, | ||
3478 | 3534 | || (size == 32 && r_type == elfcpp::R_X86_64_32)) |
3479 | 3535 | && gsym->can_use_relative_reloc(false)) |
3480 | 3536 | { |
3481 | - Reloc_section* rela_dyn = target->rela_dyn_section(layout); | |
3482 | - rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_RELATIVE, | |
3483 | - output_section, object, | |
3484 | - data_shndx, | |
3485 | - reloc.get_r_offset(), | |
3486 | - reloc.get_r_addend(), false); | |
3537 | + if (parameters->options().experimental_use_relr()) | |
3538 | + { | |
3539 | + Relr_section* relr_dyn = target->relr_dyn_section(layout); | |
3540 | + relr_dyn->add_global_relative(gsym, | |
3541 | + output_section, object, | |
3542 | + data_shndx, | |
3543 | + reloc.get_r_offset()); | |
3544 | + } | |
3545 | + else | |
3546 | + { | |
3547 | + Reloc_section* rela_dyn = target->rela_dyn_section(layout); | |
3548 | + rela_dyn->add_global_relative(gsym, | |
3549 | + elfcpp::R_X86_64_RELATIVE, | |
3550 | + output_section, object, | |
3551 | + data_shndx, | |
3552 | + reloc.get_r_offset(), | |
3553 | + reloc.get_r_addend(), false); | |
3554 | + } | |
3487 | 3555 | } |
3488 | 3556 | else |
3489 | 3557 | { |
@@ -3886,7 +3954,8 @@ Target_x86_64<size>::do_finalize_sections( | ||
3886 | 3954 | ? NULL |
3887 | 3955 | : this->plt_->rela_plt()); |
3888 | 3956 | layout->add_target_dynamic_tags(false, this->got_plt_, rel_plt, |
3889 | - this->rela_dyn_, true, false); | |
3957 | + this->rela_dyn_, true, false, | |
3958 | + this->relr_dyn_); | |
3890 | 3959 | |
3891 | 3960 | // Fill in some more dynamic tags. |
3892 | 3961 | Output_data_dynamic* const odyn = layout->dynamic_data(); |