PR 10400
* layout.h: #include <map>. (class Kept_section): Change from struct to class. Add accessors and setters. Add section size to Comdat_group mapping. Change Comdat_group to std::map. Add is_comdat_ field. Add linkonce_size field in union. (class Layout): Update declaration of find_or_add_kept_section. Don't declare find_kept_object. * layout.cc (Layout::find_or_add_kept_section): Remove candidate parameter. Add object, shndx, is_comdat, and is_group_name parameters. Change all callers. Adjust for new Kept_section. (Layout::find_kept_object): Remove. * object.cc (Sized_relobj::include_section_group): Update use of Kept_section. Rename secnum to shndx. Only record Kept_comdat_section if sections are the same size. (Sized_relobj::include_linkonce_section): Update use of Kept_section. Only record Kept_comdat_section if sections are the same size. Set size of linkonce section. (Sized_relobj::map_to_kept_section): Update call to get_kept_comdat_section. * object.h (class Sized_relobj): Rename fields in Kept_comdat_section to drop trailing underscores; change object field to Relobj*. Change Kept_comdat_section_table to store struct rather than pointer. (Sized_relobj::set_kept_comdat_section): Remove kept parameter. Add kept_object and kept_shndx parameters. Change all callers. (Sized_relobj::get_kept_comdat_section): Change return type to bool. Add kept_object and kept_shndx parameters. Change all callers. * plugin.cc (Pluginobj::include_comdat_group): Update call to Layout::find_or_add_kept_section.
This commit is contained in:
parent
98472ae205
commit
1ef4d87fe8
6 changed files with 365 additions and 164 deletions
|
@ -1,3 +1,37 @@
|
|||
2009-07-16 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
PR 10400
|
||||
* layout.h: #include <map>.
|
||||
(class Kept_section): Change from struct to class. Add accessors
|
||||
and setters. Add section size to Comdat_group mapping. Change
|
||||
Comdat_group to std::map. Add is_comdat_ field. Add
|
||||
linkonce_size field in union.
|
||||
(class Layout): Update declaration of find_or_add_kept_section.
|
||||
Don't declare find_kept_object.
|
||||
* layout.cc (Layout::find_or_add_kept_section): Remove candidate
|
||||
parameter. Add object, shndx, is_comdat, and is_group_name
|
||||
parameters. Change all callers. Adjust for new Kept_section.
|
||||
(Layout::find_kept_object): Remove.
|
||||
* object.cc (Sized_relobj::include_section_group): Update use of
|
||||
Kept_section. Rename secnum to shndx. Only record
|
||||
Kept_comdat_section if sections are the same size.
|
||||
(Sized_relobj::include_linkonce_section): Update use of
|
||||
Kept_section. Only record Kept_comdat_section if sections are the
|
||||
same size. Set size of linkonce section.
|
||||
(Sized_relobj::map_to_kept_section): Update call to
|
||||
get_kept_comdat_section.
|
||||
* object.h (class Sized_relobj): Rename fields in
|
||||
Kept_comdat_section to drop trailing underscores; change object
|
||||
field to Relobj*. Change Kept_comdat_section_table to store
|
||||
struct rather than pointer.
|
||||
(Sized_relobj::set_kept_comdat_section): Remove kept parameter.
|
||||
Add kept_object and kept_shndx parameters. Change all callers.
|
||||
(Sized_relobj::get_kept_comdat_section): Change return type to
|
||||
bool. Add kept_object and kept_shndx parameters. Change all
|
||||
callers.
|
||||
* plugin.cc (Pluginobj::include_comdat_group): Update call to
|
||||
Layout::find_or_add_kept_section.
|
||||
|
||||
2009-07-09 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* merge.cc (Object_merge_map::initialize_input_to_output_map):
|
||||
|
|
|
@ -3045,16 +3045,18 @@ Layout::output_section_name(const char* name, size_t* plen)
|
|||
|
||||
// Check if a comdat group or .gnu.linkonce section with the given
|
||||
// NAME is selected for the link. If there is already a section,
|
||||
// *KEPT_SECTION is set to point to the signature and the function
|
||||
// returns false. Otherwise, the CANDIDATE signature is recorded for
|
||||
// this NAME in the layout object, *KEPT_SECTION is set to the
|
||||
// internal copy and the function return false. In some cases, with
|
||||
// CANDIDATE->GROUP_ being false, KEPT_SECTION can point back to
|
||||
// CANDIDATE.
|
||||
// *KEPT_SECTION is set to point to the existing section and the
|
||||
// function returns false. Otherwise, OBJECT, SHNDX, IS_COMDAT, and
|
||||
// IS_GROUP_NAME are recorded for this NAME in the layout object,
|
||||
// *KEPT_SECTION is set to the internal copy and the function returns
|
||||
// true.
|
||||
|
||||
bool
|
||||
Layout::find_or_add_kept_section(const std::string& name,
|
||||
Kept_section* candidate,
|
||||
Relobj* object,
|
||||
unsigned int shndx,
|
||||
bool is_comdat,
|
||||
bool is_group_name,
|
||||
Kept_section** kept_section)
|
||||
{
|
||||
// It's normal to see a couple of entries here, for the x86 thunk
|
||||
|
@ -3068,36 +3070,46 @@ Layout::find_or_add_kept_section(const std::string& name,
|
|||
this->resized_signatures_ = true;
|
||||
}
|
||||
|
||||
std::pair<Signatures::iterator, bool> ins(
|
||||
this->signatures_.insert(std::make_pair(name, *candidate)));
|
||||
Kept_section candidate;
|
||||
std::pair<Signatures::iterator, bool> ins =
|
||||
this->signatures_.insert(std::make_pair(name, candidate));
|
||||
|
||||
if (kept_section)
|
||||
if (kept_section != NULL)
|
||||
*kept_section = &ins.first->second;
|
||||
if (ins.second)
|
||||
{
|
||||
// This is the first time we've seen this signature.
|
||||
ins.first->second.set_object(object);
|
||||
ins.first->second.set_shndx(shndx);
|
||||
if (is_comdat)
|
||||
ins.first->second.set_is_comdat();
|
||||
if (is_group_name)
|
||||
ins.first->second.set_is_group_name();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ins.first->second.is_group)
|
||||
// We have already seen this signature.
|
||||
|
||||
if (ins.first->second.is_group_name())
|
||||
{
|
||||
// We've already seen a real section group with this signature.
|
||||
// If the kept group is from a plugin object, and we're in
|
||||
// the replacement phase, accept the new one as a replacement.
|
||||
if (ins.first->second.object == NULL
|
||||
// If the kept group is from a plugin object, and we're in the
|
||||
// replacement phase, accept the new one as a replacement.
|
||||
if (ins.first->second.object() == NULL
|
||||
&& parameters->options().plugins()->in_replacement_phase())
|
||||
{
|
||||
ins.first->second = *candidate;
|
||||
ins.first->second.set_object(object);
|
||||
ins.first->second.set_shndx(shndx);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (candidate->is_group)
|
||||
else if (is_group_name)
|
||||
{
|
||||
// This is a real section group, and we've already seen a
|
||||
// linkonce section with this signature. Record that we've seen
|
||||
// a section group, and don't include this section group.
|
||||
ins.first->second.is_group = true;
|
||||
ins.first->second.set_is_group_name();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
@ -3105,25 +3117,10 @@ Layout::find_or_add_kept_section(const std::string& name,
|
|||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the given comdat signature, and return the object and section
|
||||
// index of the kept group.
|
||||
Relobj*
|
||||
Layout::find_kept_object(const std::string& signature,
|
||||
unsigned int* pshndx) const
|
||||
{
|
||||
Signatures::const_iterator p = this->signatures_.find(signature);
|
||||
if (p == this->signatures_.end())
|
||||
return NULL;
|
||||
if (pshndx != NULL)
|
||||
*pshndx = p->second.shndx;
|
||||
return p->second.object;
|
||||
}
|
||||
|
||||
// Store the allocated sections into the section list.
|
||||
|
||||
void
|
||||
|
|
214
gold/layout.h
214
gold/layout.h
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include <cstring>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
@ -90,35 +91,192 @@ class Layout_task_runner : public Task_function_runner
|
|||
Mapfile* mapfile_;
|
||||
};
|
||||
|
||||
// This struct holds information about the comdat or .gnu.linkonce
|
||||
// that will be kept.
|
||||
// This class holds information about the comdat group or
|
||||
// .gnu.linkonce section that will be kept for a given signature.
|
||||
|
||||
struct Kept_section
|
||||
class Kept_section
|
||||
{
|
||||
private:
|
||||
// For a comdat group, we build a mapping from the name of each
|
||||
// section in the group to the section index and the size in object.
|
||||
// When we discard a group in some other object file, we use this
|
||||
// map to figure out which kept section the discarded section is
|
||||
// associated with. We then use that mapping when processing relocs
|
||||
// against discarded sections.
|
||||
struct Comdat_section_info
|
||||
{
|
||||
// The section index.
|
||||
unsigned int shndx;
|
||||
// The section size.
|
||||
uint64_t size;
|
||||
|
||||
Comdat_section_info(unsigned int a_shndx, uint64_t a_size)
|
||||
: shndx(a_shndx), size(a_size)
|
||||
{ }
|
||||
};
|
||||
|
||||
// Most comdat groups have only one or two sections, so we use a
|
||||
// std::map rather than an Unordered_map to optimize for that case
|
||||
// without paying too heavily for groups with more sections.
|
||||
typedef std::map<std::string, Comdat_section_info> Comdat_group;
|
||||
|
||||
public:
|
||||
Kept_section()
|
||||
: object(NULL), shndx(0), is_group(false), group_sections(NULL)
|
||||
{ }
|
||||
Kept_section(Relobj* a_object, unsigned int a_shndx, bool a_is_group)
|
||||
: object(a_object), shndx(a_shndx), is_group(a_is_group),
|
||||
group_sections(NULL)
|
||||
{ }
|
||||
: object_(NULL), shndx_(0), is_comdat_(false), is_group_name_(false)
|
||||
{ this->u_.linkonce_size = 0; }
|
||||
|
||||
typedef Unordered_map<std::string, unsigned int> Comdat_group;
|
||||
// We need to support copies for the signature map in the Layout
|
||||
// object, but we should never copy an object after it has been
|
||||
// marked as a comdat section.
|
||||
Kept_section(const Kept_section& k)
|
||||
: object_(k.object_), shndx_(k.shndx_), is_comdat_(false),
|
||||
is_group_name_(k.is_group_name_)
|
||||
{
|
||||
gold_assert(!k.is_comdat_);
|
||||
this->u_.linkonce_size = 0;
|
||||
}
|
||||
|
||||
// The object containing the comdat or .gnu.linkonce.
|
||||
Relobj* object;
|
||||
// Index to the group section for comdats and the section itself for
|
||||
~Kept_section()
|
||||
{
|
||||
if (this->is_comdat_)
|
||||
delete this->u_.group_sections;
|
||||
}
|
||||
|
||||
// The object where this section lives.
|
||||
Relobj*
|
||||
object() const
|
||||
{ return this->object_; }
|
||||
|
||||
// Set the object.
|
||||
void
|
||||
set_object(Relobj* object)
|
||||
{
|
||||
gold_assert(this->object_ == NULL);
|
||||
this->object_ = object;
|
||||
}
|
||||
|
||||
// The section index.
|
||||
unsigned int
|
||||
shndx() const
|
||||
{ return this->shndx_; }
|
||||
|
||||
// Set the section index.
|
||||
void
|
||||
set_shndx(unsigned int shndx)
|
||||
{
|
||||
gold_assert(this->shndx_ == 0);
|
||||
this->shndx_ = shndx;
|
||||
}
|
||||
|
||||
// Whether this is a comdat group.
|
||||
bool
|
||||
is_comdat() const
|
||||
{ return this->is_comdat_; }
|
||||
|
||||
// Set that this is a comdat group.
|
||||
void
|
||||
set_is_comdat()
|
||||
{
|
||||
gold_assert(!this->is_comdat_);
|
||||
this->is_comdat_ = true;
|
||||
this->u_.group_sections = new Comdat_group();
|
||||
}
|
||||
|
||||
// Whether this is associated with the name of a group or section
|
||||
// rather than the symbol name derived from a linkonce section.
|
||||
bool
|
||||
is_group_name() const
|
||||
{ return this->is_group_name_; }
|
||||
|
||||
// Note that this represents a comdat group rather than a single
|
||||
// linkonce section.
|
||||
void
|
||||
set_is_group_name()
|
||||
{ this->is_group_name_ = true; }
|
||||
|
||||
// Add a section to the group list.
|
||||
void
|
||||
add_comdat_section(const std::string& name, unsigned int shndx,
|
||||
uint64_t size)
|
||||
{
|
||||
gold_assert(this->is_comdat_);
|
||||
Comdat_section_info sinfo(shndx, size);
|
||||
this->u_.group_sections->insert(std::make_pair(name, sinfo));
|
||||
}
|
||||
|
||||
// Look for a section name in the group list, and return whether it
|
||||
// was found. If found, returns the section index and size.
|
||||
bool
|
||||
find_comdat_section(const std::string& name, unsigned int *pshndx,
|
||||
uint64_t *psize) const
|
||||
{
|
||||
gold_assert(this->is_comdat_);
|
||||
Comdat_group::const_iterator p = this->u_.group_sections->find(name);
|
||||
if (p == this->u_.group_sections->end())
|
||||
return false;
|
||||
*pshndx = p->second.shndx;
|
||||
*psize = p->second.size;
|
||||
return true;
|
||||
}
|
||||
|
||||
// If there is only one section in the group list, return true, and
|
||||
// return the section index and size.
|
||||
bool
|
||||
find_single_comdat_section(unsigned int *pshndx, uint64_t *psize) const
|
||||
{
|
||||
gold_assert(this->is_comdat_);
|
||||
if (this->u_.group_sections->size() != 1)
|
||||
return false;
|
||||
Comdat_group::const_iterator p = this->u_.group_sections->begin();
|
||||
*pshndx = p->second.shndx;
|
||||
*psize = p->second.size;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return the size of a linkonce section.
|
||||
uint64_t
|
||||
linkonce_size() const
|
||||
{
|
||||
gold_assert(!this->is_comdat_);
|
||||
return this->u_.linkonce_size;
|
||||
}
|
||||
|
||||
// Set the size of a linkonce section.
|
||||
void
|
||||
set_linkonce_size(uint64_t size)
|
||||
{
|
||||
gold_assert(!this->is_comdat_);
|
||||
this->u_.linkonce_size = size;
|
||||
}
|
||||
|
||||
private:
|
||||
// No assignment.
|
||||
Kept_section& operator=(const Kept_section&);
|
||||
|
||||
// The object containing the comdat group or .gnu.linkonce section.
|
||||
Relobj* object_;
|
||||
// Index of the group section for comdats and the section itself for
|
||||
// .gnu.linkonce.
|
||||
unsigned int shndx;
|
||||
unsigned int shndx_;
|
||||
// True if this is for a comdat group rather than a .gnu.linkonce
|
||||
// section.
|
||||
bool is_comdat_;
|
||||
// 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 is_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;
|
||||
bool is_group_name_;
|
||||
union
|
||||
{
|
||||
// If the is_comdat_ field is true, this holds a map from names of
|
||||
// the sections in the group to section indexes in object_ and to
|
||||
// section sizes.
|
||||
Comdat_group* group_sections;
|
||||
// If the is_comdat_ field is false, this holds the size of the
|
||||
// single section.
|
||||
uint64_t linkonce_size;
|
||||
} u_;
|
||||
};
|
||||
|
||||
// This class handles the details of laying out input sections.
|
||||
|
@ -270,20 +428,14 @@ class Layout
|
|||
// Check if a comdat group or .gnu.linkonce section with the given
|
||||
// NAME is selected for the link. If there is already a section,
|
||||
// *KEPT_SECTION is set to point to the signature and the function
|
||||
// returns false. Otherwise, the CANDIDATE signature is recorded
|
||||
// for this NAME in the layout object, *KEPT_SECTION is set to the
|
||||
// internal copy and the function return false. In some cases, with
|
||||
// CANDIDATE->GROUP_ being false, KEPT_SECTION can point back to
|
||||
// CANDIDATE.
|
||||
// returns false. Otherwise, OBJECT, SHNDX,IS_COMDAT, and
|
||||
// IS_GROUP_NAME are recorded for this NAME in the layout object,
|
||||
// *KEPT_SECTION is set to the internal copy and the function return
|
||||
// false.
|
||||
bool
|
||||
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.
|
||||
Relobj*
|
||||
find_kept_object(const std::string&, unsigned int*) const;
|
||||
find_or_add_kept_section(const std::string& name, Relobj* object,
|
||||
unsigned int shndx, bool is_comdat,
|
||||
bool is_group_name, Kept_section** kept_section);
|
||||
|
||||
// Finalize the layout after all the input sections have been added.
|
||||
off_t
|
||||
|
|
180
gold/object.cc
180
gold/object.cc
|
@ -686,24 +686,20 @@ 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;
|
||||
Sized_relobj<size, big_endian>* kept_object = NULL;
|
||||
Kept_section::Comdat_group* kept_group = NULL;
|
||||
bool is_comdat;
|
||||
Kept_section* kept_section = NULL;
|
||||
|
||||
if ((flags & elfcpp::GRP_COMDAT) == 0)
|
||||
include_group = true;
|
||||
{
|
||||
include_group = true;
|
||||
is_comdat = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
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));
|
||||
this, index, true,
|
||||
true, &kept_section);
|
||||
is_comdat = true;
|
||||
}
|
||||
|
||||
size_t count = shdr.get_sh_size() / sizeof(elfcpp::Elf_Word);
|
||||
|
@ -715,27 +711,27 @@ Sized_relobj<size, big_endian>::include_section_group(
|
|||
|
||||
for (size_t i = 1; i < count; ++i)
|
||||
{
|
||||
elfcpp::Elf_Word secnum =
|
||||
elfcpp::Elf_Word shndx =
|
||||
this->adjust_shndx(elfcpp::Swap<32, big_endian>::readval(pword + i));
|
||||
|
||||
if (relocate_group)
|
||||
shndxes.push_back(secnum);
|
||||
shndxes.push_back(shndx);
|
||||
|
||||
if (secnum >= this->shnum())
|
||||
if (shndx >= this->shnum())
|
||||
{
|
||||
this->error(_("section %u in section group %u out of range"),
|
||||
secnum, index);
|
||||
shndx, index);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for an earlier section number, since we're going to get
|
||||
// it wrong--we may have already decided to include the section.
|
||||
if (secnum < index)
|
||||
if (shndx < index)
|
||||
this->error(_("invalid section group %u refers to earlier section %u"),
|
||||
index, secnum);
|
||||
index, shndx);
|
||||
|
||||
// Get the name of the member section.
|
||||
typename This::Shdr member_shdr(shdrs + secnum * This::shdr_size);
|
||||
typename This::Shdr member_shdr(shdrs + shndx * This::shdr_size);
|
||||
if (member_shdr.get_sh_name() >= section_names_size)
|
||||
{
|
||||
// This is an error, but it will be diagnosed eventually
|
||||
|
@ -745,29 +741,53 @@ Sized_relobj<size, big_endian>::include_section_group(
|
|||
}
|
||||
std::string mname(section_names + member_shdr.get_sh_name());
|
||||
|
||||
if (!include_group)
|
||||
if (include_group)
|
||||
{
|
||||
if (is_comdat)
|
||||
kept_section->add_comdat_section(mname, shndx,
|
||||
member_shdr.get_sh_size());
|
||||
}
|
||||
else
|
||||
{
|
||||
(*omit)[secnum] = true;
|
||||
if (kept_group != NULL)
|
||||
(*omit)[shndx] = true;
|
||||
|
||||
if (is_comdat)
|
||||
{
|
||||
// Find the corresponding kept section, and store that info
|
||||
// in the discarded section table.
|
||||
Kept_section::Comdat_group::const_iterator p =
|
||||
kept_group->find(mname);
|
||||
if (p != kept_group->end())
|
||||
{
|
||||
Kept_comdat_section* kept =
|
||||
new Kept_comdat_section(kept_object, p->second);
|
||||
this->set_kept_comdat_section(secnum, kept);
|
||||
}
|
||||
Relobj* kept_object = kept_section->object();
|
||||
if (kept_section->is_comdat())
|
||||
{
|
||||
// Find the corresponding kept section, and store
|
||||
// that info in the discarded section table.
|
||||
unsigned int kept_shndx;
|
||||
uint64_t kept_size;
|
||||
if (kept_section->find_comdat_section(mname, &kept_shndx,
|
||||
&kept_size))
|
||||
{
|
||||
// We don't keep a mapping for this section if
|
||||
// it has a different size. The mapping is only
|
||||
// used for relocation processing, and we don't
|
||||
// want to treat the sections as similar if the
|
||||
// sizes are different. Checking the section
|
||||
// size is the approach used by the GNU linker.
|
||||
if (kept_size == member_shdr.get_sh_size())
|
||||
this->set_kept_comdat_section(shndx, kept_object,
|
||||
kept_shndx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The existing section is a linkonce section. Add
|
||||
// a mapping if there is exactly one section in the
|
||||
// group (which is true when COUNT == 2) and if it
|
||||
// is the same size.
|
||||
if (count == 2
|
||||
&& (kept_section->linkonce_size()
|
||||
== member_shdr.get_sh_size()))
|
||||
this->set_kept_comdat_section(shndx, kept_object,
|
||||
kept_section->shndx());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (flags & elfcpp::GRP_COMDAT)
|
||||
{
|
||||
// Add the section to the kept group table.
|
||||
gold_assert(kept_group != NULL);
|
||||
kept_group->insert(std::make_pair(mname, secnum));
|
||||
}
|
||||
}
|
||||
|
||||
if (relocate_group)
|
||||
|
@ -798,8 +818,9 @@ Sized_relobj<size, big_endian>::include_linkonce_section(
|
|||
Layout* layout,
|
||||
unsigned int index,
|
||||
const char* name,
|
||||
const elfcpp::Shdr<size, big_endian>&)
|
||||
const elfcpp::Shdr<size, big_endian>& shdr)
|
||||
{
|
||||
typename elfcpp::Elf_types<size>::Elf_WXword sh_size = shdr.get_sh_size();
|
||||
// In general the symbol name we want will be the string following
|
||||
// the last '.'. However, we have to handle the case of
|
||||
// .gnu.linkonce.t.__i686.get_pc_thunk.bx, which was generated by
|
||||
|
@ -816,29 +837,24 @@ Sized_relobj<size, big_endian>::include_linkonce_section(
|
|||
symname = strrchr(name, '.') + 1;
|
||||
std::string sig1(symname);
|
||||
std::string sig2(name);
|
||||
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);
|
||||
bool include1 = layout->find_or_add_kept_section(sig1, this, index, false,
|
||||
false, &kept1);
|
||||
bool include2 = layout->find_or_add_kept_section(sig2, this, index, false,
|
||||
true, &kept2);
|
||||
|
||||
if (!include2)
|
||||
{
|
||||
// The section is being discarded on the basis of its 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 = kept2->shndx;
|
||||
Relobj* kept_relobj = kept2->object;
|
||||
if (kept_relobj != NULL)
|
||||
{
|
||||
Sized_relobj<size, big_endian>* kept_object =
|
||||
static_cast<Sized_relobj<size, big_endian>*>(kept_relobj);
|
||||
Kept_comdat_section* kept =
|
||||
new Kept_comdat_section(kept_object, kept_group_index);
|
||||
this->set_kept_comdat_section(index, kept);
|
||||
}
|
||||
// We are not including this section because we already saw the
|
||||
// name of the section as a signature. This normally implies
|
||||
// that the kept section is another linkonce section. If it is
|
||||
// the same size, record it as the section which corresponds to
|
||||
// this one.
|
||||
if (kept2->object() != NULL
|
||||
&& !kept2->is_comdat()
|
||||
&& kept2->linkonce_size() == sh_size)
|
||||
this->set_kept_comdat_section(index, kept2->object(), kept2->shndx());
|
||||
}
|
||||
else if (!include1)
|
||||
{
|
||||
|
@ -849,22 +865,18 @@ 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.
|
||||
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);
|
||||
Kept_section::Comdat_group* kept_group = kept1->group_sections;
|
||||
if (kept_group != NULL && kept_group->size() == 1)
|
||||
{
|
||||
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);
|
||||
this->set_kept_comdat_section(index, kept);
|
||||
}
|
||||
}
|
||||
unsigned int kept_shndx;
|
||||
uint64_t kept_size;
|
||||
if (kept1->object() != NULL
|
||||
&& kept1->is_comdat()
|
||||
&& kept1->find_single_comdat_section(&kept_shndx, &kept_size)
|
||||
&& kept_size == sh_size)
|
||||
this->set_kept_comdat_section(index, kept1->object(), kept_shndx);
|
||||
}
|
||||
else
|
||||
{
|
||||
kept1->set_linkonce_size(sh_size);
|
||||
kept2->set_linkonce_size(sh_size);
|
||||
}
|
||||
|
||||
return include1 && include2;
|
||||
|
@ -1216,7 +1228,7 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
|
|||
out_sections[i] = reinterpret_cast<Output_section*>(2);
|
||||
out_section_offsets[i] = invalid_address;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// During gc_pass_two if a section that was previously deferred is
|
||||
// found, do not layout the section as layout_deferred_sections will
|
||||
// do it later from gold.cc.
|
||||
|
@ -1915,15 +1927,19 @@ Sized_relobj<size, big_endian>::map_to_kept_section(
|
|||
unsigned int shndx,
|
||||
bool* found) const
|
||||
{
|
||||
Kept_comdat_section *kept = this->get_kept_comdat_section(shndx);
|
||||
if (kept != NULL)
|
||||
Relobj* kept_object;
|
||||
unsigned int kept_shndx;
|
||||
if (this->get_kept_comdat_section(shndx, &kept_object, &kept_shndx))
|
||||
{
|
||||
gold_assert(kept->object_ != NULL);
|
||||
*found = true;
|
||||
Output_section* os = kept->object_->output_section(kept->shndx_);
|
||||
Address offset = kept->object_->get_output_section_offset(kept->shndx_);
|
||||
Sized_relobj<size, big_endian>* kept_relobj =
|
||||
static_cast<Sized_relobj<size, big_endian>*>(kept_object);
|
||||
Output_section* os = kept_relobj->output_section(kept_shndx);
|
||||
Address offset = kept_relobj->get_output_section_offset(kept_shndx);
|
||||
if (os != NULL && offset != invalid_address)
|
||||
return os->address() + offset;
|
||||
{
|
||||
*found = true;
|
||||
return os->address() + offset;
|
||||
}
|
||||
}
|
||||
*found = false;
|
||||
return 0;
|
||||
|
|
|
@ -1590,14 +1590,13 @@ class Sized_relobj : public Relobj
|
|||
// kept section.
|
||||
struct Kept_comdat_section
|
||||
{
|
||||
Kept_comdat_section(Sized_relobj<size, big_endian>* object,
|
||||
unsigned int shndx)
|
||||
: object_(object), shndx_(shndx)
|
||||
Kept_comdat_section(Relobj* a_object, unsigned int a_shndx)
|
||||
: object(a_object), shndx(a_shndx)
|
||||
{ }
|
||||
Sized_relobj<size, big_endian>* object_;
|
||||
unsigned int shndx_;
|
||||
Relobj* object;
|
||||
unsigned int shndx;
|
||||
};
|
||||
typedef std::map<unsigned int, Kept_comdat_section*>
|
||||
typedef std::map<unsigned int, Kept_comdat_section>
|
||||
Kept_comdat_section_table;
|
||||
|
||||
// Adjust a section index if necessary.
|
||||
|
@ -1729,20 +1728,26 @@ class Sized_relobj : public Relobj
|
|||
// Record a mapping from discarded section SHNDX to the corresponding
|
||||
// kept section.
|
||||
void
|
||||
set_kept_comdat_section(unsigned int shndx, Kept_comdat_section* kept)
|
||||
set_kept_comdat_section(unsigned int shndx, Relobj* kept_object,
|
||||
unsigned int kept_shndx)
|
||||
{
|
||||
this->kept_comdat_sections_[shndx] = kept;
|
||||
Kept_comdat_section kept(kept_object, kept_shndx);
|
||||
this->kept_comdat_sections_.insert(std::make_pair(shndx, kept));
|
||||
}
|
||||
|
||||
// Find the kept section corresponding to the discarded section SHNDX.
|
||||
Kept_comdat_section*
|
||||
get_kept_comdat_section(unsigned int shndx) const
|
||||
// Find the kept section corresponding to the discarded section
|
||||
// SHNDX. Return true if found.
|
||||
bool
|
||||
get_kept_comdat_section(unsigned int shndx, Relobj** kept_object,
|
||||
unsigned int* kept_shndx) const
|
||||
{
|
||||
typename Kept_comdat_section_table::const_iterator p =
|
||||
this->kept_comdat_sections_.find(shndx);
|
||||
if (p == this->kept_comdat_sections_.end())
|
||||
return NULL;
|
||||
return p->second;
|
||||
return false;
|
||||
*kept_object = p->second.object;
|
||||
*kept_shndx = p->second.shndx;
|
||||
return true;
|
||||
}
|
||||
|
||||
// The GOT offsets of local symbols. This map also stores GOT offsets
|
||||
|
|
|
@ -509,12 +509,9 @@ 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)
|
||||
{
|
||||
Kept_section to_add(NULL, 1, true);
|
||||
ins.first->second = layout->find_or_add_kept_section(comdat_key,
|
||||
&to_add,
|
||||
NULL);
|
||||
}
|
||||
ins.first->second = layout->find_or_add_kept_section(comdat_key,
|
||||
NULL, 0, true,
|
||||
true, NULL);
|
||||
|
||||
return ins.first->second;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue