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]

Re: [patch] SIGSEGV in readelf.c


On Wed, Apr 29, 2009 at 06:05:44AM -0700, Denis Scherbakov wrote:
> I debugged a segmentation fault in readelf.c:5096 while reading an ia64 HP-UX 64-bit binary.
> 
> #define BYTE_GET(field)	byte_get (field, sizeof (field))
> 
> tep->start.offset = BYTE_GET ((unsigned char *) tp +  0);
> tep->end.offset   = BYTE_GET ((unsigned char *) tp +  8);
> tep->info.offset  = BYTE_GET ((unsigned char *) tp + 16);

Oops, this is a bug I introduced when removing BYTE_GET8.  I think the
following is a better fix.

	* readelf.c (slurp_ia64_unwind_table): Correct 64-bit unwind table
	read, and merge with 32-bit case.

Index: binutils/readelf.c
===================================================================
RCS file: /cvs/src/src/binutils/readelf.c,v
retrieving revision 1.442
diff -u -p -r1.442 readelf.c
--- binutils/readelf.c	25 Mar 2009 01:37:18 -0000	1.442
+++ binutils/readelf.c	29 Apr 2009 14:15:49 -0000
@@ -4975,23 +4975,14 @@ slurp_ia64_unwind_table (FILE * file,
 
   aux->table = xcmalloc (size / (3 * eh_addr_size), sizeof (aux->table[0]));
   tep = aux->table;
-  for (tp = table; tp < table + size; tp += 3 * eh_addr_size, ++tep)
+  for (tp = table; tp < table + size; ++tep)
     {
       tep->start.section = SHN_UNDEF;
       tep->end.section   = SHN_UNDEF;
       tep->info.section  = SHN_UNDEF;
-      if (is_32bit_elf)
-	{
-	  tep->start.offset = byte_get ((unsigned char *) tp + 0, 4);
-	  tep->end.offset   = byte_get ((unsigned char *) tp + 4, 4);
-	  tep->info.offset  = byte_get ((unsigned char *) tp + 8, 4);
-	}
-      else
-	{
-	  tep->start.offset = BYTE_GET ((unsigned char *) tp +  0);
-	  tep->end.offset   = BYTE_GET ((unsigned char *) tp +  8);
-	  tep->info.offset  = BYTE_GET ((unsigned char *) tp + 16);
-	}
+      tep->start.offset = byte_get (tp, eh_addr_size); tp += eh_addr_size;
+      tep->end.offset   = byte_get (tp, eh_addr_size); tp += eh_addr_size;
+      tep->info.offset  = byte_get (tp, eh_addr_size); tp += eh_addr_size;
       tep->start.offset += aux->seg_base;
       tep->end.offset   += aux->seg_base;
       tep->info.offset  += aux->seg_base;

-- 
Alan Modra
Australia Development Lab, IBM


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