mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-20 09:58:19 +08:00
PR 10931
* options.h (class General_options): Add --sort-common option. * symtab.h (class Symbol_table): Define Sort_commons_order enum. * common.cc (Sort_common): Add sort_order parameter to constructor. Add sort_order_ field. (Sort_commons::operator): Check sort_order_. (Symbol_table::allocate_commons): Determine the sort order. (Symbol_table::do_allocate_commons): Add sort_order parameter. Change all callers. (Symbol_table::do_allocate_commons_list): Likewise.
This commit is contained in:
101
gold/common.cc
101
gold/common.cc
@ -64,21 +64,26 @@ Allocate_commons_task::run(Workqueue*)
|
||||
this->symtab_->allocate_commons(this->layout_, this->mapfile_);
|
||||
}
|
||||
|
||||
// This class is used to sort the common symbol by size. We put the
|
||||
// larger common symbols first.
|
||||
// This class is used to sort the common symbol. We normally put the
|
||||
// larger common symbols first. This can be changed by using
|
||||
// --sort-commons, which tells the linker to sort by alignment.
|
||||
|
||||
template<int size>
|
||||
class Sort_commons
|
||||
{
|
||||
public:
|
||||
Sort_commons(const Symbol_table* symtab)
|
||||
: symtab_(symtab)
|
||||
Sort_commons(const Symbol_table* symtab,
|
||||
Symbol_table::Sort_commons_order sort_order)
|
||||
: symtab_(symtab), sort_order_(sort_order)
|
||||
{ }
|
||||
|
||||
bool operator()(const Symbol* a, const Symbol* b) const;
|
||||
|
||||
private:
|
||||
// The symbol table.
|
||||
const Symbol_table* symtab_;
|
||||
// How to sort.
|
||||
Symbol_table::Sort_commons_order sort_order_;
|
||||
};
|
||||
|
||||
template<int size>
|
||||
@ -94,22 +99,48 @@ Sort_commons<size>::operator()(const Symbol* pa, const Symbol* pb) const
|
||||
const Sized_symbol<size>* psa = symtab->get_sized_symbol<size>(pa);
|
||||
const Sized_symbol<size>* psb = symtab->get_sized_symbol<size>(pb);
|
||||
|
||||
// Sort by largest size first.
|
||||
// The size.
|
||||
typename Sized_symbol<size>::Size_type sa = psa->symsize();
|
||||
typename Sized_symbol<size>::Size_type sb = psb->symsize();
|
||||
|
||||
// The alignment.
|
||||
typename Sized_symbol<size>::Value_type aa = psa->value();
|
||||
typename Sized_symbol<size>::Value_type ab = psb->value();
|
||||
|
||||
if (this->sort_order_ == Symbol_table::SORT_COMMONS_BY_ALIGNMENT_DESCENDING)
|
||||
{
|
||||
if (aa < ab)
|
||||
return false;
|
||||
else if (ab < aa)
|
||||
return true;
|
||||
}
|
||||
else if (this->sort_order_
|
||||
== Symbol_table::SORT_COMMONS_BY_ALIGNMENT_ASCENDING)
|
||||
{
|
||||
if (aa < ab)
|
||||
return true;
|
||||
else if (ab < aa)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
gold_assert(this->sort_order_
|
||||
== Symbol_table::SORT_COMMONS_BY_SIZE_DESCENDING);
|
||||
|
||||
// Sort by descending size.
|
||||
if (sa < sb)
|
||||
return false;
|
||||
else if (sb < sa)
|
||||
return true;
|
||||
|
||||
// When the symbols are the same size, we sort them by alignment,
|
||||
// largest alignment first.
|
||||
typename Sized_symbol<size>::Value_type va = psa->value();
|
||||
typename Sized_symbol<size>::Value_type vb = psb->value();
|
||||
if (va < vb)
|
||||
return false;
|
||||
else if (vb < va)
|
||||
return true;
|
||||
if (this->sort_order_ == Symbol_table::SORT_COMMONS_BY_SIZE_DESCENDING)
|
||||
{
|
||||
// When the symbols are the same size, we sort them by
|
||||
// alignment, largest alignment first.
|
||||
if (aa < ab)
|
||||
return false;
|
||||
else if (ab < aa)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise we stabilize the sort by sorting by name.
|
||||
return strcmp(psa->name(), psb->name()) < 0;
|
||||
@ -120,10 +151,27 @@ Sort_commons<size>::operator()(const Symbol* pa, const Symbol* pb) const
|
||||
void
|
||||
Symbol_table::allocate_commons(Layout* layout, Mapfile* mapfile)
|
||||
{
|
||||
Sort_commons_order sort_order;
|
||||
if (!parameters->options().user_set_sort_common())
|
||||
sort_order = SORT_COMMONS_BY_SIZE_DESCENDING;
|
||||
else
|
||||
{
|
||||
const char* order = parameters->options().sort_common();
|
||||
if (*order == '\0' || strcmp(order, "descending") == 0)
|
||||
sort_order = SORT_COMMONS_BY_ALIGNMENT_DESCENDING;
|
||||
else if (strcmp(order, "ascending") == 0)
|
||||
sort_order = SORT_COMMONS_BY_ALIGNMENT_ASCENDING;
|
||||
else
|
||||
{
|
||||
gold_error("invalid --sort-common argument: %s", order);
|
||||
sort_order = SORT_COMMONS_BY_SIZE_DESCENDING;
|
||||
}
|
||||
}
|
||||
|
||||
if (parameters->target().get_size() == 32)
|
||||
{
|
||||
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
|
||||
this->do_allocate_commons<32>(layout, mapfile);
|
||||
this->do_allocate_commons<32>(layout, mapfile, sort_order);
|
||||
#else
|
||||
gold_unreachable();
|
||||
#endif
|
||||
@ -131,7 +179,7 @@ Symbol_table::allocate_commons(Layout* layout, Mapfile* mapfile)
|
||||
else if (parameters->target().get_size() == 64)
|
||||
{
|
||||
#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
|
||||
this->do_allocate_commons<64>(layout, mapfile);
|
||||
this->do_allocate_commons<64>(layout, mapfile, sort_order);
|
||||
#else
|
||||
gold_unreachable();
|
||||
#endif
|
||||
@ -144,20 +192,25 @@ Symbol_table::allocate_commons(Layout* layout, Mapfile* mapfile)
|
||||
|
||||
template<int size>
|
||||
void
|
||||
Symbol_table::do_allocate_commons(Layout* layout, Mapfile* mapfile)
|
||||
Symbol_table::do_allocate_commons(Layout* layout, Mapfile* mapfile,
|
||||
Sort_commons_order sort_order)
|
||||
{
|
||||
if (!this->commons_.empty())
|
||||
this->do_allocate_commons_list<size>(layout, COMMONS_NORMAL,
|
||||
&this->commons_, mapfile);
|
||||
&this->commons_, mapfile,
|
||||
sort_order);
|
||||
if (!this->tls_commons_.empty())
|
||||
this->do_allocate_commons_list<size>(layout, COMMONS_TLS,
|
||||
&this->tls_commons_, mapfile);
|
||||
&this->tls_commons_, mapfile,
|
||||
sort_order);
|
||||
if (!this->small_commons_.empty())
|
||||
this->do_allocate_commons_list<size>(layout, COMMONS_SMALL,
|
||||
&this->small_commons_, mapfile);
|
||||
&this->small_commons_, mapfile,
|
||||
sort_order);
|
||||
if (!this->large_commons_.empty())
|
||||
this->do_allocate_commons_list<size>(layout, COMMONS_LARGE,
|
||||
&this->large_commons_, mapfile);
|
||||
&this->large_commons_, mapfile,
|
||||
sort_order);
|
||||
}
|
||||
|
||||
// Allocate the common symbols in a list. IS_TLS indicates whether
|
||||
@ -169,7 +222,8 @@ Symbol_table::do_allocate_commons_list(
|
||||
Layout* layout,
|
||||
Commons_section_type commons_section_type,
|
||||
Commons_type* commons,
|
||||
Mapfile* mapfile)
|
||||
Mapfile* mapfile,
|
||||
Sort_commons_order sort_order)
|
||||
{
|
||||
typedef typename Sized_symbol<size>::Value_type Value_type;
|
||||
typedef typename Sized_symbol<size>::Size_type Size_type;
|
||||
@ -202,10 +256,9 @@ Symbol_table::do_allocate_commons_list(
|
||||
if (!any)
|
||||
return;
|
||||
|
||||
// Sort the common symbols by size, so that they pack better into
|
||||
// memory.
|
||||
// Sort the common symbols.
|
||||
std::sort(commons->begin(), commons->end(),
|
||||
Sort_commons<size>(this));
|
||||
Sort_commons<size>(this, sort_order));
|
||||
|
||||
// Place them in a newly allocated BSS section.
|
||||
elfcpp::Elf_Xword flags = elfcpp::SHF_WRITE | elfcpp::SHF_ALLOC;
|
||||
|
Reference in New Issue
Block a user