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 |