This is the mail archive of the
binutils@sourceware.cygnus.com
mailing list for the binutils project.
patch for readelf - dumping NOTE sections
- To: binutils at sourceware dot cygnus dot com
- Subject: patch for readelf - dumping NOTE sections
- From: fnf at toadfish dot ninemoons dot com
- Date: Wed, 24 Nov 1999 16:02:02 -0700 (MST)
- Cc: fnf at cygnus dot com
While attempting to dump a corefile created on a big endian machine
using a copy of readelf compiled on a little endian host, I ran into a
problem where readelf would try to malloc a huge chunk of memory, and
when that failed, eventually coredump.
I believe this patch fixes the endianness problem, as well as a couple
other minor nits I noticed. One of the nits is that the namesz and
descsz fields do not include the size of any padding needed to align
the note descriptors and also align the next note entry.
While investigating this problem, I discovered that core files
generated on Linux appear to violate the ELF standard that I have, by
not properly null terminating the name field and including the null
byte in the namesz field. This patch still accomodates that, but the
warning to diagnose the problem is currently commented out.
-Fred
Index: ChangeLog
===================================================================
RCS file: /cvs/binutils/binutils/binutils/ChangeLog,v
retrieving revision 1.89
diff -c -r1.89 ChangeLog
*** ChangeLog 1999/11/22 09:42:42 1.89
--- ChangeLog 1999/11/24 22:50:08
***************
*** 1,3 ****
--- 1,13 ----
+ 1999-11-24 Fred Fish <fnf@cygnus.com>
+
+ * readelf.c (process_note): Change arg from Elf_External_Note
+ to Elf32_Internal_Note, which also turns the function body
+ into little more than a call to printf.
+ (process_corefile_note_segment): Substantially rewritten
+ to properly handle case where target and host are different
+ endianness, handle note sections with padding, and add some
+ cruft to handle notes with unterminated name data.
+
1999-11-22 Nick Clifton <nickc@cygnus.com>
* objcopy.c (copy_usage): Reformat.
Index: readelf.c
===================================================================
RCS file: /cvs/binutils/binutils/binutils/readelf.c,v
retrieving revision 1.28
diff -c -r1.28 readelf.c
*** readelf.c 1999/10/04 18:59:13 1.28
--- readelf.c 1999/11/24 22:50:59
***************
*** 200,206 ****
static const char * get_osabi_name PARAMS ((unsigned char));
static int guess_is_rela PARAMS ((unsigned long));
static char * get_note_type PARAMS ((unsigned int));
! static int process_note PARAMS ((Elf_External_Note *));
static int process_corefile_note_segment PARAMS ((FILE *, unsigned long, unsigned long));
static int process_corefile_note_segments PARAMS ((FILE *));
static int process_corefile_contents PARAMS ((FILE *));
--- 200,206 ----
static const char * get_osabi_name PARAMS ((unsigned char));
static int guess_is_rela PARAMS ((unsigned long));
static char * get_note_type PARAMS ((unsigned int));
! static int process_note PARAMS ((Elf32_Internal_Note *));
static int process_corefile_note_segment PARAMS ((FILE *, unsigned long, unsigned long));
static int process_corefile_note_segments PARAMS ((FILE *));
static int process_corefile_contents PARAMS ((FILE *));
***************
*** 6605,6634 ****
}
}
static int
process_note (pnote)
! Elf_External_Note * pnote;
{
- Elf32_Internal_Note * internal;
- char * pname;
-
- internal = (Elf32_Internal_Note *) pnote;
- pname = malloc (internal->namesz + 1);
-
- if (pname == NULL)
- {
- error (_("Out of memory\n"));
- return 0;
- }
-
- memcpy (pname, pnote->name, internal->namesz);
- pname[internal->namesz] = '\0';
-
printf (" %s\t\t0x%08lx\t%s\n",
! pname, internal->descsz, get_note_type (internal->type));
!
! free (pname);
!
return 1;
}
--- 6605,6623 ----
}
}
+ /* Note that by the ELF standard, the name field is already null byte
+ terminated, and namesz includes the terminating null byte.
+ I.E. the value of namesz for the name "FSF" is 4.
+
+ If the value of namesz is zero, there is no name present. */
+
static int
process_note (pnote)
! Elf32_Internal_Note * pnote;
{
printf (" %s\t\t0x%08lx\t%s\n",
! pnote->namesz ? pnote -> namedata : "(NONE)",
! pnote->descsz, get_note_type (pnote->type));
return 1;
}
***************
*** 6640,6672 ****
{
Elf_External_Note * pnotes;
Elf_External_Note * external;
- Elf32_Internal_Note* internal;
- unsigned int notesz;
- unsigned int nlength;
- unsigned char * p;
int res = 1;
if (length <= 0)
return 0;
GET_DATA_ALLOC (offset, length, pnotes, Elf_External_Note *, "notes");
-
external = pnotes;
- p = (unsigned char *) pnotes;
- nlength = length;
printf (_("\nNotes at offset 0x%08lx with length 0x%08lx:\n"), offset, length);
printf (_(" Owner\t\tData size\tDescription\n"));
! while (nlength > 0)
{
! res &= process_note (external);
! internal = (Elf32_Internal_Note *) p;
! notesz = 3 * sizeof(unsigned long) + internal->namesz + internal->descsz;
! nlength -= notesz;
! p += notesz;
! external = (Elf_External_Note *) p;
}
free (pnotes);
--- 6629,6682 ----
{
Elf_External_Note * pnotes;
Elf_External_Note * external;
int res = 1;
if (length <= 0)
return 0;
GET_DATA_ALLOC (offset, length, pnotes, Elf_External_Note *, "notes");
external = pnotes;
printf (_("\nNotes at offset 0x%08lx with length 0x%08lx:\n"), offset, length);
printf (_(" Owner\t\tData size\tDescription\n"));
! while (external < ((char *) pnotes + length))
{
! Elf32_Internal_Note inote;
! char *temp = NULL;
! inote.type = BYTE_GET (external->type);
! inote.namesz = BYTE_GET (external->namesz);
! inote.namedata = external->name;
! inote.descsz = BYTE_GET (external->descsz);
! inote.descdata = inote.namedata + align_power (inote.namesz, 2);
! inote.descpos = offset + (inote.descdata - (char *) pnotes);
! external = inote.descdata + align_power (inote.descsz, 2);
!
! /* Verify that name is null terminated. It appears that at least
! one version of Linux (RedHat 6.0) generates corefiles that don't
! comply with the ELF spec by failing to include the null byte in
! namesz. */
! if (inote.namedata[inote.namesz] != '\0')
! {
! temp = malloc (inote.namesz + 1);
! if (temp == NULL)
! {
! error (_("Out of memory\n"));
! return (0);
! }
! strcpy (temp, inote.namedata);
! /* warn (_("'%s' NOTE name not properly null terminated\n"), temp); */
! inote.namedata = temp;
! }
!
! res &= process_note (&inote);
!
! if (temp != NULL)
! {
! free (temp);
! temp = NULL;
! }
}
free (pnotes);