This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

gold patch committed: Only relocate to comdat sections if same size


PR 10400 is about a case where gold is generating bogus debug info for
discarded comdat/linkonce sections.  When the GNU linker sees a
relocation against a discarded section from a debugging section, it acts
as though the relocation were against the section that it kept, but only
if the kept section and the discarded section are the same size.  gold
was doing the same, but it was not checking that the sections are the
same size.

This patch implements the same size check.  It does it by only recording
the mapping from the discarded section to the kept section if the two
sections ar the same size.  Since I was looking at the code, I cleaned
up a bunch of minor stuff along the way.  I clarified the distinction
between whether the signature was added for a group (which can happen
for a linkonce section as well) and whether the section was itself a
group.  I changed the mapping from section names to kept sections in a
group from a hash table to a std::map, since generally there will be
only one section in a comdat group.  I changed Kept_section from a
struct to a class and added accessors and so forth.  I changed the
interface to get_kept_comdat_section to use variables rather than
passing around a struct.

Ian


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.


Index: layout.cc
===================================================================
RCS file: /cvs/src/src/gold/layout.cc,v
retrieving revision 1.131
diff -p -u -r1.131 layout.cc
--- layout.cc	24 Jun 2009 19:48:51 -0000	1.131
+++ layout.cc	17 Jul 2009 01:00:45 -0000
@@ -3045,16 +3045,18 @@ Layout::output_section_name(const char* 
 
 // 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 s
       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 s
       // 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: layout.h
===================================================================
RCS file: /cvs/src/src/gold/layout.h,v
retrieving revision 1.67
diff -p -u -r1.67 layout.h
--- layout.h	24 Jun 2009 19:48:51 -0000	1.67
+++ layout.h	17 Jul 2009 01:00:45 -0000
@@ -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_f
   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;
+  }
 
-  typedef Unordered_map<std::string, unsigned int> Comdat_group;
+  ~Kept_section()
+  {
+    if (this->is_comdat_)
+      delete this->u_.group_sections;
+  }
 
-  // The object containing the comdat or .gnu.linkonce.
-  Relobj* object;
-  // Index to the group section for comdats and the section itself for
+  // 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
Index: object.cc
===================================================================
RCS file: /cvs/src/src/gold/object.cc,v
retrieving revision 1.95
diff -p -u -r1.95 object.cc
--- object.cc	23 Jun 2009 07:19:35 -0000	1.95
+++ object.cc	17 Jul 2009 01:00:45 -0000
@@ -686,24 +686,20 @@ Sized_relobj<size, big_endian>::include_
   // 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_
 
   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_
         }
       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_
     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_
     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_
       // 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_layou
           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_k
     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: object.h
===================================================================
RCS file: /cvs/src/src/gold/object.h,v
retrieving revision 1.75
diff -p -u -r1.75 object.h
--- object.h	5 Jun 2009 18:16:31 -0000	1.75
+++ object.h	17 Jul 2009 01:00:45 -0000
@@ -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: plugin.cc
===================================================================
RCS file: /cvs/src/src/gold/plugin.cc,v
retrieving revision 1.15
diff -p -u -r1.15 plugin.cc
--- plugin.cc	15 May 2009 17:01:04 -0000	1.15
+++ plugin.cc	17 Jul 2009 01:00:45 -0000
@@ -509,12 +509,9 @@ Pluginobj::include_comdat_group(std::str
   // 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;
 }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]