OSDN Git Service

PR 10400
authorIan Lance Taylor <ian@airs.com>
Fri, 17 Jul 2009 01:07:33 +0000 (01:07 +0000)
committerIan Lance Taylor <ian@airs.com>
Fri, 17 Jul 2009 01:07:33 +0000 (01:07 +0000)
* 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.

gold/ChangeLog
gold/layout.cc
gold/layout.h
gold/object.cc
gold/object.h
gold/plugin.cc

index 974a49f..8262c60 100644 (file)
@@ -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):
index e8625d2..0093c29 100644 (file)
@@ -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
index 86234a1..0affa81 100644 (file)
@@ -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; }
+
+  // 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;
+  }
+
+  ~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;
+  }
 
-  typedef Unordered_map<std::string, unsigned int> Comdat_group;
+  // 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;
+  }
 
-  // The object containing the comdat or .gnu.linkonce.
-  Relobj* object;
-  // Index to the group section for comdats and the section itself for
+  // 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
index 75e5a2e..1b964d7 100644 (file)
@@ -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)
-    {
-      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_);
+  Relobj* kept_object;
+  unsigned int kept_shndx;
+  if (this->get_kept_comdat_section(shndx, &kept_object, &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;
index d5f111f..dc6a156 100644 (file)
@@ -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
index b1007a7..2a21b8f 100644 (file)
@@ -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;
 }