Can now dynamically link hello, world.

This commit is contained in:
Ian Lance Taylor 2006-12-01 16:51:25 +00:00
parent 8a82f7e392
commit 16649710df
12 changed files with 541 additions and 184 deletions

View File

@ -217,8 +217,11 @@ queue_final_tasks(const General_options& options,
// Queue a task to write out the symbol table.
final_blocker->add_blocker();
workqueue->queue(new Write_symbols_task(symtab, input_objects->target(),
layout->sympool(), of,
workqueue->queue(new Write_symbols_task(symtab,
input_objects->target(),
layout->sympool(),
layout->dynpool(),
of,
final_blocker));
// Queue a task to write out everything else.

View File

@ -51,7 +51,7 @@ class Target_i386 : public Sized_target<32, false>
// Finalize the sections.
void
do_finalize_sections(Layout*);
do_finalize_sections(const General_options*, Layout*);
// Relocate a section.
void
@ -231,7 +231,8 @@ Target_i386::got_section(const General_options* options, Symbol_table* symtab,
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
@ -239,7 +240,8 @@ Target_i386::got_section(const General_options* options, Symbol_table* symtab,
// 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);
@ -248,7 +250,7 @@ Target_i386::got_section(const General_options* options, Symbol_table* symtab,
symtab->define_in_output_data(this, "_GLOBAL_OFFSET_TABLE_",
this->got_plt_,
0, 0, elfcpp::STT_OBJECT,
elfcpp::STB_GLOBAL,
elfcpp::STB_LOCAL,
elfcpp::STV_HIDDEN, 0,
false, false);
}
@ -284,6 +286,15 @@ class Output_data_plt_i386 : public Output_section_data
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;
@ -333,6 +344,16 @@ Output_data_plt_i386::Output_data_plt_i386(Layout* layout,
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
@ -354,6 +375,7 @@ Output_data_plt_i386::add_entry(Symbol* gsym)
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);
@ -503,6 +525,10 @@ Target_i386::make_plt_entry(const General_options* options,
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);
@ -587,6 +613,7 @@ Target_i386::copy_reloc(const General_options* options,
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);
}
@ -940,12 +967,46 @@ Target_i386::scan_relocs(const General_options& options,
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())
@ -992,7 +1053,7 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
if (gsym != NULL && gsym->is_defined_in_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();
}

View File

@ -42,7 +42,8 @@ Layout::Layout(const General_options& options)
: options_(options), namepool_(), sympool_(), dynpool_(), signatures_(),
section_name_map_(), segment_list_(), section_list_(),
unattached_section_list_(), special_output_list_(),
tls_segment_(NULL), symtab_section_(NULL), dynsym_section_(NULL)
tls_segment_(NULL), symtab_section_(NULL), dynsym_section_(NULL),
dynamic_section_(NULL), dynamic_data_(NULL)
{
// Make space for more than enough segments for a typical file.
// This is just for efficiency--it's OK if we wind up needing more.
@ -325,6 +326,11 @@ Layout::create_initial_dynamic_sections(const Input_objects* input_objects,
this->dynamic_section_, 0, 0,
elfcpp::STT_OBJECT, elfcpp::STB_LOCAL,
elfcpp::STV_HIDDEN, 0, false, false);
this->dynamic_data_ = new Output_data_dynamic(input_objects->target(),
&this->dynpool_);
this->dynamic_section_->add_output_section_data(this->dynamic_data_);
}
// Find the first read-only PT_LOAD segment, creating one if
@ -386,7 +392,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab)
Target* const target = input_objects->target();
const int size = target->get_size();
target->finalize_sections(this);
target->finalize_sections(&this->options_, this);
Output_segment* phdr_seg = NULL;
if (input_objects->any_dynamic())
@ -399,14 +405,9 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab)
phdr_seg = new Output_segment(elfcpp::PT_PHDR, elfcpp::PF_R);
this->segment_list_.push_back(phdr_seg);
// This holds the dynamic tags.
Output_data_dynamic* odyn;
odyn = new Output_data_dynamic(input_objects->target(),
&this->dynpool_);
// Create the dynamic symbol table, including the hash table,
// the dynamic relocations, and the version sections.
this->create_dynamic_symtab(target, odyn, symtab);
this->create_dynamic_symtab(target, symtab);
// Create the .interp section to hold the name of the
// interpreter, and put it in a PT_INTERP segment.
@ -414,7 +415,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab)
// Finish the .dynamic section to hold the dynamic data, and put
// it in a PT_DYNAMIC segment.
this->finish_dynamic_section(input_objects, symtab, odyn);
this->finish_dynamic_section(input_objects, symtab);
}
// FIXME: Handle PT_GNU_STACK.
@ -452,9 +453,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab)
// Create the symbol table sections.
// FIXME: We don't need to do this if we are stripping symbols.
Output_section* ostrtab;
this->create_symtab_sections(size, input_objects, symtab, &off,
&ostrtab);
this->create_symtab_sections(size, input_objects, symtab, &off);
// Create the .shstrtab section.
Output_section* shstrtab_section = this->create_shstrtab();
@ -463,9 +462,6 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab)
// segments.
off = this->set_section_offsets(off, &shndx);
// Now the section index of OSTRTAB is set.
this->symtab_section_->set_link(ostrtab->out_shndx());
// Create the section table header.
Output_section_headers* oshdrs = this->create_shdrs(size, big_endian, &off);
@ -685,8 +681,7 @@ Layout::set_section_offsets(off_t off, unsigned int* pshndx)
void
Layout::create_symtab_sections(int size, const Input_objects* input_objects,
Symbol_table* symtab,
off_t* poff,
Output_section** postrtab)
off_t* poff)
{
int symsize;
unsigned int align;
@ -742,7 +737,27 @@ Layout::create_symtab_sections(int size, const Input_objects* input_objects,
unsigned int local_symcount = local_symbol_index;
gold_assert(local_symcount * symsize == off - startoff);
off = symtab->finalize(local_symcount, off, &this->sympool_);
off_t dynoff;
size_t dyn_global_index;
size_t dyncount;
if (this->dynsym_section_ == NULL)
{
dynoff = 0;
dyn_global_index = 0;
dyncount = 0;
}
else
{
dyn_global_index = this->dynsym_section_->info();
off_t locsize = dyn_global_index * this->dynsym_section_->entsize();
dynoff = this->dynsym_section_->offset() + locsize;
dyncount = (this->dynsym_section_->data_size() - locsize) / symsize;
gold_assert(dyncount * symsize
== this->dynsym_section_->data_size() - locsize);
}
off = symtab->finalize(local_symcount, off, dynoff, dyn_global_index,
dyncount, &this->sympool_);
this->sympool_.set_string_offsets();
@ -765,11 +780,11 @@ Layout::create_symtab_sections(int size, const Input_objects* input_objects,
ostrtab->add_output_section_data(pstr);
osymtab->set_address(0, startoff);
osymtab->set_link_section(ostrtab);
osymtab->set_info(local_symcount);
osymtab->set_entsize(symsize);
*poff = off;
*postrtab = ostrtab;
}
// Create the .shstrtab section, which holds the names of the
@ -801,8 +816,9 @@ Output_section_headers*
Layout::create_shdrs(int size, bool big_endian, off_t* poff)
{
Output_section_headers* oshdrs;
oshdrs = new Output_section_headers(size, big_endian, this->segment_list_,
this->unattached_section_list_,
oshdrs = new Output_section_headers(size, big_endian, this,
&this->segment_list_,
&this->unattached_section_list_,
&this->namepool_);
off_t off = align_address(*poff, oshdrs->addralign());
oshdrs->set_address(0, off);
@ -815,8 +831,7 @@ Layout::create_shdrs(int size, bool big_endian, off_t* poff)
// Create the dynamic symbol table.
void
Layout::create_dynamic_symtab(const Target* target, Output_data_dynamic* odyn,
Symbol_table* symtab)
Layout::create_dynamic_symtab(const Target* target, Symbol_table* symtab)
{
// Count all the symbols in the dynamic symbol table, and set the
// dynamic symbol indexes.
@ -883,6 +898,7 @@ Layout::create_dynamic_symtab(const Target* target, Output_data_dynamic* odyn,
this->dynsym_section_ = dynsym;
Output_data_dynamic* const odyn = this->dynamic_data_;
odyn->add_section_address(elfcpp::DT_SYMTAB, dynsym);
odyn->add_constant(elfcpp::DT_SYMENT, symsize);
@ -894,6 +910,9 @@ Layout::create_dynamic_symtab(const Target* target, Output_data_dynamic* odyn,
Output_section_data* strdata = new Output_data_strtab(&this->dynpool_);
dynstr->add_output_section_data(strdata);
dynsym->set_link_section(dynstr);
this->dynamic_section_->set_link_section(dynstr);
odyn->add_section_address(elfcpp::DT_STRTAB, dynstr);
odyn->add_section_size(elfcpp::DT_STRSZ, dynstr);
@ -914,8 +933,8 @@ Layout::create_dynamic_symtab(const Target* target, Output_data_dynamic* odyn,
align);
hashsec->add_output_section_data(hashdata);
hashsec->set_link_section(dynsym);
hashsec->set_entsize(4);
// FIXME: .hash should link to .dynsym.
odyn->add_section_address(elfcpp::DT_HASH, hashsec);
}
@ -951,17 +970,16 @@ Layout::create_interp(const Target* target)
void
Layout::finish_dynamic_section(const Input_objects* input_objects,
const Symbol_table* symtab,
Output_data_dynamic* odyn)
const Symbol_table* symtab)
{
this->dynamic_section_->add_output_section_data(odyn);
Output_segment* oseg = new Output_segment(elfcpp::PT_DYNAMIC,
elfcpp::PF_R | elfcpp::PF_W);
this->segment_list_.push_back(oseg);
oseg->add_initial_output_section(this->dynamic_section_,
elfcpp::PF_R | elfcpp::PF_W);
Output_data_dynamic* const odyn = this->dynamic_data_;
for (Input_objects::Dynobj_iterator p = input_objects->dynobj_begin();
p != input_objects->dynobj_end();
++p)
@ -1231,7 +1249,8 @@ Write_symbols_task::locks(Workqueue* workqueue)
void
Write_symbols_task::run(Workqueue*)
{
this->symtab_->write_globals(this->target_, this->sympool_, this->of_);
this->symtab_->write_globals(this->target_, this->sympool_, this->dynpool_,
this->of_);
}
// Close_task_runner methods.

View File

@ -89,6 +89,12 @@ class Layout
sympool() const
{ return &this->sympool_; }
// Return the Stringpool used for dynamic symbol names and dynamic
// tags.
const Stringpool*
dynpool() const
{ return &this->dynpool_; }
// Return whether a section is a .gnu.linkonce section, given the
// section name.
static inline bool
@ -106,11 +112,33 @@ class Layout
off_t
finalize(const Input_objects*, Symbol_table*);
// Return the TLS segment.
// Return the TLS segment. This will return NULL if there isn't
// one.
Output_segment*
tls_segment() const
{ return this->tls_segment_; }
// Return the normal symbol table.
Output_section*
symtab_section() const
{
gold_assert(this->symtab_section_ != NULL);
return this->symtab_section_;
}
// Return the dynamic symbol table.
Output_section*
dynsym_section() const
{
gold_assert(this->dynsym_section_ != NULL);
return this->dynsym_section_;
}
// Return the dynamic tags.
Output_data_dynamic*
dynamic_data() const
{ return this->dynamic_data_; }
// Write out data not associated with an input file or the symbol
// table.
void
@ -160,8 +188,8 @@ class Layout
// Create the output sections for the symbol table.
void
create_symtab_sections(int size, const Input_objects*, Symbol_table*, off_t*,
Output_section** ostrtab);
create_symtab_sections(int size, const Input_objects*, Symbol_table*,
off_t*);
// Create the .shstrtab section.
Output_section*
@ -173,12 +201,11 @@ class Layout
// Create the dynamic symbol table.
void
create_dynamic_symtab(const Target*, Output_data_dynamic*, Symbol_table*);
create_dynamic_symtab(const Target*, Symbol_table*);
// Finish the .dynamic section and PT_DYNAMIC segment.
void
finish_dynamic_section(const Input_objects*, const Symbol_table*,
Output_data_dynamic*);
finish_dynamic_section(const Input_objects*, const Symbol_table*);
// Create the .interp section and PT_INTERP segment.
void
@ -284,6 +311,8 @@ class Layout
Output_section* dynsym_section_;
// The SHT_DYNAMIC output section if there is one.
Output_section* dynamic_section_;
// The dynamic data which goes into dynamic_section_.
Output_data_dynamic* dynamic_data_;
};
// This task handles writing out data which is not part of a section
@ -324,10 +353,10 @@ class Write_symbols_task : public Task
{
public:
Write_symbols_task(const Symbol_table* symtab, const Target* target,
const Stringpool* sympool, Output_file* of,
Task_token* final_blocker)
: symtab_(symtab), target_(target), sympool_(sympool), of_(of),
final_blocker_(final_blocker)
const Stringpool* sympool, const Stringpool* dynpool,
Output_file* of, Task_token* final_blocker)
: symtab_(symtab), target_(target), sympool_(sympool), dynpool_(dynpool),
of_(of), final_blocker_(final_blocker)
{ }
// The standard Task methods.
@ -345,6 +374,7 @@ class Write_symbols_task : public Task
const Symbol_table* symtab_;
const Target* target_;
const Stringpool* sympool_;
const Stringpool* dynpool_;
Output_file* of_;
Task_token* final_blocker_;
};

View File

@ -58,23 +58,25 @@ Output_data::default_alignment(int size)
Output_section_headers::Output_section_headers(
int size,
bool big_endian,
const Layout::Segment_list& segment_list,
const Layout::Section_list& unattached_section_list,
const Layout* layout,
const Layout::Segment_list* segment_list,
const Layout::Section_list* unattached_section_list,
const Stringpool* secnamepool)
: size_(size),
big_endian_(big_endian),
layout_(layout),
segment_list_(segment_list),
unattached_section_list_(unattached_section_list),
secnamepool_(secnamepool)
{
// Count all the sections. Start with 1 for the null section.
off_t count = 1;
for (Layout::Segment_list::const_iterator p = segment_list.begin();
p != segment_list.end();
for (Layout::Segment_list::const_iterator p = segment_list->begin();
p != segment_list->end();
++p)
if ((*p)->type() == elfcpp::PT_LOAD)
count += (*p)->output_section_count();
count += unattached_section_list.size();
count += unattached_section_list->size();
int shdr_size;
if (size == 32)
@ -137,20 +139,20 @@ Output_section_headers::do_sized_write(Output_file* of)
v += shdr_size;
unsigned shndx = 1;
for (Layout::Segment_list::const_iterator p = this->segment_list_.begin();
p != this->segment_list_.end();
for (Layout::Segment_list::const_iterator p = this->segment_list_->begin();
p != this->segment_list_->end();
++p)
v = (*p)->write_section_headers SELECT_SIZE_ENDIAN_NAME(size, big_endian) (
this->secnamepool_, v, &shndx
this->layout_, this->secnamepool_, v, &shndx
SELECT_SIZE_ENDIAN(size, big_endian));
for (Layout::Section_list::const_iterator p =
this->unattached_section_list_.begin();
p != this->unattached_section_list_.end();
this->unattached_section_list_->begin();
p != this->unattached_section_list_->end();
++p)
{
gold_assert(shndx == (*p)->out_shndx());
elfcpp::Shdr_write<size, big_endian> oshdr(v);
(*p)->write_header(this->secnamepool_, &oshdr);
(*p)->write_header(this->layout_, this->secnamepool_, &oshdr);
v += shdr_size;
++shndx;
}
@ -372,6 +374,18 @@ Output_data_const_buffer::do_write(Output_file* of)
// Output_section_data methods.
// Record the output section, and set the entry size and such.
void
Output_section_data::set_output_section(Output_section* os)
{
gold_assert(this->output_section_ == NULL);
this->output_section_ = os;
this->do_adjust_output_section(os);
}
// Return the section index of the output section.
unsigned int
Output_section_data::do_out_shndx() const
{
@ -496,6 +510,25 @@ Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>::write(
// Output_data_reloc_base methods.
// Adjust the output section.
template<int sh_type, bool dynamic, int size, bool big_endian>
void
Output_data_reloc_base<sh_type, dynamic, size, big_endian>
::do_adjust_output_section(Output_section* os)
{
if (sh_type == elfcpp::SHT_REL)
os->set_entsize(elfcpp::Elf_sizes<size>::rel_size);
else if (sh_type == elfcpp::SHT_RELA)
os->set_entsize(elfcpp::Elf_sizes<size>::rela_size);
else
gold_unreachable();
if (dynamic)
os->set_should_link_to_dynsym();
else
os->set_should_link_to_symtab();
}
// Write out relocation data.
template<int sh_type, bool dynamic, int size, bool big_endian>
@ -636,16 +669,17 @@ Output_data_dynamic::Dynamic_entry::write(
break;
case DYNAMIC_SECTION_ADDRESS:
val = this->u_.os->address();
val = this->u_.od->address();
break;
case DYNAMIC_SECTION_SIZE:
val = this->u_.os->data_size();
val = this->u_.od->data_size();
break;
case DYNAMIC_SYMBOL:
{
Sized_symbol<size>* s = static_cast<Sized_symbol<size>*>(this->u_.sym);
const Sized_symbol<size>* s =
static_cast<const Sized_symbol<size>*>(this->u_.sym);
val = s->value();
}
break;
@ -665,6 +699,19 @@ Output_data_dynamic::Dynamic_entry::write(
// Output_data_dynamic methods.
// Adjust the output section to set the entry size.
void
Output_data_dynamic::do_adjust_output_section(Output_section* os)
{
if (this->target_->get_size() == 32)
os->set_entsize(elfcpp::Elf_sizes<32>::dyn_size);
else if (this->target_->get_size() == 64)
os->set_entsize(elfcpp::Elf_sizes<64>::dyn_size);
else
gold_unreachable();
}
// Set the final data size.
void
@ -780,7 +827,9 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
: name_(name),
addralign_(0),
entsize_(0),
link_section_(NULL),
link_(0),
info_section_(NULL),
info_(0),
type_(type),
flags_(flags),
@ -791,7 +840,9 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
first_input_offset_(0),
may_add_data_(may_add_data),
needs_symtab_index_(false),
needs_dynsym_index_(false)
needs_dynsym_index_(false),
should_link_to_symtab_(false),
should_link_to_dynsym_(false)
{
}
@ -799,6 +850,17 @@ Output_section::~Output_section()
{
}
// Set the entry size.
void
Output_section::set_entsize(uint64_t v)
{
if (this->entsize_ == 0)
this->entsize_ = v;
else
gold_assert(this->entsize_ == v);
}
// Add the input section SHNDX, with header SHDR, named SECNAME, in
// OBJECT, to the Output_section. Return the offset of the input
// section within the output section. We don't always keep track of
@ -885,7 +947,8 @@ Output_section::do_set_address(uint64_t address, off_t startoff)
template<int size, bool big_endian>
void
Output_section::write_header(const Stringpool* secnamepool,
Output_section::write_header(const Layout* layout,
const Stringpool* secnamepool,
elfcpp::Shdr_write<size, big_endian>* oshdr) const
{
oshdr->put_sh_name(secnamepool->get_offset(this->name_));
@ -894,8 +957,18 @@ Output_section::write_header(const Stringpool* secnamepool,
oshdr->put_sh_addr(this->address());
oshdr->put_sh_offset(this->offset());
oshdr->put_sh_size(this->data_size());
oshdr->put_sh_link(this->link_);
oshdr->put_sh_info(this->info_);
if (this->link_section_ != NULL)
oshdr->put_sh_link(this->link_section_->out_shndx());
else if (this->should_link_to_symtab_)
oshdr->put_sh_link(layout->symtab_section()->out_shndx());
else if (this->should_link_to_dynsym_)
oshdr->put_sh_link(layout->dynsym_section()->out_shndx());
else
oshdr->put_sh_link(this->link_);
if (this->info_section_ != NULL)
oshdr->put_sh_info(this->info_section_->out_shndx());
else
oshdr->put_sh_info(this->info_);
oshdr->put_sh_addralign(this->addralign_);
oshdr->put_sh_entsize(this->entsize_);
}
@ -1245,7 +1318,8 @@ Output_segment::write_header(elfcpp::Phdr_write<size, big_endian>* ophdr)
template<int size, bool big_endian>
unsigned char*
Output_segment::write_section_headers(const Stringpool* secnamepool,
Output_segment::write_section_headers(const Layout* layout,
const Stringpool* secnamepool,
unsigned char* v,
unsigned int *pshndx
ACCEPT_SIZE_ENDIAN) const
@ -1258,18 +1332,19 @@ Output_segment::write_section_headers(const Stringpool* secnamepool,
v = this->write_section_headers_list
SELECT_SIZE_ENDIAN_NAME(size, big_endian) (
secnamepool, &this->output_data_, v, pshndx
layout, secnamepool, &this->output_data_, v, pshndx
SELECT_SIZE_ENDIAN(size, big_endian));
v = this->write_section_headers_list
SELECT_SIZE_ENDIAN_NAME(size, big_endian) (
secnamepool, &this->output_bss_, v, pshndx
layout, secnamepool, &this->output_bss_, v, pshndx
SELECT_SIZE_ENDIAN(size, big_endian));
return v;
}
template<int size, bool big_endian>
unsigned char*
Output_segment::write_section_headers_list(const Stringpool* secnamepool,
Output_segment::write_section_headers_list(const Layout* layout,
const Stringpool* secnamepool,
const Output_data_list* pdl,
unsigned char* v,
unsigned int* pshndx
@ -1285,7 +1360,7 @@ Output_segment::write_section_headers_list(const Stringpool* secnamepool,
const Output_section* ps = static_cast<const Output_section*>(*p);
gold_assert(*pshndx == ps->out_shndx());
elfcpp::Shdr_write<size, big_endian> oshdr(v);
ps->write_header(secnamepool, &oshdr);
ps->write_header(layout, secnamepool, &oshdr);
v += shdr_size;
++*pshndx;
}

View File

@ -185,8 +185,9 @@ class Output_section_headers : public Output_data
public:
Output_section_headers(int size,
bool big_endian,
const Layout::Segment_list&,
const Layout::Section_list&,
const Layout*,
const Layout::Segment_list*,
const Layout::Section_list*,
const Stringpool*);
// Write the data to the file.
@ -206,8 +207,9 @@ class Output_section_headers : public Output_data
int size_;
bool big_endian_;
const Layout::Segment_list& segment_list_;
const Layout::Section_list& unattached_section_list_;
const Layout* layout_;
const Layout::Segment_list* segment_list_;
const Layout::Section_list* unattached_section_list_;
const Stringpool* secnamepool_;
};
@ -303,17 +305,24 @@ class Output_section_data : public Output_data
: Output_data(0), output_section_(NULL), addralign_(addralign)
{ }
// Return the output section.
const Output_section*
output_section() const
{ return this->output_section_; }
// Record the output section.
void
set_output_section(Output_section* os)
{
gold_assert(this->output_section_ == NULL);
this->output_section_ = os;
}
set_output_section(Output_section* os);
protected:
// The child class must implement do_write.
// The child class may implement specific adjustments to the output
// section.
virtual void
do_adjust_output_section(Output_section*)
{ }
// Return the required alignment.
uint64_t
do_addralign() const
@ -695,6 +704,10 @@ class Output_data_reloc_base : public Output_section_data
do_write(Output_file*);
protected:
// Set the entry size and the link.
void
do_adjust_output_section(Output_section *os);
// Add a relocation entry.
void
add(const Output_reloc_type& reloc)
@ -975,19 +988,19 @@ class Output_data_dynamic : public Output_section_data
add_constant(elfcpp::DT tag, unsigned int val)
{ this->add_entry(Dynamic_entry(tag, val)); }
// Add a new dynamic entry with the address of a section.
// Add a new dynamic entry with the address of output data.
void
add_section_address(elfcpp::DT tag, Output_section* os)
{ this->add_entry(Dynamic_entry(tag, os, false)); }
add_section_address(elfcpp::DT tag, const Output_data* od)
{ this->add_entry(Dynamic_entry(tag, od, false)); }
// Add a new dynamic entry with the size of a section.
// Add a new dynamic entry with the size of output data.
void
add_section_size(elfcpp::DT tag, Output_section* os)
{ this->add_entry(Dynamic_entry(tag, os, true)); }
add_section_size(elfcpp::DT tag, const Output_data* od)
{ this->add_entry(Dynamic_entry(tag, od, true)); }
// Add a new dynamic entry with the address of a symbol.
void
add_symbol(elfcpp::DT tag, Symbol* sym)
add_symbol(elfcpp::DT tag, const Symbol* sym)
{ this->add_entry(Dynamic_entry(tag, sym)); }
// Add a new dynamic entry with a string.
@ -1003,6 +1016,11 @@ class Output_data_dynamic : public Output_section_data
void
do_write(Output_file*);
protected:
// Adjust the output section to set the entry size.
void
do_adjust_output_section(Output_section*);
private:
// This POD class holds a single dynamic entry.
class Dynamic_entry
@ -1014,15 +1032,15 @@ class Output_data_dynamic : public Output_section_data
{ this->u_.val = val; }
// Create an entry with the size or address of a section.
Dynamic_entry(elfcpp::DT tag, Output_section* os, bool section_size)
Dynamic_entry(elfcpp::DT tag, const Output_data* od, bool section_size)
: tag_(tag),
classification_(section_size
? DYNAMIC_SECTION_SIZE
: DYNAMIC_SECTION_ADDRESS)
{ this->u_.os = os; }
{ this->u_.od = od; }
// Create an entry with the address of a symbol.
Dynamic_entry(elfcpp::DT tag, Symbol* sym)
Dynamic_entry(elfcpp::DT tag, const Symbol* sym)
: tag_(tag), classification_(DYNAMIC_SYMBOL)
{ this->u_.sym = sym; }
@ -1056,9 +1074,9 @@ class Output_data_dynamic : public Output_section_data
// For DYNAMIC_NUMBER.
unsigned int val;
// For DYNAMIC_SECTION_ADDRESS and DYNAMIC_SECTION_SIZE.
Output_section* os;
const Output_data* od;
// For DYNAMIC_SYMBOL.
Symbol* sym;
const Symbol* sym;
// For DYNAMIC_STRING.
const char* str;
} u_;
@ -1143,18 +1161,71 @@ class Output_section : public Output_data
// Set the entsize field.
void
set_entsize(uint64_t v)
{ this->entsize_ = v; }
set_entsize(uint64_t v);
// Set the link field.
// Set the link field to the output section index of a section.
void
set_link_section(Output_data* od)
{
gold_assert(this->link_ == 0
&& !this->should_link_to_symtab_
&& !this->should_link_to_dynsym_);
this->link_section_ = od;
}
// Set the link field to a constant.
void
set_link(unsigned int v)
{ this->link_ = v; }
{
gold_assert(this->link_section_ == NULL
&& !this->should_link_to_symtab_
&& !this->should_link_to_dynsym_);
this->link_ = v;
}
// Set the info field.
// Record that this section should link to the normal symbol table.
void
set_should_link_to_symtab()
{
gold_assert(this->link_section_ == NULL
&& this->link_ == 0
&& !this->should_link_to_dynsym_);
this->should_link_to_symtab_ = true;
}
// Record that this section should link to the dynamic symbol table.
void
set_should_link_to_dynsym()
{
gold_assert(this->link_section_ == NULL
&& this->link_ == 0
&& !this->should_link_to_symtab_);
this->should_link_to_dynsym_ = true;
}
// Return the info field.
unsigned int
info() const
{
gold_assert(this->info_section_ == NULL);
return this->info_;
}
// Set the info field to the output section index of a section.
void
set_info_section(Output_data* od)
{
gold_assert(this->info_ == 0);
this->info_section_ = od;
}
// Set the info field to a constant.
void
set_info(unsigned int v)
{ this->info_ = v; }
{
gold_assert(this->info_section_ == NULL);
this->info_ = v;
}
// Set the addralign field.
void
@ -1250,7 +1321,8 @@ class Output_section : public Output_data
// Write the section header into *OPHDR.
template<int size, bool big_endian>
void
write_header(const Stringpool*, elfcpp::Shdr_write<size, big_endian>*) const;
write_header(const Layout*, const Stringpool*,
elfcpp::Shdr_write<size, big_endian>*) const;
private:
// In some cases we need to keep a list of the input sections
@ -1344,9 +1416,13 @@ class Output_section : public Output_data
// The section entry size.
uint64_t entsize_;
// The file offset is in the parent class.
// The section link field.
// Set the section link field to the index of this section.
Output_data* link_section_;
// If link_section_ is NULL, this is the link field.
unsigned int link_;
// The section info field.
// Set the section info field to the index of this section.
Output_data* info_section_;
// If info_section_ is NULL, this is the section info field.
unsigned int info_;
// The section type.
elfcpp::Elf_Word type_;
@ -1379,6 +1455,12 @@ class Output_section : public Output_data
// dynamic symbol table. This will be true if there is a dynamic
// relocation which needs it.
bool needs_dynsym_index_ : 1;
// Whether the link field of this output section should point to the
// normal symbol table.
bool should_link_to_symtab_ : 1;
// Whether the link field of this output section should point to the
// dynamic symbol table.
bool should_link_to_dynsym_ : 1;
};
// An output segment. PT_LOAD segments are built from collections of
@ -1466,8 +1548,7 @@ class Output_segment
// Write the section headers of associated sections into V.
template<int size, bool big_endian>
unsigned char*
write_section_headers(const Stringpool*,
unsigned char* v,
write_section_headers(const Layout*, const Stringpool*, unsigned char* v,
unsigned int* pshndx ACCEPT_SIZE_ENDIAN) const;
private:
@ -1497,8 +1578,8 @@ class Output_segment
// Write the section headers in the list into V.
template<int size, bool big_endian>
unsigned char*
write_section_headers_list(const Stringpool*, const Output_data_list*,
unsigned char* v,
write_section_headers_list(const Layout*, const Stringpool*,
const Output_data_list*, unsigned char* v,
unsigned int* pshdx ACCEPT_SIZE_ENDIAN) const;
// The list of output data with contents attached to this segment.

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-11-30 15:37-0800\n"
"POT-Creation-Date: 2006-12-01 08:46-0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -240,52 +240,52 @@ msgstr ""
msgid "%s: missing expected TLS relocation\n"
msgstr ""
#: i386.cc:702 i386.cc:843 i386.cc:1064
#: i386.cc:729 i386.cc:870 i386.cc:1125
#, c-format
msgid "%s: %s: unexpected reloc %u in object file\n"
msgstr ""
#: i386.cc:738 i386.cc:757
#: i386.cc:765 i386.cc:784
#, c-format
msgid "%s: %s: unsupported reloc %u against local symbol\n"
msgstr ""
#: i386.cc:879 i386.cc:900
#: i386.cc:906 i386.cc:927
#, c-format
msgid "%s: %s: unsupported reloc %u against global symbol %s\n"
msgstr ""
#: i386.cc:923
#: i386.cc:950
#, c-format
msgid "%s: %s: unsupported RELA reloc section\n"
msgstr ""
#: i386.cc:980
#: i386.cc:1041
#, c-format
msgid "%s: %s: missing expected TLS relocation\n"
msgstr ""
#: i386.cc:1096 i386.cc:1171 i386.cc:1182
#: i386.cc:1157 i386.cc:1232 i386.cc:1243
#, c-format
msgid "%s: %s: unsupported reloc %u\n"
msgstr ""
#: i386.cc:1123
#: i386.cc:1184
#, c-format
msgid "%s: %s: TLS reloc but no TLS segment\n"
msgstr ""
#: i386.cc:1156
#: i386.cc:1217
#, c-format
msgid "%s: %s: unsupported reloc type %u\n"
msgstr ""
#: i386.cc:1365
#: i386.cc:1426
#, c-format
msgid "%s: %s: TLS relocation out of range\n"
msgstr ""
#: i386.cc:1383
#: i386.cc:1444
#, c-format
msgid "%s: %s: TLS relocation against invalid instruction\n"
msgstr ""
@ -496,37 +496,37 @@ msgstr ""
msgid "%s: -%c: %s\n"
msgstr ""
#: output.cc:817
#: output.cc:881
#, c-format
msgid "%s: %s: invalid alignment %lu for section \"%s\"\n"
msgstr ""
#: output.cc:1316
#: output.cc:1393
#, c-format
msgid "%s: %s: open: %s\n"
msgstr ""
#: output.cc:1325
#: output.cc:1402
#, c-format
msgid "%s: %s: lseek: %s\n"
msgstr ""
#: output.cc:1332
#: output.cc:1409
#, c-format
msgid "%s: %s: write: %s\n"
msgstr ""
#: output.cc:1342
#: output.cc:1419
#, c-format
msgid "%s: %s: mmap: %s\n"
msgstr ""
#: output.cc:1356
#: output.cc:1433
#, c-format
msgid "%s: %s: munmap: %s\n"
msgstr ""
#: output.cc:1364
#: output.cc:1441
#, c-format
msgid "%s: %s: close: %s\n"
msgstr ""
@ -607,12 +607,12 @@ msgstr ""
msgid "%s: %s: versym for symbol %zu has no name: %u\n"
msgstr ""
#: symtab.cc:1050 symtab.cc:1201
#: symtab.cc:1063 symtab.cc:1235
#, c-format
msgid "%s: %s: unsupported symbol section 0x%x\n"
msgstr ""
#: symtab.cc:1364
#: symtab.cc:1423
#, c-format
msgid "%s: %s: warning: %s\n"
msgstr ""

View File

@ -497,6 +497,7 @@ void
Copy_relocs<size, big_endian>::Copy_reloc_entry::emit(
Output_data_reloc<elfcpp::SHT_REL, true, size, big_endian>* reloc_data)
{
this->sym_->set_needs_dynsym_entry();
reloc_data->add_global(this->sym_, this->reloc_type_, this->relobj_,
this->shndx_, this->address_);
}
@ -508,6 +509,7 @@ void
Copy_relocs<size, big_endian>::Copy_reloc_entry::emit(
Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian>* reloc_data)
{
this->sym_->set_needs_dynsym_entry();
reloc_data->add_global(this->sym_, this->reloc_type_, this->relobj_,
this->shndx_, this->address_, this->addend_);
}

View File

@ -22,7 +22,7 @@ Symbol::override_base(const elfcpp::Sym<size, big_endian>& sym,
gold_assert(this->source_ == FROM_OBJECT);
this->u_.from_object.object = object;
// FIXME: Handle SHN_XINDEX.
this->u_.from_object.shnum = sym.get_st_shndx();
this->u_.from_object.shndx = sym.get_st_shndx();
this->type_ = sym.get_st_type();
this->binding_ = sym.get_st_bind();
this->visibility_ = sym.get_st_visibility();
@ -110,7 +110,7 @@ Symbol_table::resolve(Sized_symbol<size>* to,
&& to->object()->is_dynamic())
tobits |= (1 << 1);
switch (to->shnum())
switch (to->shndx())
{
case elfcpp::SHN_UNDEF:
tobits |= (1 << 2);

View File

@ -55,7 +55,7 @@ Symbol::init_base(const char* name, const char* version, Object* object,
sym.get_st_visibility(), sym.get_st_nonvis());
this->u_.from_object.object = object;
// FIXME: Handle SHN_XINDEX.
this->u_.from_object.shnum = sym.get_st_shndx();
this->u_.from_object.shndx = sym.get_st_shndx();
this->source_ = FROM_OBJECT;
this->in_dyn_ = object->is_dynamic();
}
@ -258,7 +258,7 @@ Symbol_table::resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from
esym.put_st_size(from->symsize());
esym.put_st_info(from->binding(), from->type());
esym.put_st_other(from->visibility(), from->nonvis());
esym.put_st_shndx(from->shnum());
esym.put_st_shndx(from->shndx());
Symbol_table::resolve(to, esym.sym(), from->object());
}
@ -717,9 +717,9 @@ Symbol_table::define_special_symbol(Target* target, const char* name,
sym = this->get_sized_symbol SELECT_SIZE_NAME(size) (oldsym
SELECT_SIZE(size));
gold_assert(sym->source() == Symbol::FROM_OBJECT);
const int old_shnum = sym->shnum();
if (old_shnum != elfcpp::SHN_UNDEF
&& old_shnum != elfcpp::SHN_COMMON
const int old_shndx = sym->shndx();
if (old_shndx != elfcpp::SHN_UNDEF
&& old_shndx != elfcpp::SHN_COMMON
&& !sym->object()->is_dynamic())
{
fprintf(stderr, "%s: linker defined: multiple definition of %s\n",
@ -969,7 +969,14 @@ Symbol_table::set_dynsym_indexes(unsigned int index,
++p)
{
Symbol* sym = p->second;
if (sym->needs_dynsym_entry())
// Note that SYM may already have a dynamic symbol index, since
// some symbols appear more than once in the symbol table, with
// and without a version.
if (!sym->needs_dynsym_entry())
sym->set_dynsym_index(-1U);
else if (!sym->has_dynsym_index())
{
sym->set_dynsym_index(index);
++index;
@ -986,13 +993,19 @@ Symbol_table::set_dynsym_indexes(unsigned int index,
// OFF. Add their names to POOL. Return the new file offset.
off_t
Symbol_table::finalize(unsigned int index, off_t off, Stringpool* pool)
Symbol_table::finalize(unsigned int index, off_t off, off_t dynoff,
size_t dyn_global_index, size_t dyncount,
Stringpool* pool)
{
off_t ret;
gold_assert(index != 0);
this->first_global_index_ = index;
this->dynamic_offset_ = dynoff;
this->first_dynamic_global_index_ = dyn_global_index;
this->dynamic_count_ = dyncount;
if (this->size_ == 32)
ret = this->sized_finalize<32>(index, off, pool);
else if (this->size_ == 64)
@ -1041,14 +1054,14 @@ Symbol_table::sized_finalize(unsigned index, off_t off, Stringpool* pool)
{
case Symbol::FROM_OBJECT:
{
unsigned int shnum = sym->shnum();
unsigned int shndx = sym->shndx();
// FIXME: We need some target specific support here.
if (shnum >= elfcpp::SHN_LORESERVE
&& shnum != elfcpp::SHN_ABS)
if (shndx >= elfcpp::SHN_LORESERVE
&& shndx != elfcpp::SHN_ABS)
{
fprintf(stderr, _("%s: %s: unsupported symbol section 0x%x\n"),
program_name, sym->name(), shnum);
program_name, sym->name(), shndx);
gold_exit(false);
}
@ -1056,21 +1069,22 @@ Symbol_table::sized_finalize(unsigned index, off_t off, Stringpool* pool)
if (symobj->is_dynamic())
{
value = 0;
shnum = elfcpp::SHN_UNDEF;
shndx = elfcpp::SHN_UNDEF;
}
else if (shnum == elfcpp::SHN_UNDEF)
else if (shndx == elfcpp::SHN_UNDEF)
value = 0;
else if (shnum == elfcpp::SHN_ABS)
else if (shndx == elfcpp::SHN_ABS)
value = sym->value();
else
{
Relobj* relobj = static_cast<Relobj*>(symobj);
off_t secoff;
Output_section* os = relobj->output_section(shnum, &secoff);
Output_section* os = relobj->output_section(shndx, &secoff);
if (os == NULL)
{
sym->set_symtab_index(-1U);
gold_assert(sym->dynsym_index() == -1U);
continue;
}
@ -1132,21 +1146,21 @@ Symbol_table::sized_finalize(unsigned index, off_t off, Stringpool* pool)
void
Symbol_table::write_globals(const Target* target, const Stringpool* sympool,
Output_file* of) const
const Stringpool* dynpool, Output_file* of) const
{
if (this->size_ == 32)
{
if (target->is_big_endian())
this->sized_write_globals<32, true>(target, sympool, of);
this->sized_write_globals<32, true>(target, sympool, dynpool, of);
else
this->sized_write_globals<32, false>(target, sympool, of);
this->sized_write_globals<32, false>(target, sympool, dynpool, of);
}
else if (this->size_ == 64)
{
if (target->is_big_endian())
this->sized_write_globals<64, true>(target, sympool, of);
this->sized_write_globals<64, true>(target, sympool, dynpool, of);
else
this->sized_write_globals<64, false>(target, sympool, of);
this->sized_write_globals<64, false>(target, sympool, dynpool, of);
}
else
gold_unreachable();
@ -1158,12 +1172,22 @@ template<int size, bool big_endian>
void
Symbol_table::sized_write_globals(const Target*,
const Stringpool* sympool,
const Stringpool* dynpool,
Output_file* of) const
{
const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
unsigned int index = this->first_global_index_;
const off_t oview_size = this->output_count_ * sym_size;
unsigned char* psyms = of->get_output_view(this->offset_, oview_size);
unsigned char* const psyms = of->get_output_view(this->offset_, oview_size);
unsigned int dynamic_count = this->dynamic_count_;
off_t dynamic_size = dynamic_count * sym_size;
unsigned int first_dynamic_global_index = this->first_dynamic_global_index_;
unsigned char* dynamic_view;
if (this->dynamic_offset_ == 0)
dynamic_view = NULL;
else
dynamic_view = of->get_output_view(this->dynamic_offset_, dynamic_size);
unsigned char* ps = psyms;
for (Symbol_table_type::const_iterator p = this->table_.begin();
@ -1173,33 +1197,43 @@ Symbol_table::sized_write_globals(const Target*,
Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(p->second);
unsigned int sym_index = sym->symtab_index();
if (sym_index == -1U)
unsigned int dynsym_index;
if (dynamic_view == NULL)
dynsym_index = -1U;
else
dynsym_index = sym->dynsym_index();
if (sym_index == -1U && dynsym_index == -1U)
{
// This symbol is not included in the output file.
continue;
}
if (sym_index != index)
if (sym_index == index)
++index;
else if (sym_index != -1U)
{
// We have already seen this symbol, because it has a
// default version.
gold_assert(sym_index < index);
continue;
if (dynsym_index == -1U)
continue;
sym_index = -1U;
}
++index;
unsigned int shndx;
switch (sym->source())
{
case Symbol::FROM_OBJECT:
{
unsigned int shnum = sym->shnum();
unsigned int in_shndx = sym->shndx();
// FIXME: We need some target specific support here.
if (shnum >= elfcpp::SHN_LORESERVE
&& shnum != elfcpp::SHN_ABS)
if (in_shndx >= elfcpp::SHN_LORESERVE
&& in_shndx != elfcpp::SHN_ABS)
{
fprintf(stderr, _("%s: %s: unsupported symbol section 0x%x\n"),
program_name, sym->name(), sym->shnum());
program_name, sym->name(), in_shndx);
gold_exit(false);
}
@ -1209,13 +1243,14 @@ Symbol_table::sized_write_globals(const Target*,
// FIXME.
shndx = elfcpp::SHN_UNDEF;
}
else if (shnum == elfcpp::SHN_UNDEF || shnum == elfcpp::SHN_ABS)
shndx = shnum;
else if (in_shndx == elfcpp::SHN_UNDEF
|| in_shndx == elfcpp::SHN_ABS)
shndx = in_shndx;
else
{
Relobj* relobj = static_cast<Relobj*>(symobj);
off_t secoff;
Output_section* os = relobj->output_section(shnum, &secoff);
Output_section* os = relobj->output_section(in_shndx, &secoff);
gold_assert(os != NULL);
shndx = os->out_shndx();
}
@ -1238,21 +1273,45 @@ Symbol_table::sized_write_globals(const Target*,
gold_unreachable();
}
elfcpp::Sym_write<size, big_endian> osym(ps);
osym.put_st_name(sympool->get_offset(sym->name()));
osym.put_st_value(sym->value());
osym.put_st_size(sym->symsize());
osym.put_st_info(elfcpp::elf_st_info(sym->binding(), sym->type()));
osym.put_st_other(elfcpp::elf_st_other(sym->visibility(),
sym->nonvis()));
osym.put_st_shndx(shndx);
if (sym_index != -1U)
{
this->sized_write_symbol<size, big_endian>(sym, shndx, sympool, ps);
ps += sym_size;
}
ps += sym_size;
if (dynsym_index != -1U)
{
dynsym_index -= first_dynamic_global_index;
gold_assert(dynsym_index < dynamic_count);
unsigned char* pd = dynamic_view + (dynsym_index * sym_size);
this->sized_write_symbol<size, big_endian>(sym, shndx, dynpool, pd);
}
}
gold_assert(ps - psyms == oview_size);
of->write_output_view(this->offset_, oview_size, psyms);
if (dynamic_view != NULL)
of->write_output_view(this->dynamic_offset_, dynamic_size, dynamic_view);
}
// Write out the symbol SYM, in section SHNDX, to P. POOL is the
// strtab holding the name.
template<int size, bool big_endian>
void
Symbol_table::sized_write_symbol(Sized_symbol<size>* sym,
unsigned int shndx,
const Stringpool* pool,
unsigned char* p) const
{
elfcpp::Sym_write<size, big_endian> osym(p);
osym.put_st_name(pool->get_offset(sym->name()));
osym.put_st_value(sym->value());
osym.put_st_size(sym->symsize());
osym.put_st_info(elfcpp::elf_st_info(sym->binding(), sym->type()));
osym.put_st_other(elfcpp::elf_st_other(sym->visibility(), sym->nonvis()));
osym.put_st_shndx(shndx);
}
// Write out a section symbol. Return the update offset.

View File

@ -97,10 +97,10 @@ class Symbol
// Return the index of the section in the input relocatable or
// dynamic object file.
unsigned int
shnum() const
shndx() const
{
gold_assert(this->source_ == FROM_OBJECT);
return this->u_.from_object.shnum;
return this->u_.from_object.shndx;
}
// Return the output data section with which this symbol is
@ -235,6 +235,12 @@ class Symbol
this->dynsym_index_ = index;
}
// Return whether this symbol already has an index in the dynamic
// symbol table.
bool
has_dynsym_index() const
{ return this->dynsym_index_ != 0; }
// Return whether this symbol has an entry in the GOT section.
bool
has_got_offset() const
@ -293,8 +299,8 @@ class Symbol
is_defined() const
{
return (this->source_ != FROM_OBJECT
|| (this->shnum() != elfcpp::SHN_UNDEF
&& this->shnum() != elfcpp::SHN_COMMON));
|| (this->shndx() != elfcpp::SHN_UNDEF
&& this->shndx() != elfcpp::SHN_COMMON));
}
// Return whether this symbol is defined in a dynamic object.
@ -310,7 +316,7 @@ class Symbol
bool
is_undefined() const
{
return this->source_ == FROM_OBJECT && this->shnum() == elfcpp::SHN_UNDEF;
return this->source_ == FROM_OBJECT && this->shndx() == elfcpp::SHN_UNDEF;
}
// Return whether this is a common symbol.
@ -318,7 +324,7 @@ class Symbol
is_common() const
{
return (this->source_ == FROM_OBJECT
&& (this->shnum() == elfcpp::SHN_COMMON
&& (this->shndx() == elfcpp::SHN_COMMON
|| this->type_ == elfcpp::STT_COMMON));
}
@ -391,7 +397,7 @@ class Symbol
// seen.
Object* object;
// Section number in object_ in which symbol is defined.
unsigned int shnum;
unsigned int shndx;
} from_object;
// This struct is used if SOURCE_ == IN_OUTPUT_DATA.
@ -824,14 +830,19 @@ class Symbol_table
// Finalize the symbol table after we have set the final addresses
// of all the input sections. This sets the final symbol indexes,
// values and adds the names to *POOL. INDEX is the index of the
// first global symbol. This records the file offset OFF, and
// returns the new file offset.
// first global symbol. OFF is the file offset of the global symbol
// table, DYNOFF is the offset of the globals in the dynamic symbol
// table, DYN_GLOBAL_INDEX is the index of the first global dynamic
// symbol, and DYNCOUNT is the number of global dynamic symbols.
// This records the parameters, and returns the new file offset.
off_t
finalize(unsigned int index, off_t off, Stringpool* pool);
finalize(unsigned int index, off_t off, off_t dynoff,
size_t dyn_global_index, size_t dyncount, Stringpool* pool);
// Write out the global symbols.
void
write_globals(const Target*, const Stringpool*, Output_file*) const;
write_globals(const Target*, const Stringpool*, const Stringpool*,
Output_file*) const;
// Write out a section symbol. Return the updated offset.
void
@ -915,7 +926,14 @@ class Symbol_table
// Write globals specialized for size and endianness.
template<int size, bool big_endian>
void
sized_write_globals(const Target*, const Stringpool*, Output_file*) const;
sized_write_globals(const Target*, const Stringpool*, const Stringpool*,
Output_file*) const;
// Write out a symbol to P.
template<int size, bool big_endian>
void
sized_write_symbol(Sized_symbol<size>*, unsigned int shndx,
const Stringpool*, unsigned char* p) const;
// Write out a section symbol, specialized for size and endianness.
template<int size, bool big_endian>
@ -962,6 +980,15 @@ class Symbol_table
// The number of global symbols we want to write out.
size_t output_count_;
// The file offset of the global dynamic symbols, or 0 if none.
off_t dynamic_offset_;
// The index of the first global dynamic symbol.
unsigned int first_dynamic_global_index_;
// The number of global dynamic symbols, or 0 if none.
off_t dynamic_count_;
// The symbol hash table.
Symbol_table_type table_;

View File

@ -86,8 +86,8 @@ class Target
// This is called to tell the target to complete any sections it is
// handling. After this all sections must have their final size.
void
finalize_sections(Layout* layout)
{ return this->do_finalize_sections(layout); }
finalize_sections(const General_options* options, Layout* layout)
{ return this->do_finalize_sections(options, layout); }
protected:
// This struct holds the constant information for a child class. We
@ -121,7 +121,7 @@ class Target
// Virtual function which may be implemented by the child class.
virtual void
do_finalize_sections(Layout*)
do_finalize_sections(const General_options*, Layout*)
{ }
private: