This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [patch] SIGSEGV in readelf.c
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: Denis Scherbakov <denis_scherbakov at yahoo dot com>
- Cc: binutils at sources dot redhat dot com
- Date: Wed, 29 Apr 2009 23:52:03 +0930
- Subject: Re: [patch] SIGSEGV in readelf.c
- References: <380354.35703.qm@web65412.mail.ac4.yahoo.com>
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