This is the mail archive of the 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] Error out when there is an access beyond the end of the merged section


Currently, when there is an access beyond the end of the merged
section (I faced that situation when linking the object file with
badly-generated debug info), gold will crash with internal error:

> --eh-frame-hdr  -shared -m elf_i386 RenderBox.o
> internal error in value_from_output_section, at binutils-2.24/gold/

While gnu ld will warn us about it and finish the job:

>ld.bfd --eh-frame-hdr  -shared -m elf_i386 RenderBox.o
ld.bfd: RenderBox.o: access beyond end of merged section (1997144320)

Internal error is in any way a wrong thing here, because there is
clearly a problem with an object file itself. The following patch adds
an error message when gold sees an incorrect access in merged section,

>ld-new  --eh-frame-hdr  -shared -m elf_i386 RenderBox.o
ld-new: error: RenderBox.o: access beyond end of merged section (1997144320)

diff --git a/gold/ChangeLog b/gold/ChangeLog
index 264f127..0b617ca 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,13 @@
+2014-07-01  Alexander Ivchenko  <>
+ * (Object_merge_map::get_output_offset): error out when we see
+ that there is an access beyond the end of the merged section.
+ * merge.h (Object_merge_map::get_output_offset): Add new argument.
+ (Merge_map::get_output_offset): Adjust
+ Object_merge_map::get_output_offset call with additional argument.
+ * (Merged_symbol_value<size>::value_from_output_section):
+ Ditto.
 2014-06-27  Alan Modra  <>

  * (Symbol::should_add_dynsym_entry): Don't make inline.
diff --git a/gold/ b/gold/
index 6d444e6..18f7420 100644
--- a/gold/
+++ b/gold/
@@ -145,7 +145,8 @@ bool
 Object_merge_map::get_output_offset(const Merge_map* merge_map,
     unsigned int shndx,
     section_offset_type input_offset,
-    section_offset_type* output_offset)
+    section_offset_type* output_offset,
+    const Relobj* relobj)
   Input_merge_map* map = this->get_input_merge_map(shndx);
   if (map == NULL
@@ -174,7 +175,13 @@ Object_merge_map::get_output_offset(const
Merge_map* merge_map,

   if (input_offset - p->input_offset
       >= static_cast<section_offset_type>(p->length))
-    return false;
+    {
+      if (relobj == NULL)
+ return false;
+      else
+ relobj->error(_("access beyond end of merged section (%ld)"),
+      input_offset);
+    }

   *output_offset = p->output_offset;
   if (*output_offset != -1)
@@ -268,7 +275,7 @@ Merge_map::get_output_offset(const Relobj* object,
unsigned int shndx,
   if (object_merge_map == NULL)
     return false;
   return object_merge_map->get_output_offset(this, shndx, offset,
-     output_offset);
+     output_offset, NULL);

 // Return whether this is the merge section for SHNDX in OBJECT.
diff --git a/gold/merge.h b/gold/merge.h
index b4fd8e1..6df9879 100644
--- a/gold/merge.h
+++ b/gold/merge.h
@@ -66,11 +66,15 @@ class Object_merge_map
   // to the offset in the output section; this will be -1 if the bytes
   // are not being copied to the output.  This returns true if the
   // mapping is known, false otherwise.  *OUTPUT_OFFSET is relative to
-  // the start of the merged data in the output section.
+  // the start of the merged data in the output section. If RELOBJ
+  // is not NULL, then failure to find the output offset is fatal, but in
+  // some cases we can gracefully finish the job by providing the error
+  // information.
   get_output_offset(const Merge_map*, unsigned int shndx,
     section_offset_type offset,
-    section_offset_type* output_offset);
+    section_offset_type* output_offset,
+    const Relobj* relobj);

   // Return whether this is the merge map for section SHNDX.
diff --git a/gold/ b/gold/
index 115ab37..8f09fef 100644
--- a/gold/
+++ b/gold/
@@ -1476,7 +1476,8 @@ Merged_symbol_value<size>::value_from_output_section(
   section_offset_type output_offset;
   bool found = object->merge_map()->get_output_offset(NULL, input_shndx,
-      &output_offset);
+      &output_offset,
+      object);

   // If this assertion fails, it means that some relocation was
   // against a portion of an input merge section which we didn't map

 Is it ok?


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