public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* readelf fixes
@ 2006-03-10 13:29 Alan Modra
  0 siblings, 0 replies; 2+ messages in thread
From: Alan Modra @ 2006-03-10 13:29 UTC (permalink / raw)
  To: binutils

In developing ld debug info edit, I ran into a problem with
readelf --debug-dump=aranges, namely that many ranges were not
shown because the first entry happened to be all zero due to
the associated section being pruned.  I think it's better to
ignore the zero terminator anyway, and display everything we
have.  Also, I noticed that the .debug_line display wants the
address size from .debug_info for extended ops, when a simple
length calculation lets us infer the size.  I think the tie
between sections is unnecessary (and asking for trouble in
the face of debug info editing).

	* dwarf.c (process_extended_line_op): Remove pointer_size param.
	Use length instead to determine address size.
	(get_pointer_size_and_offset_of_comp_unit): Delete.
	(display_debug_lines): Adjust for above.
	(display_debug_aranges): Don't stop on finding two zeros.
	(display_debug_frames): For warning, print offset not pointer.

Index: binutils/dwarf.c
===================================================================
RCS file: /cvs/src/src/binutils/dwarf.c,v
retrieving revision 1.3
diff -u -p -r1.3 dwarf.c
--- binutils/dwarf.c	3 Mar 2006 18:29:40 -0000	1.3
+++ binutils/dwarf.c	10 Mar 2006 11:14:44 -0000
@@ -221,7 +221,7 @@ reset_state_machine (int is_stmt)
    Returns the number of bytes read.  */
 
 static int
-process_extended_line_op (unsigned char *data, int is_stmt, int pointer_size)
+process_extended_line_op (unsigned char *data, int is_stmt)
 {
   unsigned char op_code;
   unsigned int bytes_read;
@@ -251,7 +251,7 @@ process_extended_line_op (unsigned char 
       break;
 
     case DW_LNE_set_address:
-      adr = byte_get (data, pointer_size);
+      adr = byte_get (data, len - bytes_read - 1);
       printf (_("set Address to 0x%lx\n"), adr);
       state_machine_regs.address = adr;
       break;
@@ -1766,55 +1766,12 @@ load_debug_info (void * file)
     return 0;
 }
 
-/* Retrieve the pointer size associated with the given compilation unit.
-   Optionally the offset of this unit into the .debug_info section is
-   also retutned.  If there is no .debug_info section then an error
-   message is issued and 0 is returned.  If the requested comp unit has
-   not been defined in the .debug_info section then a warning message
-   is issued and the last know pointer size is returned.  This message
-   is only issued once per section dumped per file dumped.  */
-
-static unsigned int
-get_pointer_size_and_offset_of_comp_unit (unsigned int comp_unit,
-					  const char * section_name,
-					  unsigned long * offset_return)
-{
-  unsigned long offset = 0;
-
-  if (num_debug_info_entries == 0)
-    error (_("%s section needs a populated .debug_info section\n"),
-	   section_name);
-
-  else if (comp_unit >= num_debug_info_entries)
-    {
-      if (!warned_about_missing_comp_units)
-	{
-	  warn (_("%s section has more comp units than .debug_info section\n"),
-		section_name);
-	  warn (_("assuming that the pointer size is %d, from the last comp unit in .debug_info\n\n"),
-		last_pointer_size);
-	  warned_about_missing_comp_units = TRUE;
-	}
-    }
-  else
-    {
-      last_pointer_size = debug_information [comp_unit].pointer_size;
-      offset = debug_information [comp_unit].cu_offset;
-    }
-
-  if (offset_return != NULL)
-    * offset_return = offset;
-
-  return last_pointer_size;
-}
-
 static int
 display_debug_lines (struct dwarf_section *section, void *file)
 {
   unsigned char *start = section->start;
   unsigned char *data = start;
   unsigned char *end = start + section->size;
-  unsigned int comp_unit = 0;
 
   printf (_("\nDump of debug contents of section %s:\n\n"),
 	  section->name);
@@ -1827,7 +1784,6 @@ display_debug_lines (struct dwarf_sectio
       unsigned char *standard_opcodes;
       unsigned char *end_of_sequence;
       unsigned char *hdrptr;
-      unsigned int pointer_size;
       int initial_length_size;
       int offset_size;
       int i;
@@ -1885,12 +1841,6 @@ display_debug_lines (struct dwarf_sectio
       info.li_line_base <<= 24;
       info.li_line_base >>= 24;
 
-      /* Get the pointer size from the comp unit associated
-	 with this block of line number information.  */
-      pointer_size = get_pointer_size_and_offset_of_comp_unit
-	(comp_unit, ".debug_line", NULL);
-      comp_unit ++;
-
       printf (_("  Length:                      %ld\n"), info.li_length);
       printf (_("  DWARF Version:               %d\n"), info.li_version);
       printf (_("  Prologue Length:             %d\n"), info.li_prologue_length);
@@ -1899,9 +1849,6 @@ display_debug_lines (struct dwarf_sectio
       printf (_("  Line Base:                   %d\n"), info.li_line_base);
       printf (_("  Line Range:                  %d\n"), info.li_line_range);
       printf (_("  Opcode Base:                 %d\n"), info.li_opcode_base);
-      printf (_("  (Pointer size:               %u)%s\n"),
-	      pointer_size,
-	      warned_about_missing_comp_units ? " [assumed]" : "" );
 
       end_of_sequence = data + info.li_length + initial_length_size;
 
@@ -1993,14 +1940,7 @@ display_debug_lines (struct dwarf_sectio
 	  else switch (op_code)
 	    {
 	    case DW_LNS_extended_op:
-	      if (pointer_size == 0)
-		{
-		  warn (_("Extend line ops need a valid pointer size, guessing at 4\n"));
-		  pointer_size = 4;
-		}
-
-	      data += process_extended_line_op (data, info.li_default_is_stmt,
-						pointer_size);
+	      data += process_extended_line_op (data, info.li_default_is_stmt);
 	      break;
 
 	    case DW_LNS_copy:
@@ -2634,7 +2574,9 @@ display_debug_aranges (struct dwarf_sect
       if (excess)
 	ranges += (2 * arange.ar_pointer_size) - excess;
 
-      for (;;)
+      start += arange.ar_length + initial_length_size;
+
+      while (ranges + 2 * arange.ar_pointer_size <= start)
 	{
 	  address = byte_get (ranges, arange.ar_pointer_size);
 
@@ -2644,14 +2586,8 @@ display_debug_aranges (struct dwarf_sect
 
 	  ranges += arange.ar_pointer_size;
 
-	  /* A pair of zeros marks the end of the list.  */
-	  if (address == 0 && length == 0)
-	    break;
-
 	  printf ("    %8.8lx %lu\n", address, length);
 	}
-
-      start += arange.ar_length + initial_length_size;
     }
 
   printf ("\n");
@@ -3142,8 +3078,8 @@ display_debug_frames (struct dwarf_secti
 
 	  if (!cie)
 	    {
-	      warn ("Invalid CIE pointer %08lx in FDE at %p\n",
-		    cie_id, saved_start);
+	      warn ("Invalid CIE pointer %08lx in FDE at %08lx\n",
+		    cie_id, (unsigned long)(saved_start - section_start));
 	      start = block_end;
 	      fc->ncols = 0;
 	      fc->col_type = xmalloc (sizeof (short int));

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

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

* readelf fixes
@ 2002-11-03 19:14 Alan Modra
  0 siblings, 0 replies; 2+ messages in thread
From: Alan Modra @ 2002-11-03 19:14 UTC (permalink / raw)
  To: binutils

A bunch of fixes and enhancements.
- When >64k sections, name for section syms was wrong.
- Print the null terminator in eh_frame (At one stage the eh_frame
  optimization code was buggy, and didn't emit the terminator.  I
  had a shared lib without the terminator..)
- Decode pcrel eh_frame addresses.  We really should decode other types
  too.

	* readelf.c (byte_get_little_endian): Comment typo fix.
	(print_symbol): Constify "symbol" arg.  Don't pass "symbol" to printf
	as the format string.
	(dump_relocations): Correct section sym names.
	(process_section_headers): Clear symtab_shndx_hdr.
	(read_and_display_attr_value): Don't pass indirect string to printf
	as the format string.
	(display_debug_frames): Indicate when zero terminator found.  Decode
	DW_EH_PE_pcrel addresses.

Index: binutils/readelf.c
===================================================================
RCS file: /cvs/src/src/binutils/readelf.c,v
retrieving revision 1.176
diff -u -p -r1.176 readelf.c
--- binutils/readelf.c	9 Oct 2002 13:44:27 -0000	1.176
+++ binutils/readelf.c	4 Nov 2002 02:37:04 -0000
@@ -161,7 +161,7 @@ print_mode;
 
 /* Forward declarations for dumb compilers.  */
 static void		  print_vma		      PARAMS ((bfd_vma, print_mode));
-static void		  print_symbol		      PARAMS ((int, char *));
+static void		  print_symbol		      PARAMS ((int, const char *));
 static bfd_vma (*         byte_get)                   PARAMS ((unsigned char *, int));
 static bfd_vma            byte_get_little_endian      PARAMS ((unsigned char *, int));
 static bfd_vma            byte_get_big_endian         PARAMS ((unsigned char *, int));
@@ -406,7 +406,7 @@ byte_get_little_endian (field, size)
     case 8:
       /* We want to extract data from an 8 byte wide field and
 	 place it into a 4 byte wide field.  Since this is a little
-	 endian source we can juts use the 4 byte extraction code.  */
+	 endian source we can just use the 4 byte extraction code.  */
       /* Fall through.  */
 #endif
     case 4:
@@ -535,10 +535,10 @@ print_vma (vma, mode)
 static void
 print_symbol (width, symbol)
      int width;
-     char * symbol;
+     const char * symbol;
 {
   if (do_wide)
-    printf (symbol);
+    printf ("%s", symbol);
   else if (width < 0)
     printf ("%-*.*s", width, width, symbol);
   else
@@ -1166,7 +1166,35 @@ dump_relocations (file, rel_offset, rel_
 	      printf (is_32bit_elf ? "   " : " ");
 
 	      if (psym->st_name == 0)
-		print_symbol (22, SECTION_NAME (section_headers + psym->st_shndx));
+		{
+		  const char *sec_name = "<null>";
+		  char name_buf[40];
+
+		  if (ELF_ST_TYPE (psym->st_info) == STT_SECTION)
+		    {
+		      bfd_vma sec_index = (bfd_vma) -1;
+
+		      if (psym->st_shndx < SHN_LORESERVE)
+			sec_index = psym->st_shndx;
+		      else if (psym->st_shndx > SHN_LORESERVE)
+			sec_index = psym->st_shndx - (SHN_HIRESERVE + 1
+						      - SHN_LORESERVE);
+
+		      if (sec_index != (bfd_vma) -1)
+			sec_name = SECTION_NAME (section_headers + sec_index);
+		      else if (psym->st_shndx == SHN_ABS)
+			sec_name = "ABS";
+		      else if (psym->st_shndx == SHN_COMMON)
+			sec_name = "COMMON";
+		      else
+			{
+			  sprintf (name_buf, "<section 0x%x>",
+				   (unsigned int) psym->st_shndx);
+			  sec_name = name_buf;
+			}
+		    }
+		  print_symbol (22, sec_name);
+		}
 	      else if (strtab == NULL)
 		printf (_("<string table index %3ld>"), psym->st_name);
 	      else
@@ -3414,6 +3442,7 @@ process_section_headers (file)
   dynamic_symbols = NULL;
   dynamic_strings = NULL;
   dynamic_syminfo = NULL;
+  symtab_shndx_hdr = NULL;
 
   for (i = 0, section = section_headers;
        i < elf_header.e_shnum;
@@ -7740,8 +7769,8 @@ read_and_display_attr_value (attribute, 
       break;
 
     case DW_FORM_strp:
-      printf (_(" (indirect string, offset: 0x%lx): "), uvalue);
-      printf (fetch_indirect_string (uvalue));
+      printf (_(" (indirect string, offset: 0x%lx): %s"),
+	      uvalue, fetch_indirect_string (uvalue));
       break;
 
     case DW_FORM_indirect:
@@ -8380,7 +8409,11 @@ display_debug_frames (section, start, fi
       length = byte_get (start, 4); start += 4;
 
       if (length == 0)
-	return 1;
+	{
+	  printf ("\n%08lx ZERO terminator\n\n",
+		    (unsigned long)(saved_start - section_start));
+	  return 1;
+	}
 
       if (length == 0xffffffff)
 	{
@@ -8534,6 +8567,8 @@ display_debug_frames (section, start, fi
 	    encoded_ptr_size = size_of_encoded_value (fc->fde_encoding);
 
 	  fc->pc_begin = byte_get (start, encoded_ptr_size);
+	  if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel)
+	    fc->pc_begin += section->sh_addr + (start - section_start);
 	  start += encoded_ptr_size;
 	  fc->pc_range = byte_get (start, encoded_ptr_size);
 	  start += encoded_ptr_size;
@@ -8713,6 +8748,8 @@ display_debug_frames (section, start, fi
 
 	    case DW_CFA_set_loc:
 	      vma = byte_get (start, encoded_ptr_size);
+	      if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel)
+		vma += section->sh_addr + (start - section_start);
 	      start += encoded_ptr_size;
 	      if (do_debug_frames_interp)
 		frame_display_row (fc, &need_col_headers, &max_regs);

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

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

end of thread, other threads:[~2006-03-10 13:29 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-03-10 13:29 readelf fixes Alan Modra
  -- strict thread matches above, loose matches on Subject: below --
2002-11-03 19:14 Alan Modra

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).