This is the mail archive of the binutils@sourceware.cygnus.com 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]

patch for binutils/readelf.c, problem with .debug_line and pointer_size != 4


Hi!

The following patch solves the problem of dumping the .debug_line
sections
when the address size is not 4. The dump was hard coded...
Headers in .debug_line section do not tell what the size of address is. 
My understanding of DWARF-2 spec is that we are
supposed to look at the corresponding .debug_info compilation unit.

The fix consist in doing a pre-scan of the .debug_info section and
remember
the pointer size in a global variable. I've introduced a pre-scan for
all
the sections but only one pre-scan handler is setup.

I've checked the patch on object files of my 68HC11 port (pointer size =
2)
as well as on i386 object files (pointer size = 4). This should fix the
case of
pointer size = 8 but I can't check this.

Can you integrate this patch?

Thanks,
        Stephane

1999-08-27  Stephane Carrez  <stcarrez@worldnet.fr>

	* readelf.c (process_extended_line_op): New parameter pointer_size,
	read the address according to pointer_size.
	(debug_line_pointer_size): New global to indicate the
	size of address in .debug_line section.
	(debug_displays, prescan_debug_info): Prescan the .debug_info section
	to record the size of address in `debug_line_pointer_size'.
	(process_section_contents): Before dumping any section, execute
	the pre-scan operation defined for some debug sections.
*** ../../cygnus/binutils/binutils/readelf.c	Fri Aug 27 21:03:08 1999
--- binutils/readelf.c	Fri Aug 27 21:53:35 1999
*************** static int                display_debug_
*** 177,183 ****
  static int                display_debug_aranges       PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
  static unsigned char *    process_abbrev_section      PARAMS ((unsigned char *, unsigned char *));
  static unsigned long      read_leb128                 PARAMS ((unsigned char *, int *, int));
! static int                process_extended_line_op    PARAMS ((unsigned char *, int));
  static void               reset_state_machine         PARAMS ((int));
  static char *             get_TAG_name                PARAMS ((unsigned long));
  static char *             get_AT_name                 PARAMS ((unsigned long));
--- 177,184 ----
  static int                display_debug_aranges       PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
  static unsigned char *    process_abbrev_section      PARAMS ((unsigned char *, unsigned char *));
  static unsigned long      read_leb128                 PARAMS ((unsigned char *, int *, int));
! static int                process_extended_line_op    PARAMS ((unsigned char *,
!                                                                int, int));
  static void               reset_state_machine         PARAMS ((int));
  static char *             get_TAG_name                PARAMS ((unsigned long));
  static char *             get_AT_name                 PARAMS ((unsigned long));
*************** reset_state_machine (is_stmt)
*** 4132,4140 ****
  /* Handled an extend line op.  Returns true if this is the end
     of sequence.  */
  static int
! process_extended_line_op (data, is_stmt)
       unsigned char * data;
       int is_stmt;
  {
    unsigned char   op_code;
    int             bytes_read;
--- 4133,4142 ----
  /* Handled an extend line op.  Returns true if this is the end
     of sequence.  */
  static int
! process_extended_line_op (data, is_stmt, pointer_size)
       unsigned char * data;
       int is_stmt;
+      int pointer_size;
  {
    unsigned char   op_code;
    int             bytes_read;
*************** process_extended_line_op (data, is_stmt)
*** 4164,4171 ****
        break;
  
      case DW_LNE_set_address:
!       /* XXX - assumption here that address size is 4! */
!       adr = byte_get (data, 4);
        printf (_("set Address to 0x%lx\n"), adr);
        state_machine_regs.address = adr;
        break;
--- 4166,4172 ----
        break;
  
      case DW_LNE_set_address:
!       adr = byte_get (data, pointer_size);
        printf (_("set Address to 0x%lx\n"), adr);
        state_machine_regs.address = adr;
        break;
*************** process_extended_line_op (data, is_stmt)
*** 4193,4198 ****
--- 4194,4203 ----
    return len;
  }
  
+ /* Size of pointers in the .debug_line section. This information is not
+    really present in that section. It's obtained before dumping the debug
+    sections by doing some pre-scan of the .debug_info section. */
+ static int debug_line_pointer_size = 4;
  
  static int
  display_debug_lines (section, start, file)
*************** display_debug_lines (section, start, fil
*** 4330,4336 ****
  	  switch (op_code)
  	    {
  	    case DW_LNS_extended_op:
! 	      data += process_extended_line_op (data, info.li_default_is_stmt);
  	      break;
  	      
  	    case DW_LNS_copy:
--- 4335,4342 ----
  	  switch (op_code)
  	    {
  	    case DW_LNS_extended_op:
! 	      data += process_extended_line_op (data, info.li_default_is_stmt,
!                                                 debug_line_pointer_size);
  	      break;
  	      
  	    case DW_LNS_copy:
*************** display_debug_not_supported (section, st
*** 5817,5843 ****
    return 1;
  }
  
    /* A structure containing the name of a debug section and a pointer
       to a function that can decode it.  */
  struct
  {
    char * name;
    int (* display) PARAMS((Elf32_Internal_Shdr *, unsigned char *, FILE *));
  }
  debug_displays[] =
  {
!   { ".debug_info",        display_debug_info },
!   { ".debug_abbrev",      display_debug_abbrev },
!   { ".debug_line",        display_debug_lines },
!   { ".debug_aranges",     display_debug_aranges },
!   { ".debug_pubnames",    display_debug_pubnames },
!   { ".debug_macinfo",     display_debug_not_supported },
!   { ".debug_frame",       display_debug_not_supported },
!   { ".debug_str",         display_debug_not_supported },
!   { ".debug_static_func", display_debug_not_supported },
!   { ".debug_static_vars", display_debug_not_supported },
!   { ".debug_types",       display_debug_not_supported },
!   { ".debug_weaknames",   display_debug_not_supported }
  };
  
  static int
--- 5823,5867 ----
    return 1;
  }
  
+ /* Pre-scan the .debug_info section to record the size of address.
+    When dumping the .debug_line, we use that size information, assuming
+    that all compilation units have the same address size. */
+ static int
+ prescan_debug_info (section, start, file)
+      Elf32_Internal_Shdr * section ATTRIBUTE_UNUSED;
+      unsigned char *       start;
+      FILE *                file ATTRIBUTE_UNUSED;
+ {
+   DWARF2_External_CompUnit * external;
+ 
+   external = (DWARF2_External_CompUnit *) start;
+ 
+   debug_line_pointer_size = BYTE_GET (external->cu_pointer_size);
+   return 0;
+ }
+ 
    /* A structure containing the name of a debug section and a pointer
       to a function that can decode it.  */
  struct
  {
    char * name;
    int (* display) PARAMS((Elf32_Internal_Shdr *, unsigned char *, FILE *));
+   int (* prescan) PARAMS((Elf32_Internal_Shdr *, unsigned char *, FILE *));
  }
  debug_displays[] =
  {
!   { ".debug_info",        display_debug_info, prescan_debug_info },
!   { ".debug_abbrev",      display_debug_abbrev, 0 },
!   { ".debug_line",        display_debug_lines, 0 },
!   { ".debug_aranges",     display_debug_aranges, 0 },
!   { ".debug_pubnames",    display_debug_pubnames, 0 },
!   { ".debug_macinfo",     display_debug_not_supported, 0 },
!   { ".debug_frame",       display_debug_not_supported, 0 },
!   { ".debug_str",         display_debug_not_supported, 0 },
!   { ".debug_static_func", display_debug_not_supported, 0 },
!   { ".debug_static_vars", display_debug_not_supported, 0 },
!   { ".debug_types",       display_debug_not_supported, 0 },
!   { ".debug_weaknames",   display_debug_not_supported, 0 }
  };
  
  static int
*************** process_section_contents (file)
*** 5890,5895 ****
--- 5914,5953 ----
  
    if (! do_dump)
      return 1;
+ 
+   /* Pre-scan the debug sections to find some debug information not
+      present in some of them. For the .debug_line, we must find out the
+      size of address (specified in .debug_info and .debug_aranges). */
+   for (i = 0, section = section_headers;
+        i < elf_header.e_shnum
+        && i < num_dump_sects;
+        i ++, section ++)
+     {
+       char *          name = SECTION_NAME (section);
+       int             j;
+ 
+       if (section->sh_size == 0)
+         continue;
+ 
+       /* See if there is some pre-scan operation for this section.  */
+       for (j = NUM_ELEM (debug_displays); j--;)
+         if (strcmp (debug_displays[j].name, name) == 0)
+           {
+             bfd_size_type   length;
+             unsigned char * start;
+ 
+             if (debug_displays[j].prescan == 0)
+               break;
+             
+             length = section->sh_size;
+             GET_DATA_ALLOC (section->sh_offset, length, start, unsigned char *,
+                             "debug section data");
+ 
+             debug_displays[j].prescan (section, start, file);
+             free (start);
+             break;
+           }
+     }
  
    for (i = 0, section = section_headers;
         i < elf_header.e_shnum

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