using namespace gold;
+// A class to handle the .got.plt section.
+
+class Output_data_got_plt_i386 : public Output_section_data_build
+{
+ public:
+ Output_data_got_plt_i386(Layout* layout)
+ : Output_section_data_build(4),
+ layout_(layout)
+ { }
+
+ protected:
+ // Write out the PLT data.
+ void
+ do_write(Output_file*);
+
+ // Write to a map file.
+ void
+ do_print_to_mapfile(Mapfile* mapfile) const
+ { mapfile->print_output_data(this, "** GOT PLT"); }
+
+ private:
+ // A pointer to the Layout class, so that we can find the .dynamic
+ // section when we write out the GOT PLT section.
+ Layout* layout_;
+};
+
// A class to handle the PLT data.
// This is an abstract base class that handles most of the linker details
// but does not know the actual contents of PLT entries. The derived
typedef Output_data_reloc<elfcpp::SHT_REL, true, 32, false> Reloc_section;
Output_data_plt_i386(Layout*, uint64_t addralign,
- Output_data_space*, Output_data_space*);
+ Output_data_got_plt_i386*, Output_data_space*);
// Add an entry to the PLT.
void
unsigned int got_offset;
};
- // A pointer to the Layout class, so that we can find the .dynamic
- // section when we write out the GOT PLT section.
- Layout* layout_;
// The reloc section.
Reloc_section* rel_;
// The TLS_DESC relocations, if necessary. These must follow the
// regular relocatoins and the TLS_DESC relocations.
Reloc_section* irelative_rel_;
// The .got.plt section.
- Output_data_space* got_plt_;
+ Output_data_got_plt_i386* got_plt_;
// The part of the .got.plt section used for IRELATIVE relocs.
Output_data_space* got_irelative_;
// The number of PLT entries.
{
public:
Output_data_plt_i386_standard(Layout* layout,
- Output_data_space* got_plt,
+ Output_data_got_plt_i386* got_plt,
Output_data_space* got_irelative)
: Output_data_plt_i386(layout, plt_entry_size, got_plt, got_irelative)
{ }
{
public:
Output_data_plt_i386_exec(Layout* layout,
- Output_data_space* got_plt,
+ Output_data_got_plt_i386* got_plt,
Output_data_space* got_irelative)
: Output_data_plt_i386_standard(layout, got_plt, got_irelative)
{ }
{
public:
Output_data_plt_i386_dyn(Layout* layout,
- Output_data_space* got_plt,
+ Output_data_got_plt_i386* got_plt,
Output_data_space* got_irelative)
: Output_data_plt_i386_standard(layout, got_plt, got_irelative)
{ }
// This chooses the right PLT flavor for an executable or a shared object.
Output_data_plt_i386*
make_data_plt(Layout* layout,
- Output_data_space* got_plt,
+ Output_data_got_plt_i386* got_plt,
Output_data_space* got_irelative,
bool dyn)
{ return this->do_make_data_plt(layout, got_plt, got_irelative, dyn); }
virtual Output_data_plt_i386*
do_make_data_plt(Layout* layout,
- Output_data_space* got_plt,
+ Output_data_got_plt_i386* got_plt,
Output_data_space* got_irelative,
bool dyn)
{
got_section(Symbol_table*, Layout*);
// Get the GOT PLT section.
- Output_data_space*
+ Output_data_got_plt_i386*
got_plt_section() const
{
gold_assert(this->got_plt_ != NULL);
// The PLT section.
Output_data_plt_i386* plt_;
// The GOT PLT section.
- Output_data_space* got_plt_;
+ Output_data_got_plt_i386* got_plt_;
// The GOT section for IRELATIVE relocations.
Output_data_space* got_irelative_;
// The GOT section for TLSDESC relocations.
| elfcpp::SHF_WRITE),
this->got_, got_order, true);
- this->got_plt_ = new Output_data_space(4, "** GOT PLT");
+ this->got_plt_ = new Output_data_got_plt_i386(layout);
layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE),
return this->rel_irelative_;
}
+// Write the first three reserved words of the .got.plt section.
+// The remainder of the section is written while writing the PLT
+// in Output_data_plt_i386::do_write.
+
+void
+Output_data_got_plt_i386::do_write(Output_file* of)
+{
+ // The first entry in the GOT is the address of the .dynamic section
+ // aka the PT_DYNAMIC segment. The next two entries are reserved.
+ // We saved space for them when we created the section in
+ // Target_i386::got_section.
+ const off_t got_file_offset = this->offset();
+ gold_assert(this->data_size() >= 12);
+ unsigned char* const got_view = of->get_output_view(got_file_offset, 12);
+ Output_section* dynamic = this->layout_->dynamic_section();
+ uint32_t dynamic_addr = dynamic == NULL ? 0 : dynamic->address();
+ elfcpp::Swap<32, false>::writeval(got_view, dynamic_addr);
+ memset(got_view + 4, 0, 8);
+ of->write_output_view(got_file_offset, 12, got_view);
+}
+
// Create the PLT section. The ordinary .got section is an argument,
// since we need to refer to the start. We also create our own .got
// section just for PLT entries.
Output_data_plt_i386::Output_data_plt_i386(Layout* layout,
uint64_t addralign,
- Output_data_space* got_plt,
+ Output_data_got_plt_i386* got_plt,
Output_data_space* got_irelative)
: Output_section_data(addralign),
- layout_(layout), tls_desc_rel_(NULL),
- irelative_rel_(NULL), got_plt_(got_plt), got_irelative_(got_irelative),
- count_(0), irelative_count_(0), global_ifuncs_(), local_ifuncs_()
+ tls_desc_rel_(NULL), irelative_rel_(NULL), got_plt_(got_plt),
+ got_irelative_(got_irelative), count_(0), irelative_count_(0),
+ global_ifuncs_(), local_ifuncs_()
{
this->rel_ = new Reloc_section(false);
layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL,
const section_size_type got_size =
convert_to_section_size_type(this->got_plt_->data_size()
+ this->got_irelative_->data_size());
+
unsigned char* const got_view = of->get_output_view(got_file_offset,
got_size);
this->fill_first_plt_entry(pov, got_address);
pov += this->get_plt_entry_size();
- unsigned char* got_pov = got_view;
-
- // The first entry in the GOT is the address of the .dynamic section
- // aka the PT_DYNAMIC segment. The next two entries are reserved.
- // We saved space for them when we created the section in
- // Target_i386::got_section.
- Output_section* dynamic = this->layout_->dynamic_section();
- uint32_t dynamic_addr = dynamic == NULL ? 0 : dynamic->address();
- elfcpp::Swap<32, false>::writeval(got_pov, dynamic_addr);
- got_pov += 4;
- memset(got_pov, 0, 8);
- got_pov += 8;
+ // The first three entries in the GOT are reserved, and are written
+ // by Output_data_got_plt_i386::do_write.
+ unsigned char* got_pov = got_view + 12;
const int rel_size = elfcpp::Elf_sizes<32>::rel_size;
{
public:
Output_data_plt_i386_nacl(Layout* layout,
- Output_data_space* got_plt,
+ Output_data_got_plt_i386* got_plt,
Output_data_space* got_irelative)
: Output_data_plt_i386(layout, plt_entry_size, got_plt, got_irelative)
{ }
{
public:
Output_data_plt_i386_nacl_exec(Layout* layout,
- Output_data_space* got_plt,
+ Output_data_got_plt_i386* got_plt,
Output_data_space* got_irelative)
: Output_data_plt_i386_nacl(layout, got_plt, got_irelative)
{ }
{
public:
Output_data_plt_i386_nacl_dyn(Layout* layout,
- Output_data_space* got_plt,
+ Output_data_got_plt_i386* got_plt,
Output_data_space* got_irelative)
: Output_data_plt_i386_nacl(layout, got_plt, got_irelative)
{ }
protected:
virtual Output_data_plt_i386*
do_make_data_plt(Layout* layout,
- Output_data_space* got_plt,
+ Output_data_got_plt_i386* got_plt,
Output_data_space* got_irelative,
bool dyn)
{
using namespace gold;
+// A class to handle the .got.plt section.
+
+class Output_data_got_plt_x86_64 : public Output_section_data_build
+{
+ public:
+ Output_data_got_plt_x86_64(Layout* layout)
+ : Output_section_data_build(8),
+ layout_(layout)
+ { }
+
+ Output_data_got_plt_x86_64(Layout* layout, off_t data_size)
+ : Output_section_data_build(data_size, 8),
+ layout_(layout)
+ { }
+
+ protected:
+ // Write out the PLT data.
+ void
+ do_write(Output_file*);
+
+ // Write to a map file.
+ void
+ do_print_to_mapfile(Mapfile* mapfile) const
+ { mapfile->print_output_data(this, "** GOT PLT"); }
+
+ private:
+ // A pointer to the Layout class, so that we can find the .dynamic
+ // section when we write out the GOT PLT section.
+ Layout* layout_;
+};
+
// A class to handle the PLT data.
// This is an abstract base class that handles most of the linker details
// but does not know the actual contents of PLT entries. The derived
Output_data_plt_x86_64(Layout* layout, uint64_t addralign,
Output_data_got<64, false>* got,
- Output_data_space* got_plt,
+ Output_data_got_plt_x86_64* got_plt,
Output_data_space* got_irelative)
- : Output_section_data(addralign), layout_(layout), tlsdesc_rel_(NULL),
+ : Output_section_data(addralign), tlsdesc_rel_(NULL),
irelative_rel_(NULL), got_(got), got_plt_(got_plt),
got_irelative_(got_irelative), count_(0), irelative_count_(0),
tlsdesc_got_offset_(-1U), free_list_()
Output_data_plt_x86_64(Layout* layout, uint64_t plt_entry_size,
Output_data_got<64, false>* got,
- Output_data_space* got_plt,
+ Output_data_got_plt_x86_64* got_plt,
Output_data_space* got_irelative,
unsigned int plt_count)
: Output_section_data((plt_count + 1) * plt_entry_size,
plt_entry_size, false),
- layout_(layout), tlsdesc_rel_(NULL), irelative_rel_(NULL), got_(got),
+ tlsdesc_rel_(NULL), irelative_rel_(NULL), got_(got),
got_plt_(got_plt), got_irelative_(got_irelative), count_(plt_count),
irelative_count_(0), tlsdesc_got_offset_(-1U), free_list_()
{
void
do_write(Output_file*);
- // A pointer to the Layout class, so that we can find the .dynamic
- // section when we write out the GOT PLT section.
- Layout* layout_;
// The reloc section.
Reloc_section* rel_;
// The TLSDESC relocs, if necessary. These must follow the regular
// The .got section.
Output_data_got<64, false>* got_;
// The .got.plt section.
- Output_data_space* got_plt_;
+ Output_data_got_plt_x86_64* got_plt_;
// The part of the .got.plt section used for IRELATIVE relocs.
Output_data_space* got_irelative_;
// The number of PLT entries.
public:
Output_data_plt_x86_64_standard(Layout* layout,
Output_data_got<64, false>* got,
- Output_data_space* got_plt,
+ Output_data_got_plt_x86_64* got_plt,
Output_data_space* got_irelative)
: Output_data_plt_x86_64<size>(layout, plt_entry_size,
got, got_plt, got_irelative)
Output_data_plt_x86_64_standard(Layout* layout,
Output_data_got<64, false>* got,
- Output_data_space* got_plt,
+ Output_data_got_plt_x86_64* got_plt,
Output_data_space* got_irelative,
unsigned int plt_count)
: Output_data_plt_x86_64<size>(layout, plt_entry_size,
Output_data_plt_x86_64<size>*
make_data_plt(Layout* layout,
Output_data_got<64, false>* got,
- Output_data_space* got_plt,
+ Output_data_got_plt_x86_64* got_plt,
Output_data_space* got_irelative)
{
return this->do_make_data_plt(layout, got, got_plt, got_irelative);
Output_data_plt_x86_64<size>*
make_data_plt(Layout* layout,
Output_data_got<64, false>* got,
- Output_data_space* got_plt,
+ Output_data_got_plt_x86_64* got_plt,
Output_data_space* got_irelative,
unsigned int plt_count)
{
virtual Output_data_plt_x86_64<size>*
do_make_data_plt(Layout* layout,
Output_data_got<64, false>* got,
- Output_data_space* got_plt,
+ Output_data_got_plt_x86_64* got_plt,
Output_data_space* got_irelative)
{
return new Output_data_plt_x86_64_standard<size>(layout, got, got_plt,
virtual Output_data_plt_x86_64<size>*
do_make_data_plt(Layout* layout,
Output_data_got<64, false>* got,
- Output_data_space* got_plt,
+ Output_data_got_plt_x86_64* got_plt,
Output_data_space* got_irelative,
unsigned int plt_count)
{
got_section(Symbol_table*, Layout*);
// Get the GOT PLT section.
- Output_data_space*
+ Output_data_got_plt_x86_64*
got_plt_section() const
{
gold_assert(this->got_plt_ != NULL);
// The PLT section.
Output_data_plt_x86_64<size>* plt_;
// The GOT PLT section.
- Output_data_space* got_plt_;
+ Output_data_got_plt_x86_64* got_plt_;
// The GOT section for IRELATIVE relocations.
Output_data_space* got_irelative_;
// The GOT section for TLSDESC relocations.
| elfcpp::SHF_WRITE),
this->got_, got_order, true);
- this->got_plt_ = new Output_data_space(8, "** GOT PLT");
+ this->got_plt_ = new Output_data_got_plt_x86_64(layout);
layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE),
return this->rela_irelative_;
}
+// Write the first three reserved words of the .got.plt section.
+// The remainder of the section is written while writing the PLT
+// in Output_data_plt_i386::do_write.
+
+void
+Output_data_got_plt_x86_64::do_write(Output_file* of)
+{
+ // The first entry in the GOT is the address of the .dynamic section
+ // aka the PT_DYNAMIC segment. The next two entries are reserved.
+ // We saved space for them when we created the section in
+ // Target_x86_64::got_section.
+ const off_t got_file_offset = this->offset();
+ gold_assert(this->data_size() >= 24);
+ unsigned char* const got_view = of->get_output_view(got_file_offset, 24);
+ Output_section* dynamic = this->layout_->dynamic_section();
+ uint64_t dynamic_addr = dynamic == NULL ? 0 : dynamic->address();
+ elfcpp::Swap<64, false>::writeval(got_view, dynamic_addr);
+ memset(got_view + 8, 0, 16);
+ of->write_output_view(got_file_offset, 24, got_view);
+}
+
// Initialize the PLT section.
template<int size>
unsigned int* pcount;
unsigned int offset;
unsigned int reserved;
- Output_data_space* got;
+ Output_section_data_build* got;
if (gsym->type() == elfcpp::STT_GNU_IFUNC
&& gsym->can_use_relative_reloc(false))
{
this->fill_first_plt_entry(pov, got_address, plt_address);
pov += this->get_plt_entry_size();
- unsigned char* got_pov = got_view;
-
- // The first entry in the GOT is the address of the .dynamic section
- // aka the PT_DYNAMIC segment. The next two entries are reserved.
- // We saved space for them when we created the section in
- // Target_x86_64::got_section.
- Output_section* dynamic = this->layout_->dynamic_section();
- uint32_t dynamic_addr = dynamic == NULL ? 0 : dynamic->address();
- elfcpp::Swap<64, false>::writeval(got_pov, dynamic_addr);
- got_pov += 8;
- memset(got_pov, 0, 16);
- got_pov += 16;
+ // The first three entries in the GOT are reserved, and are written
+ // by Output_data_got_plt_x86_64::do_write.
+ unsigned char* got_pov = got_view + 24;
unsigned int plt_offset = this->get_plt_entry_size();
unsigned int got_offset = 24;
true);
// Add the three reserved entries.
- this->got_plt_ = new Output_data_space((plt_count + 3) * 8, 8, "** GOT PLT");
+ this->got_plt_ = new Output_data_got_plt_x86_64(layout, (plt_count + 3) * 8);
layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE),
public:
Output_data_plt_x86_64_nacl(Layout* layout,
Output_data_got<64, false>* got,
- Output_data_space* got_plt,
+ Output_data_got_plt_x86_64* got_plt,
Output_data_space* got_irelative)
: Output_data_plt_x86_64<size>(layout, plt_entry_size,
got, got_plt, got_irelative)
Output_data_plt_x86_64_nacl(Layout* layout,
Output_data_got<64, false>* got,
- Output_data_space* got_plt,
+ Output_data_got_plt_x86_64* got_plt,
Output_data_space* got_irelative,
unsigned int plt_count)
: Output_data_plt_x86_64<size>(layout, plt_entry_size,
virtual Output_data_plt_x86_64<size>*
do_make_data_plt(Layout* layout,
Output_data_got<64, false>* got,
- Output_data_space* got_plt,
+ Output_data_got_plt_x86_64* got_plt,
Output_data_space* got_irelative)
{
return new Output_data_plt_x86_64_nacl<size>(layout, got, got_plt,
virtual Output_data_plt_x86_64<size>*
do_make_data_plt(Layout* layout,
Output_data_got<64, false>* got,
- Output_data_space* got_plt,
+ Output_data_got_plt_x86_64* got_plt,
Output_data_space* got_irelative,
unsigned int plt_count)
{