Clean up setting address and section offset.
This commit is contained in:
parent
6ac84f65c2
commit
27bc2bce09
13 changed files with 381 additions and 193 deletions
|
@ -231,7 +231,7 @@ Symbol_table::do_allocate_commons(const General_options&,
|
|||
off += ssym->symsize();
|
||||
}
|
||||
|
||||
poc->set_space_size(off);
|
||||
poc->set_current_data_size(off);
|
||||
|
||||
this->commons_.clear();
|
||||
}
|
||||
|
|
|
@ -88,10 +88,10 @@ Eh_frame_hdr::Eh_frame_hdr(Output_section* eh_frame_section,
|
|||
{
|
||||
}
|
||||
|
||||
// Set the final address and size of the exception frame header.
|
||||
// Set the size of the exception frame header.
|
||||
|
||||
void
|
||||
Eh_frame_hdr::do_set_address(uint64_t, off_t)
|
||||
Eh_frame_hdr::set_final_data_size()
|
||||
{
|
||||
unsigned int data_size = eh_frame_hdr_size + 4;
|
||||
if (!this->any_unrecognized_eh_frame_sections_)
|
||||
|
@ -976,8 +976,9 @@ Eh_frame::fde_count() const
|
|||
// Set the final data size.
|
||||
|
||||
void
|
||||
Eh_frame::do_set_address(uint64_t, off_t start_file_offset)
|
||||
Eh_frame::set_final_data_size()
|
||||
{
|
||||
off_t start_file_offset = this->offset();
|
||||
off_t output_offset = 0;
|
||||
|
||||
for (Unmergeable_cie_offsets::iterator p =
|
||||
|
|
|
@ -65,7 +65,7 @@ class Eh_frame_hdr : public Output_section_data
|
|||
|
||||
// Set the final data size.
|
||||
void
|
||||
do_set_address(uint64_t address, off_t offset);
|
||||
set_final_data_size();
|
||||
|
||||
// Write the data to the file.
|
||||
void
|
||||
|
@ -314,7 +314,7 @@ class Eh_frame : public Output_section_data
|
|||
|
||||
// Set the final data size.
|
||||
void
|
||||
do_set_address(uint64_t, off_t);
|
||||
set_final_data_size();
|
||||
|
||||
// Return the output address for an input address.
|
||||
bool
|
||||
|
|
|
@ -251,7 +251,7 @@ void
|
|||
queue_final_tasks(const General_options& options,
|
||||
const Input_objects* input_objects,
|
||||
const Symbol_table* symtab,
|
||||
const Layout* layout,
|
||||
Layout* layout,
|
||||
Workqueue* workqueue,
|
||||
Output_file* of)
|
||||
{
|
||||
|
|
|
@ -272,7 +272,7 @@ extern void
|
|||
queue_final_tasks(const General_options&,
|
||||
const Input_objects*,
|
||||
const Symbol_table*,
|
||||
const Layout*,
|
||||
Layout*,
|
||||
Workqueue*,
|
||||
Output_file* of);
|
||||
|
||||
|
|
12
gold/i386.cc
12
gold/i386.cc
|
@ -348,7 +348,7 @@ Target_i386::got_section(Symbol_table* symtab, Layout* layout)
|
|||
this->got_plt_);
|
||||
|
||||
// The first three entries are reserved.
|
||||
this->got_plt_->set_space_size(3 * 4);
|
||||
this->got_plt_->set_current_data_size(3 * 4);
|
||||
|
||||
// Define _GLOBAL_OFFSET_TABLE_ at the start of the PLT.
|
||||
symtab->define_in_output_data(this, "_GLOBAL_OFFSET_TABLE_", NULL,
|
||||
|
@ -417,7 +417,7 @@ class Output_data_plt_i386 : public Output_section_data
|
|||
|
||||
// Set the final size.
|
||||
void
|
||||
do_set_address(uint64_t, off_t)
|
||||
set_final_data_size()
|
||||
{ this->set_data_size((this->count_ + 1) * plt_entry_size); }
|
||||
|
||||
// Write out the PLT data.
|
||||
|
@ -466,12 +466,12 @@ Output_data_plt_i386::add_entry(Symbol* gsym)
|
|||
|
||||
++this->count_;
|
||||
|
||||
off_t got_offset = this->got_plt_->data_size();
|
||||
off_t got_offset = this->got_plt_->current_data_size();
|
||||
|
||||
// Every PLT entry needs a GOT entry which points back to the PLT
|
||||
// entry (this will be changed by the dynamic linker, normally
|
||||
// lazily when the function is called).
|
||||
this->got_plt_->set_space_size(got_offset + 4);
|
||||
this->got_plt_->set_current_data_size(got_offset + 4);
|
||||
|
||||
// Every PLT entry needs a reloc.
|
||||
gsym->set_needs_dynsym_entry();
|
||||
|
@ -700,10 +700,10 @@ Target_i386::copy_reloc(const General_options* options,
|
|||
if (align > dynbss->addralign())
|
||||
dynbss->set_space_alignment(align);
|
||||
|
||||
off_t dynbss_size = dynbss->data_size();
|
||||
off_t dynbss_size = dynbss->current_data_size();
|
||||
dynbss_size = align_address(dynbss_size, align);
|
||||
off_t offset = dynbss_size;
|
||||
dynbss->set_space_size(dynbss_size + symsize);
|
||||
dynbss->set_current_data_size(dynbss_size + symsize);
|
||||
|
||||
symtab->define_with_copy_reloc(this, ssym, dynbss, offset);
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ 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),
|
||||
section_headers_(NULL), tls_segment_(NULL), symtab_section_(NULL),
|
||||
dynsym_section_(NULL), dynamic_section_(NULL), dynamic_data_(NULL),
|
||||
eh_frame_section_(NULL), output_file_size_(-1),
|
||||
input_requires_executable_stack_(false),
|
||||
|
@ -76,9 +76,9 @@ Layout::Layout(const General_options& options)
|
|||
// This is just for efficiency--it's OK if we wind up needing more.
|
||||
this->segment_list_.reserve(12);
|
||||
|
||||
// We expect three unattached Output_data objects: the file header,
|
||||
// the segment headers, and the section headers.
|
||||
this->special_output_list_.reserve(3);
|
||||
// We expect two unattached Output_data objects: the file header and
|
||||
// the segment headers.
|
||||
this->special_output_list_.reserve(2);
|
||||
}
|
||||
|
||||
// Hash a key we use to look up an output section mapping.
|
||||
|
@ -695,37 +695,33 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab)
|
|||
this->special_output_list_.push_back(file_header);
|
||||
|
||||
// We set the output section indexes in set_segment_offsets and
|
||||
// set_section_offsets.
|
||||
// set_section_indexes.
|
||||
unsigned int shndx = 1;
|
||||
|
||||
// Set the file offsets of all the segments, and all the sections
|
||||
// they contain.
|
||||
off_t off = this->set_segment_offsets(target, load_seg, &shndx);
|
||||
|
||||
// Set the file offsets of all the data sections not associated with
|
||||
// segments. This makes sure that debug sections have their offsets
|
||||
// before symbols are finalized.
|
||||
off = this->set_section_offsets(off, true);
|
||||
|
||||
// Create the symbol table sections.
|
||||
this->create_symtab_sections(input_objects, symtab, &off);
|
||||
|
||||
// Create the .shstrtab section.
|
||||
Output_section* shstrtab_section = this->create_shstrtab();
|
||||
|
||||
// Set the file offsets of all the non-data sections not associated with
|
||||
// segments.
|
||||
// Set the file offsets of all the non-data sections which don't
|
||||
// have to wait for the input sections.
|
||||
off = this->set_section_offsets(off, false);
|
||||
|
||||
// Now that all sections have been created, set the section indexes.
|
||||
shndx = this->set_section_indexes(shndx);
|
||||
|
||||
// Create the section table header.
|
||||
Output_section_headers* oshdrs = this->create_shdrs(&off);
|
||||
this->create_shdrs(&off);
|
||||
|
||||
file_header->set_section_info(oshdrs, shstrtab_section);
|
||||
file_header->set_section_info(this->section_headers_, shstrtab_section);
|
||||
|
||||
// Now we know exactly where everything goes in the output file.
|
||||
// Now we know exactly where everything goes in the output file
|
||||
// (except for non-allocated sections which require postprocessing).
|
||||
Output_data::layout_complete();
|
||||
|
||||
this->output_file_size_ = off;
|
||||
|
@ -1063,21 +1059,22 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
|
|||
// segment.
|
||||
|
||||
off_t
|
||||
Layout::set_section_offsets(off_t off,
|
||||
bool do_bits_sections)
|
||||
Layout::set_section_offsets(off_t off, bool after_input_sections)
|
||||
{
|
||||
for (Section_list::iterator p = this->unattached_section_list_.begin();
|
||||
p != this->unattached_section_list_.end();
|
||||
++p)
|
||||
{
|
||||
bool is_bits_section = ((*p)->type() == elfcpp::SHT_PROGBITS
|
||||
|| (*p)->type() == elfcpp::SHT_NOBITS);
|
||||
if (is_bits_section != do_bits_sections)
|
||||
continue;
|
||||
if ((*p)->offset() != -1)
|
||||
// The symtab section is handled in create_symtab_sections.
|
||||
if (*p == this->symtab_section_)
|
||||
continue;
|
||||
|
||||
if ((*p)->after_input_sections() != after_input_sections)
|
||||
continue;
|
||||
|
||||
off = align_address(off, (*p)->addralign());
|
||||
(*p)->set_address(0, off);
|
||||
(*p)->set_file_offset(off);
|
||||
(*p)->finalize_data_size();
|
||||
off += (*p)->data_size();
|
||||
}
|
||||
return off;
|
||||
|
@ -1194,8 +1191,8 @@ Layout::create_symtab_sections(const Input_objects* input_objects,
|
|||
0);
|
||||
this->symtab_section_ = osymtab;
|
||||
|
||||
Output_section_data* pos = new Output_data_space(off - startoff,
|
||||
align);
|
||||
Output_section_data* pos = new Output_data_fixed_space(off - startoff,
|
||||
align);
|
||||
osymtab->add_output_section_data(pos);
|
||||
|
||||
const char* strtab_name = this->namepool_.add(".strtab", false, NULL);
|
||||
|
@ -1206,7 +1203,8 @@ Layout::create_symtab_sections(const Input_objects* input_objects,
|
|||
Output_section_data* pstr = new Output_data_strtab(&this->sympool_);
|
||||
ostrtab->add_output_section_data(pstr);
|
||||
|
||||
osymtab->set_address(0, startoff);
|
||||
osymtab->set_file_offset(startoff);
|
||||
osymtab->finalize_data_size();
|
||||
osymtab->set_link_section(ostrtab);
|
||||
osymtab->set_info(local_symcount);
|
||||
osymtab->set_entsize(symsize);
|
||||
|
@ -1227,10 +1225,13 @@ Layout::create_shstrtab()
|
|||
|
||||
const char* name = this->namepool_.add(".shstrtab", false, NULL);
|
||||
|
||||
this->namepool_.set_string_offsets();
|
||||
|
||||
Output_section* os = this->make_output_section(name, elfcpp::SHT_STRTAB, 0);
|
||||
|
||||
// We can't write out this section until we've set all the section
|
||||
// names, and we don't set the names of compressed output sections
|
||||
// until relocations are complete.
|
||||
os->set_after_input_sections();
|
||||
|
||||
Output_section_data* posd = new Output_data_strtab(&this->namepool_);
|
||||
os->add_output_section_data(posd);
|
||||
|
||||
|
@ -1240,7 +1241,7 @@ Layout::create_shstrtab()
|
|||
// Create the section headers. SIZE is 32 or 64. OFF is the file
|
||||
// offset.
|
||||
|
||||
Output_section_headers*
|
||||
void
|
||||
Layout::create_shdrs(off_t* poff)
|
||||
{
|
||||
Output_section_headers* oshdrs;
|
||||
|
@ -1249,11 +1250,10 @@ Layout::create_shdrs(off_t* poff)
|
|||
&this->unattached_section_list_,
|
||||
&this->namepool_);
|
||||
off_t off = align_address(*poff, oshdrs->addralign());
|
||||
oshdrs->set_address(0, off);
|
||||
oshdrs->set_address_and_file_offset(0, off);
|
||||
off += oshdrs->data_size();
|
||||
*poff = off;
|
||||
this->special_output_list_.push_back(oshdrs);
|
||||
return oshdrs;
|
||||
this->section_headers_ = oshdrs;
|
||||
}
|
||||
|
||||
// Create the dynamic symbol table.
|
||||
|
@ -1321,8 +1321,8 @@ Layout::create_dynamic_symtab(const Target* target, Symbol_table* symtab,
|
|||
elfcpp::SHT_DYNSYM,
|
||||
elfcpp::SHF_ALLOC);
|
||||
|
||||
Output_section_data* odata = new Output_data_space(index * symsize,
|
||||
align);
|
||||
Output_section_data* odata = new Output_data_fixed_space(index * symsize,
|
||||
align);
|
||||
dynsym->add_output_section_data(odata);
|
||||
|
||||
dynsym->set_info(local_symcount);
|
||||
|
@ -1880,8 +1880,18 @@ Layout::write_data(const Symbol_table* symtab, Output_file* of) const
|
|||
// input sections are complete.
|
||||
|
||||
void
|
||||
Layout::write_sections_after_input_sections(Output_file* of) const
|
||||
Layout::write_sections_after_input_sections(Output_file* of)
|
||||
{
|
||||
// Determine the final section offsets, and thus the final output
|
||||
// file size.
|
||||
off_t off = this->output_file_size_;
|
||||
off = this->set_section_offsets(off, true);
|
||||
if (off > this->output_file_size_)
|
||||
{
|
||||
of->resize(off);
|
||||
this->output_file_size_ = off;
|
||||
}
|
||||
|
||||
for (Section_list::const_iterator p = this->section_list_.begin();
|
||||
p != this->section_list_.end();
|
||||
++p)
|
||||
|
@ -1889,6 +1899,16 @@ Layout::write_sections_after_input_sections(Output_file* of) const
|
|||
if ((*p)->after_input_sections())
|
||||
(*p)->write(of);
|
||||
}
|
||||
|
||||
for (Section_list::const_iterator p = this->unattached_section_list_.begin();
|
||||
p != this->unattached_section_list_.end();
|
||||
++p)
|
||||
{
|
||||
if ((*p)->after_input_sections())
|
||||
(*p)->write(of);
|
||||
}
|
||||
|
||||
this->section_headers_->write(of);
|
||||
}
|
||||
|
||||
// Write_sections_task methods.
|
||||
|
|
|
@ -214,7 +214,7 @@ class Layout
|
|||
// Write out output sections which can not be written until all the
|
||||
// input sections are complete.
|
||||
void
|
||||
write_sections_after_input_sections(Output_file* of) const;
|
||||
write_sections_after_input_sections(Output_file* of);
|
||||
|
||||
// Return an output section named NAME, or NULL if there is none.
|
||||
Output_section*
|
||||
|
@ -275,7 +275,7 @@ class Layout
|
|||
create_shstrtab();
|
||||
|
||||
// Create the section header table.
|
||||
Output_section_headers*
|
||||
void
|
||||
create_shdrs(off_t*);
|
||||
|
||||
// Create the dynamic symbol table.
|
||||
|
@ -344,7 +344,7 @@ class Layout
|
|||
// Set the final file offsets of all the sections not associated
|
||||
// with a segment.
|
||||
off_t
|
||||
set_section_offsets(off_t, bool do_bits_sections);
|
||||
set_section_offsets(off_t, bool after_input_sections);
|
||||
|
||||
// Set the final section indexes of all the sections not associated
|
||||
// with a segment. Returns the next unused index.
|
||||
|
@ -407,6 +407,8 @@ class Layout
|
|||
// The list of unattached Output_data objects which require special
|
||||
// handling because they are not Output_sections.
|
||||
Data_list special_output_list_;
|
||||
// The section headers.
|
||||
Output_section_headers* section_headers_;
|
||||
// A pointer to the PT_TLS segment if there is one.
|
||||
Output_segment* tls_segment_;
|
||||
// The SHT_SYMTAB output section.
|
||||
|
@ -554,7 +556,7 @@ class Write_symbols_task : public Task
|
|||
class Write_after_input_sections_task : public Task
|
||||
{
|
||||
public:
|
||||
Write_after_input_sections_task(const Layout* layout, Output_file* of,
|
||||
Write_after_input_sections_task(Layout* layout, Output_file* of,
|
||||
Task_token* input_sections_blocker,
|
||||
Task_token* final_blocker)
|
||||
: layout_(layout), of_(of),
|
||||
|
@ -580,7 +582,7 @@ class Write_after_input_sections_task : public Task
|
|||
private:
|
||||
class Write_sections_locker;
|
||||
|
||||
const Layout* layout_;
|
||||
Layout* layout_;
|
||||
Output_file* of_;
|
||||
Task_token* input_sections_blocker_;
|
||||
Task_token* final_blocker_;
|
||||
|
|
|
@ -428,7 +428,7 @@ Output_merge_data::do_add_input_section(Relobj* object, unsigned int shndx)
|
|||
// constants.
|
||||
|
||||
void
|
||||
Output_merge_data::do_set_address(uint64_t, off_t)
|
||||
Output_merge_data::set_final_data_size()
|
||||
{
|
||||
// Release the memory we don't need.
|
||||
this->p_ = static_cast<unsigned char*>(realloc(this->p_, this->len_));
|
||||
|
@ -502,7 +502,7 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
|
|||
|
||||
template<typename Char_type>
|
||||
void
|
||||
Output_merge_string<Char_type>::do_set_address(uint64_t, off_t)
|
||||
Output_merge_string<Char_type>::set_final_data_size()
|
||||
{
|
||||
this->stringpool_.set_string_offsets();
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ class Output_merge_data : public Output_merge_base
|
|||
|
||||
// Set the final data size.
|
||||
void
|
||||
do_set_address(uint64_t, off_t);
|
||||
set_final_data_size();
|
||||
|
||||
// Write the data to the file.
|
||||
void
|
||||
|
@ -215,7 +215,7 @@ class Output_merge_string : public Output_merge_base
|
|||
|
||||
// Set the final data size.
|
||||
void
|
||||
do_set_address(uint64_t, off_t);
|
||||
set_final_data_size();
|
||||
|
||||
// Write the data to the file.
|
||||
void
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace gold
|
|||
|
||||
// Output_data variables.
|
||||
|
||||
bool Output_data::sizes_are_fixed;
|
||||
bool Output_data::allocated_sizes_are_fixed;
|
||||
|
||||
// Output_data methods.
|
||||
|
||||
|
@ -51,18 +51,6 @@ Output_data::~Output_data()
|
|||
{
|
||||
}
|
||||
|
||||
// Set the address and offset.
|
||||
|
||||
void
|
||||
Output_data::set_address(uint64_t addr, off_t off)
|
||||
{
|
||||
this->address_ = addr;
|
||||
this->offset_ = off;
|
||||
|
||||
// Let the child class know.
|
||||
this->do_set_address(addr, off);
|
||||
}
|
||||
|
||||
// Return the default alignment for the target size.
|
||||
|
||||
uint64_t
|
||||
|
@ -335,6 +323,8 @@ Output_file_header::set_section_info(const Output_section_headers* shdrs,
|
|||
void
|
||||
Output_file_header::do_write(Output_file* of)
|
||||
{
|
||||
gold_assert(this->offset() == 0);
|
||||
|
||||
if (parameters->get_size() == 32)
|
||||
{
|
||||
if (parameters->is_big_endian())
|
||||
|
@ -491,11 +481,10 @@ Output_section_data::do_out_shndx() const
|
|||
|
||||
// Output_data_strtab methods.
|
||||
|
||||
// Set the address. We don't actually care about the address, but we
|
||||
// do set our final size.
|
||||
// Set the final data size.
|
||||
|
||||
void
|
||||
Output_data_strtab::do_set_address(uint64_t, off_t)
|
||||
Output_data_strtab::set_final_data_size()
|
||||
{
|
||||
this->strtab_->set_string_offsets();
|
||||
this->set_data_size(this->strtab_->get_strtab_size());
|
||||
|
@ -890,7 +879,7 @@ Output_data_dynamic::do_adjust_output_section(Output_section* os)
|
|||
// Set the final data size.
|
||||
|
||||
void
|
||||
Output_data_dynamic::do_set_address(uint64_t, off_t)
|
||||
Output_data_dynamic::set_final_data_size()
|
||||
{
|
||||
// Add the terminating entry.
|
||||
this->add_constant(elfcpp::DT_NULL, 0);
|
||||
|
@ -1003,7 +992,7 @@ Output_section::Input_section::set_address(uint64_t addr, off_t off,
|
|||
if (this->is_input_section())
|
||||
this->u2_.object->set_section_offset(this->shndx_, off - secoff);
|
||||
else
|
||||
this->u2_.posd->set_address(addr, off);
|
||||
this->u2_.posd->set_address_and_file_offset(addr, off);
|
||||
}
|
||||
|
||||
// Try to turn an input offset into an output offset.
|
||||
|
@ -1065,8 +1054,14 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
|
|||
needs_dynsym_index_(false),
|
||||
should_link_to_symtab_(false),
|
||||
should_link_to_dynsym_(false),
|
||||
after_input_sections_(false)
|
||||
after_input_sections_(false),
|
||||
requires_postprocessing_(false)
|
||||
{
|
||||
// An unallocated section has no address. Forcing this means that
|
||||
// we don't need special treatment for symbols defined in debug
|
||||
// sections.
|
||||
if ((flags & elfcpp::SHF_ALLOC) == 0)
|
||||
this->set_address(0);
|
||||
}
|
||||
|
||||
Output_section::~Output_section()
|
||||
|
@ -1139,7 +1134,7 @@ Output_section::add_input_section(Sized_relobj<size, big_endian>* object,
|
|||
}
|
||||
}
|
||||
|
||||
off_t offset_in_section = this->data_size();
|
||||
off_t offset_in_section = this->current_data_size_for_child();
|
||||
off_t aligned_offset_in_section = align_address(offset_in_section,
|
||||
addralign);
|
||||
|
||||
|
@ -1163,7 +1158,8 @@ Output_section::add_input_section(Sized_relobj<size, big_endian>* object,
|
|||
}
|
||||
}
|
||||
|
||||
this->set_data_size(aligned_offset_in_section + shdr.get_sh_size());
|
||||
this->set_current_data_size_for_child(aligned_offset_in_section
|
||||
+ shdr.get_sh_size());
|
||||
|
||||
// We need to keep track of this section if we are already keeping
|
||||
// track of sections, or if we are relaxing. FIXME: Add test for
|
||||
|
@ -1191,7 +1187,7 @@ void
|
|||
Output_section::add_output_section_data(Input_section* inp)
|
||||
{
|
||||
if (this->input_sections_.empty())
|
||||
this->first_input_offset_ = this->data_size();
|
||||
this->first_input_offset_ = this->current_data_size_for_child();
|
||||
|
||||
this->input_sections_.push_back(*inp);
|
||||
|
||||
|
@ -1344,15 +1340,20 @@ Output_section::output_address(const Relobj* object, unsigned int shndx,
|
|||
gold_unreachable();
|
||||
}
|
||||
|
||||
// Set the address of an Output_section. This is where we handle
|
||||
// Set the data size of an Output_section. This is where we handle
|
||||
// setting the addresses of any Output_section_data objects.
|
||||
|
||||
void
|
||||
Output_section::do_set_address(uint64_t address, off_t startoff)
|
||||
Output_section::set_final_data_size()
|
||||
{
|
||||
if (this->input_sections_.empty())
|
||||
return;
|
||||
{
|
||||
this->set_data_size(this->current_data_size_for_child());
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t address = this->address();
|
||||
off_t startoff = this->offset();
|
||||
off_t off = startoff + this->first_input_offset_;
|
||||
for (Input_section_list::iterator p = this->input_sections_.begin();
|
||||
p != this->input_sections_.end();
|
||||
|
@ -1664,7 +1665,7 @@ Output_segment::set_section_list_addresses(Output_data_list* pdl,
|
|||
++p)
|
||||
{
|
||||
off = align_address(off, (*p)->addralign());
|
||||
(*p)->set_address(addr + (off - startoff), off);
|
||||
(*p)->set_address_and_file_offset(addr + (off - startoff), off);
|
||||
|
||||
// Unless this is a PT_TLS segment, we want to ignore the size
|
||||
// of a SHF_TLS/SHT_NOBITS section. Such a section does not
|
||||
|
@ -1870,15 +1871,36 @@ Output_file::open(off_t file_size)
|
|||
gold_fatal(_("%s: open: %s"), this->name_, strerror(errno));
|
||||
this->o_ = o;
|
||||
|
||||
this->map();
|
||||
}
|
||||
|
||||
// Resize the output file.
|
||||
|
||||
void
|
||||
Output_file::resize(off_t file_size)
|
||||
{
|
||||
if (::munmap(this->base_, this->file_size_) < 0)
|
||||
gold_error(_("%s: munmap: %s"), this->name_, strerror(errno));
|
||||
this->file_size_ = file_size;
|
||||
this->map();
|
||||
}
|
||||
|
||||
// Map the file into memory.
|
||||
|
||||
void
|
||||
Output_file::map()
|
||||
{
|
||||
int o = this->o_;
|
||||
|
||||
// Write out one byte to make the file the right size.
|
||||
if (::lseek(o, file_size - 1, SEEK_SET) < 0)
|
||||
if (::lseek(o, this->file_size_ - 1, SEEK_SET) < 0)
|
||||
gold_fatal(_("%s: lseek: %s"), this->name_, strerror(errno));
|
||||
char b = 0;
|
||||
if (::write(o, &b, 1) != 1)
|
||||
gold_fatal(_("%s: write: %s"), this->name_, strerror(errno));
|
||||
|
||||
// Map the file into memory.
|
||||
void* base = ::mmap(NULL, file_size, PROT_READ | PROT_WRITE,
|
||||
void* base = ::mmap(NULL, this->file_size_, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, o, 0);
|
||||
if (base == MAP_FAILED)
|
||||
gold_fatal(_("%s: mmap: %s"), this->name_, strerror(errno));
|
||||
|
|
345
gold/output.h
345
gold/output.h
|
@ -49,32 +49,44 @@ class Sized_relobj;
|
|||
class Output_data
|
||||
{
|
||||
public:
|
||||
explicit Output_data(off_t data_size = 0)
|
||||
: address_(0), data_size_(data_size), offset_(-1),
|
||||
explicit Output_data()
|
||||
: address_(0), data_size_(0), offset_(-1),
|
||||
is_address_valid_(false), is_data_size_valid_(false),
|
||||
is_offset_valid_(false),
|
||||
dynamic_reloc_count_(0)
|
||||
{ }
|
||||
|
||||
virtual
|
||||
~Output_data();
|
||||
|
||||
// Return the address. This is only valid after Layout::finalize is
|
||||
// finished.
|
||||
// Return the address. For allocated sections, this is only valid
|
||||
// after Layout::finalize is finished.
|
||||
uint64_t
|
||||
address() const
|
||||
{ return this->address_; }
|
||||
{
|
||||
gold_assert(this->is_address_valid_);
|
||||
return this->address_;
|
||||
}
|
||||
|
||||
// Return the size of the data. This must be valid after
|
||||
// Layout::finalize calls set_address, but need not be valid before
|
||||
// then.
|
||||
// Return the size of the data. For allocated sections, this must
|
||||
// be valid after Layout::finalize calls set_address, but need not
|
||||
// be valid before then.
|
||||
off_t
|
||||
data_size() const
|
||||
{ return this->data_size_; }
|
||||
{
|
||||
gold_assert(this->is_data_size_valid_);
|
||||
return this->data_size_;
|
||||
}
|
||||
|
||||
// Return the file offset. This is only valid after
|
||||
// Layout::finalize is finished.
|
||||
// Layout::finalize is finished. For some non-allocated sections,
|
||||
// it may not be valid until near the end of the link.
|
||||
off_t
|
||||
offset() const
|
||||
{ return this->offset_; }
|
||||
{
|
||||
gold_assert(this->is_offset_valid_);
|
||||
return this->offset_;
|
||||
}
|
||||
|
||||
// Return the required alignment.
|
||||
uint64_t
|
||||
|
@ -107,10 +119,46 @@ class Output_data
|
|||
set_out_shndx(unsigned int shndx)
|
||||
{ this->do_set_out_shndx(shndx); }
|
||||
|
||||
// Set the address and file offset of this data. This is called
|
||||
// during Layout::finalize.
|
||||
// Set the address and file offset of this data, and finalize the
|
||||
// size of the data. This is called during Layout::finalize for
|
||||
// allocated sections.
|
||||
void
|
||||
set_address(uint64_t addr, off_t off);
|
||||
set_address_and_file_offset(uint64_t addr, off_t off)
|
||||
{
|
||||
this->set_address(addr);
|
||||
this->set_file_offset(off);
|
||||
this->finalize_data_size();
|
||||
}
|
||||
|
||||
// Set the address.
|
||||
void
|
||||
set_address(uint64_t addr)
|
||||
{
|
||||
gold_assert(!this->is_address_valid_);
|
||||
this->address_ = addr;
|
||||
this->is_address_valid_ = true;
|
||||
}
|
||||
|
||||
// Set the file offset.
|
||||
void
|
||||
set_file_offset(off_t off)
|
||||
{
|
||||
gold_assert(!this->is_offset_valid_);
|
||||
this->offset_ = off;
|
||||
this->is_offset_valid_ = true;
|
||||
}
|
||||
|
||||
// Finalize the data size.
|
||||
void
|
||||
finalize_data_size()
|
||||
{
|
||||
if (!this->is_data_size_valid_)
|
||||
{
|
||||
// Tell the child class to set the data size.
|
||||
this->set_final_data_size();
|
||||
gold_assert(this->is_data_size_valid_);
|
||||
}
|
||||
}
|
||||
|
||||
// Write the data to the output file. This is called after
|
||||
// Layout::finalize is complete.
|
||||
|
@ -118,16 +166,16 @@ class Output_data
|
|||
write(Output_file* file)
|
||||
{ this->do_write(file); }
|
||||
|
||||
// This is called by Layout::finalize to note that all sizes must
|
||||
// now be fixed.
|
||||
// This is called by Layout::finalize to note that the sizes of
|
||||
// allocated sections must now be fixed.
|
||||
static void
|
||||
layout_complete()
|
||||
{ Output_data::sizes_are_fixed = true; }
|
||||
{ Output_data::allocated_sizes_are_fixed = true; }
|
||||
|
||||
// Used to check that layout has been done.
|
||||
static bool
|
||||
is_layout_complete()
|
||||
{ return Output_data::sizes_are_fixed; }
|
||||
{ return Output_data::allocated_sizes_are_fixed; }
|
||||
|
||||
// Count the number of dynamic relocations applied to this section.
|
||||
void
|
||||
|
@ -177,20 +225,51 @@ class Output_data
|
|||
do_set_out_shndx(unsigned int)
|
||||
{ gold_unreachable(); }
|
||||
|
||||
// Set the address and file offset of the data. This only needs to
|
||||
// be implemented if the child needs to know. The child class can
|
||||
// set its size in this call.
|
||||
// This is a hook for derived classes to set the data size. This is
|
||||
// called by finalize_data_size, normally called during
|
||||
// Layout::finalize, when the section address is set.
|
||||
virtual void
|
||||
do_set_address(uint64_t, off_t)
|
||||
{ }
|
||||
set_final_data_size()
|
||||
{ gold_unreachable(); }
|
||||
|
||||
// Functions that child classes may call.
|
||||
|
||||
// Whether the address is valid.
|
||||
bool
|
||||
is_address_valid() const
|
||||
{ return this->is_address_valid_; }
|
||||
|
||||
// Whether the file offset is valid.
|
||||
bool
|
||||
is_offset_valid() const
|
||||
{ return this->is_offset_valid_; }
|
||||
|
||||
// Whether the data size is valid.
|
||||
bool
|
||||
is_data_size_valid() const
|
||||
{ return this->is_data_size_valid_; }
|
||||
|
||||
// Set the size of the data.
|
||||
void
|
||||
set_data_size(off_t data_size)
|
||||
{
|
||||
gold_assert(!Output_data::sizes_are_fixed);
|
||||
gold_assert(!this->is_data_size_valid_);
|
||||
this->data_size_ = data_size;
|
||||
this->is_data_size_valid_ = true;
|
||||
}
|
||||
|
||||
// Get the current data size--this is for the convenience of
|
||||
// sections which build up their size over time.
|
||||
off_t
|
||||
current_data_size_for_child() const
|
||||
{ return this->data_size_; }
|
||||
|
||||
// Set the current data size--this is for the convenience of
|
||||
// sections which build up their size over time.
|
||||
void
|
||||
set_current_data_size_for_child(off_t data_size)
|
||||
{
|
||||
gold_assert(!this->is_data_size_valid_);
|
||||
this->data_size_ = data_size;
|
||||
}
|
||||
|
||||
|
@ -207,15 +286,22 @@ class Output_data
|
|||
Output_data& operator=(const Output_data&);
|
||||
|
||||
// This is used for verification, to make sure that we don't try to
|
||||
// change any sizes after we set the section addresses.
|
||||
static bool sizes_are_fixed;
|
||||
// change any sizes of allocated sections after we set the section
|
||||
// addresses.
|
||||
static bool allocated_sizes_are_fixed;
|
||||
|
||||
// Memory address in file (not always meaningful).
|
||||
// Memory address in output file.
|
||||
uint64_t address_;
|
||||
// Size of data in file.
|
||||
// Size of data in output file.
|
||||
off_t data_size_;
|
||||
// Offset within file.
|
||||
// File offset of contents in output file.
|
||||
off_t offset_;
|
||||
// Whether address_ is valid.
|
||||
bool is_address_valid_;
|
||||
// Whether data_size_ is valid.
|
||||
bool is_data_size_valid_;
|
||||
// Whether offset_ is valid.
|
||||
bool is_offset_valid_;
|
||||
// Count of dynamic relocations applied to this section.
|
||||
unsigned int dynamic_reloc_count_;
|
||||
};
|
||||
|
@ -230,6 +316,7 @@ class Output_section_headers : public Output_data
|
|||
const Layout::Section_list*,
|
||||
const Stringpool*);
|
||||
|
||||
protected:
|
||||
// Write the data to the file.
|
||||
void
|
||||
do_write(Output_file*);
|
||||
|
@ -258,6 +345,7 @@ class Output_segment_headers : public Output_data
|
|||
public:
|
||||
Output_segment_headers(const Layout::Segment_list& segment_list);
|
||||
|
||||
protected:
|
||||
// Write the data to the file.
|
||||
void
|
||||
do_write(Output_file*);
|
||||
|
@ -290,6 +378,7 @@ class Output_file_header : public Output_data
|
|||
void set_section_info(const Output_section_headers*,
|
||||
const Output_section* shstrtab);
|
||||
|
||||
protected:
|
||||
// Write the data to the file.
|
||||
void
|
||||
do_write(Output_file*);
|
||||
|
@ -299,12 +388,6 @@ class Output_file_header : public Output_data
|
|||
do_addralign() const
|
||||
{ return Output_data::default_alignment(); }
|
||||
|
||||
// Set the address and offset--we only implement this for error
|
||||
// checking.
|
||||
void
|
||||
do_set_address(uint64_t, off_t off) const
|
||||
{ gold_assert(off == 0); }
|
||||
|
||||
private:
|
||||
// Write the data to the file with the right size and endianness.
|
||||
template<int size, bool big_endian>
|
||||
|
@ -327,11 +410,11 @@ class Output_section_data : public Output_data
|
|||
{
|
||||
public:
|
||||
Output_section_data(off_t data_size, uint64_t addralign)
|
||||
: Output_data(data_size), output_section_(NULL), addralign_(addralign)
|
||||
{ }
|
||||
: Output_data(), output_section_(NULL), addralign_(addralign)
|
||||
{ this->set_data_size(data_size); }
|
||||
|
||||
Output_section_data(uint64_t addralign)
|
||||
: Output_data(0), output_section_(NULL), addralign_(addralign)
|
||||
: Output_data(), output_section_(NULL), addralign_(addralign)
|
||||
{ }
|
||||
|
||||
// Return the output section.
|
||||
|
@ -401,6 +484,34 @@ class Output_section_data : public Output_data
|
|||
uint64_t addralign_;
|
||||
};
|
||||
|
||||
// Some Output_section_data classes build up their data step by step,
|
||||
// rather than all at once. This class provides an interface for
|
||||
// them.
|
||||
|
||||
class Output_section_data_build : public Output_section_data
|
||||
{
|
||||
public:
|
||||
Output_section_data_build(uint64_t addralign)
|
||||
: Output_section_data(addralign)
|
||||
{ }
|
||||
|
||||
// Get the current data size.
|
||||
off_t
|
||||
current_data_size() const
|
||||
{ return this->current_data_size_for_child(); }
|
||||
|
||||
// Set the current data size.
|
||||
void
|
||||
set_current_data_size(off_t data_size)
|
||||
{ this->set_current_data_size_for_child(data_size); }
|
||||
|
||||
protected:
|
||||
// Set the final data size.
|
||||
virtual void
|
||||
set_final_data_size()
|
||||
{ this->set_data_size(this->current_data_size_for_child()); }
|
||||
};
|
||||
|
||||
// A simple case of Output_data in which we have constant data to
|
||||
// output.
|
||||
|
||||
|
@ -420,14 +531,7 @@ class Output_data_const : public Output_section_data
|
|||
data_(reinterpret_cast<const char*>(p), len)
|
||||
{ }
|
||||
|
||||
// Add more data.
|
||||
void
|
||||
add_data(const std::string& add)
|
||||
{
|
||||
this->data_.append(add);
|
||||
this->set_data_size(this->data_.size());
|
||||
}
|
||||
|
||||
protected:
|
||||
// Write the data to the output file.
|
||||
void
|
||||
do_write(Output_file*);
|
||||
|
@ -447,6 +551,7 @@ class Output_data_const_buffer : public Output_section_data
|
|||
: Output_section_data(len, addralign), p_(p)
|
||||
{ }
|
||||
|
||||
protected:
|
||||
// Write the data the output file.
|
||||
void
|
||||
do_write(Output_file*);
|
||||
|
@ -455,30 +560,42 @@ class Output_data_const_buffer : public Output_section_data
|
|||
const unsigned char* p_;
|
||||
};
|
||||
|
||||
// A place holder for data written out via some other mechanism.
|
||||
// A place holder for a fixed amount of data written out via some
|
||||
// other mechanism.
|
||||
|
||||
class Output_data_space : public Output_section_data
|
||||
class Output_data_fixed_space : public Output_section_data
|
||||
{
|
||||
public:
|
||||
Output_data_space(off_t data_size, uint64_t addralign)
|
||||
Output_data_fixed_space(off_t data_size, uint64_t addralign)
|
||||
: Output_section_data(data_size, addralign)
|
||||
{ }
|
||||
|
||||
explicit Output_data_space(uint64_t addralign)
|
||||
: Output_section_data(addralign)
|
||||
{ }
|
||||
|
||||
// Set the size.
|
||||
protected:
|
||||
// Write out the data--the actual data must be written out
|
||||
// elsewhere.
|
||||
void
|
||||
set_space_size(off_t space_size)
|
||||
{ this->set_data_size(space_size); }
|
||||
do_write(Output_file*)
|
||||
{ }
|
||||
};
|
||||
|
||||
// A place holder for variable sized data written out via some other
|
||||
// mechanism.
|
||||
|
||||
class Output_data_space : public Output_section_data_build
|
||||
{
|
||||
public:
|
||||
explicit Output_data_space(uint64_t addralign)
|
||||
: Output_section_data_build(addralign)
|
||||
{ }
|
||||
|
||||
// Set the alignment.
|
||||
void
|
||||
set_space_alignment(uint64_t align)
|
||||
{ this->set_addralign(align); }
|
||||
|
||||
// Write out the data--this must be handled elsewhere.
|
||||
protected:
|
||||
// Write out the data--the actual data must be written out
|
||||
// elsewhere.
|
||||
void
|
||||
do_write(Output_file*)
|
||||
{ }
|
||||
|
@ -493,10 +610,11 @@ class Output_data_strtab : public Output_section_data
|
|||
: Output_section_data(1), strtab_(strtab)
|
||||
{ }
|
||||
|
||||
protected:
|
||||
// This is called to set the address and file offset. Here we make
|
||||
// sure that the Stringpool is finalized.
|
||||
void
|
||||
do_set_address(uint64_t, off_t);
|
||||
set_final_data_size();
|
||||
|
||||
// Write out the data.
|
||||
void
|
||||
|
@ -743,7 +861,7 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
|
|||
// the reloc type.
|
||||
|
||||
template<int sh_type, bool dynamic, int size, bool big_endian>
|
||||
class Output_data_reloc_base : public Output_section_data
|
||||
class Output_data_reloc_base : public Output_section_data_build
|
||||
{
|
||||
public:
|
||||
typedef Output_reloc<sh_type, dynamic, size, big_endian> Output_reloc_type;
|
||||
|
@ -753,14 +871,14 @@ class Output_data_reloc_base : public Output_section_data
|
|||
|
||||
// Construct the section.
|
||||
Output_data_reloc_base()
|
||||
: Output_section_data(Output_data::default_alignment_for_size(size))
|
||||
: Output_section_data_build(Output_data::default_alignment_for_size(size))
|
||||
{ }
|
||||
|
||||
protected:
|
||||
// Write out the data.
|
||||
void
|
||||
do_write(Output_file*);
|
||||
|
||||
protected:
|
||||
// Set the entry size and the link.
|
||||
void
|
||||
do_adjust_output_section(Output_section *os);
|
||||
|
@ -770,7 +888,7 @@ class Output_data_reloc_base : public Output_section_data
|
|||
add(Output_data *od, const Output_reloc_type& reloc)
|
||||
{
|
||||
this->relocs_.push_back(reloc);
|
||||
this->set_data_size(this->relocs_.size() * reloc_size);
|
||||
this->set_current_data_size(this->relocs_.size() * reloc_size);
|
||||
od->add_dynamic_reloc();
|
||||
}
|
||||
|
||||
|
@ -920,13 +1038,13 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
|
|||
// needed.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
class Output_data_got : public Output_section_data
|
||||
class Output_data_got : public Output_section_data_build
|
||||
{
|
||||
public:
|
||||
typedef typename elfcpp::Elf_types<size>::Elf_Addr Valtype;
|
||||
|
||||
Output_data_got()
|
||||
: Output_section_data(Output_data::default_alignment_for_size(size)),
|
||||
: Output_section_data_build(Output_data::default_alignment_for_size(size)),
|
||||
entries_()
|
||||
{ }
|
||||
|
||||
|
@ -964,6 +1082,7 @@ class Output_data_got : public Output_section_data
|
|||
return this->last_got_offset();
|
||||
}
|
||||
|
||||
protected:
|
||||
// Write out the GOT table.
|
||||
void
|
||||
do_write(Output_file*);
|
||||
|
@ -1039,7 +1158,7 @@ class Output_data_got : public Output_section_data
|
|||
// Set the size of the section.
|
||||
void
|
||||
set_got_size()
|
||||
{ this->set_data_size(this->got_offset(this->entries_.size())); }
|
||||
{ this->set_current_data_size(this->got_offset(this->entries_.size())); }
|
||||
|
||||
// The list of GOT entries.
|
||||
Got_entries entries_;
|
||||
|
@ -1085,19 +1204,19 @@ class Output_data_dynamic : public Output_section_data
|
|||
add_string(elfcpp::DT tag, const std::string& str)
|
||||
{ this->add_string(tag, str.c_str()); }
|
||||
|
||||
// Set the final data size.
|
||||
void
|
||||
do_set_address(uint64_t, off_t);
|
||||
|
||||
// Write out the dynamic entries.
|
||||
void
|
||||
do_write(Output_file*);
|
||||
|
||||
protected:
|
||||
// Adjust the output section to set the entry size.
|
||||
void
|
||||
do_adjust_output_section(Output_section*);
|
||||
|
||||
// Set the final data size.
|
||||
void
|
||||
set_final_data_size();
|
||||
|
||||
// Write out the dynamic entries.
|
||||
void
|
||||
do_write(Output_file*);
|
||||
|
||||
private:
|
||||
// This POD class holds a single dynamic entry.
|
||||
class Dynamic_entry
|
||||
|
@ -1222,22 +1341,6 @@ class Output_section : public Output_data
|
|||
flags() const
|
||||
{ return this->flags_; }
|
||||
|
||||
// Return the section index in the output file.
|
||||
unsigned int
|
||||
do_out_shndx() const
|
||||
{
|
||||
gold_assert(this->out_shndx_ != -1U);
|
||||
return this->out_shndx_;
|
||||
}
|
||||
|
||||
// Set the output section index.
|
||||
void
|
||||
do_set_out_shndx(unsigned int shndx)
|
||||
{
|
||||
gold_assert(this->out_shndx_ == -1U);
|
||||
this->out_shndx_ = shndx;
|
||||
}
|
||||
|
||||
// Return the entsize field.
|
||||
uint64_t
|
||||
entsize() const
|
||||
|
@ -1380,6 +1483,18 @@ class Output_section : public Output_data
|
|||
set_after_input_sections()
|
||||
{ this->after_input_sections_ = true; }
|
||||
|
||||
// Return whether this section requires postprocessing after all
|
||||
// relocations have been applied.
|
||||
bool
|
||||
requires_postprocessing() const
|
||||
{ return this->requires_postprocessing_; }
|
||||
|
||||
// Record that this section requires postprocessing after all
|
||||
// relocations have been applied.
|
||||
void
|
||||
set_requires_postprocessing()
|
||||
{ this->requires_postprocessing_ = true; }
|
||||
|
||||
// Return whether the offset OFFSET in the input section SHNDX in
|
||||
// object OBJECT is being included in the link.
|
||||
bool
|
||||
|
@ -1397,12 +1512,35 @@ class Output_section : public Output_data
|
|||
output_address(const Relobj* object, unsigned int shndx,
|
||||
off_t offset) const;
|
||||
|
||||
// Set the address of the Output_section. For a typical
|
||||
// Write the section header into *OPHDR.
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
write_header(const Layout*, const Stringpool*,
|
||||
elfcpp::Shdr_write<size, big_endian>*) const;
|
||||
|
||||
protected:
|
||||
// Return the section index in the output file.
|
||||
unsigned int
|
||||
do_out_shndx() const
|
||||
{
|
||||
gold_assert(this->out_shndx_ != -1U);
|
||||
return this->out_shndx_;
|
||||
}
|
||||
|
||||
// Set the output section index.
|
||||
void
|
||||
do_set_out_shndx(unsigned int shndx)
|
||||
{
|
||||
gold_assert(this->out_shndx_ == -1U);
|
||||
this->out_shndx_ = shndx;
|
||||
}
|
||||
|
||||
// Set the final data size of the Output_section. For a typical
|
||||
// Output_section, there is nothing to do, but if there are any
|
||||
// Output_section_data objects we need to set the final addresses
|
||||
// Output_section_data objects we need to set their final addresses
|
||||
// here.
|
||||
void
|
||||
do_set_address(uint64_t, off_t);
|
||||
set_final_data_size();
|
||||
|
||||
// Write the data to the file. For a typical Output_section, this
|
||||
// does nothing: the data is written out by calling Object::Relocate
|
||||
|
@ -1431,12 +1569,6 @@ class Output_section : public Output_data
|
|||
do_is_section_flag_set(elfcpp::Elf_Xword flag) const
|
||||
{ return (this->flags_ & flag) != 0; }
|
||||
|
||||
// Write the section header into *OPHDR.
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
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
|
||||
// associated with this output section. We only need the list if we
|
||||
|
@ -1658,7 +1790,7 @@ class Output_section : public Output_data
|
|||
// Most of these fields are only valid after layout.
|
||||
|
||||
// The name of the section. This will point into a Stringpool.
|
||||
const char* name_;
|
||||
const char* const name_;
|
||||
// The section address is in the parent class.
|
||||
// The section alignment.
|
||||
uint64_t addralign_;
|
||||
|
@ -1674,9 +1806,9 @@ class Output_section : public Output_data
|
|||
// If info_section_ is NULL, this is the section info field.
|
||||
unsigned int info_;
|
||||
// The section type.
|
||||
elfcpp::Elf_Word type_;
|
||||
const elfcpp::Elf_Word type_;
|
||||
// The section flags.
|
||||
elfcpp::Elf_Xword flags_;
|
||||
const elfcpp::Elf_Xword flags_;
|
||||
// The section index.
|
||||
unsigned int out_shndx_;
|
||||
// If there is a STT_SECTION for this output section in the normal
|
||||
|
@ -1715,6 +1847,9 @@ class Output_section : public Output_data
|
|||
// Whether this section should be written after all the input
|
||||
// sections are complete.
|
||||
bool after_input_sections_ : 1;
|
||||
// Whether this section requires post processing after all
|
||||
// relocations have been applied.
|
||||
bool requires_postprocessing_ : 1;
|
||||
};
|
||||
|
||||
// An output segment. PT_LOAD segments are built from collections of
|
||||
|
@ -1895,6 +2030,10 @@ class Output_file
|
|||
void
|
||||
open(off_t file_size);
|
||||
|
||||
// Resize the output file.
|
||||
void
|
||||
resize(off_t file_size);
|
||||
|
||||
// Close the output file and make sure there are no error.
|
||||
void
|
||||
close();
|
||||
|
@ -1945,6 +2084,10 @@ class Output_file
|
|||
{ }
|
||||
|
||||
private:
|
||||
// Map the file into memory.
|
||||
void
|
||||
map();
|
||||
|
||||
// General options.
|
||||
const General_options& options_;
|
||||
// Target.
|
||||
|
|
|
@ -332,7 +332,7 @@ Target_x86_64::got_section(Symbol_table* symtab, Layout* layout)
|
|||
this->got_plt_);
|
||||
|
||||
// The first three entries are reserved.
|
||||
this->got_plt_->set_space_size(3 * 8);
|
||||
this->got_plt_->set_current_data_size(3 * 8);
|
||||
|
||||
// Define _GLOBAL_OFFSET_TABLE_ at the start of the PLT.
|
||||
symtab->define_in_output_data(this, "_GLOBAL_OFFSET_TABLE_", NULL,
|
||||
|
@ -397,7 +397,7 @@ class Output_data_plt_x86_64 : public Output_section_data
|
|||
|
||||
// Set the final size.
|
||||
void
|
||||
do_set_address(uint64_t, off_t)
|
||||
set_final_data_size()
|
||||
{ this->set_data_size((this->count_ + 1) * plt_entry_size); }
|
||||
|
||||
// Write out the PLT data.
|
||||
|
@ -446,12 +446,12 @@ Output_data_plt_x86_64::add_entry(Symbol* gsym)
|
|||
|
||||
++this->count_;
|
||||
|
||||
off_t got_offset = this->got_plt_->data_size();
|
||||
off_t got_offset = this->got_plt_->current_data_size();
|
||||
|
||||
// Every PLT entry needs a GOT entry which points back to the PLT
|
||||
// entry (this will be changed by the dynamic linker, normally
|
||||
// lazily when the function is called).
|
||||
this->got_plt_->set_space_size(got_offset + 8);
|
||||
this->got_plt_->set_current_data_size(got_offset + 8);
|
||||
|
||||
// Every PLT entry needs a reloc.
|
||||
gsym->set_needs_dynsym_entry();
|
||||
|
@ -654,10 +654,10 @@ Target_x86_64::copy_reloc(const General_options* options,
|
|||
if (align > dynbss->addralign())
|
||||
dynbss->set_space_alignment(align);
|
||||
|
||||
off_t dynbss_size = dynbss->data_size();
|
||||
off_t dynbss_size = dynbss->current_data_size();
|
||||
dynbss_size = align_address(dynbss_size, align);
|
||||
off_t offset = dynbss_size;
|
||||
dynbss->set_space_size(dynbss_size + symsize);
|
||||
dynbss->set_current_data_size(dynbss_size + symsize);
|
||||
|
||||
symtab->define_with_copy_reloc(this, ssym, dynbss, offset);
|
||||
|
||||
|
|
Loading…
Reference in a new issue