| OLD | NEW |
| 1 // x86_64.cc -- x86_64 target support for gold. | 1 // x86_64.cc -- x86_64 target support for gold. |
| 2 | 2 |
| 3 // Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. | 3 // Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. |
| 4 // Written by Ian Lance Taylor <iant@google.com>. | 4 // Written by Ian Lance Taylor <iant@google.com>. |
| 5 | 5 |
| 6 // This file is part of gold. | 6 // This file is part of gold. |
| 7 | 7 |
| 8 // This program is free software; you can redistribute it and/or modify | 8 // This program is free software; you can redistribute it and/or modify |
| 9 // it under the terms of the GNU General Public License as published by | 9 // it under the terms of the GNU General Public License as published by |
| 10 // the Free Software Foundation; either version 3 of the License, or | 10 // the Free Software Foundation; either version 3 of the License, or |
| (...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 if (this->got_ == NULL) | 465 if (this->got_ == NULL) |
| 466 { | 466 { |
| 467 gold_assert(symtab != NULL && layout != NULL); | 467 gold_assert(symtab != NULL && layout != NULL); |
| 468 | 468 |
| 469 this->got_ = new Output_data_got<64, false>(); | 469 this->got_ = new Output_data_got<64, false>(); |
| 470 | 470 |
| 471 Output_section* os; | 471 Output_section* os; |
| 472 os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, | 472 os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, |
| 473 (elfcpp::SHF_ALLOC | 473 (elfcpp::SHF_ALLOC |
| 474 | elfcpp::SHF_WRITE), | 474 | elfcpp::SHF_WRITE), |
| 475 » » » » » this->got_); | 475 » » » » » this->got_, false); |
| 476 os->set_is_relro(); | 476 os->set_is_relro(); |
| 477 | 477 |
| 478 // The old GNU linker creates a .got.plt section. We just | 478 // The old GNU linker creates a .got.plt section. We just |
| 479 // create another set of data in the .got section. Note that we | 479 // create another set of data in the .got section. Note that we |
| 480 // always create a PLT if we create a GOT, although the PLT | 480 // always create a PLT if we create a GOT, although the PLT |
| 481 // might be empty. | 481 // might be empty. |
| 482 this->got_plt_ = new Output_data_space(8, "** GOT PLT"); | 482 this->got_plt_ = new Output_data_space(8, "** GOT PLT"); |
| 483 os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, | 483 os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, |
| 484 (elfcpp::SHF_ALLOC | 484 (elfcpp::SHF_ALLOC |
| 485 | elfcpp::SHF_WRITE), | 485 | elfcpp::SHF_WRITE), |
| 486 » » » » » this->got_plt_); | 486 » » » » » this->got_plt_, false); |
| 487 os->set_is_relro(); | 487 os->set_is_relro(); |
| 488 | 488 |
| 489 // The first three entries are reserved. | 489 // The first three entries are reserved. |
| 490 this->got_plt_->set_current_data_size(3 * 8); | 490 this->got_plt_->set_current_data_size(3 * 8); |
| 491 | 491 |
| 492 // Define _GLOBAL_OFFSET_TABLE_ at the start of the PLT. | 492 // Define _GLOBAL_OFFSET_TABLE_ at the start of the PLT. |
| 493 symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL, | 493 symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL, |
| 494 this->got_plt_, | 494 this->got_plt_, |
| 495 0, 0, elfcpp::STT_OBJECT, | 495 0, 0, elfcpp::STT_OBJECT, |
| 496 elfcpp::STB_LOCAL, | 496 elfcpp::STB_LOCAL, |
| 497 elfcpp::STV_HIDDEN, 0, | 497 elfcpp::STV_HIDDEN, 0, |
| 498 false, false); | 498 false, false); |
| 499 } | 499 } |
| 500 | 500 |
| 501 return this->got_; | 501 return this->got_; |
| 502 } | 502 } |
| 503 | 503 |
| 504 // Get the dynamic reloc section, creating it if necessary. | 504 // Get the dynamic reloc section, creating it if necessary. |
| 505 | 505 |
| 506 Target_x86_64::Reloc_section* | 506 Target_x86_64::Reloc_section* |
| 507 Target_x86_64::rela_dyn_section(Layout* layout) | 507 Target_x86_64::rela_dyn_section(Layout* layout) |
| 508 { | 508 { |
| 509 if (this->rela_dyn_ == NULL) | 509 if (this->rela_dyn_ == NULL) |
| 510 { | 510 { |
| 511 gold_assert(layout != NULL); | 511 gold_assert(layout != NULL); |
| 512 this->rela_dyn_ = new Reloc_section(parameters->options().combreloc()); | 512 this->rela_dyn_ = new Reloc_section(parameters->options().combreloc()); |
| 513 layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA, | 513 layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA, |
| 514 » » » » elfcpp::SHF_ALLOC, this->rela_dyn_); | 514 » » » » elfcpp::SHF_ALLOC, this->rela_dyn_, true); |
| 515 } | 515 } |
| 516 return this->rela_dyn_; | 516 return this->rela_dyn_; |
| 517 } | 517 } |
| 518 | 518 |
| 519 // A class to handle the PLT data. | 519 // A class to handle the PLT data. |
| 520 | 520 |
| 521 class Output_data_plt_x86_64 : public Output_section_data | 521 class Output_data_plt_x86_64 : public Output_section_data |
| 522 { | 522 { |
| 523 public: | 523 public: |
| 524 typedef Output_data_reloc<elfcpp::SHT_RELA, true, 64, false> Reloc_section; | 524 typedef Output_data_reloc<elfcpp::SHT_RELA, true, 64, false> Reloc_section; |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 // section just for PLT entries. | 604 // section just for PLT entries. |
| 605 | 605 |
| 606 Output_data_plt_x86_64::Output_data_plt_x86_64(Layout* layout, | 606 Output_data_plt_x86_64::Output_data_plt_x86_64(Layout* layout, |
| 607 Output_data_got<64, false>* got, | 607 Output_data_got<64, false>* got, |
| 608 Output_data_space* got_plt) | 608 Output_data_space* got_plt) |
| 609 : Output_section_data(8), got_(got), got_plt_(got_plt), count_(0), | 609 : Output_section_data(8), got_(got), got_plt_(got_plt), count_(0), |
| 610 tlsdesc_got_offset_(-1U) | 610 tlsdesc_got_offset_(-1U) |
| 611 { | 611 { |
| 612 this->rel_ = new Reloc_section(false); | 612 this->rel_ = new Reloc_section(false); |
| 613 layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA, | 613 layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA, |
| 614 » » » » elfcpp::SHF_ALLOC, this->rel_); | 614 » » » » elfcpp::SHF_ALLOC, this->rel_, true); |
| 615 } | 615 } |
| 616 | 616 |
| 617 void | 617 void |
| 618 Output_data_plt_x86_64::do_adjust_output_section(Output_section* os) | 618 Output_data_plt_x86_64::do_adjust_output_section(Output_section* os) |
| 619 { | 619 { |
| 620 os->set_entsize(plt_entry_size); | 620 os->set_entsize(plt_entry_size); |
| 621 } | 621 } |
| 622 | 622 |
| 623 // Add an entry to the PLT. | 623 // Add an entry to the PLT. |
| 624 | 624 |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 800 if (this->plt_ == NULL) | 800 if (this->plt_ == NULL) |
| 801 { | 801 { |
| 802 // Create the GOT sections first. | 802 // Create the GOT sections first. |
| 803 this->got_section(symtab, layout); | 803 this->got_section(symtab, layout); |
| 804 | 804 |
| 805 this->plt_ = new Output_data_plt_x86_64(layout, this->got_, | 805 this->plt_ = new Output_data_plt_x86_64(layout, this->got_, |
| 806 this->got_plt_); | 806 this->got_plt_); |
| 807 layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS, | 807 layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS, |
| 808 (elfcpp::SHF_ALLOC | 808 (elfcpp::SHF_ALLOC |
| 809 | elfcpp::SHF_EXECINSTR), | 809 | elfcpp::SHF_EXECINSTR), |
| 810 » » » » this->plt_); | 810 » » » » this->plt_, false); |
| 811 } | 811 } |
| 812 } | 812 } |
| 813 | 813 |
| 814 // Create a PLT entry for a global symbol. | 814 // Create a PLT entry for a global symbol. |
| 815 | 815 |
| 816 void | 816 void |
| 817 Target_x86_64::make_plt_entry(Symbol_table* symtab, Layout* layout, | 817 Target_x86_64::make_plt_entry(Symbol_table* symtab, Layout* layout, |
| 818 Symbol* gsym) | 818 Symbol* gsym) |
| 819 { | 819 { |
| 820 if (gsym->has_plt_offset()) | 820 if (gsym->has_plt_offset()) |
| (...skipping 831 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1652 | 1652 |
| 1653 // Finalize the sections. | 1653 // Finalize the sections. |
| 1654 | 1654 |
| 1655 void | 1655 void |
| 1656 Target_x86_64::do_finalize_sections(Layout* layout) | 1656 Target_x86_64::do_finalize_sections(Layout* layout) |
| 1657 { | 1657 { |
| 1658 // Fill in some more dynamic tags. | 1658 // Fill in some more dynamic tags. |
| 1659 Output_data_dynamic* const odyn = layout->dynamic_data(); | 1659 Output_data_dynamic* const odyn = layout->dynamic_data(); |
| 1660 if (odyn != NULL) | 1660 if (odyn != NULL) |
| 1661 { | 1661 { |
| 1662 if (this->got_plt_ != NULL) | 1662 if (this->got_plt_ != NULL |
| 1663 » && this->got_plt_->output_section() != NULL) |
| 1663 odyn->add_section_address(elfcpp::DT_PLTGOT, this->got_plt_); | 1664 odyn->add_section_address(elfcpp::DT_PLTGOT, this->got_plt_); |
| 1664 | 1665 |
| 1665 if (this->plt_ != NULL) | 1666 if (this->plt_ != NULL |
| 1667 » && this->plt_->output_section() != NULL) |
| 1666 { | 1668 { |
| 1667 const Output_data* od = this->plt_->rel_plt(); | 1669 const Output_data* od = this->plt_->rel_plt(); |
| 1668 odyn->add_section_size(elfcpp::DT_PLTRELSZ, od); | 1670 odyn->add_section_size(elfcpp::DT_PLTRELSZ, od); |
| 1669 odyn->add_section_address(elfcpp::DT_JMPREL, od); | 1671 odyn->add_section_address(elfcpp::DT_JMPREL, od); |
| 1670 odyn->add_constant(elfcpp::DT_PLTREL, elfcpp::DT_RELA); | 1672 odyn->add_constant(elfcpp::DT_PLTREL, elfcpp::DT_RELA); |
| 1671 if (this->plt_->has_tlsdesc_entry()) | 1673 if (this->plt_->has_tlsdesc_entry()) |
| 1672 { | 1674 { |
| 1673 unsigned int plt_offset = this->plt_->get_tlsdesc_plt_offset(); | 1675 unsigned int plt_offset = this->plt_->get_tlsdesc_plt_offset(); |
| 1674 unsigned int got_offset = this->plt_->get_tlsdesc_got_offset(); | 1676 unsigned int got_offset = this->plt_->get_tlsdesc_got_offset(); |
| 1675 this->got_->finalize_data_size(); | 1677 this->got_->finalize_data_size(); |
| 1676 odyn->add_section_plus_offset(elfcpp::DT_TLSDESC_PLT, | 1678 odyn->add_section_plus_offset(elfcpp::DT_TLSDESC_PLT, |
| 1677 this->plt_, plt_offset); | 1679 this->plt_, plt_offset); |
| 1678 odyn->add_section_plus_offset(elfcpp::DT_TLSDESC_GOT, | 1680 odyn->add_section_plus_offset(elfcpp::DT_TLSDESC_GOT, |
| 1679 this->got_, got_offset); | 1681 this->got_, got_offset); |
| 1680 } | 1682 } |
| 1681 } | 1683 } |
| 1682 | 1684 |
| 1683 if (this->rela_dyn_ != NULL) | 1685 if (this->rela_dyn_ != NULL |
| 1686 » && this->rela_dyn_->output_section() != NULL) |
| 1684 { | 1687 { |
| 1685 const Output_data* od = this->rela_dyn_; | 1688 const Output_data* od = this->rela_dyn_; |
| 1686 odyn->add_section_address(elfcpp::DT_RELA, od); | 1689 odyn->add_section_address(elfcpp::DT_RELA, od); |
| 1687 odyn->add_section_size(elfcpp::DT_RELASZ, od); | 1690 odyn->add_section_size(elfcpp::DT_RELASZ, od); |
| 1688 odyn->add_constant(elfcpp::DT_RELAENT, | 1691 odyn->add_constant(elfcpp::DT_RELAENT, |
| 1689 elfcpp::Elf_sizes<64>::rela_size); | 1692 elfcpp::Elf_sizes<64>::rela_size); |
| 1690 } | 1693 } |
| 1691 | 1694 |
| 1692 if (!parameters->options().shared()) | 1695 if (!parameters->options().shared()) |
| 1693 { | 1696 { |
| (...skipping 1044 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2738 | 2741 |
| 2739 Target* | 2742 Target* |
| 2740 do_instantiate_target() | 2743 do_instantiate_target() |
| 2741 { return new Target_x86_64(); } | 2744 { return new Target_x86_64(); } |
| 2742 | 2745 |
| 2743 }; | 2746 }; |
| 2744 | 2747 |
| 2745 Target_selector_x86_64 target_selector_x86_64; | 2748 Target_selector_x86_64 target_selector_x86_64; |
| 2746 | 2749 |
| 2747 } // End anonymous namespace. | 2750 } // End anonymous namespace. |
| OLD | NEW |