This is the mail archive of the
binutils@sourceware.cygnus.com
mailing list for the binutils project.
patch for binutils/readelf.c, problem with .debug_line and pointer_size != 4
- To: binutils@sourceware.cygnus.com
- Subject: patch for binutils/readelf.c, problem with .debug_line and pointer_size != 4
- From: Stephane Carrez <stephane.carrez@free.fr>
- Date: Fri, 27 Aug 1999 23:18:57 +0200
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