GNU Binutils with patches for OS216
修訂 | 0757c0695b9a8c42e0405418081dce0175bee136 (tree) |
---|---|
時間 | 2016-07-04 18:04:48 |
作者 | Marcin Kościelnicki <koriakin@0x04...> |
Commiter | Marcin Kościelnicki |
gold/s390: Support partial got relro.
@@ -78,6 +78,38 @@ class Output_data_got_plt_s390 : public Output_section_data_build | ||
78 | 78 | Layout* layout_; |
79 | 79 | }; |
80 | 80 | |
81 | +// A class to handle the first entry of .got when partial relro is in use. | |
82 | + | |
83 | +template<int size> | |
84 | +class Output_data_got_dynamic_s390 : public Output_section_data_build | |
85 | +{ | |
86 | + public: | |
87 | + Output_data_got_dynamic_s390(Layout* layout) | |
88 | + : Output_section_data_build(size/8), | |
89 | + layout_(layout) | |
90 | + { } | |
91 | + | |
92 | + Output_data_got_dynamic_s390(Layout* layout, off_t data_size) | |
93 | + : Output_section_data_build(data_size, size/8), | |
94 | + layout_(layout) | |
95 | + { } | |
96 | + | |
97 | + protected: | |
98 | + // Write out the PLT data. | |
99 | + void | |
100 | + do_write(Output_file*); | |
101 | + | |
102 | + // Write to a map file. | |
103 | + void | |
104 | + do_print_to_mapfile(Mapfile* mapfile) const | |
105 | + { mapfile->print_output_data(this, "** GOT DYNAMIC"); } | |
106 | + | |
107 | + private: | |
108 | + // A pointer to the Layout class, so that we can find the .dynamic | |
109 | + // section when we write out the GOT section. | |
110 | + Layout* layout_; | |
111 | +}; | |
112 | + | |
81 | 113 | // A class to handle the PLT data. |
82 | 114 | |
83 | 115 | template<int size> |
@@ -90,10 +122,11 @@ class Output_data_plt_s390 : public Output_section_data | ||
90 | 122 | Output_data_plt_s390(Layout* layout, |
91 | 123 | Output_data_got<size, true>* got, |
92 | 124 | Output_data_got_plt_s390<size>* got_plt, |
93 | - Output_data_space* got_irelative) | |
125 | + Output_data_space* got_irelative, | |
126 | + Output_section_data_build* got_dynamic) | |
94 | 127 | : Output_section_data(4), layout_(layout), |
95 | 128 | irelative_rel_(NULL), got_(got), got_plt_(got_plt), |
96 | - got_irelative_(got_irelative), count_(0), | |
129 | + got_irelative_(got_irelative), got_dynamic_(got_dynamic), count_(0), | |
97 | 130 | irelative_count_(0), free_list_() |
98 | 131 | { this->init(layout); } |
99 | 132 |
@@ -101,11 +134,13 @@ class Output_data_plt_s390 : public Output_section_data | ||
101 | 134 | Output_data_got<size, true>* got, |
102 | 135 | Output_data_got_plt_s390<size>* got_plt, |
103 | 136 | Output_data_space* got_irelative, |
137 | + Output_section_data_build* got_dynamic, | |
104 | 138 | unsigned int plt_count) |
105 | 139 | : Output_section_data((plt_count + 1) * plt_entry_size, |
106 | 140 | 4, false), |
107 | 141 | layout_(layout), irelative_rel_(NULL), got_(got), |
108 | - got_plt_(got_plt), got_irelative_(got_irelative), count_(plt_count), | |
142 | + got_plt_(got_plt), got_irelative_(got_irelative), | |
143 | + got_dynamic_(got_dynamic), count_(plt_count), | |
109 | 144 | irelative_count_(0), free_list_() |
110 | 145 | { |
111 | 146 | this->init(layout); |
@@ -195,7 +230,8 @@ class Output_data_plt_s390 : public Output_section_data | ||
195 | 230 | void |
196 | 231 | fill_first_plt_entry(unsigned char* pov, |
197 | 232 | typename elfcpp::Elf_types<size>::Elf_Addr got_address, |
198 | - typename elfcpp::Elf_types<size>::Elf_Addr plt_address); | |
233 | + typename elfcpp::Elf_types<size>::Elf_Addr plt_address, | |
234 | + unsigned int got_plt_offset); | |
199 | 235 | |
200 | 236 | // Fill in a normal PLT entry. Returns the offset into the entry that |
201 | 237 | // should be the initial GOT slot value. |
@@ -238,6 +274,8 @@ class Output_data_plt_s390 : public Output_section_data | ||
238 | 274 | Output_data_got_plt_s390<size>* got_plt_; |
239 | 275 | // The part of the .got.plt section used for IRELATIVE relocs. |
240 | 276 | Output_data_space* got_irelative_; |
277 | + // The header of .got section. | |
278 | + Output_section_data_build* got_dynamic_; | |
241 | 279 | // The number of PLT entries. |
242 | 280 | unsigned int count_; |
243 | 281 | // Number of PLT entries with R_TILEGX_IRELATIVE relocs. These |
@@ -251,6 +289,7 @@ class Output_data_plt_s390 : public Output_section_data | ||
251 | 289 | static const int plt_entry_size = 0x20; |
252 | 290 | // The first entry in the PLT. |
253 | 291 | static const unsigned char first_plt_entry_32_abs[plt_entry_size]; |
292 | + static const unsigned char first_plt_entry_32_pic12[plt_entry_size]; | |
254 | 293 | static const unsigned char first_plt_entry_32_pic[plt_entry_size]; |
255 | 294 | static const unsigned char first_plt_entry_64[plt_entry_size]; |
256 | 295 | // Other entries in the PLT for an executable. |
@@ -646,7 +685,7 @@ class Target_s390 : public Sized_target<size, true> | ||
646 | 685 | got_address() const |
647 | 686 | { |
648 | 687 | gold_assert(this->got_ != NULL); |
649 | - return this->got_plt_->address(); | |
688 | + return this->got_dynamic_->address(); | |
650 | 689 | } |
651 | 690 | |
652 | 691 | typename elfcpp::Elf_types<size>::Elf_Addr |
@@ -741,6 +780,10 @@ class Target_s390 : public Sized_target<size, true> | ||
741 | 780 | Output_data_got_plt_s390<size>* got_plt_; |
742 | 781 | // The GOT section for IRELATIVE relocations. |
743 | 782 | Output_data_space* got_irelative_; |
783 | + // The section containing the first GOT entry (_DYNAMIC) - this is | |
784 | + // Output_data_got_dynamic_s390 if partial relro is in use, same | |
785 | + // as got_plt_ otherwise. | |
786 | + Output_section_data_build* got_dynamic_; | |
744 | 787 | // The _GLOBAL_OFFSET_TABLE_ symbol. |
745 | 788 | Symbol* global_offset_table_; |
746 | 789 | // The dynamic reloc section. |
@@ -1247,18 +1290,18 @@ Output_data_plt_s390<size>::first_plt_entry_32_abs[plt_entry_size] = | ||
1247 | 1290 | 0x58, 0x10, 0x10, 0x08, // l %r1, 8(%r1) |
1248 | 1291 | 0x07, 0xf1, // br %r1 |
1249 | 1292 | 0x00, 0x00, // padding |
1250 | - 0x00, 0x00, 0x00, 0x00, // _GLOBAL_OFFSET_TABLE_ (to fill) | |
1293 | + 0x00, 0x00, 0x00, 0x00, // DT_GOTPLT (to fill) | |
1251 | 1294 | 0x00, 0x00, 0x00, 0x00, // padding |
1252 | 1295 | }; |
1253 | 1296 | |
1254 | 1297 | template<int size> |
1255 | 1298 | const unsigned char |
1256 | -Output_data_plt_s390<size>::first_plt_entry_32_pic[plt_entry_size] = | |
1299 | +Output_data_plt_s390<size>::first_plt_entry_32_pic12[plt_entry_size] = | |
1257 | 1300 | { |
1258 | 1301 | 0x50, 0x10, 0xf0, 0x1c, // st %r1, 28(%r15) |
1259 | - 0x58, 0x10, 0xc0, 0x04, // l %r1, 4(%r12) | |
1302 | + 0x58, 0x10, 0xc0, 0x00, // l %r1, DT_GOTPLT@got+4(%r12) (to fill) | |
1260 | 1303 | 0x50, 0x10, 0xf0, 0x18, // st %r1, 24(%r15) |
1261 | - 0x58, 0x10, 0xc0, 0x08, // l %r1, 8(%r12) | |
1304 | + 0x58, 0x10, 0xc0, 0x00, // l %r1, DT_GOTPLT@got+8(%r12) (to fill) | |
1262 | 1305 | 0x07, 0xf1, // br %r1 |
1263 | 1306 | 0x00, 0x00, // padding |
1264 | 1307 | 0x00, 0x00, 0x00, 0x00, // padding |
@@ -1268,10 +1311,25 @@ Output_data_plt_s390<size>::first_plt_entry_32_pic[plt_entry_size] = | ||
1268 | 1311 | |
1269 | 1312 | template<int size> |
1270 | 1313 | const unsigned char |
1314 | +Output_data_plt_s390<size>::first_plt_entry_32_pic[plt_entry_size] = | |
1315 | +{ | |
1316 | + 0x50, 0x10, 0xf0, 0x1c, // st %r1, 28(%r15) | |
1317 | + 0x0d, 0x10, // basr %r1, %r0 | |
1318 | + 0x5a, 0x10, 0x10, 0x12, // a %r1, 18(%r1) | |
1319 | + 0xd2, 0x03, 0xf0, 0x18, 0x10, 0x04, // mvc 24(4,%r15), 4(%r1) | |
1320 | + 0x58, 0x10, 0x10, 0x08, // l %r1, 8(%r1) | |
1321 | + 0x07, 0xf1, // br %r1 | |
1322 | + 0x00, 0x00, // padding | |
1323 | + 0x00, 0x00, 0x00, 0x00, // DT_GOTPLT - . + 18 (to fill) | |
1324 | + 0x00, 0x00, 0x00, 0x00, // padding | |
1325 | +}; | |
1326 | + | |
1327 | +template<int size> | |
1328 | +const unsigned char | |
1271 | 1329 | Output_data_plt_s390<size>::first_plt_entry_64[plt_entry_size] = |
1272 | 1330 | { |
1273 | 1331 | 0xe3, 0x10, 0xf0, 0x38, 0x00, 0x24, // stg %r1, 56(%r15) |
1274 | - 0xc0, 0x10, 0x00, 0x00, 0x00, 0x00, // larl %r1, _GLOBAL_OFFSET_TABLE_ (to fill) | |
1332 | + 0xc0, 0x10, 0x00, 0x00, 0x00, 0x00, // larl %r1, DT_GOTPLT (to fill) | |
1275 | 1333 | 0xd2, 0x07, 0xf0, 0x30, 0x10, 0x08, // mvc 48(8,%r15), 8(%r1) |
1276 | 1334 | 0xe3, 0x10, 0x10, 0x10, 0x00, 0x04, // lg %r1, 16(%r1) |
1277 | 1335 | 0x07, 0xf1, // br %r1 |
@@ -1284,22 +1342,33 @@ template<int size> | ||
1284 | 1342 | void |
1285 | 1343 | Output_data_plt_s390<size>::fill_first_plt_entry( |
1286 | 1344 | unsigned char* pov, |
1287 | - typename elfcpp::Elf_types<size>::Elf_Addr got_address, | |
1288 | - typename elfcpp::Elf_types<size>::Elf_Addr plt_address) | |
1345 | + typename elfcpp::Elf_types<size>::Elf_Addr got_plt_address, | |
1346 | + typename elfcpp::Elf_types<size>::Elf_Addr plt_address, | |
1347 | + unsigned int got_plt_offset) | |
1289 | 1348 | { |
1290 | 1349 | if (size == 64) |
1291 | 1350 | { |
1292 | 1351 | memcpy(pov, first_plt_entry_64, plt_entry_size); |
1293 | - S390_relocate_functions<size>::pcrela32dbl(pov + 8, got_address, (plt_address + 6)); | |
1352 | + S390_relocate_functions<size>::pcrela32dbl(pov + 8, got_plt_address, (plt_address + 6)); | |
1294 | 1353 | } |
1295 | 1354 | else if (!parameters->options().output_is_position_independent()) |
1296 | 1355 | { |
1297 | 1356 | memcpy(pov, first_plt_entry_32_abs, plt_entry_size); |
1298 | - elfcpp::Swap<32, true>::writeval(pov + 24, got_address); | |
1357 | + elfcpp::Swap<32, true>::writeval(pov + 24, got_plt_address); | |
1299 | 1358 | } |
1300 | 1359 | else |
1301 | 1360 | { |
1302 | - memcpy(pov, first_plt_entry_32_pic, plt_entry_size); | |
1361 | + if (got_plt_offset < 0xff8) | |
1362 | + { | |
1363 | + memcpy(pov, first_plt_entry_32_pic12, plt_entry_size); | |
1364 | + S390_relocate_functions<size>::rela12(pov + 6, got_plt_offset + 4); | |
1365 | + S390_relocate_functions<size>::rela12(pov + 14, got_plt_offset + 8); | |
1366 | + } | |
1367 | + else | |
1368 | + { | |
1369 | + memcpy(pov, first_plt_entry_32_pic, plt_entry_size); | |
1370 | + elfcpp::Swap<32, true>::writeval(pov + 24, got_plt_address - (plt_address + 6)); | |
1371 | + } | |
1303 | 1372 | } |
1304 | 1373 | } |
1305 | 1374 |
@@ -1536,9 +1605,12 @@ Output_data_plt_s390<size>::do_write(Output_file* of) | ||
1536 | 1605 | // which is where the GOT pointer will point, and where the |
1537 | 1606 | // three reserved GOT entries are located. |
1538 | 1607 | typename elfcpp::Elf_types<size>::Elf_Addr got_address |
1539 | - = this->got_plt_->address(); | |
1608 | + = this->got_dynamic_->address(); | |
1540 | 1609 | |
1541 | - this->fill_first_plt_entry(pov, got_address, plt_address); | |
1610 | + unsigned int got_plt_offset = this->got_plt_->address() - got_address; | |
1611 | + | |
1612 | + this->fill_first_plt_entry(pov, this->got_plt_->address(), plt_address, | |
1613 | + got_plt_offset); | |
1542 | 1614 | pov += this->get_plt_entry_size(); |
1543 | 1615 | |
1544 | 1616 | unsigned char* got_pov = got_view; |
@@ -1547,7 +1619,7 @@ Output_data_plt_s390<size>::do_write(Output_file* of) | ||
1547 | 1619 | |
1548 | 1620 | unsigned int plt_offset = this->get_plt_entry_size(); |
1549 | 1621 | unsigned int plt_rel_offset = 0; |
1550 | - unsigned int got_offset = 3 * size / 8; | |
1622 | + unsigned int got_offset = 3 * size / 8 + got_plt_offset; | |
1551 | 1623 | const unsigned int count = this->count_ + this->irelative_count_; |
1552 | 1624 | // The first three entries in the GOT are reserved, and are written |
1553 | 1625 | // by Output_data_got_plt_s390::do_write. |
@@ -1590,22 +1662,43 @@ Target_s390<size>::got_section(Symbol_table* symtab, Layout* layout) | ||
1590 | 1662 | { |
1591 | 1663 | gold_assert(symtab != NULL && layout != NULL); |
1592 | 1664 | |
1593 | - // When using -z now, we can treat .got as a relro section. | |
1594 | - // Without -z now, it is modified after program startup by lazy | |
1595 | - // PLT relocations. | |
1596 | - bool is_got_relro = parameters->options().now(); | |
1597 | - Output_section_order got_order = (is_got_relro | |
1598 | - ? ORDER_RELRO_LAST | |
1599 | - : ORDER_DATA); | |
1665 | + bool is_got_relro, is_got_plt_relro; | |
1666 | + Output_section_order got_order, got_plt_order; | |
1667 | + const char *got_plt_name; | |
1668 | + if (parameters->options().relro()) | |
1669 | + { | |
1670 | + // Partial GOT relro. | |
1671 | + is_got_relro = true; | |
1672 | + is_got_plt_relro = false; | |
1673 | + got_order = ORDER_RELRO_LAST; | |
1674 | + got_plt_order = ORDER_NON_RELRO_FIRST; | |
1675 | + got_plt_name = ".got.plt"; | |
1676 | + } | |
1677 | + else if (parameters->options().now()) | |
1678 | + { | |
1679 | + // When using -z now, we can treat the whole .got as a relro section. | |
1680 | + is_got_plt_relro = is_got_relro = true; | |
1681 | + got_order = got_plt_order = ORDER_RELRO_LAST; | |
1682 | + got_plt_name = ".got"; | |
1683 | + } | |
1684 | + else | |
1685 | + { | |
1686 | + // Without -z now, it is modified after program startup by lazy | |
1687 | + // PLT relocations. | |
1688 | + is_got_plt_relro = is_got_relro = false; | |
1689 | + got_order = got_plt_order = ORDER_DATA; | |
1690 | + got_plt_name = ".got"; | |
1691 | + } | |
1600 | 1692 | |
1601 | 1693 | // The old GNU linker creates a .got.plt section. We just |
1602 | 1694 | // create another set of data in the .got section. Note that we |
1603 | 1695 | // always create a PLT if we create a GOT, although the PLT |
1604 | 1696 | // might be empty. |
1605 | 1697 | this->got_plt_ = new Output_data_got_plt_s390<size>(layout); |
1606 | - layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, | |
1698 | + layout->add_output_section_data(got_plt_name, elfcpp::SHT_PROGBITS, | |
1607 | 1699 | (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), |
1608 | - this->got_plt_, got_order, is_got_relro); | |
1700 | + this->got_plt_, got_plt_order, | |
1701 | + is_got_plt_relro); | |
1609 | 1702 | |
1610 | 1703 | // The first three entries are reserved. |
1611 | 1704 | this->got_plt_->set_current_data_size(3 * size / 8); |
@@ -1613,10 +1706,23 @@ Target_s390<size>::got_section(Symbol_table* symtab, Layout* layout) | ||
1613 | 1706 | // If there are any IRELATIVE relocations, they get GOT entries |
1614 | 1707 | // in .got.plt after the jump slot entries. |
1615 | 1708 | this->got_irelative_ = new Output_data_space(size / 8, "** GOT IRELATIVE PLT"); |
1616 | - layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, | |
1709 | + layout->add_output_section_data(got_plt_name, elfcpp::SHT_PROGBITS, | |
1617 | 1710 | (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), |
1618 | 1711 | this->got_irelative_, |
1619 | - got_order, is_got_relro); | |
1712 | + got_plt_order, is_got_plt_relro); | |
1713 | + | |
1714 | + if (parameters->options().relro()) | |
1715 | + { | |
1716 | + // For partial relro, we need a _DYNAMIC pointer at | |
1717 | + // _GLOBAL_OFFSET_TABLE_, not at DT_GOTPLT. | |
1718 | + this->got_dynamic_ = new Output_data_got_dynamic_s390<size>(layout); | |
1719 | + layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, | |
1720 | + (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), | |
1721 | + this->got_dynamic_, got_order, true); | |
1722 | + this->got_dynamic_->set_current_data_size(size / 8); | |
1723 | + } | |
1724 | + else | |
1725 | + this->got_dynamic_ = this->got_plt_; | |
1620 | 1726 | |
1621 | 1727 | // Unlike some targets (.e.g x86), S/390 does not use separate .got and |
1622 | 1728 | // .got.plt sections in output. The output .got section contains both |
@@ -1629,9 +1735,9 @@ Target_s390<size>::got_section(Symbol_table* symtab, Layout* layout) | ||
1629 | 1735 | |
1630 | 1736 | // Define _GLOBAL_OFFSET_TABLE_ at the start of the GOT. |
1631 | 1737 | this->global_offset_table_ = |
1632 | - symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL, | |
1738 | + symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL, | |
1633 | 1739 | Symbol_table::PREDEFINED, |
1634 | - this->got_plt_, | |
1740 | + this->got_dynamic_, | |
1635 | 1741 | 0, 0, elfcpp::STT_OBJECT, |
1636 | 1742 | elfcpp::STB_LOCAL, |
1637 | 1743 | elfcpp::STV_HIDDEN, 0, |
@@ -1693,7 +1799,7 @@ Output_data_got_plt_s390<size>::do_write(Output_file* of) | ||
1693 | 1799 | // The first entry in the GOT is the address of the .dynamic section |
1694 | 1800 | // aka the PT_DYNAMIC segment. The next two entries are reserved. |
1695 | 1801 | // We saved space for them when we created the section in |
1696 | - // Target_x86_64::got_section. | |
1802 | + // Target_s390::got_section. | |
1697 | 1803 | const off_t got_file_offset = this->offset(); |
1698 | 1804 | gold_assert(this->data_size() >= 3 * size / 8); |
1699 | 1805 | unsigned char* const got_view = |
@@ -1705,6 +1811,26 @@ Output_data_got_plt_s390<size>::do_write(Output_file* of) | ||
1705 | 1811 | of->write_output_view(got_file_offset, 3 * size / 8, got_view); |
1706 | 1812 | } |
1707 | 1813 | |
1814 | +// Write the first reserved word of the .got section. | |
1815 | + | |
1816 | +template<int size> | |
1817 | +void | |
1818 | +Output_data_got_dynamic_s390<size>::do_write(Output_file* of) | |
1819 | +{ | |
1820 | + // The first entry in the GOT is the address of the .dynamic section | |
1821 | + // aka the PT_DYNAMIC segment. The next two entries are reserved. | |
1822 | + // We saved space for them when we created the section in | |
1823 | + // Target_s390::got_section. | |
1824 | + const off_t got_file_offset = this->offset(); | |
1825 | + gold_assert(this->data_size() == size / 8); | |
1826 | + unsigned char* const got_view = | |
1827 | + of->get_output_view(got_file_offset, size / 8); | |
1828 | + Output_section* dynamic = this->layout_->dynamic_section(); | |
1829 | + uint64_t dynamic_addr = dynamic == NULL ? 0 : dynamic->address(); | |
1830 | + elfcpp::Swap<size, true>::writeval(got_view, dynamic_addr); | |
1831 | + of->write_output_view(got_file_offset, size / 8, got_view); | |
1832 | +} | |
1833 | + | |
1708 | 1834 | // Create the PLT section. |
1709 | 1835 | |
1710 | 1836 | template<int size> |
@@ -1722,7 +1848,8 @@ Target_s390<size>::make_plt_section(Symbol_table* symtab, Layout* layout) | ||
1722 | 1848 | this->rela_dyn_section(layout); |
1723 | 1849 | |
1724 | 1850 | this->plt_ = new Output_data_plt_s390<size>(layout, |
1725 | - this->got_, this->got_plt_, this->got_irelative_); | |
1851 | + this->got_, this->got_plt_, this->got_irelative_, | |
1852 | + this->got_dynamic_); | |
1726 | 1853 | |
1727 | 1854 | // Add unwind information if requested. |
1728 | 1855 | if (parameters->options().ld_generated_unwind_info()) |
@@ -1814,34 +1941,72 @@ Target_s390<size>::init_got_plt_for_update(Symbol_table* symtab, | ||
1814 | 1941 | { |
1815 | 1942 | gold_assert(this->got_ == NULL); |
1816 | 1943 | |
1944 | + bool is_got_relro, is_got_plt_relro; | |
1945 | + Output_section_order got_order, got_plt_order; | |
1946 | + const char *got_plt_name; | |
1947 | + if (parameters->options().relro()) | |
1948 | + { | |
1949 | + // Partial GOT relro. | |
1950 | + is_got_relro = true; | |
1951 | + is_got_plt_relro = false; | |
1952 | + got_order = ORDER_RELRO_LAST; | |
1953 | + got_plt_order = ORDER_NON_RELRO_FIRST; | |
1954 | + got_plt_name = ".got.plt"; | |
1955 | + } | |
1956 | + else if (parameters->options().now()) | |
1957 | + { | |
1958 | + // When using -z now, we can treat the whole .got as a relro section. | |
1959 | + is_got_plt_relro = is_got_relro = true; | |
1960 | + got_order = got_plt_order = ORDER_RELRO_LAST; | |
1961 | + got_plt_name = ".got"; | |
1962 | + } | |
1963 | + else | |
1964 | + { | |
1965 | + // Without -z now, it is modified after program startup by lazy | |
1966 | + // PLT relocations. | |
1967 | + is_got_plt_relro = is_got_relro = false; | |
1968 | + got_order = got_plt_order = ORDER_DATA; | |
1969 | + got_plt_name = ".got"; | |
1970 | + } | |
1971 | + | |
1817 | 1972 | // Add the three reserved entries. |
1818 | 1973 | this->got_plt_ = new Output_data_got_plt_s390<size>(layout, (plt_count + 3) * size / 8); |
1819 | - layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, | |
1820 | - (elfcpp::SHF_ALLOC | |
1821 | - | elfcpp::SHF_WRITE), | |
1822 | - this->got_plt_, ORDER_NON_RELRO_FIRST, | |
1823 | - false); | |
1974 | + layout->add_output_section_data(got_plt_name, elfcpp::SHT_PROGBITS, | |
1975 | + (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), | |
1976 | + this->got_plt_, got_plt_order, | |
1977 | + is_got_plt_relro); | |
1824 | 1978 | |
1825 | 1979 | // If there are any IRELATIVE relocations, they get GOT entries in |
1826 | 1980 | // .got.plt after the jump slot entries. |
1827 | 1981 | this->got_irelative_ = new Output_data_space(0, size / 8, "** GOT IRELATIVE PLT"); |
1828 | - layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, | |
1982 | + layout->add_output_section_data(got_plt_name, elfcpp::SHT_PROGBITS, | |
1829 | 1983 | elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, |
1830 | 1984 | this->got_irelative_, |
1831 | - ORDER_NON_RELRO_FIRST, false); | |
1985 | + got_plt_order, is_got_plt_relro); | |
1986 | + | |
1987 | + if (parameters->options().relro()) | |
1988 | + { | |
1989 | + // For partial relro, we need a _DYNAMIC pointer at | |
1990 | + // _GLOBAL_OFFSET_TABLE_, not at DT_GOTPLT. | |
1991 | + this->got_dynamic_ = new Output_data_got_dynamic_s390<size>(layout); | |
1992 | + layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, | |
1993 | + (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), | |
1994 | + this->got_dynamic_, got_order, true); | |
1995 | + this->got_dynamic_->set_current_data_size(size / 8); | |
1996 | + } | |
1997 | + else | |
1998 | + this->got_dynamic_ = this->got_plt_; | |
1832 | 1999 | |
1833 | 2000 | this->got_ = new Output_data_got<size, true>(got_count * size / 8); |
1834 | 2001 | layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, |
1835 | - (elfcpp::SHF_ALLOC | |
1836 | - | elfcpp::SHF_WRITE), | |
1837 | - this->got_, ORDER_RELRO_LAST, | |
1838 | - true); | |
2002 | + (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), | |
2003 | + this->got_, got_order, is_got_relro); | |
1839 | 2004 | |
1840 | 2005 | // Define _GLOBAL_OFFSET_TABLE_ at the start of the PLT. |
1841 | 2006 | this->global_offset_table_ = |
1842 | 2007 | symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL, |
1843 | 2008 | Symbol_table::PREDEFINED, |
1844 | - this->got_plt_, | |
2009 | + this->got_dynamic_, | |
1845 | 2010 | 0, 0, elfcpp::STT_OBJECT, |
1846 | 2011 | elfcpp::STB_LOCAL, |
1847 | 2012 | elfcpp::STV_HIDDEN, 0, |
@@ -1849,7 +2014,8 @@ Target_s390<size>::init_got_plt_for_update(Symbol_table* symtab, | ||
1849 | 2014 | |
1850 | 2015 | // Create the PLT section. |
1851 | 2016 | this->plt_ = new Output_data_plt_s390<size>(layout, |
1852 | - this->got_, this->got_plt_, this->got_irelative_, plt_count); | |
2017 | + this->got_, this->got_plt_, this->got_irelative_, | |
2018 | + this->got_dynamic_, plt_count); | |
1853 | 2019 | |
1854 | 2020 | // Add unwind information if requested. |
1855 | 2021 | if (parameters->options().ld_generated_unwind_info()) |
@@ -4051,6 +4217,10 @@ Target_s390<size>::do_finalize_sections( | ||
4051 | 4217 | if (sym != NULL) |
4052 | 4218 | { |
4053 | 4219 | uint64_t data_size = this->got_->current_data_size(); |
4220 | + data_size += this->got_plt_->current_data_size(); | |
4221 | + data_size += this->got_irelative_->current_data_size(); | |
4222 | + if (this->got_plt_ != this->got_dynamic_) | |
4223 | + data_size += this->got_dynamic_->current_data_size(); | |
4054 | 4224 | symtab->get_sized_symbol<size>(sym)->set_symsize(data_size); |
4055 | 4225 | } |
4056 | 4226 |