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]

PATCH: readelf: Apply relocation addends to whole section


This patch applies relocation addends to whole section once instead of
in pieces.

FYI, both the current and new debug_apply_rela_addends assumes the
relocation field size is fixed. But this is wrong. On x86-64, 
relocations with both 32bit and 64bit fields, R_X86_64_32 and
R_X86_64_64, may be used in DWARF info. We are lucky so far since
we don't have appends > 32bits even for 64bit fields in most cases. To
properly fix it, we need to get the field size based on the relocation
type.


H.J.
----
2005-09-02  H.J. Lu  <hongjiu.lu@intel.com>

	* readelf.c (debug_apply_rela_addends): Relocate the whole
	section.
	(process_debug_info): Don't call debug_apply_rela_addends.
	(display_debug_frames): Likewise.
	(get_debug_info): Call debug_apply_rela_addends.
	(debug_displays): Add the "relocate" field.
	(display_debug_section): Call debug_apply_rela_addends if
	needed.

--- binutils/readelf.c.reloc	2005-09-02 08:27:45.000000000 -0700
+++ binutils/readelf.c	2005-09-02 11:38:33.000000000 -0700
@@ -7747,14 +7747,17 @@ free_debug_abbrev (void)
 static int
 debug_apply_rela_addends (FILE *file,
 			  Elf_Internal_Shdr *section,
-			  int reloc_size,
-			  unsigned char *sec_data,
-			  unsigned char *start,
-			  unsigned char *end)
+			  unsigned char *start)
 {
   Elf_Internal_Shdr *relsec;
+  unsigned char *end = start + section->sh_size;
+  /* FIXME: The relocation field size is relocation type dependent.  */
+  unsigned int reloc_size = 4;
+
+  if (elf_header.e_type != ET_REL)
+    return 1;
 
-  if (end - start < reloc_size)
+  if (section->sh_size < reloc_size)
     return 1;
 
   for (relsec = section_headers;
@@ -7785,11 +7788,14 @@ debug_apply_rela_addends (FILE *file,
 	{
 	  unsigned char *loc;
 
-	  if (rp->r_offset >= (bfd_vma) (start - sec_data)
-	      && rp->r_offset < (bfd_vma) (end - sec_data) - reloc_size)
-	    loc = sec_data + rp->r_offset;
-	  else
-	    continue;
+	  loc = start + rp->r_offset;
+	  if ((loc + reloc_size) > end)
+	    {
+	      warn (_("skipping invalid relocation offset 0x%lx in section %s\n"),
+		    (unsigned long) rp->r_offset,
+		    SECTION_NAME (section));
+	      continue;
+	    }
 
 	  if (is_32bit_elf)
 	    {
@@ -9177,11 +9183,6 @@ process_debug_info (Elf_Internal_Shdr *s
       cu_offset = start - section_begin;
       start += compunit.cu_length + initial_length_size;
 
-      if (elf_header.e_type == ET_REL
-	  && !debug_apply_rela_addends (file, section, offset_size,
-					section_begin, hdrptr, start))
-	return 0;
-
       cu_abbrev_offset_ptr = hdrptr;
       compunit.cu_abbrev_offset = byte_get (hdrptr, offset_size);
       hdrptr += offset_size;
@@ -9393,7 +9394,9 @@ get_debug_info (FILE * file)
   if (start == NULL)
     return 0;
 
-  ret = process_debug_info (section, start, file, 1);
+  ret = (debug_apply_rela_addends (file, section, start)
+	 && process_debug_info (section, start, file, 1));
+
   free (start);
 
   return ret ? num_debug_info_entries : 0;
@@ -10594,11 +10597,6 @@ display_debug_frames (Elf_Internal_Shdr 
       block_end = saved_start + length + initial_length_size;
       cie_id = byte_get (start, offset_size); start += offset_size;
 
-      if (elf_header.e_type == ET_REL
-	  && !debug_apply_rela_addends (file, section, offset_size,
-					section_start, start, block_end))
-	return 0;
-
       if (is_eh ? (cie_id == 0) : (cie_id == DW_CIE_ID))
 	{
 	  int version;
@@ -11236,25 +11234,26 @@ static struct
 {
   const char *const name;
   int (*display) (Elf_Internal_Shdr *, unsigned char *, FILE *);
+  unsigned int relocate : 1;
 }
 debug_displays[] =
 {
-  { ".debug_abbrev",		display_debug_abbrev },
-  { ".debug_aranges",		display_debug_aranges },
-  { ".debug_frame",		display_debug_frames },
-  { ".debug_info",		display_debug_info },
-  { ".debug_line",		display_debug_lines },
-  { ".debug_pubnames",		display_debug_pubnames },
-  { ".eh_frame",		display_debug_frames },
-  { ".debug_macinfo",		display_debug_macinfo },
-  { ".debug_str",		display_debug_str },
-  { ".debug_loc",		display_debug_loc },
-  { ".debug_pubtypes",		display_debug_pubnames },
-  { ".debug_ranges",		display_debug_ranges },
-  { ".debug_static_func",	display_debug_not_supported },
-  { ".debug_static_vars",	display_debug_not_supported },
-  { ".debug_types",		display_debug_not_supported },
-  { ".debug_weaknames",		display_debug_not_supported }
+  { ".debug_abbrev",		display_debug_abbrev,		0 },
+  { ".debug_aranges",		display_debug_aranges,		0 },
+  { ".debug_frame",		display_debug_frames,		1 },
+  { ".debug_info",		display_debug_info,		1 },
+  { ".debug_line",		display_debug_lines,		0 },
+  { ".debug_pubnames",		display_debug_pubnames,		0 },
+  { ".eh_frame",		display_debug_frames,		1 },
+  { ".debug_macinfo",		display_debug_macinfo,		0 },
+  { ".debug_str",		display_debug_str,		0 },
+  { ".debug_loc",		display_debug_loc,		0 },
+  { ".debug_pubtypes",		display_debug_pubnames,		0 },
+  { ".debug_ranges",		display_debug_ranges,		0 },
+  { ".debug_static_func",	display_debug_not_supported,	0 },
+  { ".debug_static_vars",	display_debug_not_supported,	0 },
+  { ".debug_types",		display_debug_not_supported,	0 },
+  { ".debug_weaknames",		display_debug_not_supported,	0 }
 };
 
 static int
@@ -11289,7 +11288,10 @@ display_debug_section (Elf_Internal_Shdr
 	    break;
 	  }
 
-	result &= debug_displays[i].display (section, start, file);
+	if (!debug_displays[i].relocate
+	    || debug_apply_rela_addends (file, section, start))
+	  result &= debug_displays[i].display (section, start, file);
+
 	free (start);
 
 	/* If we loaded in the abbrev section


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