From 1007acb31dab630af1c33753224c009931bff6f5 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Fri, 30 Sep 2005 14:53:24 +0000 Subject: [PATCH] 2005-09-30 H.J. Lu * readelf.c: Reordered. (is_relocatable): New. (dwarf_section): New structure for DWARF section. (load_debug_section): New. (free_debug_section): Likewise. (debug_str_section): Likewise. (debug_abbrev_section): Likewise. (debug_str_contents): Removed. (debug_str_size): Likewise. (debug_loc_contents): Likewise. (debug_loc_size): Likewise. (debug_range_contents): Likewise. (debug_range_size): Likewise. (load_debug_str): Likewise. (free_debug_str): Likewise. (load_debug_loc): Likewise. (free_debug_loc): Likewise. (load_debug_arange): Likewise. (free_debug_arange): Likewise. (load_debug_abbrev): Likewise. (free_debug_abbrev): Likewise. (fetch_indirect_string): Updated. (debug_apply_rela_addends): Likewise. (process_debug_info): Likewise. (get_debug_info): Likewise. (display_debug_lines): Likewise. (display_debug_pubnames): Likewise. (display_debug_macinfo): Likewise. (display_debug_abbrev): Likewise. (display_debug_loc): Likewise. (display_debug_str): Likewise. (display_debug_info): Likewise. (display_debug_aranges): Likewise. (display_debug_ranges): Likewise. (display_debug_frames): Likewise. (display_debug_not_supported): Likewise. (debug_displays): Likewise. (display_debug_section): Likewise. (get_file_header): Set is_relocatable. --- binutils/ChangeLog | 42 +++ binutils/readelf.c | 886 +++++++++++++++++++++------------------------ 2 files changed, 448 insertions(+), 480 deletions(-) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index e6f14f6c5d5..c992f651d3d 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,45 @@ +2005-09-30 H.J. Lu + + * readelf.c: Reordered. + (is_relocatable): New. + (dwarf_section): New structure for DWARF section. + (load_debug_section): New. + (free_debug_section): Likewise. + (debug_str_section): Likewise. + (debug_abbrev_section): Likewise. + (debug_str_contents): Removed. + (debug_str_size): Likewise. + (debug_loc_contents): Likewise. + (debug_loc_size): Likewise. + (debug_range_contents): Likewise. + (debug_range_size): Likewise. + (load_debug_str): Likewise. + (free_debug_str): Likewise. + (load_debug_loc): Likewise. + (free_debug_loc): Likewise. + (load_debug_arange): Likewise. + (free_debug_arange): Likewise. + (load_debug_abbrev): Likewise. + (free_debug_abbrev): Likewise. + (fetch_indirect_string): Updated. + (debug_apply_rela_addends): Likewise. + (process_debug_info): Likewise. + (get_debug_info): Likewise. + (display_debug_lines): Likewise. + (display_debug_pubnames): Likewise. + (display_debug_macinfo): Likewise. + (display_debug_abbrev): Likewise. + (display_debug_loc): Likewise. + (display_debug_str): Likewise. + (display_debug_info): Likewise. + (display_debug_aranges): Likewise. + (display_debug_ranges): Likewise. + (display_debug_frames): Likewise. + (display_debug_not_supported): Likewise. + (debug_displays): Likewise. + (display_debug_section): Likewise. + (get_file_header): Set is_relocatable. + 2005-09-30 H.J. Lu * readelf.c (debug_apply_rela_addends): Relocate the whole diff --git a/binutils/readelf.c b/binutils/readelf.c index 85239e62027..7da3966c787 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -171,6 +171,7 @@ static int do_debug_loc; static int do_arch; static int do_notes; static int is_32bit_elf; +static int is_relocatable; static int have_frame_base; static int need_base_address; static bfd_vma eh_addr_size; @@ -363,68 +364,6 @@ get_data (void *var, FILE *file, long offset, size_t size, size_t nmemb, return mvar; } -static bfd_vma -byte_get_little_endian (unsigned char *field, int size) -{ - switch (size) - { - case 1: - return *field; - - case 2: - return ((unsigned int) (field[0])) - | (((unsigned int) (field[1])) << 8); - -#ifndef BFD64 - 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 just use the 4 byte extraction code. */ - /* Fall through. */ -#endif - case 4: - return ((unsigned long) (field[0])) - | (((unsigned long) (field[1])) << 8) - | (((unsigned long) (field[2])) << 16) - | (((unsigned long) (field[3])) << 24); - -#ifdef BFD64 - case 8: - return ((bfd_vma) (field[0])) - | (((bfd_vma) (field[1])) << 8) - | (((bfd_vma) (field[2])) << 16) - | (((bfd_vma) (field[3])) << 24) - | (((bfd_vma) (field[4])) << 32) - | (((bfd_vma) (field[5])) << 40) - | (((bfd_vma) (field[6])) << 48) - | (((bfd_vma) (field[7])) << 56); -#endif - default: - error (_("Unhandled data length: %d\n"), size); - abort (); - } -} - -static bfd_vma -byte_get_signed (unsigned char *field, int size) -{ - bfd_vma x = byte_get (field, size); - - switch (size) - { - case 1: - return (x ^ 0x80) - 0x80; - case 2: - return (x ^ 0x8000) - 0x8000; - case 4: - return (x ^ 0x80000000) - 0x80000000; - case 8: - return x; - default: - abort (); - } -} - static void byte_put_little_endian (unsigned char *field, bfd_vma value, int size) { @@ -614,48 +553,6 @@ print_symbol (int width, const char *symbol) printf ("%-.*s", width, symbol); } -static bfd_vma -byte_get_big_endian (unsigned char *field, int size) -{ - switch (size) - { - case 1: - return *field; - - case 2: - return ((unsigned int) (field[1])) | (((int) (field[0])) << 8); - -#ifndef BFD64 - case 8: - /* Although we are extracing data from an 8 byte wide field, - we are returning only 4 bytes of data. */ - field += 4; - /* Fall thru */ -#endif - case 4: - return ((unsigned long) (field[3])) - | (((unsigned long) (field[2])) << 8) - | (((unsigned long) (field[1])) << 16) - | (((unsigned long) (field[0])) << 24); - -#ifdef BFD64 - case 8: - return ((bfd_vma) (field[7])) - | (((bfd_vma) (field[6])) << 8) - | (((bfd_vma) (field[5])) << 16) - | (((bfd_vma) (field[4])) << 24) - | (((bfd_vma) (field[3])) << 32) - | (((bfd_vma) (field[2])) << 40) - | (((bfd_vma) (field[1])) << 48) - | (((bfd_vma) (field[0])) << 56); -#endif - - default: - error (_("Unhandled data length: %d\n"), size); - abort (); - } -} - static void byte_put_big_endian (unsigned char *field, bfd_vma value, int size) { @@ -7467,295 +7364,67 @@ dump_section (Elf_Internal_Shdr *section, FILE *file) } -static unsigned long int -read_leb128 (unsigned char *data, unsigned int *length_return, int sign) -{ - unsigned long int result = 0; - unsigned int num_read = 0; - unsigned int shift = 0; - unsigned char byte; - - do - { - byte = *data++; - num_read++; - - result |= ((unsigned long int) (byte & 0x7f)) << shift; - - shift += 7; - - } - while (byte & 0x80); - - if (length_return != NULL) - *length_return = num_read; - - if (sign && (shift < 8 * sizeof (result)) && (byte & 0x40)) - result |= -1L << shift; - - return result; -} - -typedef struct State_Machine_Registers -{ - unsigned long address; - unsigned int file; - unsigned int line; - unsigned int column; - int is_stmt; - int basic_block; - int end_sequence; -/* This variable hold the number of the last entry seen - in the File Table. */ - unsigned int last_file_entry; -} SMR; - -static SMR state_machine_regs; - -static void -reset_state_machine (int is_stmt) -{ - state_machine_regs.address = 0; - state_machine_regs.file = 1; - state_machine_regs.line = 1; - state_machine_regs.column = 0; - state_machine_regs.is_stmt = is_stmt; - state_machine_regs.basic_block = 0; - state_machine_regs.end_sequence = 0; - state_machine_regs.last_file_entry = 0; -} - -/* Handled an extend line op. - Returns the number of bytes read. */ - -static int -process_extended_line_op (unsigned char *data, int is_stmt, int pointer_size) +struct dwarf_section { - unsigned char op_code; - unsigned int bytes_read; - unsigned int len; - unsigned char *name; - unsigned long adr; - - len = read_leb128 (data, & bytes_read, 0); - data += bytes_read; - - if (len == 0) - { - warn (_("badly formed extended line op encountered!\n")); - return bytes_read; - } - - len += bytes_read; - op_code = *data++; - - printf (_(" Extended opcode %d: "), op_code); - - switch (op_code) - { - case DW_LNE_end_sequence: - printf (_("End of Sequence\n\n")); - reset_state_machine (is_stmt); - 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; - - case DW_LNE_define_file: - printf (_(" define new File Table entry\n")); - printf (_(" Entry\tDir\tTime\tSize\tName\n")); - - printf (_(" %d\t"), ++state_machine_regs.last_file_entry); - name = data; - data += strlen ((char *) data) + 1; - printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); - data += bytes_read; - printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); - data += bytes_read; - printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); - printf (_("%s\n\n"), name); - break; - - default: - printf (_("UNKNOWN: length %d\n"), len - bytes_read); - break; - } - - return len; -} + const char *name; + unsigned char *start; + bfd_vma address; + bfd_size_type size; +}; -static const char *debug_str_contents; -static bfd_vma debug_str_size; +static int process_debug_info (struct dwarf_section *, void *, int); static void -load_debug_str (FILE *file) +load_debug_section (struct dwarf_section *section, void *file) { Elf_Internal_Shdr *sec; + char buf [64]; /* If it is already loaded, do nothing. */ - if (debug_str_contents != NULL) + if (section->start != NULL) return; - /* Locate the .debug_str section. */ - sec = find_section (".debug_str"); + /* Locate the debug section. */ + sec = find_section (section->name); if (sec == NULL) return; - debug_str_size = sec->sh_size; - - debug_str_contents = get_data (NULL, file, sec->sh_offset, 1, sec->sh_size, - _("debug_str section data")); + snprintf (buf, sizeof (buf), _("%s section data"), section->name); + section->address = sec->sh_addr; + section->size = sec->sh_size; + section->start = get_data (NULL, file, sec->sh_offset, 1, + sec->sh_size, buf); } static void -free_debug_str (void) +free_debug_section (struct dwarf_section *section) { - if (debug_str_contents == NULL) + if (section->start == NULL) return; - free ((char *) debug_str_contents); - debug_str_contents = NULL; - debug_str_size = 0; -} - -static const char * -fetch_indirect_string (unsigned long offset) -{ - if (debug_str_contents == NULL) - return _(""); - - if (offset > debug_str_size) - { - warn (_("DW_FORM_strp offset too big: %lx\n"), offset); - return _(""); - } - - return debug_str_contents + offset; + free ((char *) section->start); + section->start = NULL; + section->address = 0; + section->size = 0; } -static const char *debug_loc_contents; -static bfd_vma debug_loc_size; +/* Apply addends of RELA relocations. */ -static void -load_debug_loc (FILE *file) +static int +debug_apply_rela_addends (void *file, + Elf_Internal_Shdr *section, + unsigned char *start) { - Elf_Internal_Shdr *sec; - - /* If it is already loaded, do nothing. */ - if (debug_loc_contents != NULL) - return; + Elf_Internal_Shdr *relsec; + unsigned char *end = start + section->sh_size; + /* FIXME: The relocation field size is relocation type dependent. */ + unsigned int reloc_size = 4; - /* Locate the .debug_loc section. */ - sec = find_section (".debug_loc"); - if (sec == NULL) - return; + if (!is_relocatable) + return 1; - debug_loc_size = sec->sh_size; - - debug_loc_contents = get_data (NULL, file, sec->sh_offset, 1, sec->sh_size, - _("debug_loc section data")); -} - -static void -free_debug_loc (void) -{ - if (debug_loc_contents == NULL) - return; - - free ((char *) debug_loc_contents); - debug_loc_contents = NULL; - debug_loc_size = 0; -} - -static const char * debug_range_contents; -static unsigned long debug_range_size; - -static void -load_debug_range (FILE *file) -{ - Elf_Internal_Shdr *sec; - - /* If it is already loaded, do nothing. */ - if (debug_range_contents != NULL) - return; - - /* Locate the .debug_ranges section. */ - sec = find_section (".debug_ranges"); - if (sec == NULL) - return; - - debug_range_size = sec->sh_size; - - debug_range_contents = get_data (NULL, file, sec->sh_offset, 1, sec->sh_size, - _("debug_range section data")); -} - -static void -free_debug_range (void) -{ - if (debug_range_contents == NULL) - return; - - free ((char *) debug_range_contents); - debug_range_contents = NULL; - debug_range_size = 0; -} - -static unsigned char *debug_abbrev_contents; -static unsigned long debug_abbrev_size; - -static void -load_debug_abbrev (FILE *file) -{ - Elf_Internal_Shdr *sec; - - /* If it is already loaded, do nothing. */ - if (debug_abbrev_contents != NULL) - return; - - /* Locate the .debug_ranges section. */ - sec = find_section (".debug_abbrev"); - if (sec == NULL) - return; - - debug_abbrev_size = sec->sh_size; - - debug_abbrev_contents = get_data (NULL, file, sec->sh_offset, 1, - sec->sh_size, - _("debug_abbrev section data")); -} - -static void -free_debug_abbrev (void) -{ - if (debug_abbrev_contents == NULL) - return; - - free ((char *) debug_abbrev_contents); - debug_abbrev_contents = NULL; - debug_abbrev_size = 0; -} - -/* Apply addends of RELA relocations. */ - -static int -debug_apply_rela_addends (FILE *file, - Elf_Internal_Shdr *section, - unsigned char *start) -{ - Elf_Internal_Shdr *relsec; - unsigned char *end = start + section->sh_size; - /* FIXME: The relocation field size is relocation type dependent. */ - unsigned int reloc_size = 4; - - if (elf_header.e_type != ET_REL) - return 1; - - if (section->sh_size < reloc_size) - return 1; + if (section->sh_size < reloc_size) + return 1; for (relsec = section_headers; relsec < section_headers + elf_header.e_shnum; @@ -7848,6 +7517,259 @@ debug_apply_rela_addends (FILE *file, return 1; } +static bfd_vma +byte_get_little_endian (unsigned char *field, int size) +{ + switch (size) + { + case 1: + return *field; + + case 2: + return ((unsigned int) (field[0])) + | (((unsigned int) (field[1])) << 8); + +#ifndef BFD64 + 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 just use the 4 byte extraction code. */ + /* Fall through. */ +#endif + case 4: + return ((unsigned long) (field[0])) + | (((unsigned long) (field[1])) << 8) + | (((unsigned long) (field[2])) << 16) + | (((unsigned long) (field[3])) << 24); + +#ifdef BFD64 + case 8: + return ((bfd_vma) (field[0])) + | (((bfd_vma) (field[1])) << 8) + | (((bfd_vma) (field[2])) << 16) + | (((bfd_vma) (field[3])) << 24) + | (((bfd_vma) (field[4])) << 32) + | (((bfd_vma) (field[5])) << 40) + | (((bfd_vma) (field[6])) << 48) + | (((bfd_vma) (field[7])) << 56); +#endif + default: + error (_("Unhandled data length: %d\n"), size); + abort (); + } +} + +static bfd_vma +byte_get_signed (unsigned char *field, int size) +{ + bfd_vma x = byte_get (field, size); + + switch (size) + { + case 1: + return (x ^ 0x80) - 0x80; + case 2: + return (x ^ 0x8000) - 0x8000; + case 4: + return (x ^ 0x80000000) - 0x80000000; + case 8: + return x; + default: + abort (); + } +} + +static bfd_vma +byte_get_big_endian (unsigned char *field, int size) +{ + switch (size) + { + case 1: + return *field; + + case 2: + return ((unsigned int) (field[1])) | (((int) (field[0])) << 8); + +#ifndef BFD64 + case 8: + /* Although we are extracing data from an 8 byte wide field, + we are returning only 4 bytes of data. */ + field += 4; + /* Fall thru */ +#endif + case 4: + return ((unsigned long) (field[3])) + | (((unsigned long) (field[2])) << 8) + | (((unsigned long) (field[1])) << 16) + | (((unsigned long) (field[0])) << 24); + +#ifdef BFD64 + case 8: + return ((bfd_vma) (field[7])) + | (((bfd_vma) (field[6])) << 8) + | (((bfd_vma) (field[5])) << 16) + | (((bfd_vma) (field[4])) << 24) + | (((bfd_vma) (field[3])) << 32) + | (((bfd_vma) (field[2])) << 40) + | (((bfd_vma) (field[1])) << 48) + | (((bfd_vma) (field[0])) << 56); +#endif + + default: + error (_("Unhandled data length: %d\n"), size); + abort (); + } +} + +static unsigned long int +read_leb128 (unsigned char *data, unsigned int *length_return, int sign) +{ + unsigned long int result = 0; + unsigned int num_read = 0; + unsigned int shift = 0; + unsigned char byte; + + do + { + byte = *data++; + num_read++; + + result |= ((unsigned long int) (byte & 0x7f)) << shift; + + shift += 7; + + } + while (byte & 0x80); + + if (length_return != NULL) + *length_return = num_read; + + if (sign && (shift < 8 * sizeof (result)) && (byte & 0x40)) + result |= -1L << shift; + + return result; +} + +typedef struct State_Machine_Registers +{ + unsigned long address; + unsigned int file; + unsigned int line; + unsigned int column; + int is_stmt; + int basic_block; + int end_sequence; +/* This variable hold the number of the last entry seen + in the File Table. */ + unsigned int last_file_entry; +} SMR; + +static SMR state_machine_regs; + +static void +reset_state_machine (int is_stmt) +{ + state_machine_regs.address = 0; + state_machine_regs.file = 1; + state_machine_regs.line = 1; + state_machine_regs.column = 0; + state_machine_regs.is_stmt = is_stmt; + state_machine_regs.basic_block = 0; + state_machine_regs.end_sequence = 0; + state_machine_regs.last_file_entry = 0; +} + +/* Handled an extend line op. + Returns the number of bytes read. */ + +static int +process_extended_line_op (unsigned char *data, int is_stmt, int pointer_size) +{ + unsigned char op_code; + unsigned int bytes_read; + unsigned int len; + unsigned char *name; + unsigned long adr; + + len = read_leb128 (data, & bytes_read, 0); + data += bytes_read; + + if (len == 0) + { + warn (_("badly formed extended line op encountered!\n")); + return bytes_read; + } + + len += bytes_read; + op_code = *data++; + + printf (_(" Extended opcode %d: "), op_code); + + switch (op_code) + { + case DW_LNE_end_sequence: + printf (_("End of Sequence\n\n")); + reset_state_machine (is_stmt); + 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; + + case DW_LNE_define_file: + printf (_(" define new File Table entry\n")); + printf (_(" Entry\tDir\tTime\tSize\tName\n")); + + printf (_(" %d\t"), ++state_machine_regs.last_file_entry); + name = data; + data += strlen ((char *) data) + 1; + printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); + data += bytes_read; + printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); + data += bytes_read; + printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); + printf (_("%s\n\n"), name); + break; + + default: + printf (_("UNKNOWN: length %d\n"), len - bytes_read); + break; + } + + return len; +} + +static struct dwarf_section debug_str_section = { + ".debug_str", + NULL, + 0, + 0 +}; + +static const char * +fetch_indirect_string (unsigned long offset) +{ + if (debug_str_section.start == NULL) + return _(""); + + if (offset > debug_str_section.size) + { + warn (_("DW_FORM_strp offset too big: %lx\n"), offset); + return _(""); + } + + return debug_str_section.start + offset; +} + +static struct dwarf_section debug_abbrev_section = { + ".debug_abbrev", + NULL, + 0, + 0 +}; + /* FIXME: There are better and more efficient ways to handle these structures. For now though, I just want something that is simple to implement. */ @@ -9080,10 +9002,11 @@ read_and_display_attr (unsigned long attribute, anything to the user. */ static int -process_debug_info (Elf_Internal_Shdr *section, unsigned char *start, - FILE *file, int do_loc) +process_debug_info (struct dwarf_section *section, void *file, + int do_loc) { - unsigned char *end = start + section->sh_size; + unsigned char *start = section->start; + unsigned char *end = start + section->size; unsigned char *section_begin; unsigned int unit; unsigned int num_units = 0; @@ -9113,7 +9036,7 @@ process_debug_info (Elf_Internal_Shdr *section, unsigned char *start, if (num_units == 0) { - error (_("No comp units in .debug_info section ?")); + error (_("No comp units in %s section ?"), section->name); return 0; } @@ -9130,18 +9053,16 @@ process_debug_info (Elf_Internal_Shdr *section, unsigned char *start, if (!do_loc) { - printf (_("The section %s contains:\n\n"), - SECTION_NAME (section)); + printf (_("The section %s contains:\n\n"), section->name); - load_debug_str (file); - load_debug_loc (file); - load_debug_range (file); + load_debug_section (&debug_str_section, file); } - load_debug_abbrev (file); - if (debug_abbrev_contents == NULL) + load_debug_section (&debug_abbrev_section, file); + if (debug_abbrev_section.start == NULL) { - warn (_("Unable to locate .debug_abbrev section!\n")); + warn (_("Unable to locate %s section!\n"), + debug_abbrev_section.name); return 0; } @@ -9223,8 +9144,10 @@ process_debug_info (Elf_Internal_Shdr *section, unsigned char *start, /* Process the abbrevs used by this compilation unit. */ process_abbrev_section - (debug_abbrev_contents + compunit.cu_abbrev_offset, - debug_abbrev_contents + debug_abbrev_size); + ((unsigned char *) debug_abbrev_section.start + + compunit.cu_abbrev_offset, + (unsigned char *) debug_abbrev_section.start + + debug_abbrev_section.size); level = 0; while (tags < start) @@ -9298,7 +9221,7 @@ process_debug_info (Elf_Internal_Shdr *section, unsigned char *start, } } - free_debug_abbrev (); + free_debug_section (&debug_abbrev_section); /* Set num_debug_info_entries here so that it can be used to check if we need to process .debug_loc and .debug_ranges sections. */ @@ -9308,9 +9231,7 @@ process_debug_info (Elf_Internal_Shdr *section, unsigned char *start, if (!do_loc) { - free_debug_range (); - free_debug_str (); - free_debug_loc (); + free_debug_section (&debug_str_section); printf ("\n"); } @@ -9367,11 +9288,11 @@ get_pointer_size_and_offset_of_comp_unit (unsigned int comp_unit, compilation units upon success. */ static unsigned int -get_debug_info (FILE * file) +get_debug_info (void * file) { Elf_Internal_Shdr * section; - unsigned char * start; - int ret; + struct dwarf_section sec; + int ret; /* Reset the last pointer size so that we can issue correct error messages if we are displaying the contents of more than one section. */ @@ -9382,33 +9303,37 @@ get_debug_info (FILE * file) if (num_debug_info_entries > 0) return num_debug_info_entries; - section = find_section (".debug_info"); + sec.name = ".debug_info"; + section = find_section (sec.name); if (section == NULL) return 0; - start = get_data (NULL, file, section->sh_offset, 1, section->sh_size, - _("extracting information from .debug_info section")); - if (start == NULL) + sec.start = get_data (NULL, file, section->sh_offset, 1, + section->sh_size, + _("extracting information from .debug_info section")); + if (sec.start == NULL) return 0; - ret = (debug_apply_rela_addends (file, section, start) - && process_debug_info (section, start, file, 1)); + sec.address = section->sh_addr; + sec.size = section->sh_size; + ret = (debug_apply_rela_addends (file, section, sec.start) + && process_debug_info (&sec, file, 1)); - free (start); + free (sec.start); return ret ? num_debug_info_entries : 0; } static int -display_debug_lines (Elf_Internal_Shdr *section, - unsigned char *start, FILE *file) +display_debug_lines (struct dwarf_section *section, void *file) { + unsigned char *start = section->start; unsigned char *data = start; - unsigned char *end = start + section->sh_size; + unsigned char *end = start + section->size; unsigned int comp_unit = 0; printf (_("\nDump of debug contents of section %s:\n\n"), - SECTION_NAME (section)); + section->name); get_debug_info (file); @@ -9443,7 +9368,7 @@ display_debug_lines (Elf_Internal_Shdr *section, initial_length_size = 4; } - if (info.li_length + initial_length_size > section->sh_size) + if (info.li_length + initial_length_size > section->size) { warn (_("The line info appears to be corrupt - the section is too small\n")); @@ -9692,16 +9617,14 @@ display_debug_lines (Elf_Internal_Shdr *section, } static int -display_debug_pubnames (Elf_Internal_Shdr *section, - unsigned char *start, - FILE *file ATTRIBUTE_UNUSED) +display_debug_pubnames (struct dwarf_section *section, + void *file ATTRIBUTE_UNUSED) { DWARF2_Internal_PubNames pubnames; - unsigned char *end; + unsigned char *start = section->start; + unsigned char *end = start + section->size; - end = start + section->sh_size; - - printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section)); + printf (_("Contents of the %s section:\n\n"), section->name); while (start < end) { @@ -9778,16 +9701,16 @@ display_debug_pubnames (Elf_Internal_Shdr *section, } static int -display_debug_macinfo (Elf_Internal_Shdr *section, - unsigned char *start, - FILE *file ATTRIBUTE_UNUSED) +display_debug_macinfo (struct dwarf_section *section, + void *file ATTRIBUTE_UNUSED) { - unsigned char *end = start + section->sh_size; + unsigned char *start = section->start; + unsigned char *end = start + section->size; unsigned char *curr = start; unsigned int bytes_read; enum dwarf_macinfo_record_type op; - printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section)); + printf (_("Contents of the %s section:\n\n"), section->name); while (curr < end) { @@ -9855,14 +9778,14 @@ display_debug_macinfo (Elf_Internal_Shdr *section, static int -display_debug_abbrev (Elf_Internal_Shdr *section, - unsigned char *start, - FILE *file ATTRIBUTE_UNUSED) +display_debug_abbrev (struct dwarf_section *section, + void *file ATTRIBUTE_UNUSED) { abbrev_entry *entry; - unsigned char *end = start + section->sh_size; + unsigned char *start = section->start; + unsigned char *end = start + section->size; - printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section)); + printf (_("Contents of the %s section:\n\n"), section->name); do { @@ -9898,9 +9821,9 @@ display_debug_abbrev (Elf_Internal_Shdr *section, } static int -display_debug_loc (Elf_Internal_Shdr *section, - unsigned char *start, FILE *file) +display_debug_loc (struct dwarf_section *section, void *file) { + unsigned char *start = section->start; unsigned char *section_end; unsigned long bytes; unsigned char *section_begin = start; @@ -9913,12 +9836,12 @@ display_debug_loc (Elf_Internal_Shdr *section, int use_debug_info = 1; unsigned char *next; - bytes = section->sh_size; + bytes = section->size; section_end = start + bytes; if (bytes == 0) { - printf (_("\nThe .debug_loc section is empty.\n")); + printf (_("\nThe %s section is empty.\n"), section->name); return 0; } @@ -9969,10 +9892,10 @@ display_debug_loc (Elf_Internal_Shdr *section, error (_("No location lists in .debug_info section!\n")); if (debug_information [first].loc_offsets [0] != 0) - warn (_("Location lists in .debug_loc section start at 0x%lx\n"), - debug_information [first].loc_offsets [0]); + warn (_("Location lists in %s section start at 0x%lx\n"), + section->name, debug_information [first].loc_offsets [0]); - printf (_("Contents of the .debug_loc section:\n\n")); + printf (_("Contents of the %s section:\n\n"), section->name); printf (_(" Offset Begin End Expression\n")); seen_first_offset = 0; @@ -10090,23 +10013,20 @@ display_debug_loc (Elf_Internal_Shdr *section, } static int -display_debug_str (Elf_Internal_Shdr *section, - unsigned char *start, - FILE *file ATTRIBUTE_UNUSED) +display_debug_str (struct dwarf_section *section, + void *file ATTRIBUTE_UNUSED) { - unsigned long bytes; - bfd_vma addr; - - addr = section->sh_addr; - bytes = section->sh_size; + unsigned char *start = section->start; + unsigned long bytes = section->size; + bfd_vma addr = section->address; if (bytes == 0) { - printf (_("\nThe .debug_str section is empty.\n")); + printf (_("\nThe %s section is empty.\n"), section->name); return 0; } - printf (_("Contents of the .debug_str section:\n\n")); + printf (_("Contents of the %s section:\n\n"), section->name); while (bytes) { @@ -10152,21 +10072,20 @@ display_debug_str (Elf_Internal_Shdr *section, static int -display_debug_info (Elf_Internal_Shdr * section, - unsigned char * start, FILE * file) +display_debug_info (struct dwarf_section *section, void *file) { - return process_debug_info (section, start, file, 0); + return process_debug_info (section, file, 0); } static int -display_debug_aranges (Elf_Internal_Shdr *section, - unsigned char *start, - FILE *file ATTRIBUTE_UNUSED) +display_debug_aranges (struct dwarf_section *section, + void *file ATTRIBUTE_UNUSED) { - unsigned char *end = start + section->sh_size; + unsigned char *start = section->start; + unsigned char *end = start + section->size; - printf (_("The section %s contains:\n\n"), SECTION_NAME (section)); + printf (_("The section %s contains:\n\n"), section->name); while (start < end) { @@ -10256,10 +10175,10 @@ display_debug_aranges (Elf_Internal_Shdr *section, } static int -display_debug_ranges (Elf_Internal_Shdr *section, - unsigned char *start, - FILE *file ATTRIBUTE_UNUSED) +display_debug_ranges (struct dwarf_section *section, + void *file ATTRIBUTE_UNUSED) { + unsigned char *start = section->start; unsigned char *section_end; unsigned long bytes; unsigned char *section_begin = start; @@ -10272,12 +10191,12 @@ display_debug_ranges (Elf_Internal_Shdr *section, int use_debug_info = 1; unsigned char *next; - bytes = section->sh_size; + bytes = section->size; section_end = start + bytes; if (bytes == 0) { - printf (_("\nThe .debug_ranges section is empty.\n")); + printf (_("\nThe %s section is empty.\n"), section->name); return 0; } @@ -10328,10 +10247,10 @@ display_debug_ranges (Elf_Internal_Shdr *section, error (_("No range lists in .debug_info section!\n")); if (debug_information [first].range_lists [0] != 0) - warn (_("Range lists in .debug_ranges section start at 0x%lx\n"), - debug_information [first].range_lists [0]); + warn (_("Range lists in %s section start at 0x%lx\n"), + section->name, debug_information [first].range_lists [0]); - printf (_("Contents of the .debug_ranges section:\n\n")); + printf (_("Contents of the %s section:\n\n"), section->name); printf (_(" Offset Begin End\n")); seen_first_offset = 0; @@ -10356,11 +10275,13 @@ display_debug_ranges (Elf_Internal_Shdr *section, else { if (start < next) - warn (_("There is a hole [0x%lx - 0x%lx] in .debug_ranges section.\n"), - (long)(start - section_begin), (long)(next - section_begin)); + warn (_("There is a hole [0x%lx - 0x%lx] in %s section.\n"), + (long)(start - section_begin), + (long)(next - section_begin), section->name); else if (start > next) - warn (_("There is an overlap [0x%lx - 0x%lx] in .debug_ranges section.\n"), - (long)(start - section_begin), (long)(next - section_begin)); + warn (_("There is an overlap [0x%lx - 0x%lx] in %s section.\n"), + (long)(start - section_begin), + (long)(next - section_begin), section->name); } start = next; @@ -10540,20 +10461,20 @@ get_encoded_value (unsigned char *data, int encoding) #define SLEB() read_leb128 (start, & length_return, 1); start += length_return static int -display_debug_frames (Elf_Internal_Shdr *section, - unsigned char *start, - FILE *file ATTRIBUTE_UNUSED) +display_debug_frames (struct dwarf_section *section, + void *file ATTRIBUTE_UNUSED) { - unsigned char *end = start + section->sh_size; + unsigned char *start = section->start; + unsigned char *end = start + section->size; unsigned char *section_start = start; Frame_Chunk *chunks = 0; Frame_Chunk *remembered_state = 0; Frame_Chunk *rs; - int is_eh = streq (SECTION_NAME (section), ".eh_frame"); + int is_eh = streq (section->name, ".eh_frame"); unsigned int length_return; int max_regs = 0; - printf (_("The section %s contains:\n"), SECTION_NAME (section)); + printf (_("The section %s contains:\n"), section->name); while (start < end) { @@ -10761,10 +10682,11 @@ display_debug_frames (Elf_Internal_Shdr *section, fc->pc_begin = get_encoded_value (start, fc->fde_encoding); if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel - /* Don't adjust for ET_REL since there's invariably a pcrel - reloc here, which we haven't applied. */ - && elf_header.e_type != ET_REL) - fc->pc_begin += section->sh_addr + (start - section_start); + /* Don't adjust for relocatable file since there's + invariably a pcrel reloc here, which we haven't + applied. */ + && !is_relocatable) + fc->pc_begin += section->address + (start - section_start); start += encoded_ptr_size; fc->pc_range = byte_get (start, encoded_ptr_size); start += encoded_ptr_size; @@ -10964,8 +10886,8 @@ display_debug_frames (Elf_Internal_Shdr *section, case DW_CFA_set_loc: vma = get_encoded_value (start, fc->fde_encoding); if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel - && elf_header.e_type != ET_REL) - vma += section->sh_addr + (start - section_start); + && !is_relocatable) + vma += section->address + (start - section_start); start += encoded_ptr_size; if (do_debug_frames_interp) frame_display_row (fc, &need_col_headers, &max_regs); @@ -11217,12 +11139,11 @@ display_debug_frames (Elf_Internal_Shdr *section, #undef SLEB static int -display_debug_not_supported (Elf_Internal_Shdr *section, - unsigned char *start ATTRIBUTE_UNUSED, - FILE *file ATTRIBUTE_UNUSED) +display_debug_not_supported (struct dwarf_section *section, + void *file ATTRIBUTE_UNUSED) { printf (_("Displaying the debug contents of section %s is not yet supported.\n"), - SECTION_NAME (section)); + section->name); return 1; } @@ -11232,7 +11153,7 @@ display_debug_not_supported (Elf_Internal_Shdr *section, static struct { const char *const name; - int (*display) (Elf_Internal_Shdr *, unsigned char *, FILE *); + int (*display) (struct dwarf_section *, void *); unsigned int relocate : 1; } debug_displays[] = @@ -11277,21 +11198,24 @@ display_debug_section (Elf_Internal_Shdr *section, FILE *file) for (i = NUM_ELEM (debug_displays); i--;) if (streq (debug_displays[i].name, name)) { - unsigned char *start; - - start = get_data (NULL, file, section->sh_offset, 1, length, - _("debug section data")); - if (start == NULL) + struct dwarf_section sec; + + sec.name = name; + sec.address = section->sh_addr; + sec.size = section->sh_size; + sec.start = get_data (NULL, file, section->sh_offset, 1, + length, _("debug section data")); + if (sec.start == NULL) { result = 0; break; } if (!debug_displays[i].relocate - || debug_apply_rela_addends (file, section, start)) - result &= debug_displays[i].display (section, start, file); + || debug_apply_rela_addends (file, section, sec.start)) + result &= debug_displays[i].display (&sec, file); - free (start); + free (sec.start); /* If we loaded in the abbrev section at some point, we must release it here. */ @@ -12230,6 +12154,8 @@ get_file_header (FILE *file) get_64bit_section_headers (file, 1); } + is_relocatable = elf_header.e_type == ET_REL; + return 1; } -- 2.30.2