aboutsummaryrefslogtreecommitdiff
path: root/gold/layout.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2008-02-04 06:45:50 +0000
committerIan Lance Taylor <iant@google.com>2008-02-04 06:45:50 +0000
commit3802b2dd6b937e2904b6e2de087e224437eab493 (patch)
treeac185197a2a44c92c3785020c2ce1e389f2b0287 /gold/layout.cc
parentae7d22a6f2f59251b85ef5655b800f2dfe2dfbee (diff)
downloadgdb-3802b2dd6b937e2904b6e2de087e224437eab493.zip
gdb-3802b2dd6b937e2904b6e2de087e224437eab493.tar.gz
gdb-3802b2dd6b937e2904b6e2de087e224437eab493.tar.bz2
Implement SIZEOF_HEADERS, section constraints, other minor linker
script items.
Diffstat (limited to 'gold/layout.cc')
-rw-r--r--gold/layout.cc143
1 files changed, 78 insertions, 65 deletions
diff --git a/gold/layout.cc b/gold/layout.cc
index a0fcc49..1e597ac 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -397,9 +397,9 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object,
hdr_os->set_after_input_sections();
- Output_segment* hdr_oseg =
- new Output_segment(elfcpp::PT_GNU_EH_FRAME, elfcpp::PF_R);
- this->segment_list_.push_back(hdr_oseg);
+ Output_segment* hdr_oseg;
+ hdr_oseg = this->make_output_segment(elfcpp::PT_GNU_EH_FRAME,
+ elfcpp::PF_R);
hdr_oseg->add_output_section(hdr_os, elfcpp::PF_R);
this->eh_frame_data_->set_eh_frame_hdr(hdr_posd);
@@ -523,9 +523,8 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
if (p == this->segment_list_.end())
{
- Output_segment* oseg = new Output_segment(elfcpp::PT_LOAD,
- seg_flags);
- this->segment_list_.push_back(oseg);
+ Output_segment* oseg = this->make_output_segment(elfcpp::PT_LOAD,
+ seg_flags);
oseg->add_output_section(os, seg_flags);
}
@@ -549,9 +548,8 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
if (p == this->segment_list_.end())
{
- Output_segment* oseg = new Output_segment(elfcpp::PT_NOTE,
- seg_flags);
- this->segment_list_.push_back(oseg);
+ Output_segment* oseg = this->make_output_segment(elfcpp::PT_NOTE,
+ seg_flags);
oseg->add_output_section(os, seg_flags);
}
}
@@ -561,11 +559,8 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
if ((flags & elfcpp::SHF_TLS) != 0)
{
if (this->tls_segment_ == NULL)
- {
- this->tls_segment_ = new Output_segment(elfcpp::PT_TLS,
- seg_flags);
- this->segment_list_.push_back(this->tls_segment_);
- }
+ this->tls_segment_ = this->make_output_segment(elfcpp::PT_TLS,
+ seg_flags);
this->tls_segment_->add_output_section(os, seg_flags);
}
}
@@ -573,6 +568,27 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
return os;
}
+// Return the number of segments we expect to see.
+
+size_t
+Layout::expected_segment_count() const
+{
+ size_t ret = this->segment_list_.size();
+
+ // If we didn't see a SECTIONS clause in a linker script, we should
+ // already have the complete list of segments. Otherwise we ask the
+ // SECTIONS clause how many segments it expects, and add in the ones
+ // we already have (PT_GNU_STACK, PT_GNU_EH_FRAME, etc.)
+
+ if (!this->script_options_->saw_sections_clause())
+ return ret;
+ else
+ {
+ const Script_sections* ss = this->script_options_->script_sections();
+ return ret + ss->expected_segment_count(this);
+ }
+}
+
// Handle the .note.GNU-stack section at layout time. SEEN_GNU_STACK
// is whether we saw a .note.GNU-stack section in the object file.
// GNU_STACK_FLAGS is the section flags. The flags give the
@@ -603,11 +619,11 @@ Layout::create_initial_dynamic_sections(Symbol_table* symtab)
if (parameters->doing_static_link())
return;
- const char* dynamic_name = this->namepool_.add(".dynamic", false, NULL);
- this->dynamic_section_ = this->make_output_section(dynamic_name,
- elfcpp::SHT_DYNAMIC,
- (elfcpp::SHF_ALLOC
- | elfcpp::SHF_WRITE));
+ this->dynamic_section_ = this->choose_output_section(NULL, ".dynamic",
+ elfcpp::SHT_DYNAMIC,
+ (elfcpp::SHF_ALLOC
+ | elfcpp::SHF_WRITE),
+ false);
symtab->define_in_output_data("_DYNAMIC", NULL, this->dynamic_section_, 0, 0,
elfcpp::STT_OBJECT, elfcpp::STB_LOCAL,
@@ -684,8 +700,8 @@ Layout::find_first_load_seg()
return *p;
}
- Output_segment* load_seg = new Output_segment(elfcpp::PT_LOAD, elfcpp::PF_R);
- this->segment_list_.push_back(load_seg);
+ Output_segment* load_seg = this->make_output_segment(elfcpp::PT_LOAD,
+ elfcpp::PF_R);
return load_seg;
}
@@ -734,11 +750,16 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
this->create_gold_note();
this->create_executable_stack_info(target);
+ Output_segment* phdr_seg = NULL;
if (!parameters->output_is_object() && !parameters->doing_static_link())
{
// There was a dynamic object in the link. We need to create
// some information for the dynamic linker.
+ // Create the PT_PHDR segment which will hold the program
+ // headers.
+ phdr_seg = this->make_output_segment(elfcpp::PT_PHDR, elfcpp::PF_R);
+
// Create the dynamic symbol table, including the hash table.
Output_section* dynstr;
std::vector<Symbol*> dynamic_symbols;
@@ -775,16 +796,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
else
load_seg = this->find_first_load_seg();
- Output_segment* phdr_seg = NULL;
- if (load_seg != NULL
- && !parameters->output_is_object()
- && !parameters->doing_static_link())
- {
- // Create the PT_PHDR segment which will hold the program
- // headers.
- phdr_seg = new Output_segment(elfcpp::PT_PHDR, elfcpp::PF_R);
- this->segment_list_.push_back(phdr_seg);
- }
+ gold_assert(phdr_seg == NULL || load_seg != NULL);
// Lay out the segment headers.
Output_segment_headers* segment_headers;
@@ -988,8 +1000,7 @@ Layout::create_executable_stack_info(const Target* target)
int flags = elfcpp::PF_R | elfcpp::PF_W;
if (is_stack_executable)
flags |= elfcpp::PF_X;
- Output_segment* oseg = new Output_segment(elfcpp::PT_GNU_STACK, flags);
- this->segment_list_.push_back(oseg);
+ this->make_output_segment(elfcpp::PT_GNU_STACK, flags);
}
}
@@ -1591,10 +1602,10 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects,
// Create the dynamic symbol table section.
- const char* dynsym_name = this->namepool_.add(".dynsym", false, NULL);
- Output_section* dynsym = this->make_output_section(dynsym_name,
- elfcpp::SHT_DYNSYM,
- elfcpp::SHF_ALLOC);
+ Output_section* dynsym = this->choose_output_section(NULL, ".dynsym",
+ elfcpp::SHT_DYNSYM,
+ elfcpp::SHF_ALLOC,
+ false);
Output_section_data* odata = new Output_data_fixed_space(index * symsize,
align);
@@ -1612,10 +1623,10 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects,
// Create the dynamic string table section.
- const char* dynstr_name = this->namepool_.add(".dynstr", false, NULL);
- Output_section* dynstr = this->make_output_section(dynstr_name,
- elfcpp::SHT_STRTAB,
- elfcpp::SHF_ALLOC);
+ Output_section* dynstr = this->choose_output_section(NULL, ".dynstr",
+ elfcpp::SHT_STRTAB,
+ elfcpp::SHF_ALLOC,
+ false);
Output_section_data* strdata = new Output_data_strtab(&this->dynpool_);
dynstr->add_output_section_data(strdata);
@@ -1637,10 +1648,10 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects,
Dynobj::create_elf_hash_table(*pdynamic_symbols, local_symcount,
&phash, &hashlen);
- const char* hash_name = this->namepool_.add(".hash", false, NULL);
- Output_section* hashsec = this->make_output_section(hash_name,
- elfcpp::SHT_HASH,
- elfcpp::SHF_ALLOC);
+ Output_section* hashsec = this->choose_output_section(NULL, ".hash",
+ elfcpp::SHT_HASH,
+ elfcpp::SHF_ALLOC,
+ false);
Output_section_data* hashdata = new Output_data_const_buffer(phash,
hashlen,
@@ -1753,10 +1764,10 @@ Layout::sized_create_version_sections(
const Output_section* dynstr
ACCEPT_SIZE_ENDIAN)
{
- const char* vname = this->namepool_.add(".gnu.version", false, NULL);
- Output_section* vsec = this->make_output_section(vname,
- elfcpp::SHT_GNU_versym,
- elfcpp::SHF_ALLOC);
+ Output_section* vsec = this->choose_output_section(NULL, ".gnu.version",
+ elfcpp::SHT_GNU_versym,
+ elfcpp::SHF_ALLOC,
+ false);
unsigned char* vbuf;
unsigned int vsize;
@@ -1775,10 +1786,11 @@ Layout::sized_create_version_sections(
if (versions->any_defs())
{
- const char* vdname = this->namepool_.add(".gnu.version_d", false, NULL);
- Output_section *vdsec;
- vdsec = this->make_output_section(vdname, elfcpp::SHT_GNU_verdef,
- elfcpp::SHF_ALLOC);
+ Output_section* vdsec;
+ vdsec= this->choose_output_section(NULL, ".gnu.version_d",
+ elfcpp::SHT_GNU_verdef,
+ elfcpp::SHF_ALLOC,
+ false);
unsigned char* vdbuf;
unsigned int vdsize;
@@ -1801,10 +1813,11 @@ Layout::sized_create_version_sections(
if (versions->any_needs())
{
- const char* vnname = this->namepool_.add(".gnu.version_r", false, NULL);
Output_section* vnsec;
- vnsec = this->make_output_section(vnname, elfcpp::SHT_GNU_verneed,
- elfcpp::SHF_ALLOC);
+ vnsec = this->choose_output_section(NULL, ".gnu.version_r",
+ elfcpp::SHT_GNU_verneed,
+ elfcpp::SHF_ALLOC,
+ false);
unsigned char* vnbuf;
unsigned int vnsize;
@@ -1842,14 +1855,14 @@ Layout::create_interp(const Target* target)
Output_section_data* odata = new Output_data_const(interp, len, 1);
- const char* interp_name = this->namepool_.add(".interp", false, NULL);
- Output_section* osec = this->make_output_section(interp_name,
- elfcpp::SHT_PROGBITS,
- elfcpp::SHF_ALLOC);
+ Output_section* osec = this->choose_output_section(NULL, ".interp",
+ elfcpp::SHT_PROGBITS,
+ elfcpp::SHF_ALLOC,
+ false);
osec->add_output_section_data(odata);
- Output_segment* oseg = new Output_segment(elfcpp::PT_INTERP, elfcpp::PF_R);
- this->segment_list_.push_back(oseg);
+ Output_segment* oseg = this->make_output_segment(elfcpp::PT_INTERP,
+ elfcpp::PF_R);
oseg->add_initial_output_section(osec, elfcpp::PF_R);
}
@@ -1859,9 +1872,9 @@ void
Layout::finish_dynamic_section(const Input_objects* input_objects,
const Symbol_table* symtab)
{
- Output_segment* oseg = new Output_segment(elfcpp::PT_DYNAMIC,
- elfcpp::PF_R | elfcpp::PF_W);
- this->segment_list_.push_back(oseg);
+ Output_segment* oseg = this->make_output_segment(elfcpp::PT_DYNAMIC,
+ (elfcpp::PF_R
+ | elfcpp::PF_W));
oseg->add_initial_output_section(this->dynamic_section_,
elfcpp::PF_R | elfcpp::PF_W);