OLD | NEW |
1 // arm.cc -- arm target support for gold. | 1 // arm.cc -- arm target support for gold. |
2 | 2 |
3 // Copyright 2009 Free Software Foundation, Inc. | 3 // Copyright 2009 Free Software Foundation, Inc. |
4 // Written by Doug Kwan <dougkwan@google.com> based on the i386 code | 4 // Written by Doug Kwan <dougkwan@google.com> based on the i386 code |
5 // by Ian Lance Taylor <iant@google.com>. | 5 // by Ian Lance Taylor <iant@google.com>. |
6 | 6 |
7 // This file is part of gold. | 7 // This file is part of gold. |
8 | 8 |
9 // This program is free software; you can redistribute it and/or modify | 9 // This program is free software; you can redistribute it and/or modify |
10 // it under the terms of the GNU General Public License as published by | 10 // it under the terms of the GNU General Public License as published by |
(...skipping 1057 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1068 if (this->got_ == NULL) | 1068 if (this->got_ == NULL) |
1069 { | 1069 { |
1070 gold_assert(symtab != NULL && layout != NULL); | 1070 gold_assert(symtab != NULL && layout != NULL); |
1071 | 1071 |
1072 this->got_ = new Output_data_got<32, big_endian>(); | 1072 this->got_ = new Output_data_got<32, big_endian>(); |
1073 | 1073 |
1074 Output_section* os; | 1074 Output_section* os; |
1075 os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, | 1075 os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, |
1076 (elfcpp::SHF_ALLOC | 1076 (elfcpp::SHF_ALLOC |
1077 | elfcpp::SHF_WRITE), | 1077 | elfcpp::SHF_WRITE), |
1078 » » » » » this->got_); | 1078 » » » » » this->got_, false); |
1079 os->set_is_relro(); | 1079 os->set_is_relro(); |
1080 | 1080 |
1081 // The old GNU linker creates a .got.plt section. We just | 1081 // The old GNU linker creates a .got.plt section. We just |
1082 // create another set of data in the .got section. Note that we | 1082 // create another set of data in the .got section. Note that we |
1083 // always create a PLT if we create a GOT, although the PLT | 1083 // always create a PLT if we create a GOT, although the PLT |
1084 // might be empty. | 1084 // might be empty. |
1085 this->got_plt_ = new Output_data_space(4, "** GOT PLT"); | 1085 this->got_plt_ = new Output_data_space(4, "** GOT PLT"); |
1086 os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, | 1086 os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, |
1087 (elfcpp::SHF_ALLOC | 1087 (elfcpp::SHF_ALLOC |
1088 | elfcpp::SHF_WRITE), | 1088 | elfcpp::SHF_WRITE), |
1089 » » » » » this->got_plt_); | 1089 » » » » » this->got_plt_, false); |
1090 os->set_is_relro(); | 1090 os->set_is_relro(); |
1091 | 1091 |
1092 // The first three entries are reserved. | 1092 // The first three entries are reserved. |
1093 this->got_plt_->set_current_data_size(3 * 4); | 1093 this->got_plt_->set_current_data_size(3 * 4); |
1094 | 1094 |
1095 // Define _GLOBAL_OFFSET_TABLE_ at the start of the PLT. | 1095 // Define _GLOBAL_OFFSET_TABLE_ at the start of the PLT. |
1096 symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL, | 1096 symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL, |
1097 this->got_plt_, | 1097 this->got_plt_, |
1098 0, 0, elfcpp::STT_OBJECT, | 1098 0, 0, elfcpp::STT_OBJECT, |
1099 elfcpp::STB_LOCAL, | 1099 elfcpp::STB_LOCAL, |
1100 elfcpp::STV_HIDDEN, 0, | 1100 elfcpp::STV_HIDDEN, 0, |
1101 false, false); | 1101 false, false); |
1102 } | 1102 } |
1103 return this->got_; | 1103 return this->got_; |
1104 } | 1104 } |
1105 | 1105 |
1106 // Get the dynamic reloc section, creating it if necessary. | 1106 // Get the dynamic reloc section, creating it if necessary. |
1107 | 1107 |
1108 template<bool big_endian> | 1108 template<bool big_endian> |
1109 typename Target_arm<big_endian>::Reloc_section* | 1109 typename Target_arm<big_endian>::Reloc_section* |
1110 Target_arm<big_endian>::rel_dyn_section(Layout* layout) | 1110 Target_arm<big_endian>::rel_dyn_section(Layout* layout) |
1111 { | 1111 { |
1112 if (this->rel_dyn_ == NULL) | 1112 if (this->rel_dyn_ == NULL) |
1113 { | 1113 { |
1114 gold_assert(layout != NULL); | 1114 gold_assert(layout != NULL); |
1115 this->rel_dyn_ = new Reloc_section(parameters->options().combreloc()); | 1115 this->rel_dyn_ = new Reloc_section(parameters->options().combreloc()); |
1116 layout->add_output_section_data(".rel.dyn", elfcpp::SHT_REL, | 1116 layout->add_output_section_data(".rel.dyn", elfcpp::SHT_REL, |
1117 » » » » elfcpp::SHF_ALLOC, this->rel_dyn_); | 1117 » » » » elfcpp::SHF_ALLOC, this->rel_dyn_, true); |
1118 } | 1118 } |
1119 return this->rel_dyn_; | 1119 return this->rel_dyn_; |
1120 } | 1120 } |
1121 | 1121 |
1122 // A class to handle the PLT data. | 1122 // A class to handle the PLT data. |
1123 | 1123 |
1124 template<bool big_endian> | 1124 template<bool big_endian> |
1125 class Output_data_plt_arm : public Output_section_data | 1125 class Output_data_plt_arm : public Output_section_data |
1126 { | 1126 { |
1127 public: | 1127 public: |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1179 // since we need to refer to the start. We also create our own .got | 1179 // since we need to refer to the start. We also create our own .got |
1180 // section just for PLT entries. | 1180 // section just for PLT entries. |
1181 | 1181 |
1182 template<bool big_endian> | 1182 template<bool big_endian> |
1183 Output_data_plt_arm<big_endian>::Output_data_plt_arm(Layout* layout, | 1183 Output_data_plt_arm<big_endian>::Output_data_plt_arm(Layout* layout, |
1184 Output_data_space* got_plt) | 1184 Output_data_space* got_plt) |
1185 : Output_section_data(4), got_plt_(got_plt), count_(0) | 1185 : Output_section_data(4), got_plt_(got_plt), count_(0) |
1186 { | 1186 { |
1187 this->rel_ = new Reloc_section(false); | 1187 this->rel_ = new Reloc_section(false); |
1188 layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL, | 1188 layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL, |
1189 » » » » elfcpp::SHF_ALLOC, this->rel_); | 1189 » » » » elfcpp::SHF_ALLOC, this->rel_, true); |
1190 } | 1190 } |
1191 | 1191 |
1192 template<bool big_endian> | 1192 template<bool big_endian> |
1193 void | 1193 void |
1194 Output_data_plt_arm<big_endian>::do_adjust_output_section(Output_section* os) | 1194 Output_data_plt_arm<big_endian>::do_adjust_output_section(Output_section* os) |
1195 { | 1195 { |
1196 os->set_entsize(0); | 1196 os->set_entsize(0); |
1197 } | 1197 } |
1198 | 1198 |
1199 // Add an entry to the PLT. | 1199 // Add an entry to the PLT. |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1341 | 1341 |
1342 if (this->plt_ == NULL) | 1342 if (this->plt_ == NULL) |
1343 { | 1343 { |
1344 // Create the GOT sections first. | 1344 // Create the GOT sections first. |
1345 this->got_section(symtab, layout); | 1345 this->got_section(symtab, layout); |
1346 | 1346 |
1347 this->plt_ = new Output_data_plt_arm<big_endian>(layout, this->got_plt_); | 1347 this->plt_ = new Output_data_plt_arm<big_endian>(layout, this->got_plt_); |
1348 layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS, | 1348 layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS, |
1349 (elfcpp::SHF_ALLOC | 1349 (elfcpp::SHF_ALLOC |
1350 | elfcpp::SHF_EXECINSTR), | 1350 | elfcpp::SHF_EXECINSTR), |
1351 » » » » this->plt_); | 1351 » » » » this->plt_, false); |
1352 } | 1352 } |
1353 this->plt_->add_entry(gsym); | 1353 this->plt_->add_entry(gsym); |
1354 } | 1354 } |
1355 | 1355 |
1356 // Report an unsupported relocation against a local symbol. | 1356 // Report an unsupported relocation against a local symbol. |
1357 | 1357 |
1358 template<bool big_endian> | 1358 template<bool big_endian> |
1359 void | 1359 void |
1360 Target_arm<big_endian>::Scan::unsupported_reloc_local( | 1360 Target_arm<big_endian>::Scan::unsupported_reloc_local( |
1361 Sized_relobj<32, big_endian>* object, | 1361 Sized_relobj<32, big_endian>* object, |
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1824 // Finalize the sections. | 1824 // Finalize the sections. |
1825 | 1825 |
1826 template<bool big_endian> | 1826 template<bool big_endian> |
1827 void | 1827 void |
1828 Target_arm<big_endian>::do_finalize_sections(Layout* layout) | 1828 Target_arm<big_endian>::do_finalize_sections(Layout* layout) |
1829 { | 1829 { |
1830 // Fill in some more dynamic tags. | 1830 // Fill in some more dynamic tags. |
1831 Output_data_dynamic* const odyn = layout->dynamic_data(); | 1831 Output_data_dynamic* const odyn = layout->dynamic_data(); |
1832 if (odyn != NULL) | 1832 if (odyn != NULL) |
1833 { | 1833 { |
1834 if (this->got_plt_ != NULL) | 1834 if (this->got_plt_ != NULL |
| 1835 » && this->got_plt_->output_section() != NULL) |
1835 odyn->add_section_address(elfcpp::DT_PLTGOT, this->got_plt_); | 1836 odyn->add_section_address(elfcpp::DT_PLTGOT, this->got_plt_); |
1836 | 1837 |
1837 if (this->plt_ != NULL) | 1838 if (this->plt_ != NULL |
| 1839 » && this->plt_->output_section() != NULL) |
1838 { | 1840 { |
1839 const Output_data* od = this->plt_->rel_plt(); | 1841 const Output_data* od = this->plt_->rel_plt(); |
1840 odyn->add_section_size(elfcpp::DT_PLTRELSZ, od); | 1842 odyn->add_section_size(elfcpp::DT_PLTRELSZ, od); |
1841 odyn->add_section_address(elfcpp::DT_JMPREL, od); | 1843 odyn->add_section_address(elfcpp::DT_JMPREL, od); |
1842 odyn->add_constant(elfcpp::DT_PLTREL, elfcpp::DT_REL); | 1844 odyn->add_constant(elfcpp::DT_PLTREL, elfcpp::DT_REL); |
1843 } | 1845 } |
1844 | 1846 |
1845 if (this->rel_dyn_ != NULL) | 1847 if (this->rel_dyn_ != NULL |
| 1848 » && this->rel_dyn_->output_section() != NULL) |
1846 { | 1849 { |
1847 const Output_data* od = this->rel_dyn_; | 1850 const Output_data* od = this->rel_dyn_; |
1848 odyn->add_section_address(elfcpp::DT_REL, od); | 1851 odyn->add_section_address(elfcpp::DT_REL, od); |
1849 odyn->add_section_size(elfcpp::DT_RELSZ, od); | 1852 odyn->add_section_size(elfcpp::DT_RELSZ, od); |
1850 odyn->add_constant(elfcpp::DT_RELENT, | 1853 odyn->add_constant(elfcpp::DT_RELENT, |
1851 elfcpp::Elf_sizes<32>::rel_size); | 1854 elfcpp::Elf_sizes<32>::rel_size); |
1852 } | 1855 } |
1853 | 1856 |
1854 if (!parameters->options().shared()) | 1857 if (!parameters->options().shared()) |
1855 { | 1858 { |
(...skipping 16 matching lines...) Expand all Loading... |
1872 Output_section* exidx_section = | 1875 Output_section* exidx_section = |
1873 layout->find_output_section(".ARM.exidx"); | 1876 layout->find_output_section(".ARM.exidx"); |
1874 | 1877 |
1875 if (exidx_section != NULL | 1878 if (exidx_section != NULL |
1876 && exidx_section->type() == elfcpp::SHT_ARM_EXIDX) | 1879 && exidx_section->type() == elfcpp::SHT_ARM_EXIDX) |
1877 { | 1880 { |
1878 gold_assert(layout->find_output_segment(elfcpp::PT_ARM_EXIDX, 0, 0) | 1881 gold_assert(layout->find_output_segment(elfcpp::PT_ARM_EXIDX, 0, 0) |
1879 == NULL); | 1882 == NULL); |
1880 Output_segment* exidx_segment = | 1883 Output_segment* exidx_segment = |
1881 layout->make_output_segment(elfcpp::PT_ARM_EXIDX, elfcpp::PF_R); | 1884 layout->make_output_segment(elfcpp::PT_ARM_EXIDX, elfcpp::PF_R); |
1882 » exidx_segment->add_output_section(exidx_section, elfcpp::PF_R); | 1885 » exidx_segment->add_output_section(exidx_section, elfcpp::PF_R, |
| 1886 » » » » » false); |
1883 } | 1887 } |
1884 } | 1888 } |
1885 } | 1889 } |
1886 | 1890 |
1887 // Return whether a direct absolute static relocation needs to be applied. | 1891 // Return whether a direct absolute static relocation needs to be applied. |
1888 // In cases where Scan::local() or Scan::global() has created | 1892 // In cases where Scan::local() or Scan::global() has created |
1889 // a dynamic relocation other than R_ARM_RELATIVE, the addend | 1893 // a dynamic relocation other than R_ARM_RELATIVE, the addend |
1890 // of the relocation is carried in the data, and we must not | 1894 // of the relocation is carried in the data, and we must not |
1891 // apply the static relocation. | 1895 // apply the static relocation. |
1892 | 1896 |
(...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2478 | 2482 |
2479 Target* | 2483 Target* |
2480 do_instantiate_target() | 2484 do_instantiate_target() |
2481 { return new Target_arm<big_endian>(); } | 2485 { return new Target_arm<big_endian>(); } |
2482 }; | 2486 }; |
2483 | 2487 |
2484 Target_selector_arm<false> target_selector_arm; | 2488 Target_selector_arm<false> target_selector_arm; |
2485 Target_selector_arm<true> target_selector_armbe; | 2489 Target_selector_arm<true> target_selector_armbe; |
2486 | 2490 |
2487 } // End anonymous namespace. | 2491 } // End anonymous namespace. |
OLD | NEW |