mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-23 18:14:13 +08:00
Can now dynamically link hello, world.
This commit is contained in:
parent
8a82f7e392
commit
16649710df
@ -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.
|
||||
|
77
gold/i386.cc
77
gold/i386.cc
@ -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();
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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_;
|
||||
};
|
||||
|
121
gold/output.cc
121
gold/output.cc
@ -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;
|
||||
}
|
||||
|
149
gold/output.h
149
gold/output.h
@ -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.
|
||||
|
@ -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 ""
|
||||
|
@ -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_);
|
||||
}
|
||||
|
@ -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);
|
||||
|
141
gold/symtab.cc
141
gold/symtab.cc
@ -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.
|
||||
|
@ -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_;
|
||||
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user