This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[gold] Error out when there is an access beyond the end of the merged section
- From: Alexander Ivchenko <aivchenk at gmail dot com>
- To: binutils <binutils at sourceware dot org>, Cary Coutant <ccoutant at google dot com>
- Date: Tue, 1 Jul 2014 16:22:53 +0400
- Subject: [gold] Error out when there is an access beyond the end of the merged section
- Authentication-results: sourceware.org; auth=none
Hi,
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:
>ld.gold --eh-frame-hdr -shared -m elf_i386 RenderBox.o
>ld.gold: internal error in value_from_output_section, at binutils-2.24/gold/reloc.cc:1485
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,
e.g:
>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 <alexander.ivchenko@intel.com>
+
+ * merge.cc (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.
+ * reloc.cc (Merged_symbol_value<size>::value_from_output_section):
+ Ditto.
+
2014-06-27 Alan Modra <amodra@gmail.com>
* symtab.cc (Symbol::should_add_dynsym_entry): Don't make inline.
diff --git a/gold/merge.cc b/gold/merge.cc
index 6d444e6..18f7420 100644
--- a/gold/merge.cc
+++ b/gold/merge.cc
@@ -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.
bool
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.
bool
diff --git a/gold/reloc.cc b/gold/reloc.cc
index 115ab37..8f09fef 100644
--- a/gold/reloc.cc
+++ b/gold/reloc.cc
@@ -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,
input_offset,
- &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?
--Alexander