aboutsummaryrefslogtreecommitdiff
path: root/gold/output.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>2010-08-03 14:07:13 +0000
committerIan Lance Taylor <ian@airs.com>2010-08-03 14:07:13 +0000
commit22f0da72ea2fc99e409548ce883b751aa822c2c3 (patch)
tree29f8b535bf96223cf9150606e977ff8ef924a8c6 /gold/output.cc
parente4d9f07834de9797e18e4810d985764a23c00dcc (diff)
downloadgdb-22f0da72ea2fc99e409548ce883b751aa822c2c3.zip
gdb-22f0da72ea2fc99e409548ce883b751aa822c2c3.tar.gz
gdb-22f0da72ea2fc99e409548ce883b751aa822c2c3.tar.bz2
2010-08-03 Ian Lance Taylor <iant@google.com>
PR 11805 * layout.h (enum Output_section_order): Define. (class Layout): Update declarations. * layout.cc (Layout::get_output_section): Add order parameter. Remove is_interp, is_dynamic_linker_section, is_last_relro, and is_first_non_relro parameters. Change all callers. (Layout::choose_output_section): Likewise. (Layout::add_output_section_data): Likewise. (Layout::make_output_section): Likewise. Set order. (Layout::default_section_order): New function. (Layout::layout_eh_frame): Call add_output_section_to_nonload. * output.cc (Output_section::Output_section): Initialize order_. Don't initialize deleted fields. (Output_segment::Output_segment): Don't initialize deleted fields. (Output_segment::add_output_section_to_load): New function replacing add_output_section. Change all callers to call this or add_output_section_to_nonload. (Output_segment::add_output_section_to_nonload): New function. (Output_segment::remove_output_section): Rewrite. (Output_segment::add_initial_output_data): Likewise. (Output_segment::has_any_data_sections): Likewise. (Output_segment::is_first_section_relro): Likewise. (Output_segment::maximum_alignment): Likewise. (Output_segment::has_dynamic_reloc): New function replacing dynamic_reloc_count. Change all callers. (Output_segment::has_dynamic_reloc_list): New function replacing dynamic_reloc_count_list. Change all callers. (Output_segment::set_section_addresses): Rewrite. (Output_segment::set_offset): Rewrite. (Output_segment::find_first_and_last_list): Remove. (Output_segment::set_tls_offsets): Rewrite. (Output_segment::first_section_load_address): Likewise. (Output_segment::output_section_count): Likewise. (Output_segment::section_with_lowest_load_address): Likewise. (Output_segment::write_section_headers): Likewise. (Output_segment::print_sections_to_map): Likewise. * output.h (class Output_data): Remove dynamic_reloc_count_ field. Add has_dynamic_reloc_ field. Make bools into bitfields. (Output_data::add_dynamic_reloc): Rewrite. (Output_data::has_dynamic_reloc): New function. (Output_data::dynamic_reloc_count): Remove. (class Output_section): Add order_ field. Remvoe is_relro_local_, is_last_relro_, is_first_non_relro_, is_interp_, is_dynamic_linker_section_ fields. Add order and set_order functions. Remove is_relro_local, set_is_relro_local, is_last_relro, set_is_last_relro, is_first_non_relro, set_is_first_non_relro functions, is_interp, set_is_interp, is_dynamic_linker_section, and set_is_dynamic_linker_section functions. (class Output_segment): Change Output_data_list from std::list to std:;vector. Add output_lists_ field. Remove output_data_ and output_bss_ fields. Update declarations.
Diffstat (limited to 'gold/output.cc')
-rw-r--r--gold/output.cc588
1 files changed, 187 insertions, 401 deletions
diff --git a/gold/output.cc b/gold/output.cc
index 506edf7..55080a1 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -1917,6 +1917,7 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
info_(0),
type_(type),
flags_(flags),
+ order_(ORDER_INVALID),
out_shndx_(-1U),
symtab_index_(0),
dynsym_index_(0),
@@ -1938,13 +1939,8 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
must_sort_attached_input_sections_(false),
attached_input_sections_are_sorted_(false),
is_relro_(false),
- is_relro_local_(false),
- is_last_relro_(false),
- is_first_non_relro_(false),
is_small_section_(false),
is_large_section_(false),
- is_interp_(false),
- is_dynamic_linker_section_(false),
generate_code_fills_at_write_(false),
is_entsize_zero_(false),
section_offsets_need_adjustment_(false),
@@ -3409,9 +3405,7 @@ Output_section::print_merge_stats()
// Output segment methods.
Output_segment::Output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags)
- : output_data_(),
- output_bss_(),
- vaddr_(0),
+ : vaddr_(0),
paddr_(0),
memsz_(0),
max_align_(0),
@@ -3430,293 +3424,64 @@ Output_segment::Output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags)
this->flags_ = elfcpp::PF_R;
}
-// Add an Output_section to an Output_segment.
+// Add an Output_section to a PT_LOAD Output_segment.
void
-Output_segment::add_output_section(Output_section* os,
- elfcpp::Elf_Word seg_flags,
- bool do_sort)
+Output_segment::add_output_section_to_load(Layout* layout,
+ Output_section* os,
+ elfcpp::Elf_Word seg_flags)
{
+ gold_assert(this->type() == elfcpp::PT_LOAD);
gold_assert((os->flags() & elfcpp::SHF_ALLOC) != 0);
gold_assert(!this->is_max_align_known_);
gold_assert(os->is_large_data_section() == this->is_large_data_segment());
- gold_assert(this->type() == elfcpp::PT_LOAD || !do_sort);
this->update_flags_for_output_section(seg_flags);
- Output_segment::Output_data_list* pdl;
- if (os->type() == elfcpp::SHT_NOBITS)
- pdl = &this->output_bss_;
+ // We don't want to change the ordering if we have a linker script
+ // with a SECTIONS clause.
+ Output_section_order order = os->order();
+ if (layout->script_options()->saw_sections_clause())
+ order = static_cast<Output_section_order>(0);
else
- pdl = &this->output_data_;
+ gold_assert(order != ORDER_INVALID);
- // Note that while there may be many input sections in an output
- // section, there are normally only a few output sections in an
- // output segment. The loops below are expected to be fast.
-
- // So that PT_NOTE segments will work correctly, we need to ensure
- // that all SHT_NOTE sections are adjacent.
- if (os->type() == elfcpp::SHT_NOTE && !pdl->empty())
- {
- Output_segment::Output_data_list::iterator p = pdl->end();
- do
- {
- --p;
- if ((*p)->is_section_type(elfcpp::SHT_NOTE))
- {
- ++p;
- pdl->insert(p, os);
- return;
- }
- }
- while (p != pdl->begin());
- }
-
- // Similarly, so that PT_TLS segments will work, we need to group
- // SHF_TLS sections. An SHF_TLS/SHT_NOBITS section is a special
- // case: we group the SHF_TLS/SHT_NOBITS sections right after the
- // SHF_TLS/SHT_PROGBITS sections. This lets us set up PT_TLS
- // correctly. SHF_TLS sections get added to both a PT_LOAD segment
- // and the PT_TLS segment; we do this grouping only for the PT_LOAD
- // segment.
- if (this->type_ != elfcpp::PT_TLS
- && (os->flags() & elfcpp::SHF_TLS) != 0)
- {
- pdl = &this->output_data_;
- if (!pdl->empty())
- {
- bool nobits = os->type() == elfcpp::SHT_NOBITS;
- bool sawtls = false;
- Output_segment::Output_data_list::iterator p = pdl->end();
- gold_assert(p != pdl->begin());
- do
- {
- --p;
- bool insert;
- if ((*p)->is_section_flag_set(elfcpp::SHF_TLS))
- {
- sawtls = true;
- // Put a NOBITS section after the first TLS section.
- // Put a PROGBITS section after the first
- // TLS/PROGBITS section.
- insert = nobits || !(*p)->is_section_type(elfcpp::SHT_NOBITS);
- }
- else
- {
- // If we've gone past the TLS sections, but we've
- // seen a TLS section, then we need to insert this
- // section now.
- insert = sawtls;
- }
-
- if (insert)
- {
- ++p;
- pdl->insert(p, os);
- return;
- }
- }
- while (p != pdl->begin());
- }
-
- // There are no TLS sections yet; put this one at the requested
- // location in the section list.
- }
-
- if (do_sort)
- {
- // For the PT_GNU_RELRO segment, we need to group relro
- // sections, and we need to put them before any non-relro
- // sections. Any relro local sections go before relro non-local
- // sections. One section may be marked as the last relro
- // section.
- if (os->is_relro())
- {
- gold_assert(pdl == &this->output_data_);
- Output_segment::Output_data_list::iterator p;
- for (p = pdl->begin(); p != pdl->end(); ++p)
- {
- if (!(*p)->is_section())
- break;
-
- Output_section* pos = (*p)->output_section();
- if (!pos->is_relro()
- || (os->is_relro_local() && !pos->is_relro_local())
- || (!os->is_last_relro() && pos->is_last_relro()))
- break;
- }
-
- pdl->insert(p, os);
- return;
- }
+ this->output_lists_[order].push_back(os);
+}
- // One section may be marked as the first section which follows
- // the relro sections.
- if (os->is_first_non_relro())
- {
- gold_assert(pdl == &this->output_data_);
- Output_segment::Output_data_list::iterator p;
- for (p = pdl->begin(); p != pdl->end(); ++p)
- {
- if (!(*p)->is_section())
- break;
+// Add an Output_section to a non-PT_LOAD Output_segment.
- Output_section* pos = (*p)->output_section();
- if (!pos->is_relro())
- break;
- }
+void
+Output_segment::add_output_section_to_nonload(Output_section* os,
+ elfcpp::Elf_Word seg_flags)
+{
+ gold_assert(this->type() != elfcpp::PT_LOAD);
+ gold_assert((os->flags() & elfcpp::SHF_ALLOC) != 0);
+ gold_assert(!this->is_max_align_known_);
- pdl->insert(p, os);
- return;
- }
- }
+ this->update_flags_for_output_section(seg_flags);
- // Small data sections go at the end of the list of data sections.
- // If OS is not small, and there are small sections, we have to
- // insert it before the first small section.
- if (os->type() != elfcpp::SHT_NOBITS
- && !os->is_small_section()
- && !pdl->empty()
- && pdl->back()->is_section()
- && pdl->back()->output_section()->is_small_section())
- {
- for (Output_segment::Output_data_list::iterator p = pdl->begin();
- p != pdl->end();
- ++p)
- {
- if ((*p)->is_section()
- && (*p)->output_section()->is_small_section())
- {
- pdl->insert(p, os);
- return;
- }
- }
- gold_unreachable();
- }
+ this->output_lists_[0].push_back(os);
+}
- // A small BSS section goes at the start of the BSS sections, after
- // other small BSS sections.
- if (os->type() == elfcpp::SHT_NOBITS && os->is_small_section())
- {
- for (Output_segment::Output_data_list::iterator p = pdl->begin();
- p != pdl->end();
- ++p)
- {
- if (!(*p)->is_section()
- || !(*p)->output_section()->is_small_section())
- {
- pdl->insert(p, os);
- return;
- }
- }
- }
+// Remove an Output_section from this segment. It is an error if it
+// is not present.
- // A large BSS section goes at the end of the BSS sections, which
- // means that one that is not large must come before the first large
- // one.
- if (os->type() == elfcpp::SHT_NOBITS
- && !os->is_large_section()
- && !pdl->empty()
- && pdl->back()->is_section()
- && pdl->back()->output_section()->is_large_section())
+void
+Output_segment::remove_output_section(Output_section* os)
+{
+ for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
{
- for (Output_segment::Output_data_list::iterator p = pdl->begin();
- p != pdl->end();
- ++p)
+ Output_data_list* pdl = &this->output_lists_[i];
+ for (Output_data_list::iterator p = pdl->begin(); p != pdl->end(); ++p)
{
- if ((*p)->is_section()
- && (*p)->output_section()->is_large_section())
+ if (*p == os)
{
- pdl->insert(p, os);
+ pdl->erase(p);
return;
}
}
- gold_unreachable();
- }
-
- // We do some further output section sorting in order to make the
- // generated program run more efficiently. We should only do this
- // when not using a linker script, so it is controled by the DO_SORT
- // parameter.
- if (do_sort)
- {
- // FreeBSD requires the .interp section to be in the first page
- // of the executable. That is a more efficient location anyhow
- // for any OS, since it means that the kernel will have the data
- // handy after it reads the program headers.
- if (os->is_interp() && !pdl->empty())
- {
- pdl->insert(pdl->begin(), os);
- return;
- }
-
- // Put loadable non-writable notes immediately after the .interp
- // sections, so that the PT_NOTE segment is on the first page of
- // the executable.
- if (os->type() == elfcpp::SHT_NOTE
- && (os->flags() & elfcpp::SHF_WRITE) == 0
- && !pdl->empty())
- {
- Output_segment::Output_data_list::iterator p = pdl->begin();
- if ((*p)->is_section() && (*p)->output_section()->is_interp())
- ++p;
- pdl->insert(p, os);
- return;
- }
-
- // If this section is used by the dynamic linker, and it is not
- // writable, then put it first, after the .interp section and
- // any loadable notes. This makes it more likely that the
- // dynamic linker will have to read less data from the disk.
- if (os->is_dynamic_linker_section()
- && !pdl->empty()
- && (os->flags() & elfcpp::SHF_WRITE) == 0)
- {
- bool is_reloc = (os->type() == elfcpp::SHT_REL
- || os->type() == elfcpp::SHT_RELA);
- Output_segment::Output_data_list::iterator p = pdl->begin();
- while (p != pdl->end()
- && (*p)->is_section()
- && ((*p)->output_section()->is_dynamic_linker_section()
- || (*p)->output_section()->type() == elfcpp::SHT_NOTE))
- {
- // Put reloc sections after the other ones. Putting the
- // dynamic reloc sections first confuses BFD, notably
- // objcopy and strip.
- if (!is_reloc
- && ((*p)->output_section()->type() == elfcpp::SHT_REL
- || (*p)->output_section()->type() == elfcpp::SHT_RELA))
- break;
- ++p;
- }
- pdl->insert(p, os);
- return;
- }
}
-
- // If there were no constraints on the output section, just add it
- // to the end of the list.
- pdl->push_back(os);
-}
-
-// Remove an Output_section from this segment. It is an error if it
-// is not present.
-
-void
-Output_segment::remove_output_section(Output_section* os)
-{
- // We only need this for SHT_PROGBITS.
- gold_assert(os->type() == elfcpp::SHT_PROGBITS);
- for (Output_data_list::iterator p = this->output_data_.begin();
- p != this->output_data_.end();
- ++p)
- {
- if (*p == os)
- {
- this->output_data_.erase(p);
- return;
- }
- }
gold_unreachable();
}
@@ -3727,7 +3492,30 @@ void
Output_segment::add_initial_output_data(Output_data* od)
{
gold_assert(!this->is_max_align_known_);
- this->output_data_.push_front(od);
+ Output_data_list::iterator p = this->output_lists_[0].begin();
+ this->output_lists_[0].insert(p, od);
+}
+
+// Return true if this segment has any sections which hold actual
+// data, rather than being a BSS section.
+
+bool
+Output_segment::has_any_data_sections() const
+{
+ for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
+ {
+ const Output_data_list* pdl = &this->output_lists_[i];
+ for (Output_data_list::const_iterator p = pdl->begin();
+ p != pdl->end();
+ ++p)
+ {
+ if (!(*p)->is_section())
+ return true;
+ if ((*p)->output_section()->type() != elfcpp::SHT_NOBITS)
+ return true;
+ }
+ }
+ return false;
}
// Return whether the first data section is a relro section.
@@ -3735,9 +3523,16 @@ Output_segment::add_initial_output_data(Output_data* od)
bool
Output_segment::is_first_section_relro() const
{
- return (!this->output_data_.empty()
- && this->output_data_.front()->is_section()
- && this->output_data_.front()->output_section()->is_relro());
+ for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
+ {
+ const Output_data_list* pdl = &this->output_lists_[i];
+ if (!pdl->empty())
+ {
+ Output_data* p = pdl->front();
+ return p->is_section() && p->output_section()->is_relro();
+ }
+ }
+ return false;
}
// Return the maximum alignment of the Output_data in Output_segment.
@@ -3747,16 +3542,13 @@ Output_segment::maximum_alignment()
{
if (!this->is_max_align_known_)
{
- uint64_t addralign;
-
- addralign = Output_segment::maximum_alignment_list(&this->output_data_);
- if (addralign > this->max_align_)
- this->max_align_ = addralign;
-
- addralign = Output_segment::maximum_alignment_list(&this->output_bss_);
- if (addralign > this->max_align_)
- this->max_align_ = addralign;
-
+ for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
+ {
+ const Output_data_list* pdl = &this->output_lists_[i];
+ uint64_t addralign = Output_segment::maximum_alignment_list(pdl);
+ if (addralign > this->max_align_)
+ this->max_align_ = addralign;
+ }
this->is_max_align_known_ = true;
}
@@ -3780,26 +3572,28 @@ Output_segment::maximum_alignment_list(const Output_data_list* pdl)
return ret;
}
-// Return the number of dynamic relocs applied to this segment.
+// Return whether this segment has any dynamic relocs.
-unsigned int
-Output_segment::dynamic_reloc_count() const
+bool
+Output_segment::has_dynamic_reloc() const
{
- return (this->dynamic_reloc_count_list(&this->output_data_)
- + this->dynamic_reloc_count_list(&this->output_bss_));
+ for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
+ if (this->has_dynamic_reloc_list(&this->output_lists_[i]))
+ return true;
+ return false;
}
-// Return the number of dynamic relocs applied to an Output_data_list.
+// Return whether this Output_data_list has any dynamic relocs.
-unsigned int
-Output_segment::dynamic_reloc_count_list(const Output_data_list* pdl) const
+bool
+Output_segment::has_dynamic_reloc_list(const Output_data_list* pdl) const
{
- unsigned int count = 0;
for (Output_data_list::const_iterator p = pdl->begin();
p != pdl->end();
++p)
- count += (*p)->dynamic_reloc_count();
- return count;
+ if ((*p)->has_dynamic_reloc())
+ return true;
+ return false;
}
// Set the section addresses for an Output_segment. If RESET is true,
@@ -3827,26 +3621,30 @@ Output_segment::set_section_addresses(const Layout* layout, bool reset,
{
uint64_t relro_size = 0;
off_t off = *poff;
- for (Output_data_list::iterator p = this->output_data_.begin();
- p != this->output_data_.end();
- ++p)
+ for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
{
- if (!(*p)->is_section())
- break;
- Output_section* pos = (*p)->output_section();
- if (!pos->is_relro())
- break;
- gold_assert(!(*p)->is_section_flag_set(elfcpp::SHF_TLS));
- if ((*p)->is_address_valid())
- relro_size += (*p)->data_size();
- else
+ Output_data_list* pdl = &this->output_lists_[i];
+ Output_data_list::iterator p;
+ for (p = pdl->begin(); p != pdl->end(); ++p)
{
- // FIXME: This could be faster.
- (*p)->set_address_and_file_offset(addr + relro_size,
- off + relro_size);
- relro_size += (*p)->data_size();
- (*p)->reset_address_and_file_offset();
+ if (!(*p)->is_section())
+ break;
+ Output_section* pos = (*p)->output_section();
+ if (!pos->is_relro())
+ break;
+ if ((*p)->is_address_valid())
+ relro_size += (*p)->data_size();
+ else
+ {
+ // FIXME: This could be faster.
+ (*p)->set_address_and_file_offset(addr + relro_size,
+ off + relro_size);
+ relro_size += (*p)->data_size();
+ (*p)->reset_address_and_file_offset();
+ }
}
+ if (p != pdl->end())
+ break;
}
relro_size += increase_relro;
@@ -3877,16 +3675,21 @@ Output_segment::set_section_addresses(const Layout* layout, bool reset,
this->offset_ = orig_off;
- addr = this->set_section_list_addresses(layout, reset, &this->output_data_,
- addr, poff, pshndx, &in_tls);
- this->filesz_ = *poff - orig_off;
-
- off_t off = *poff;
+ off_t off = 0;
+ uint64_t ret;
+ for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
+ {
+ addr = this->set_section_list_addresses(layout, reset,
+ &this->output_lists_[i],
+ addr, poff, pshndx, &in_tls);
+ if (i < static_cast<int>(ORDER_SMALL_BSS))
+ {
+ this->filesz_ = *poff - orig_off;
+ off = *poff;
+ }
- uint64_t ret = this->set_section_list_addresses(layout, reset,
- &this->output_bss_,
- addr, poff, pshndx,
- &in_tls);
+ ret = addr;
+ }
// If the last section was a TLS section, align upward to the
// alignment of the TLS segment, so that the overall size of the TLS
@@ -4029,7 +3832,11 @@ Output_segment::set_offset(unsigned int increase)
gold_assert(!this->are_addresses_set_);
- if (this->output_data_.empty() && this->output_bss_.empty())
+ // A non-load section only uses output_lists_[0].
+
+ Output_data_list* pdl = &this->output_lists_[0];
+
+ if (pdl->empty())
{
gold_assert(increase == 0);
this->vaddr_ = 0;
@@ -4042,13 +3849,31 @@ Output_segment::set_offset(unsigned int increase)
return;
}
- // Find the first and last section by address. The sections may
- // have been sorted for the PT_LOAD segment.
+ // Find the first and last section by address.
const Output_data* first = NULL;
const Output_data* last_data = NULL;
const Output_data* last_bss = NULL;
- this->find_first_and_last_list(&this->output_data_, &first, &last_data);
- this->find_first_and_last_list(&this->output_bss_, &first, &last_bss);
+ for (Output_data_list::const_iterator p = pdl->begin();
+ p != pdl->end();
+ ++p)
+ {
+ if (first == NULL
+ || (*p)->address() < first->address()
+ || ((*p)->address() == first->address()
+ && (*p)->data_size() < first->data_size()))
+ first = *p;
+ const Output_data** plast;
+ if ((*p)->is_section()
+ && (*p)->output_section()->type() == elfcpp::SHT_NOBITS)
+ plast = &last_bss;
+ else
+ plast = &last_data;
+ if (*plast == NULL
+ || (*p)->address() > (*plast)->address()
+ || ((*p)->address() == (*plast)->address()
+ && (*p)->data_size() > (*plast)->data_size()))
+ *plast = *p;
+ }
this->vaddr_ = first->address();
this->paddr_ = (first->has_load_address()
@@ -4057,7 +3882,7 @@ Output_segment::set_offset(unsigned int increase)
this->are_addresses_set_ = true;
this->offset_ = first->offset();
- if (this->output_data_.empty())
+ if (last_data == NULL)
this->filesz_ = 0;
else
this->filesz_ = (last_data->address()
@@ -4083,37 +3908,6 @@ Output_segment::set_offset(unsigned int increase)
}
}
-// Look through a list of Output_data objects and find the first and
-// last by address.
-
-void
-Output_segment::find_first_and_last_list(const Output_data_list* pdl,
- const Output_data** pfirst,
- const Output_data** plast) const
-{
- const Output_data* first = *pfirst;
- const Output_data* last = *plast;
- for (Output_data_list::const_iterator p = pdl->begin(); p != pdl->end(); ++p)
- {
- if (first == NULL
- || (*p)->address() < first->address()
- || ((*p)->address() == first->address()
- && (*p)->data_size() < first->data_size()))
- {
- first = *p;
- *pfirst = first;
- }
- if (last == NULL
- || (*p)->address() > last->address()
- || ((*p)->address() == last->address()
- && (*p)->data_size() > last->data_size()))
- {
- last = *p;
- *plast = last;
- }
- }
-}
-
// Set the TLS offsets of the sections in the PT_TLS segment.
void
@@ -4121,34 +3915,30 @@ Output_segment::set_tls_offsets()
{
gold_assert(this->type_ == elfcpp::PT_TLS);
- for (Output_data_list::iterator p = this->output_data_.begin();
- p != this->output_data_.end();
- ++p)
- (*p)->set_tls_offset(this->vaddr_);
-
- for (Output_data_list::iterator p = this->output_bss_.begin();
- p != this->output_bss_.end();
+ for (Output_data_list::iterator p = this->output_lists_[0].begin();
+ p != this->output_lists_[0].end();
++p)
(*p)->set_tls_offset(this->vaddr_);
}
-// Return the address of the first section.
+// Return the load address of the first section.
uint64_t
Output_segment::first_section_load_address() const
{
- for (Output_data_list::const_iterator p = this->output_data_.begin();
- p != this->output_data_.end();
- ++p)
- if ((*p)->is_section())
- return (*p)->has_load_address() ? (*p)->load_address() : (*p)->address();
-
- for (Output_data_list::const_iterator p = this->output_bss_.begin();
- p != this->output_bss_.end();
- ++p)
- if ((*p)->is_section())
- return (*p)->has_load_address() ? (*p)->load_address() : (*p)->address();
-
+ for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
+ {
+ const Output_data_list* pdl = &this->output_lists_[i];
+ for (Output_data_list::const_iterator p = pdl->begin();
+ p != pdl->end();
+ ++p)
+ {
+ if ((*p)->is_section())
+ return ((*p)->has_load_address()
+ ? (*p)->load_address()
+ : (*p)->address());
+ }
+ }
gold_unreachable();
}
@@ -4157,8 +3947,10 @@ Output_segment::first_section_load_address() const
unsigned int
Output_segment::output_section_count() const
{
- return (this->output_section_count_list(&this->output_data_)
- + this->output_section_count_list(&this->output_bss_));
+ unsigned int ret = 0;
+ for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
+ ret += this->output_section_count_list(&this->output_lists_[i]);
+ return ret;
}
// Return the number of Output_sections in an Output_data_list.
@@ -4186,18 +3978,9 @@ Output_segment::section_with_lowest_load_address() const
{
Output_section* found = NULL;
uint64_t found_lma = 0;
- this->lowest_load_address_in_list(&this->output_data_, &found, &found_lma);
-
- Output_section* found_data = found;
- this->lowest_load_address_in_list(&this->output_bss_, &found, &found_lma);
- if (found != found_data && found_data != NULL)
- {
- gold_error(_("nobits section %s may not precede progbits section %s "
- "in same segment"),
- found->name(), found_data->name());
- return NULL;
- }
-
+ for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
+ this->lowest_load_address_in_list(&this->output_lists_[i], &found,
+ &found_lma);
return found;
}
@@ -4257,12 +4040,15 @@ Output_segment::write_section_headers(const Layout* layout,
if (this->type_ != elfcpp::PT_LOAD)
return v;
- v = this->write_section_headers_list<size, big_endian>(layout, secnamepool,
- &this->output_data_,
- v, pshndx);
- v = this->write_section_headers_list<size, big_endian>(layout, secnamepool,
- &this->output_bss_,
- v, pshndx);
+ for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
+ {
+ const Output_data_list* pdl = &this->output_lists_[i];
+ v = this->write_section_headers_list<size, big_endian>(layout,
+ secnamepool,
+ pdl,
+ v, pshndx);
+ }
+
return v;
}
@@ -4299,8 +4085,8 @@ Output_segment::print_sections_to_mapfile(Mapfile* mapfile) const
{
if (this->type() != elfcpp::PT_LOAD)
return;
- this->print_section_list_to_mapfile(mapfile, &this->output_data_);
- this->print_section_list_to_mapfile(mapfile, &this->output_bss_);
+ for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
+ this->print_section_list_to_mapfile(mapfile, &this->output_lists_[i]);
}
// Print an output section list to the map file.