// Finalize the sections.
void
- do_finalize_sections(Layout*);
+ do_finalize_sections(const General_options*, Layout*);
// Relocate a section.
void
this->got_ = new Output_data_got<32, false>(options);
layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
- elfcpp::SHF_ALLOC, this->got_);
+ elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
+ this->got_);
// The old GNU linker creates a .got.plt section. We just
// create another set of data in the .got section. Note that we
// might be empty.
this->got_plt_ = new Output_data_space(4);
layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
- elfcpp::SHF_ALLOC, this->got_plt_);
+ elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
+ this->got_plt_);
// The first three entries are reserved.
this->got_plt_->set_space_size(3 * 4);
// Define _GLOBAL_OFFSET_TABLE_ at the start of the PLT.
- symtab->define_in_output_data(this, "_GLOBAL_OFFSET_TABLE_",
+ symtab->define_in_output_data(this, "_GLOBAL_OFFSET_TABLE_", NULL,
this->got_plt_,
0, 0, elfcpp::STT_OBJECT,
- elfcpp::STB_GLOBAL,
+ elfcpp::STB_LOCAL,
elfcpp::STV_HIDDEN, 0,
false, false);
}
void
add_entry(Symbol* gsym);
+ // Return the .rel.plt section data.
+ const Reloc_section*
+ rel_plt() const
+ { return this->rel_; }
+
+ protected:
+ void
+ do_adjust_output_section(Output_section* os);
+
private:
// The size of an entry in the PLT.
static const int plt_entry_size = 16;
elfcpp::SHF_ALLOC, this->rel_);
}
+// For some reason
+
+void
+Output_data_plt_i386::do_adjust_output_section(Output_section* os)
+{
+ // UnixWare sets the entsize of .plt to 4, and so does the old GNU
+ // linker, and so do we.
+ os->set_entsize(4);
+}
+
// Add an entry to the PLT.
void
this->got_plt_->set_space_size(got_offset + 4);
// Every PLT entry needs a reloc.
+ gsym->set_needs_dynsym_entry();
this->rel_->add_global(gsym, elfcpp::R_386_JUMP_SLOT, this->got_plt_,
got_offset);
this->plt_ = new Output_data_plt_i386(layout, this->got_plt_,
options->is_shared());
+ layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
+ (elfcpp::SHF_ALLOC
+ | elfcpp::SHF_EXECINSTR),
+ this->plt_);
}
this->plt_->add_entry(gsym);
dynbss->set_space_size(dynbss_size + symsize);
// Define the symbol in the .dynbss section.
- symtab->define_in_output_data(this, ssym->name(), dynbss, offset,
- symsize, ssym->type(), ssym->binding(),
- ssym->visibility(), ssym->nonvis(),
- false, false);
+ symtab->define_in_output_data(this, ssym->name(), ssym->version(),
+ dynbss, offset, symsize, ssym->type(),
+ ssym->binding(), ssym->visibility(),
+ ssym->nonvis(), false, false);
// Add the COPY reloc.
+ ssym->set_needs_dynsym_entry();
Reloc_section* rel_dyn = this->rel_dyn_section(layout);
rel_dyn->add_global(ssym, elfcpp::R_386_COPY, dynbss, offset);
}
// relocation in order to avoid a COPY relocation.
gold_assert(!options.is_shared());
- if (gsym->is_defined_in_dynobj())
+ if (gsym->is_from_dynobj())
{
// This symbol is defined in a dynamic object. If it is a
// function, we make a PLT entry. Otherwise we need to
global_symbols);
}
-// Finalize the sections. This is where we emit any relocs we saved
-// in an attempt to avoid generating extra COPY relocs.
+// Finalize the sections.
void
-Target_i386::do_finalize_sections(Layout* layout)
+Target_i386::do_finalize_sections(const General_options* options,
+ Layout* layout)
{
+ // Fill in some more dynamic tags.
+ Output_data_dynamic* const odyn = layout->dynamic_data();
+ if (odyn != NULL)
+ {
+ if (this->got_plt_ != NULL)
+ odyn->add_section_address(elfcpp::DT_PLTGOT, this->got_plt_);
+
+ if (this->plt_ != NULL)
+ {
+ const Output_data* od = this->plt_->rel_plt();
+ odyn->add_section_size(elfcpp::DT_PLTRELSZ, od);
+ odyn->add_section_address(elfcpp::DT_JMPREL, od);
+ odyn->add_constant(elfcpp::DT_PLTREL, elfcpp::DT_REL);
+ }
+
+ if (this->rel_dyn_ != NULL)
+ {
+ const Output_data* od = this->rel_dyn_;
+ odyn->add_section_address(elfcpp::DT_REL, od);
+ odyn->add_section_size(elfcpp::DT_RELSZ, od);
+ odyn->add_constant(elfcpp::DT_RELENT,
+ elfcpp::Elf_sizes<32>::rel_size);
+ }
+
+ if (!options->is_shared())
+ {
+ // The value of the DT_DEBUG tag is filled in by the dynamic
+ // linker at run time, and used by the debugger.
+ odyn->add_constant(elfcpp::DT_DEBUG, 0);
+ }
+ }
+
+ // Emit any relocs we saved in an attempt to avoid generating COPY
+ // relocs.
if (this->copy_relocs_ == NULL)
return;
if (this->copy_relocs_->any_to_emit())
}
// Pick the value to use for symbols defined in shared objects.
- if (gsym != NULL && gsym->is_defined_in_dynobj())
+ if (gsym != NULL && gsym->is_from_dynobj())
{
if (gsym->has_plt_offset())
- address = target->plt_section()->address() + gsym->plt_offset();
+ value = target->plt_section()->address() + gsym->plt_offset();
else
gold_unreachable();
}