This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] gold: make the kept comdat structure have a direct link to sections map
- From: Mikolaj Zalewski <mikolajz at google dot com>
- To: binutils at sourceware dot org
- Date: Fri, 27 Feb 2009 16:25:53 +0100
- Subject: [PATCH] gold: make the kept comdat structure have a direct link to sections map
Currently, if a comdat is already declared in a previous object and
we need to access its sections, Layout needs to map the comdat name to
original object/section index and the obejct must map section the
index to comdat information. With this patch, the Layout's
Kept_section structure has already all the information about the
comdat. The patch also changes the way comdat information is accessed
- it only does one insert, instead of an insert and if insert failed
then a find for the entry. This decreased linking CPU time on a sample
test by 2-2,5%. It produces the same binary as the previous version
and make check passed.
2009-02-27 Mikolaj Zalewski <mikolajz@google.com>
* layout.cc (find_or_add_comdat): a more generic version of add_comdat
(add_comdat): removed
* layout.h (Kept_section): move out of Layout
(Kept_section::group_sections_): new field
(Layout::Kep_section): remove
(find_or_add_comdat): a more generic version of add_comdat
(add_comdat): removed
* object.cc (include_section_group): use find_or_add_comdat and
Kept_section::group_sections_
(include_linkonce_section): use find_or_add_comdat and
Kept_section::group_sections_
* object.cc (Comdat_group): removed
(Comdat_group_table): removed
(find_comdat_grouop): removed
(add_comdat_group): removed
(comdat_groups_): removed
* plugin.cc (include_comdat_group): use the new Layout::find_or_add_comdat
From 1e5303fd0881f13f2feef2844a7e5e2d3bee167a Mon Sep 17 00:00:00 2001
From: Mikolaj Zalewski <mikolajz@google.com>
Date: Fri, 27 Feb 2009 12:29:39 +0100
Subject: [PATCH] - Map kept comdat groups directly to sections maps instead of going through
a comdat section index mapping
- Use only one insert when a comdat is already present instead of insert and
find
diff --git a/gold/layout.cc b/gold/layout.cc
index 2bc1483..9237e00 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -2930,21 +2930,24 @@ Layout::output_section_name(const char* name, size_t* plen)
return name;
}
-// Record the signature of a comdat section, and return whether to
-// include it in the link. If GROUP is true, this is a regular
-// section group. If GROUP is false, this is a group signature
-// derived from the name of a linkonce section. We want linkonce
-// signatures and group signatures to block each other, but we don't
-// want a linkonce signature to block another linkonce signature.
+// Check if a comdat group or .gnu.linkonce section with the given NAME
+// is selected for the link. If there is already a section, its signature is
+// pointed by KEPT_SECTION and the function returns false. Otherwise, the
+// CANDIDATE signature is recorded for this NAME in the layout object, the
+// internal copy is pointed by KEPT_SECTION and the function return false.
+// In some cases, with candidate->group_ being false, KEPT_SECTION can point
+// back to CANDIDATE.
bool
-Layout::add_comdat(Relobj* object, unsigned int shndx,
- const std::string& signature, bool group)
+Layout::find_or_add_kept_section(const std::string name,
+ Kept_section* candidate,
+ Kept_section** kept_section)
{
- Kept_section kept(object, shndx, group);
std::pair<Signatures::iterator, bool> ins(
- this->signatures_.insert(std::make_pair(signature, kept)));
+ this->signatures_.insert(std::make_pair(name, *candidate)));
+ if (kept_section)
+ *kept_section = &ins.first->second;
if (ins.second)
{
// This is the first time we've seen this signature.
@@ -2959,12 +2962,12 @@ Layout::add_comdat(Relobj* object, unsigned int shndx,
if (ins.first->second.object_ == NULL
&& parameters->options().plugins()->in_replacement_phase())
{
- ins.first->second = kept;
+ ins.first->second = *candidate;
return true;
}
return false;
}
- else if (group)
+ else if (candidate->group_)
{
// This is a real section group, and we've already seen a
// linkonce section with this signature. Record that we've seen
@@ -2977,6 +2980,7 @@ Layout::add_comdat(Relobj* object, unsigned int shndx,
// We've already seen a linkonce section and this is a linkonce
// section. These don't block each other--this may be the same
// symbol name with different section types.
+ *kept_section = candidate;
return true;
}
}
@@ -3101,7 +3105,7 @@ Layout::write_sections_after_input_sections(Output_file* of)
{
off_t off = this->output_file_size_;
off = this->set_section_offsets(off, POSTPROCESSING_SECTIONS_PASS);
-
+
// Now that we've finalized the names, we can finalize the shstrab.
off =
this->set_section_offsets(off,
diff --git a/gold/layout.h b/gold/layout.h
index ca8b7c7..32ee0c8 100644
--- a/gold/layout.h
+++ b/gold/layout.h
@@ -89,6 +89,37 @@ class Layout_task_runner : public Task_function_runner
Mapfile* mapfile_;
};
+// This struct hold information about the comdat or .gnu.linkonce that will be
+// kept
+
+struct Kept_section
+ {
+ Kept_section()
+ : object_(NULL), shndx_(0), group_(false), group_sections_(NULL)
+ { }
+ Kept_section(Relobj* object, unsigned int shndx, bool group)
+ : object_(object), shndx_(shndx), group_(group), group_sections_(NULL)
+ { }
+
+ // The object containing the comdat or .gnu.linkonce.
+ Relobj* object_;
+ // Index to the group section for comdats and the section itself for
+ // .gnu.linkonce.
+ unsigned int shndx_;
+ // The Kept_sections are values of a mapping, that maps names to them.
+ // This field is true if this struct is associated with the name of a
+ // comdat or .gnu.linkonce, false if it is associated with the name of a
+ // symbol obtained from the .gnu.linkonce.* name through some heuristics.
+ bool group_;
+
+ typedef Unordered_map<std::string, unsigned int> Comdat_group;
+
+ // For comdats, a map from names of the sections in the group to indexes
+ // in OBJECT_. NULL for .gnu.linkonce.
+ Comdat_group* group_sections_;
+ };
+
+
// This class handles the details of laying out input sections.
class Layout
@@ -225,18 +256,23 @@ class Layout
{
// Debugging sections can only be recognized by name.
return (strncmp(name, ".debug", sizeof(".debug") - 1) == 0
- || strncmp(name, ".gnu.linkonce.wi.",
+ || strncmp(name, ".gnu.linkonce.wi.",
sizeof(".gnu.linkonce.wi.") - 1) == 0
|| strncmp(name, ".line", sizeof(".line") - 1) == 0
|| strncmp(name, ".stab", sizeof(".stab") - 1) == 0);
}
- // Record the signature of a comdat section, and return whether to
- // include it in the link. The GROUP parameter is true for a
- // section group signature, false for a signature derived from a
- // .gnu.linkonce section.
+ // Check if a comdat group or .gnu.linkonce section with the given NAME
+ // is selected for the link. If there is already a section, its signature is
+ // pointed by KEPT_SECTION and the function returns false. Otherwise, the
+ // CANDIDATE signature is recorded for this NAME in the layout object, the
+ // internal copy is pointed by KEPT_SECTION and the function return false.
+ // In some cases, with candidate->group_ being false, KEPT_SECTION can point
+ // back to CANDIDATE.
bool
- add_comdat(Relobj*, unsigned int, const std::string&, bool group);
+ find_or_add_kept_section(const std::string name,
+ Kept_section* candidate,
+ Kept_section** kept_section);
// Find the given comdat signature, and return the object and section
// index of the kept group.
@@ -577,19 +613,7 @@ class Layout
static bool
segment_precedes(const Output_segment* seg1, const Output_segment* seg2);
- // A mapping used for group signatures.
- struct Kept_section
- {
- Kept_section()
- : object_(NULL), shndx_(0), group_(false)
- { }
- Kept_section(Relobj* object, unsigned int shndx, bool group)
- : object_(object), shndx_(shndx), group_(group)
- { }
- Relobj* object_;
- unsigned int shndx_;
- bool group_;
- };
+ // A mapping used for kept comdats/.gnu.linkonce group signatures.
typedef Unordered_map<std::string, Kept_section> Signatures;
// Mapping from input section name/type/flags to output section. We
diff --git a/gold/object.cc b/gold/object.cc
index 7685802..6c841a3 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -327,7 +327,6 @@ Sized_relobj<size, big_endian>::Sized_relobj(
local_values_(),
local_got_offsets_(),
kept_comdat_sections_(),
- comdat_groups_(),
has_eh_frame_(false)
{
}
@@ -674,30 +673,26 @@ Sized_relobj<size, big_endian>::include_section_group(
// Record this section group in the layout, and see whether we've already
// seen one with the same signature.
- bool include_group = ((flags & elfcpp::GRP_COMDAT) == 0
- || layout->add_comdat(this, index, signature, true));
-
+ bool include_group;
Sized_relobj<size, big_endian>* kept_object = NULL;
- Comdat_group* kept_group = NULL;
+ Kept_section::Comdat_group* kept_group = NULL;
- if (!include_group)
+ if (flags & elfcpp::GRP_COMDAT)
{
- // This group is being discarded. Find the object and group
- // that was kept in its place.
- unsigned int kept_group_index = 0;
- Relobj* kept_relobj = layout->find_kept_object(signature,
- &kept_group_index);
- kept_object = static_cast<Sized_relobj<size, big_endian>*>(kept_relobj);
- if (kept_object != NULL)
- kept_group = kept_object->find_comdat_group(kept_group_index);
- }
- else if (flags & elfcpp::GRP_COMDAT)
- {
- // This group is being kept. Create the table to map section names
- // to section indexes and add it to the table of groups.
- kept_group = new Comdat_group();
- this->add_comdat_group(index, kept_group);
+ Kept_section this_group(this, index, true);
+ Kept_section *kept_section_group;
+ include_group = layout->find_or_add_kept_section(signature,
+ &this_group,
+ &kept_section_group);
+ if (include_group)
+ kept_section_group->group_sections_ = new Kept_section::Comdat_group;
+
+ kept_group = kept_section_group->group_sections_;
+ kept_object = static_cast<Sized_relobj<size, big_endian>*>(
+ kept_section_group->object_);
}
+ else
+ include_group = true;
size_t count = shdr.get_sh_size() / sizeof(elfcpp::Elf_Word);
@@ -745,7 +740,8 @@ Sized_relobj<size, big_endian>::include_section_group(
{
// Find the corresponding kept section, and store that info
// in the discarded section table.
- Comdat_group::const_iterator p = kept_group->find(mname);
+ Kept_section::Comdat_group::const_iterator p =
+ kept_group->find(mname);
if (p != kept_group->end())
{
Kept_comdat_section* kept =
@@ -808,8 +804,12 @@ Sized_relobj<size, big_endian>::include_linkonce_section(
symname = strrchr(name, '.') + 1;
std::string sig1(symname);
std::string sig2(name);
- bool include1 = layout->add_comdat(this, index, sig1, false);
- bool include2 = layout->add_comdat(this, index, sig2, true);
+ Kept_section candidate1(this, index, false);
+ Kept_section candidate2(this, index, true);
+ Kept_section* kept1;
+ Kept_section* kept2;
+ bool include1 = layout->find_or_add_kept_section(sig1, &candidate1, &kept1);
+ bool include2 = layout->find_or_add_kept_section(sig2, &candidate2, &kept2);
if (!include2)
{
@@ -817,8 +817,8 @@ Sized_relobj<size, big_endian>::include_linkonce_section(
// name (i.e., the kept section was also a linkonce section).
// In this case, the section index stored with the layout object
// is the linkonce section that was kept.
- unsigned int kept_group_index = 0;
- Relobj* kept_relobj = layout->find_kept_object(sig2, &kept_group_index);
+ unsigned int kept_group_index = kept2->shndx_;
+ Relobj* kept_relobj = kept2->object_;
if (kept_relobj != NULL)
{
Sized_relobj<size, big_endian>* kept_object
@@ -837,17 +837,16 @@ Sized_relobj<size, big_endian>::include_linkonce_section(
// this linkonce section. We'll handle the simple case where
// the group has only one member section. Otherwise, it's not
// worth the effort.
- unsigned int kept_group_index = 0;
- Relobj* kept_relobj = layout->find_kept_object(sig1, &kept_group_index);
+ Relobj* kept_relobj = kept1->object_;
if (kept_relobj != NULL)
{
Sized_relobj<size, big_endian>* kept_object =
static_cast<Sized_relobj<size, big_endian>*>(kept_relobj);
- Comdat_group* kept_group =
- kept_object->find_comdat_group(kept_group_index);
+ Kept_section::Comdat_group* kept_group = kept1->group_sections_;
if (kept_group != NULL && kept_group->size() == 1)
{
- Comdat_group::const_iterator p = kept_group->begin();
+ Kept_section::Comdat_group::const_iterator p =
+ kept_group->begin();
gold_assert(p != kept_group->end());
Kept_comdat_section* kept =
new Kept_comdat_section(kept_object, p->second);
diff --git a/gold/object.h b/gold/object.h
index 6efc0fe..b1745ec 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -1579,32 +1579,6 @@ class Sized_relobj : public Relobj
typedef std::map<unsigned int, Kept_comdat_section*>
Kept_comdat_section_table;
- // Information needed to keep track of kept comdat groups. This is
- // simply a map from the section name to its section index. This may
- // not be a one-to-one mapping, but we ignore that possibility since
- // this is used only to attempt to handle stray relocations from
- // non-comdat debug sections that refer to comdat loadable sections.
- typedef Unordered_map<std::string, unsigned int> Comdat_group;
-
- // A map from group section index to the table of group members.
- typedef std::map<unsigned int, Comdat_group*> Comdat_group_table;
-
- // Find a comdat group table given its group section SHNDX.
- Comdat_group*
- find_comdat_group(unsigned int shndx) const
- {
- Comdat_group_table::const_iterator p =
- this->comdat_groups_.find(shndx);
- if (p != this->comdat_groups_.end())
- return p->second;
- return NULL;
- }
-
- // Record a new comdat group whose group section index is SHNDX.
- void
- add_comdat_group(unsigned int shndx, Comdat_group* group)
- { this->comdat_groups_[shndx] = group; }
-
// Adjust a section index if necessary.
unsigned int
adjust_shndx(unsigned int shndx)
@@ -1818,8 +1792,6 @@ class Sized_relobj : public Relobj
std::vector<Address> section_offsets_;
// Table mapping discarded comdat sections to corresponding kept sections.
Kept_comdat_section_table kept_comdat_sections_;
- // Table of kept comdat groups.
- Comdat_group_table comdat_groups_;
// Whether this object has a GNU style .eh_frame section.
bool has_eh_frame_;
// The list of sections whose layout was deferred.
diff --git a/gold/plugin.cc b/gold/plugin.cc
index e58751e..7d50ad0 100644
--- a/gold/plugin.cc
+++ b/gold/plugin.cc
@@ -506,7 +506,11 @@ Pluginobj::include_comdat_group(std::string comdat_key, Layout* layout)
// If this is the first time we've seen this comdat key, ask the
// layout object whether it should be included.
if (ins.second)
- ins.first->second = layout->add_comdat(NULL, 1, comdat_key, true);
+ {
+ Kept_section to_add(NULL, 1, true);
+ ins.first->second = layout->find_or_add_kept_section(
+ comdat_key, &to_add, NULL);
+ }
return ins.first->second;
}
--
1.5.4.5