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] proposed fix for PR/23016


Hi all,

The patch below is a first draft of a fix for PR binutils/23016; hoping
to solicit comments.

For relocatable links, this add some logic to avoid merging two input
relocation sections if the sections targeted by said relocations have
different section types. The motivating example for this change is a
relocatable link on X86_64 that includes objects compiled by
Clang/LLVM (which uses a section type of X86_64_UNWIND for the
.eh_frame section) and GCC (which uses a section type of PROGBITS),
resulting in an assert in output.h.

I would welcome suggestions on how to write a test for this fix: in
order to trigger the problematic scenario there needs to be a
relocatable link with two input files each containing an input section
(with relocations) with the same name/flags but different section
types-- not sure how to accomplish that short of writing in assembler
(maybe there is some C compiler option I could use that would
perturb section types?).

I'd also like to ask for opinions on whether it makes sense to extend
this to avoid merging in the case where the target sections of the two
relocation sections have different flags (as opposed to types).

Thanks, Than

gold/
2018-03-30  Than McIntosh  <thanm@google.com>

        * output.h (Output_section::get_info_section): New method.
        * layout.cc (Layout::layout_reloc):
        Change logic for merging relocation sections.

diff --git a/gold/layout.cc b/gold/layout.cc
index f5fe805ea..860fe42d6 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -1338,16 +1338,35 @@ Layout::layout_reloc(Sized_relobj_file<size,
big_endian>* object,
   // In a relocatable link relocs for a grouped section must not be
   // combined with other reloc sections.
   Output_section* os;
-  if (!parameters->options().relocatable()
-      || (data_section->flags() & elfcpp::SHF_GROUP) == 0)
-    os = this->choose_output_section(object, name.c_str(), sh_type,
-      shdr.get_sh_flags(), false,
-      ORDER_INVALID, false, true, false);
+  if (parameters->options().relocatable())
+    {
+      if ((data_section->flags() & elfcpp::SHF_GROUP) != 0)
+        {
+          const char* n = this->namepool_.add(name.c_str(), true, NULL);
+          os = this->make_output_section(n, sh_type, shdr.get_sh_flags(),
+                                         ORDER_INVALID, false);
+        }
+      else
+        {
+          // Avoid merging two relocation sections if the info sections
+          // to which they refer have different types.
+          os = this->choose_output_section(object, name.c_str(), sh_type,
+                                           shdr.get_sh_flags(), false,
+                                           ORDER_INVALID, false, true, false);
+          if (os->get_info_section() != NULL
+             && os->get_info_section()->type() != data_section->type())
+            {
+              const char* n = this->namepool_.add(name.c_str(), true, NULL);
+              os = this->make_output_section(n, sh_type, shdr.get_sh_flags(),
+                                             ORDER_INVALID, false);
+            }
+        }
+    }
   else
     {
-      const char* n = this->namepool_.add(name.c_str(), true, NULL);
-      os = this->make_output_section(n, sh_type, shdr.get_sh_flags(),
-      ORDER_INVALID, false);
+      os = this->choose_output_section(object, name.c_str(), sh_type,
+                                       shdr.get_sh_flags(), false,
+                                       ORDER_INVALID, false, true, false);
     }

   os->set_should_link_to_symtab();
diff --git a/gold/output.h b/gold/output.h
index c7545ca81..8f959d2ce 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -3388,6 +3388,13 @@ class Output_section : public Output_data
     this->info_uses_section_index_= true;
   }

+  // Return info section for this output section (may be NULL).
+  const Output_section*
+  get_info_section() const
+  {
+    return this->info_section_;
+  }
+
   // Set the info field to the symbol table index of a symbol.
   void
   set_info_symndx(const Symbol* sym)


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