public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* Re: Patch to readelf...
@ 1999-08-31  1:47 Nick Clifton
  1999-08-31  8:40 ` scottb
  0 siblings, 1 reply; 10+ messages in thread
From: Nick Clifton @ 1999-08-31  1:47 UTC (permalink / raw)
  To: scottb; +Cc: binutils

Hi Scott,

: I decided to submit this stuff in stages.  I have cleaned up the patch,
: and removed all of the ARM Linux specific stuff.  The code now simply
: parses the NOTE segment and lists the type of notes it finds.
: Please have a look at this an let me know if anything else needs
: changing.

Great Scott!

  (Sorry I just had to say that once)

Anyway this patch looks much more reasonable.  A couple of minor
niggles which wouldn't stop the patch from being accepted, but which
it would be nice to see fixed:

  * Comments ought to be like mini-sentances.  So they ought to start
    with a capital letter and end with a period followed by two
    spaces.

  * Your code still ignores the return values of the functions it
    calls.  Why go to the effort of returning a value if it is not
    used ?

  * You do not include any prototypes for the new functions.  It would
    be nice to see the new functions prototyped just like all the
    other functions in readelf.

Cheers
	Nick

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Patch to readelf...
  1999-08-31  1:47 Patch to readelf Nick Clifton
@ 1999-08-31  8:40 ` scottb
  0 siblings, 0 replies; 10+ messages in thread
From: scottb @ 1999-08-31  8:40 UTC (permalink / raw)
  To: Nick Clifton; +Cc: binutils

Nick Clifton wrote:
> 
> Anyway this patch looks much more reasonable.  A couple of minor
> niggles which wouldn't stop the patch from being accepted, but which
> it would be nice to see fixed:

The niggles are now fixed :).  process_corefile_note_segment() still has
to return an int due to the GET_DATA_ALLOC macro.

Scott
Index: binutils/readelf.c
===================================================================
RCS file: /cvs/binutils/binutils/binutils/readelf.c,v
retrieving revision 1.25
diff -u -w -r1.25 readelf.c
--- readelf.c	1999/08/28 08:13:43	1.25
+++ readelf.c	1999/08/31 15:32:05
@@ -194,6 +194,12 @@
 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 void		  process_note		         PARAMS ((Elf_External_Note *));
+static int		  process_corefile_note_segment  PARAMS ((FILE *, unsigned long, unsigned long));
+static void		  process_corefile_note_segments PARAMS ((FILE *));
+static int 		  process_corefile_contents	 PARAMS ((FILE *));
+
 typedef int Elf32_Word;
 
 #ifndef TRUE
@@ -6349,6 +6355,153 @@
   return 1;
 }
 
+static char *
+get_note_type (e_type)
+     unsigned e_type;
+{
+  static char buff[64];
+  
+  switch (e_type)
+    {
+    case NT_PRSTATUS:	return _("NT_PRSTATUS (prstatus structure)");
+    case NT_FPREGSET:	return _("NT_FPREGSET (floating point registers)");
+    case NT_PRPSINFO:   return _("NT_PRPSINFO (prpsinfo structure)");
+    case NT_TASKSTRUCT: return _("NT_TASKSTRUCT (task structure)");
+    case NT_PSTATUS:	return _("NT_PSTATUS (pstatus structure)");
+    case NT_FPREGS:	return _("NT_FPREGS (floating point registers)");
+    case NT_PSINFO:	return _("NT_PSINFO (psinfo structure)");
+    case NT_LWPSTATUS:	return _("NT_LWPSTATUS (lwpstatus_t structure)");
+    case NT_LWPSINFO:	return _("NT_LWPSINFO (lwpsinfo_t structure)");
+    default:
+      sprintf (buff, _("Unknown note type: (0x%08x)"), e_type);
+      return buff;
+    }
+}
+
+static void
+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;
+    }
+
+  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);
+}
+
+static int
+process_corefile_note_segment (file, offset, length)
+     FILE * file;
+     unsigned long offset;
+     unsigned long length;
+{
+  Elf_External_Note	*pnotes, *external;
+  Elf32_Internal_Note	*internal;
+  unsigned int	notesz, nlength;
+  unsigned char *p;
+  
+  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)
+  {
+    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);
+  return 1;
+}
+
+static void
+process_corefile_note_segments (file)
+     FILE * file;
+{
+  Elf_Internal_Phdr * program_headers;
+  Elf_Internal_Phdr * segment;
+  unsigned int	      i;
+
+  program_headers = (Elf_Internal_Phdr *) malloc
+    (elf_header.e_phnum * sizeof (Elf_Internal_Phdr));
+
+  if (program_headers == NULL)
+    {
+      error (_("Out of memory\n"));
+      return;
+    }
+
+  if (is_32bit_elf)
+    i = get_32bit_program_headers (file, program_headers);
+  else
+    i = get_64bit_program_headers (file, program_headers);
+
+  if (i == 0)
+    {
+      free (program_headers);
+      return;
+    }
+  
+  for (i = 0, segment = program_headers;
+       i < elf_header.e_phnum;
+       i ++, segment ++)
+    {
+      if (segment->p_type == PT_NOTE)
+	{
+	  process_corefile_note_segment (file, 
+	  				 (unsigned long)segment->p_offset,
+	  				 (unsigned long)segment->p_filesz);
+	}
+    }
+    
+  free (program_headers);
+}
+
+static int
+process_corefile_contents (file)
+     FILE * file;
+{
+  /* If file is not a core file then exit.  */
+  if (elf_header.e_type != ET_CORE)
+    return 1;
+    
+  /* No program headers means no NOTE segment.  */
+  if (elf_header.e_phnum == 0)
+    {
+      printf (_("No note segments present in the core file.\n"));
+      return 1;
+   }
+
+  process_corefile_note_segments (file);
+
+  return 1;
+}
+
 static int
 process_arch_specific (file)
      FILE * file;
@@ -6506,6 +6659,8 @@
   process_version_sections (file);
 
   process_section_contents (file);
+  
+  process_corefile_contents (file);
 
   process_arch_specific (file);
 
Index: include/elf/common.h
===================================================================
RCS file: /cvs/binutils/binutils/include/elf/common.h,v
retrieving revision 1.3
diff -u -w -r1.3 common.h
--- common.h	1999/06/03 08:20:07	1.3
+++ common.h	1999/08/31 15:32:05
@@ -239,6 +239,7 @@
 #define NT_PRSTATUS	1		/* Contains copy of prstatus struct */
 #define NT_FPREGSET	2		/* Contains copy of fpregset struct */
 #define NT_PRPSINFO	3		/* Contains copy of prpsinfo struct */
+#define NT_TASKSTRUCT	4		/* Contains copy of task struct */
 
 /* Note segments for core files on dir-style procfs systems. */
 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Patch to readelf...
@ 1999-08-31 10:00 Nick Clifton
  0 siblings, 0 replies; 10+ messages in thread
From: Nick Clifton @ 1999-08-31 10:00 UTC (permalink / raw)
  To: scottb; +Cc: binutils

Hi Scott,

: The niggles are now fixed :).  process_corefile_note_segment() still has
: to return an int due to the GET_DATA_ALLOC macro.

OK - well the patch as it stands is still missing one thing - a
ChangeLog entry.  Also to be conformat to the philosophy of readelf,
the new ability ought to be controlled by a command line switch.

However seeing as I am such a nice guy I have done both of these
things for you and checked your patch in! :-)

Cheers
	Nick

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Patch to readelf...
  1999-08-19  9:29 Nick Clifton
  1999-08-19  9:47 ` Jakub Jelinek
  1999-08-19 11:56 ` scottb
@ 1999-08-30 12:11 ` scottb
  2 siblings, 0 replies; 10+ messages in thread
From: scottb @ 1999-08-30 12:11 UTC (permalink / raw)
  To: Nick Clifton; +Cc: binutils mailing list

Nick Clifton wrote:
> 
> If you would like to tidy the patch up, I would be happy to review it
> again.

Hi Nick, 

I decided to submit this stuff in stages.  I have cleaned up the patch,
and removed all of the ARM Linux specific stuff.  The code now simply
parses the NOTE segment and lists the type of notes it finds.
Please have a look at this an let me know if anything else needs
changing.

Scott

1999-08-30  Scott Bambrough <scottb@netwinder.org>

       * include/elf/common.h: Added NT_TASKSTRUCT note type.
       * binutils/readelf.c: Added code to list the type of notes found
	 in the note segments in elf core files.
Index: binutils/readelf.c
===================================================================
RCS file: /cvs/binutils/binutils/binutils/readelf.c,v
retrieving revision 1.25
diff -u -p -w -r1.25 readelf.c
--- readelf.c	1999/08/28 08:13:43	1.25
+++ readelf.c	1999/08/30 18:55:12
@@ -6349,7 +6349,156 @@ process_mips_specific (file)
   return 1;
 }
 
+static char *
+get_note_type (e_type)
+     unsigned e_type;
+{
+  static char buff[64];
+  
+  switch (e_type)
+    {
+    case NT_PRSTATUS:	return _("NT_PRSTATUS (prstatus structure)");
+    case NT_FPREGSET:	return _("NT_FPREGSET (floating point registers)");
+    case NT_PRPSINFO:   return _("NT_PRPSINFO (prpsinfo structure)");
+    case NT_TASKSTRUCT: return _("NT_TASKSTRUCT (task structure)");
+    case NT_PSTATUS:	return _("NT_PSTATUS (pstatus structure)");
+    case NT_FPREGS:	return _("NT_FPREGS (floating point registers)");
+    case NT_PSINFO:	return _("NT_PSINFO (psinfo structure)");
+    case NT_LWPSTATUS:	return _("NT_LWPSTATUS (lwpstatus_t structure)");
+    case NT_LWPSINFO:	return _("NT_LWPSINFO (lwpsinfo_t structure)");
+    default:
+      sprintf (buff, _("Unknown note type: (0x%08x)"), e_type);
+      return buff;
+    }
+}
+
+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;
+}
+
 static int
+process_corefile_note_segment (file, offset, length)
+     FILE * file;
+     unsigned long offset;
+     unsigned long length;
+{
+  Elf_External_Note	*pnotes, *external;
+  Elf32_Internal_Note	*internal;
+  unsigned int	notesz, nlength;
+  unsigned char *p;
+  
+  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)
+  {
+    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);
+  return 1;
+}
+
+static int
+process_corefile_note_segments (file)
+     FILE * file;
+{
+  Elf_Internal_Phdr * program_headers;
+  Elf_Internal_Phdr * segment;
+  unsigned int	      i;
+
+  program_headers = (Elf_Internal_Phdr *) malloc
+    (elf_header.e_phnum * sizeof (Elf_Internal_Phdr));
+
+  if (program_headers == NULL)
+    {
+      error (_("Out of memory\n"));
+      return 0;
+    }
+
+  if (is_32bit_elf)
+    i = get_32bit_program_headers (file, program_headers);
+  else
+    i = get_64bit_program_headers (file, program_headers);
+
+  if (i == 0)
+    {
+      free (program_headers);
+      return 0;
+    }
+  
+  for (i = 0, segment = program_headers;
+       i < elf_header.e_phnum;
+       i ++, segment ++)
+    {
+      if (segment->p_type == PT_NOTE)
+	{
+	  process_corefile_note_segment (file, 
+	  				 (unsigned long)segment->p_offset,
+	  				 (unsigned long)segment->p_filesz);
+	}
+    }
+    
+  free (program_headers);
+  return 1;
+}
+
+static int
+process_corefile_contents (file)
+     FILE * file;
+{
+  /* if not a core file then exit */
+  if (elf_header.e_type != ET_CORE)
+    return 1;
+    
+  /* no program headers means no NOTE segment */
+  if (elf_header.e_phnum == 0)
+    {
+      printf (_("No notes segments present in the core file.\n"));
+      return 1;
+   }
+
+  process_corefile_note_segments (file);
+
+  return 1;
+}
+
+static int
 process_arch_specific (file)
      FILE * file;
 {
@@ -6506,6 +6655,8 @@ process_file (file_name)
   process_version_sections (file);
 
   process_section_contents (file);
+  
+  process_corefile_contents (file);
 
   process_arch_specific (file);
 
Index: include/elf/common.h
===================================================================
RCS file: /cvs/binutils/binutils/include/elf/common.h,v
retrieving revision 1.3
diff -u -p -w -r1.3 common.h
--- common.h	1999/06/03 08:20:07	1.3
+++ common.h	1999/08/30 18:55:16
@@ -239,6 +239,7 @@ Foundation, Inc., 59 Temple Place - Suit
 #define NT_PRSTATUS	1		/* Contains copy of prstatus struct */
 #define NT_FPREGSET	2		/* Contains copy of fpregset struct */
 #define NT_PRPSINFO	3		/* Contains copy of prpsinfo struct */
+#define NT_TASKSTRUCT	4		/* Contains copy of task struct */
 
 /* Note segments for core files on dir-style procfs systems. */
 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Patch to readelf...
  1999-08-19 11:56 ` scottb
@ 1999-08-19 12:40   ` Ian Lance Taylor
  0 siblings, 0 replies; 10+ messages in thread
From: Ian Lance Taylor @ 1999-08-19 12:40 UTC (permalink / raw)
  To: scottb; +Cc: binutils

   Date: Thu, 19 Aug 1999 13:26:19 -0400
   From: scottb <scottb@netwinder.org>

   If I remove the arm_* functions, is the remaining code still too Linux
   specific?  I'm not familiar enough with other architechures to know if
   the information in the notes is common enough for general use.

   If people think it is worth pursuing, I'll happily tidy up the patch for
   further review.

I think it would be nice if readelf could dump information from core
files.

Ideally it would be done in a manner which would work when cross
compiling.  That means that you can not use header files like
<sys/procfs.h> which are not present on every system.  It means that
you must define the structures yourself.  It means that you must swap
the data in case the host and target have a different endianness.

In practice, of course, core files are not that common when
cross-compiling.  Therefore, I think it would be acceptable to only
support core file dumping on a native system.  This means configury
work to only compile code on the appropriate system.

Ian

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Patch to readelf...
  1999-08-19  9:29 Nick Clifton
  1999-08-19  9:47 ` Jakub Jelinek
@ 1999-08-19 11:56 ` scottb
  1999-08-19 12:40   ` Ian Lance Taylor
  1999-08-30 12:11 ` scottb
  2 siblings, 1 reply; 10+ messages in thread
From: scottb @ 1999-08-19 11:56 UTC (permalink / raw)
  To: binutils mailing list

Nick Clifton wrote:
> 
> I would like to accept this patch, but....
> 
>   * It is too ARM Linux specific.  For example the structure 'struct
>     user_fp' that you reference in several of your functions is not
>     defined in my i386 Linux environment.
> 
>   * Similarly I am worried that other platforms will not have the new
>     header files that you include (eg <sys/procfs.h>).
> 
>   * The code does not conform to the GNU coding standard.  In
>     particular you have lots of invocations of printf where there is
>     no space between the function name and the opening parenthesis,
>     plus in several places you have a brace at the end of a for
>     statement instead of all alone on the following line.
> 
>   * In several places function return values are ignored when they
>     need not be.
> 
> If you would like to tidy the patch up, I would be happy to review it
> again.

I'm sorry.  I knew this patch was not going to be up to snuff for
inclusion.  I was wondering if it was sufficiently interesting enough to
warrant further work.  I originally wrote this as a quick extension to
examine the core files while working on porting GDB.  I figured I'd ask
the people on the list if they though it worth pursuing, before doing
any further work.

I also have concerns about readelf.c getting very large and unmanageable
as expressed by Jakub.  In order to prevent that and to isolate
architecture specific code, it would be necessary to split stuff out
into a separate file, alter the makefile, etc.

If I remove the arm_* functions, is the remaining code still too Linux
specific?  I'm not familiar enough with other architechures to know if
the information in the notes is common enough for general use.

If people think it is worth pursuing, I'll happily tidy up the patch for
further review.

Scott
Scott

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Patch to readelf...
  1999-08-19  8:10 scottb
@ 1999-08-19 11:24 ` Ian Lance Taylor
  0 siblings, 0 replies; 10+ messages in thread
From: Ian Lance Taylor @ 1999-08-19 11:24 UTC (permalink / raw)
  To: scottb; +Cc: binutils

   Date: Thu, 19 Aug 1999 11:06:40 -0400
   From: scottb <scottb@netwinder.org>

   I've been plumbing the depths of ARM Linux corefiles lately and have
   extended readelf's capabilities in the area of dumping core files.  I
   thought I would pass along the work and see if anyone thought it was
   interesting enough for inclusion in the tree. 

Thanks for the patch.  Unfortunately, we can't include this patch as
is.  readelf needs to work in a cross-compilation environment.  That
means that it can not include header files like <sys/procfs.h> and
<sys/user.h> which do not exist on all systems.  Even in cases where
<sys/procfs.h> exists, there is no reason to assume that it defines
the NT_* macros or structs like user_fp.

Of course, the patch may still be useful for people working on ARM
GNU/Linux.

Ian

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Patch to readelf...
  1999-08-19  9:29 Nick Clifton
@ 1999-08-19  9:47 ` Jakub Jelinek
  1999-08-19 11:56 ` scottb
  1999-08-30 12:11 ` scottb
  2 siblings, 0 replies; 10+ messages in thread
From: Jakub Jelinek @ 1999-08-19  9:47 UTC (permalink / raw)
  To: Nick Clifton; +Cc: scottb, binutils

On Thu, Aug 19, 1999 at 05:28:25PM +0100, Nick Clifton wrote:
> Hi Scott,
> 
> : I've been plumbing the depths of ARM Linux corefiles lately and have
> : extended readelf's capabilities in the area of dumping core files.  I
> : thought I would pass along the work and see if anyone thought it was
> : interesting enough for inclusion in the tree. 
> : 
> : 1999-08-19  Scott Bambrough <scottb@netwinder.org>
> : 
> : 	* include/elf/common.h: Added NT_TASKSTRUCT note type.
> : 	* binutils/readelf.c: Added code to parse the NT_PRSTATUS,
> : 	  NT_PRPSINFO, and NT_FPREGSET note segments found in elf core
> : 	  files.  Added ARM specific code to process arm registers and 
> : 	  arm floating point registers.
> 
> I would like to accept this patch, but....
> 
>   * It is too ARM Linux specific.  For example the structure 'struct
>     user_fp' that you reference in several of your functions is not
>     defined in my i386 Linux environment.
> 
>   * Similarly I am worried that other platforms will not have the new
>     header files that you include (eg <sys/procfs.h>).

IMHO only generic code for core file handling should go into readelf.c, the
rest should probably be into some separate modules in config/, otherwise
readelf.c will become a monster.

Cheers,
    Jakub
___________________________________________________________________
Jakub Jelinek | jj@sunsite.mff.cuni.cz | http://sunsite.mff.cuni.cz
Administrator of SunSITE Czech Republic, MFF, Charles University
___________________________________________________________________
UltraLinux  |  http://ultra.linux.cz/  |  http://ultra.penguin.cz/
Linux version 2.3.13 on a sparc64 machine (1343.49 BogoMips)
___________________________________________________________________

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Patch to readelf...
@ 1999-08-19  9:29 Nick Clifton
  1999-08-19  9:47 ` Jakub Jelinek
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Nick Clifton @ 1999-08-19  9:29 UTC (permalink / raw)
  To: scottb; +Cc: binutils

Hi Scott,

: I've been plumbing the depths of ARM Linux corefiles lately and have
: extended readelf's capabilities in the area of dumping core files.  I
: thought I would pass along the work and see if anyone thought it was
: interesting enough for inclusion in the tree. 
: 
: 1999-08-19  Scott Bambrough <scottb@netwinder.org>
: 
: 	* include/elf/common.h: Added NT_TASKSTRUCT note type.
: 	* binutils/readelf.c: Added code to parse the NT_PRSTATUS,
: 	  NT_PRPSINFO, and NT_FPREGSET note segments found in elf core
: 	  files.  Added ARM specific code to process arm registers and 
: 	  arm floating point registers.

I would like to accept this patch, but....

  * It is too ARM Linux specific.  For example the structure 'struct
    user_fp' that you reference in several of your functions is not
    defined in my i386 Linux environment.

  * Similarly I am worried that other platforms will not have the new
    header files that you include (eg <sys/procfs.h>).

  * The code does not conform to the GNU coding standard.  In
    particular you have lots of invocations of printf where there is
    no space between the function name and the opening parenthesis,
    plus in several places you have a brace at the end of a for
    statement instead of all alone on the following line.

  * In several places function return values are ignored when they
    need not be.

If you would like to tidy the patch up, I would be happy to review it
again.

Cheers
	Nick

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Patch to readelf...
@ 1999-08-19  8:10 scottb
  1999-08-19 11:24 ` Ian Lance Taylor
  0 siblings, 1 reply; 10+ messages in thread
From: scottb @ 1999-08-19  8:10 UTC (permalink / raw)
  To: binutils mailing list

Hi,

I've been plumbing the depths of ARM Linux corefiles lately and have
extended readelf's capabilities in the area of dumping core files.  I
thought I would pass along the work and see if anyone thought it was
interesting enough for inclusion in the tree. 

1999-08-19  Scott Bambrough <scottb@netwinder.org>

	* include/elf/common.h: Added NT_TASKSTRUCT note type.
	* binutils/readelf.c: Added code to parse the NT_PRSTATUS,
	  NT_PRPSINFO, and NT_FPREGSET note segments found in elf core
	  files.  Added ARM specific code to process arm registers and 
	  arm floating point registers.
Index: binutils/readelf.c
===================================================================
RCS file: /cvs/binutils/binutils/binutils/readelf.c,v
retrieving revision 1.20
diff -u -r1.20 readelf.c
--- readelf.c	1999/08/09 17:16:23	1.20
+++ readelf.c	1999/08/19 14:40:25
@@ -20,12 +20,15 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
    02111-1307, USA.  */
-\f
 
+
 #include <assert.h>
 #include <sys/stat.h>
 #include <stdio.h>
 #include <time.h>
+#include <sys/procfs.h>
+#include <signal.h>
+#include <sys/user.h>
 
 #if __GNUC__ >= 2
 /* Define BFD64 here, even if our default architecture is 32 bit ELF
@@ -6267,7 +6270,500 @@
   return 1;
 }
 
+static char *
+get_note_type (e_type)
+     unsigned e_type;
+{
+  static char buff[64];
+  
+  switch (e_type)
+    {
+    case NT_PRSTATUS:	return _("NT_PRSTATUS (prstatus structure)");
+    case NT_FPREGSET:	return _("NT_FPREGSET (floating point registers)");
+    case NT_PRPSINFO:   return _("NT_PRPSINFO (prpsinfo structure)");
+    case NT_TASKSTRUCT: return _("NT_TASKSTRUCT (task structure)");
+    case NT_PSTATUS: return _("NT_PSTATUS (pstatus structure)");
+    case NT_FPREGS: return _("NT_FPREGS (floating point registers)");
+    case NT_PSINFO: return _("NT_PSINFO (psinfo structure)");
+    case NT_LWPSTATUS: return _("NT_LWPSTATUS (lwpstatus_t structure)");
+    case NT_LWPSINFO: return _("NT_LWPSINFO (lwpsinfo_t structure)");
+    default:
+      sprintf (buff, _("Unknown note type: (0x%08x)"), e_type);
+      return buff;
+    }
+}
+
+static char *
+get_signal_type (nsig)
+     unsigned long int nsig;
+{
+  static char buff[64];
+  
+  switch (nsig)
+    {
+     case 0         : return _("NONE"); 
+     case SIGHUP    : return _("SIGHUP - Hangup (POSIX)");
+     case SIGINT    : return _("SIGINT - Interrupt (ANSI)");
+     case SIGQUIT   : return _("SIGQUIT - Quit (POSIX)");
+     case SIGILL    : return _("SIGILL - Illegal instruction (ANSI)");
+     case SIGTRAP   : return _("SIGTRAP - Trace trap (POSIX)");
+     case SIGABRT   : return _("SIGABRT - Abort (ANSI)");
+     case SIGBUS    : return _("SIGBUS - BUS error (4.2 BSD)");
+     case SIGFPE    : return _("SIGFPE - Floating-point exception (ANSI)");
+     case SIGKILL   : return _("SIGKILL - Kill, unblockable (POSIX)");
+     case SIGUSR1   : return _("SIGUSR1 - User-defined signal 1 (POSIX)");
+     case SIGSEGV   : return _("SIGSEGV - Segmentation violation (ANSI)");
+     case SIGUSR2   : return _("SIGUSR2 - User-defined signal 2 (POSIX)");
+     case SIGPIPE   : return _("SIGPIPE - Broken pipe (POSIX)");
+     case SIGALRM   : return _("SIGALRM - Alarm clock (POSIX)");
+     case SIGTERM   : return _("SIGTERM - Termination (ANSI)");
+     case SIGSTKFLT : return _("SIGSTKFLT - Stack fault");
+     case SIGCHLD   : return _("SIGCHLD - Child status has changed (POSIX)");
+     case SIGCONT   : return _("SIGCONT - Continue (POSIX)");
+     case SIGSTOP   : return _("SIGSTOP - Stop, unblockable (POSIX)");
+     case SIGTSTP   : return _("SIGTSTP - Keyboard stop (POSIX)");
+     case SIGTTIN   : return _("SIGTTIN - Background read from tty (POSIX)");
+     case SIGTTOU   : return _("SIGTTOU - Background write to tty (POSIX)");
+     case SIGURG    : return _("SIGURG - Urgent condition on socket (4.2 BSD)");
+     case SIGXCPU   : return _("SIGXCPU - CPU limit exceeded (4.2 BSD)");
+     case SIGXFSZ   : return _("SIGXFSZ - File size limit exceeded (4.2 BSD)");
+     case SIGVTALRM : return _("SIGVTALRM - Virtual alarm clock (4.2 BSD)");
+     case SIGPROF   : return _("SIGPROF - Profiling alarm clock (4.2 BSD)");
+     case SIGWINCH  : return _("SIGWINCH - Window size change (4.3 BSD, Sun)");
+     case SIGPOLL   : return _("SIGPOLL - Pollable event occurred (System V)");
+     case SIGPWR    : return _("SIGPWR - Power failure restart (System V)");
+
+     default:
+       sprintf (buff, _("Unknown signal: (0x%08x)"), nsig);
+       return buff;
+    }
+}
+
 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;
+}
+
+static void
+print_process_identifiers(pid, ppid, pgrp, sid)
+  unsigned long int pid;
+  unsigned long int ppid;
+  unsigned long int pgrp;
+  unsigned long int sid;
+{
+  printf(_("   Process identifiers:\n"));
+  printf(_("            Process id: 0x%08lx\n"), pid);
+  printf(_("     Parent process id: 0x%08lx\n"), ppid);
+  printf(_("              Group id: 0x%08lx\n"), pgrp);
+  printf(_("            Session id: 0x%08lx\n"), sid);
+}
+
+static void
+arm_print_gregs (regs)
+  elf_gregset_t *regs;
+{
+  unsigned int i;
+  static char* registers[] = { "r0",  "r1", "r2", "r3", "r4",
+  			       "r5",  "r6", "r7", "r8", "r9",
+  			       "r10", "fp", "ip", "sp", "lr",
+  			       "pc", "cpsr" };
+
+  /* if not an ARM machine then exit */
+  if (elf_header.e_machine != EM_ARM)
+    return;
+
+  printf(_("\n  General registers:\n"));
+  
+  for (i=0;i<17;i++) {
+    if (i != 0 && (i % 3) == 0) printf("\n");
+    printf(_("%6s: 0x%08x\t"), registers[i], regs[i]);
+  }
+  if ((i % 3) != 0) printf("\n");
+}
+
+static void
+arm_print_fpsr (regs)
+  struct user_fp *regs;
+{
+  unsigned int i;
+
+  printf("\n  Floating point status register: (0x%08x)\n",regs->fpsr);
+  
+  i = regs->fpsr >> 24;
+  switch (i)
+  {
+   case 0x00: printf(_("    System id: pre-FPA software system\n")); break;
+   case 0x80: printf(_("    System id: pre-FPA hardware system\n")); break;
+   case 0x01: printf(_("    System id: floating point emulator\n")); break;
+   case 0x81: printf(_("    System id: FPA11 hardware system\n")); break;
+   default:   printf(_("    System id: unknown floating point system\n"));
+  }
+  
+  i = regs->fpsr >> 16;
+  printf(_("\n    Exception traps enabled: "));
+  if ((i & 0x1F) == 0) {
+    printf(_("(none)"));
+  } else {
+    if (i & 0x10) printf(_("IXE "));
+    if (i & 0x08) printf(_("UFE "));
+    if (i & 0x04) printf(_("OFE "));
+    if (i & 0x02) printf(_("OZE "));
+    if (i & 0x01) printf(_("IOE"));
+  }
+  printf("\n");
+  
+  i = regs->fpsr >> 8;
+  printf(_("\n    System control byte:\n"));
+  printf(_("      AC %s: use alternative carry definition\n"),
+	 i & 0x10 ? _("set") : _("clear"));
+  printf(_("      EP %s: use expanded packed decimal format\n"),
+	 i & 0x08 ? _("set") : _("clear"));
+  printf(_("      SO %s: select synchronous operation of FPA\n"),
+	 i & 0x04 ? _("set") : _("clear"));
+  printf(_("      NE %s: NaN exception\n"),
+	 i & 0x02 ? _("set") : _("clear"));
+  printf(_("      ND %s: No denormalized numbers\n"),
+	 i & 0x01 ? _("set") : _("clear"));
+
+  i = regs->fpsr;
+  printf(_("\n    Cumulative exception flags: "));
+  if ((i & 0x1F) == 0) {
+    printf(_("(none)"));
+  } else {
+    if (i & 0x10) printf(_("IXC "));
+    if (i & 0x08) printf(_("UFC "));
+    if (i & 0x04) printf(_("OFC "));
+    if (i & 0x02) printf(_("OZC "));
+    if (i & 0x01) printf(_("IOC"));
+  }
+  printf("\n");
+}
+
+static void
+arm_print_fpregs (regs)
+  struct user_fp *regs;
+{
+  unsigned int i;
+  unsigned long int *p;
+  static char* registers[] = { "f0", "f1", "f2", "f3",
+  			       "f4", "f5", "f6", "f7" };
+
+  /* if not an ARM machine then exit */
+  if (elf_header.e_machine != EM_ARM)
+    return;
+
+  printf(_("\n  Floating point registers:\n"));
+  
+  p = (unsigned long int *)&regs->fpregs[0];
+  for (i=0;i<8;i++) {
+    printf(_("\t%6s: 0x%08x 0x%08x 0x%08x"),
+           registers[i], *p++, *p++, *p++);
+#if 0           
+    /* check for NWFPE */
+    if (regs->init_flag)
+    {
+      switch (regs->ftype[i])
+      {
+      case 1: printf(_(" (float)")); break;
+      case 2: printf(_(" (double)")); break;
+      case 3: printf(_(" (extended)")); break;
+      }
+    }
+#endif
+    printf("\n");
+  }
+  
+  printf(_("\t%6s: 0x%08x\n"), _("fpsr"), regs->fpsr);
+  printf(_("\t%6s: 0x%08x\n"), _("fpcr"), regs->fpcr);
+  
+  arm_print_fpsr(regs);  
+}
+
+static int
+process_prstatus (pnote)
+  Elf_External_Note	*pnote;
+{
+  Elf32_Internal_Note	*internal;
+  prstatus_t *pdata;
+  char utime[20], stime[20], cutime[20], cstime[20];
+    
+  internal = (Elf32_Internal_Note *)pnote;
+  pdata = (prstatus_t*)(pnote->name + internal->namesz);
+  
+  sprintf(utime,"%ld sec, %ld usec",
+  	  (unsigned long int)pdata->pr_utime.tv_sec,
+  	  (unsigned long int)pdata->pr_utime.tv_usec);
+  sprintf(stime,"%ld sec, %ld usec",
+  	  (unsigned long int)pdata->pr_stime.tv_sec,
+  	  (unsigned long int)pdata->pr_stime.tv_usec);
+  sprintf(cutime,"%ld sec, %ld usec",
+  	  (unsigned long int)pdata->pr_cutime.tv_sec,
+  	  (unsigned long int)pdata->pr_cutime.tv_usec);
+  sprintf(cstime,"%ld sec, %ld usec",
+  	  (unsigned long int)pdata->pr_cstime.tv_sec,
+  	  (unsigned long int)pdata->pr_cstime.tv_usec);
+
+  printf(_("\nPRSTATUS Note:\n"));
+  
+  print_process_identifiers((unsigned long int)pdata->pr_pid,
+		     	    (unsigned long int)pdata->pr_ppid,
+		     	    (unsigned long int)pdata->pr_pgrp,
+		     	    (unsigned long int)pdata->pr_sid);
+			    
+  printf(_("\n  Process timings:\n"));			    
+  printf(_("                 User time: %s\n"), utime);
+  printf(_("               System time: %s\n"), stime);
+  printf(_("      Cumulative user time: %s\n"), cutime);
+  printf(_("    Cumulative system time: %s\n"), cstime);
+ 	 
+  printf(_("\n  Signal information:\n"));
+  printf(_("    Process terminated with signal %ld (%s)\n"),
+  	 (unsigned long int)pdata->pr_info.si_signo,
+  	 get_signal_type ((unsigned long int)pdata->pr_info.si_signo));
+  printf(_("      Error number: 0x%08lx\n"),
+  	 (unsigned long int)pdata->pr_info.si_errno);
+  printf(_("        Error code: 0x%08lx\n"),
+  	 (unsigned long int)pdata->pr_info.si_code);
+  printf(_("    Current signal: %ld (%s)\n"),
+  	 (unsigned long int)pdata->pr_cursig,
+  	 get_signal_type ((unsigned long int)pdata->pr_cursig));
+  printf(_("    Pending signal: %ld (%s)\n"),
+  	 pdata->pr_sigpend, get_signal_type (pdata->pr_sigpend));
+  printf(_("    Blocked signal: %ld (%s)\n"),
+  	 pdata->pr_sighold, get_signal_type (pdata->pr_sighold));
+  	 
+  arm_print_gregs(&pdata->pr_reg);
+  
+  printf("\n  FPU used: %s\n",pdata->pr_fpvalid ? _("YES") : _("NO"));
+  	 
+  return 1;
+}
+
+static int
+process_prpsinfo (pnote)
+  Elf_External_Note	*pnote;
+{
+  Elf32_Internal_Note	*internal;
+  prpsinfo_t *pdata;
+    
+  internal = (Elf32_Internal_Note *)pnote;
+  pdata = (prpsinfo_t*)(pnote->name + internal->namesz);
+  
+  printf(_("\nPRPSINFO Note:\n"));
+  
+  print_process_identifiers((unsigned long int)pdata->pr_pid,
+		     	    (unsigned long int)pdata->pr_ppid,
+		     	    (unsigned long int)pdata->pr_pgrp,
+		     	    (unsigned long int)pdata->pr_sid);
+			    
+  printf(_("\n   Process information:\n"));
+  printf(_("      Process filename: %s\n"), pdata->pr_fname);
+  printf(_("     Process arguments: %s\n"), pdata->pr_psargs);
+  printf(_("       Process user id: 0x%08lx\n"), pdata->pr_uid);
+  printf(_("      Process group id: 0x%08lx\n"), pdata->pr_gid);
+  printf(_("         Process flags: 0x%08lx\n"), pdata->pr_flag);
+  printf(_("    Process nice level: 0x%02x\n"), pdata->pr_nice);
+
+  printf(_("         Process state: %c (%0x02x)"),
+	   pdata->pr_sname, pdata->pr_state);
+  printf(pdata->pr_zomb ? _(" (zombie)\n") : "\n");
+
+  return 1;
+}
+
+static int
+process_fpregset (pnote)
+  Elf_External_Note	*pnote;
+{
+  Elf32_Internal_Note	*internal;
+  struct user_fp *pdata;
+    
+  internal = (Elf32_Internal_Note *)pnote;
+  pdata = (struct user_fp*)(pnote->name + internal->namesz);
+  
+  printf(_("\nFPREGSET Note:"));
+  arm_print_fpregs (pdata);
+
+  return 1;
+}
+
+static int
+process_note_data (pnote)
+  Elf_External_Note	*pnote;
+{
+  Elf32_Internal_Note	*internal;
+  internal = (Elf32_Internal_Note *)pnote;
+
+  switch (internal->type)
+    {
+    case NT_PRSTATUS: return process_prstatus(pnote);
+    case NT_PRPSINFO: return process_prpsinfo(pnote);
+    case NT_FPREGSET: return process_fpregset(pnote);
+    case NT_TASKSTRUCT:
+    default:
+      return 0;
+    }
+}
+
+static int
+process_note_segment (file, offset, length)
+     FILE * file;
+     unsigned long offset;
+     unsigned long length;
+{
+  Elf_External_Note	*pnotes, *external;
+  Elf32_Internal_Note	*internal;
+  unsigned int	notesz, nlength;
+  unsigned char *p;
+  
+  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) {
+    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);
+  return 1;
+}
+
+static int
+process_note_segment_data (file, offset, length)
+     FILE * file;
+     unsigned long offset;
+     unsigned long length;
+{
+  Elf_External_Note	*pnotes, *external;
+  Elf32_Internal_Note	*internal;
+  unsigned int	notesz, nlength;
+  unsigned char *p;
+  
+  if (length <= 0)
+    return(0);
+    
+  GET_DATA_ALLOC (offset, length, pnotes, Elf_External_Note *, "notes");
+
+  external = pnotes; 
+  p = (unsigned char *)pnotes;
+  nlength = length;
+ 
+  while (nlength > 0) {
+    process_note_data (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);
+  return 1;
+}
+
+static int
+process_note_segments (file)
+     FILE * file;
+{
+  Elf_Internal_Phdr * program_headers;
+  Elf_Internal_Phdr * segment;
+  unsigned int	      i;
+
+  program_headers = (Elf_Internal_Phdr *) malloc
+    (elf_header.e_phnum * sizeof (Elf_Internal_Phdr));
+
+  if (program_headers == NULL)
+    {
+      error (_("Out of memory\n"));
+      return 0;
+    }
+
+  i = get_32bit_program_headers (file, program_headers);
+
+  if (i == 0)
+    {
+      free (program_headers);
+      return 0;
+    }
+  
+  for (i = 0, segment = program_headers;
+       i < elf_header.e_phnum;
+       i ++, segment ++)
+    {
+      if (segment->p_type == PT_NOTE)
+	{
+	  process_note_segment (file, 
+	  			(unsigned long)segment->p_offset,
+	  			(unsigned long)segment->p_filesz);
+	}
+    }
+    
+  for (i = 0, segment = program_headers;
+       i < elf_header.e_phnum;
+       i ++, segment ++)
+    {
+      if (segment->p_type == PT_NOTE)
+	{
+	  process_note_segment_data (file, 
+	  			     (unsigned long)segment->p_offset,
+	  			     (unsigned long)segment->p_filesz);
+	}
+    }
+    
+  free (program_headers);
+  return 1;
+}
+
+static int
+process_arm_corefile (file)
+     FILE * file;
+{
+  /* if not a core file then exit */
+  if (elf_header.e_type != ET_CORE)
+    return 1;
+    
+  /* no program headers means no NOTE segment */
+  if (elf_header.e_phnum == 0)
+    return 1;
+
+  process_note_segments (file);
+
+  return 1;
+}
+
+static int
 process_arch_specific (file)
      FILE * file;
 {
@@ -6276,6 +6772,9 @@
 
   switch (elf_header.e_machine)
     {
+    case EM_ARM:
+      return process_arm_corefile (file);
+      break;
     case EM_MIPS:
     case EM_MIPS_RS4_BE:
       return process_mips_specific (file);
Index: include/elf/common.h
===================================================================
RCS file: /cvs/binutils/binutils/include/elf/common.h,v
retrieving revision 1.3
diff -u -r1.3 common.h
--- common.h	1999/06/03 08:20:07	1.3
+++ common.h	1999/08/19 14:40:27
@@ -239,6 +239,7 @@
 #define NT_PRSTATUS	1		/* Contains copy of prstatus struct */
 #define NT_FPREGSET	2		/* Contains copy of fpregset struct */
 #define NT_PRPSINFO	3		/* Contains copy of prpsinfo struct */
+#define NT_TASKSTRUCT	4		/* Contains copy of task struct */
 
 /* Note segments for core files on dir-style procfs systems. */
 

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~1999-08-31 10:00 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-08-31  1:47 Patch to readelf Nick Clifton
1999-08-31  8:40 ` scottb
  -- strict thread matches above, loose matches on Subject: below --
1999-08-31 10:00 Nick Clifton
1999-08-19  9:29 Nick Clifton
1999-08-19  9:47 ` Jakub Jelinek
1999-08-19 11:56 ` scottb
1999-08-19 12:40   ` Ian Lance Taylor
1999-08-30 12:11 ` scottb
1999-08-19  8:10 scottb
1999-08-19 11:24 ` Ian Lance Taylor

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).