diff options
-rw-r--r-- | binutils/ChangeLog | 42 | ||||
-rw-r--r-- | binutils/readelf.c | 852 |
2 files changed, 431 insertions, 463 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog index e6f14f6c5d..c992f651d3 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,5 +1,47 @@ 2005-09-30 H.J. Lu <hongjiu.lu@intel.com> + * 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 <hongjiu.lu@intel.com> + * readelf.c (debug_apply_rela_addends): Relocate the whole section. (process_debug_info): Don't call debug_apply_rela_addends. diff --git a/binutils/readelf.c b/binutils/readelf.c index 85239e6202..7da3966c78 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,6 +7364,263 @@ dump_section (Elf_Internal_Shdr *section, FILE *file) } +struct dwarf_section +{ + const char *name; + unsigned char *start; + bfd_vma address; + bfd_size_type size; +}; + +static int process_debug_info (struct dwarf_section *, void *, int); + +static void +load_debug_section (struct dwarf_section *section, void *file) +{ + Elf_Internal_Shdr *sec; + char buf [64]; + + /* If it is already loaded, do nothing. */ + if (section->start != NULL) + return; + + /* Locate the debug section. */ + sec = find_section (section->name); + if (sec == NULL) + return; + + 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_section (struct dwarf_section *section) +{ + if (section->start == NULL) + return; + + free ((char *) section->start); + section->start = NULL; + section->address = 0; + section->size = 0; +} + +/* Apply addends of RELA relocations. */ + +static int +debug_apply_rela_addends (void *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 (!is_relocatable) + return 1; + + if (section->sh_size < reloc_size) + return 1; + + for (relsec = section_headers; + relsec < section_headers + elf_header.e_shnum; + ++relsec) + { + unsigned long nrelas; + Elf_Internal_Rela *rela, *rp; + Elf_Internal_Shdr *symsec; + Elf_Internal_Sym *symtab; + Elf_Internal_Sym *sym; + + if (relsec->sh_type != SHT_RELA + || SECTION_HEADER_INDEX (relsec->sh_info) >= elf_header.e_shnum + || SECTION_HEADER (relsec->sh_info) != section + || relsec->sh_size == 0 + || SECTION_HEADER_INDEX (relsec->sh_link) >= elf_header.e_shnum) + continue; + + if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size, + &rela, &nrelas)) + return 0; + + symsec = SECTION_HEADER (relsec->sh_link); + symtab = GET_ELF_SYMBOLS (file, symsec); + + for (rp = rela; rp < rela + nrelas; ++rp) + { + unsigned char *loc; + + loc = start + rp->r_offset; + if ((loc + reloc_size) > end) + { + warn (_("skipping invalid relocation offset 0x%lx in section %s\n"), + (unsigned long) rp->r_offset, + SECTION_NAME (section)); + continue; + } + + if (is_32bit_elf) + { + sym = symtab + ELF32_R_SYM (rp->r_info); + + if (ELF32_R_SYM (rp->r_info) != 0 + && ELF32_ST_TYPE (sym->st_info) != STT_SECTION + /* Relocations against object symbols can happen, + eg when referencing a global array. For an + example of this see the _clz.o binary in libgcc.a. */ + && ELF32_ST_TYPE (sym->st_info) != STT_OBJECT) + { + warn (_("skipping unexpected symbol type %s in relocation in section .rela%s\n"), + get_symbol_type (ELF32_ST_TYPE (sym->st_info)), + SECTION_NAME (section)); + continue; + } + } + else + { + /* In MIPS little-endian objects, r_info isn't really a + 64-bit little-endian value: it has a 32-bit little-endian + symbol index followed by four individual byte fields. + Reorder INFO accordingly. */ + if (elf_header.e_machine == EM_MIPS + && elf_header.e_ident[EI_DATA] != ELFDATA2MSB) + rp->r_info = (((rp->r_info & 0xffffffff) << 32) + | ((rp->r_info >> 56) & 0xff) + | ((rp->r_info >> 40) & 0xff00) + | ((rp->r_info >> 24) & 0xff0000) + | ((rp->r_info >> 8) & 0xff000000)); + + sym = symtab + ELF64_R_SYM (rp->r_info); + + if (ELF64_R_SYM (rp->r_info) != 0 + && ELF64_ST_TYPE (sym->st_info) != STT_SECTION + && ELF64_ST_TYPE (sym->st_info) != STT_OBJECT) + { + warn (_("skipping unexpected symbol type %s in relocation in section .rela.%s\n"), + get_symbol_type (ELF64_ST_TYPE (sym->st_info)), + SECTION_NAME (section)); + continue; + } + } + + byte_put (loc, rp->r_addend, reloc_size); + } + + free (symtab); + free (rela); + break; + } + 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) { @@ -7587,266 +7741,34 @@ process_extended_line_op (unsigned char *data, int is_stmt, int pointer_size) return len; } -static const char *debug_str_contents; -static bfd_vma debug_str_size; - -static void -load_debug_str (FILE *file) -{ - Elf_Internal_Shdr *sec; - - /* If it is already loaded, do nothing. */ - if (debug_str_contents != NULL) - return; - - /* Locate the .debug_str section. */ - sec = find_section (".debug_str"); - 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")); -} - -static void -free_debug_str (void) -{ - if (debug_str_contents == NULL) - return; - - free ((char *) debug_str_contents); - debug_str_contents = NULL; - debug_str_size = 0; -} +static struct dwarf_section debug_str_section = { + ".debug_str", + NULL, + 0, + 0 +}; static const char * fetch_indirect_string (unsigned long offset) { - if (debug_str_contents == NULL) + if (debug_str_section.start == NULL) return _("<no .debug_str section>"); - if (offset > debug_str_size) + if (offset > debug_str_section.size) { warn (_("DW_FORM_strp offset too big: %lx\n"), offset); return _("<offset is too big>"); } - return debug_str_contents + offset; -} - -static const char *debug_loc_contents; -static bfd_vma debug_loc_size; - -static void -load_debug_loc (FILE *file) -{ - Elf_Internal_Shdr *sec; - - /* If it is already loaded, do nothing. */ - if (debug_loc_contents != NULL) - return; - - /* Locate the .debug_loc section. */ - sec = find_section (".debug_loc"); - if (sec == NULL) - return; - - 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; + return debug_str_section.start + offset; } -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; - - for (relsec = section_headers; - relsec < section_headers + elf_header.e_shnum; - ++relsec) - { - unsigned long nrelas; - Elf_Internal_Rela *rela, *rp; - Elf_Internal_Shdr *symsec; - Elf_Internal_Sym *symtab; - Elf_Internal_Sym *sym; - - if (relsec->sh_type != SHT_RELA - || SECTION_HEADER_INDEX (relsec->sh_info) >= elf_header.e_shnum - || SECTION_HEADER (relsec->sh_info) != section - || relsec->sh_size == 0 - || SECTION_HEADER_INDEX (relsec->sh_link) >= elf_header.e_shnum) - continue; - - if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size, - &rela, &nrelas)) - return 0; - - symsec = SECTION_HEADER (relsec->sh_link); - symtab = GET_ELF_SYMBOLS (file, symsec); - - for (rp = rela; rp < rela + nrelas; ++rp) - { - unsigned char *loc; - - loc = start + rp->r_offset; - if ((loc + reloc_size) > end) - { - warn (_("skipping invalid relocation offset 0x%lx in section %s\n"), - (unsigned long) rp->r_offset, - SECTION_NAME (section)); - continue; - } - - if (is_32bit_elf) - { - sym = symtab + ELF32_R_SYM (rp->r_info); - - if (ELF32_R_SYM (rp->r_info) != 0 - && ELF32_ST_TYPE (sym->st_info) != STT_SECTION - /* Relocations against object symbols can happen, - eg when referencing a global array. For an - example of this see the _clz.o binary in libgcc.a. */ - && ELF32_ST_TYPE (sym->st_info) != STT_OBJECT) - { - warn (_("skipping unexpected symbol type %s in relocation in section .rela%s\n"), - get_symbol_type (ELF32_ST_TYPE (sym->st_info)), - SECTION_NAME (section)); - continue; - } - } - else - { - /* In MIPS little-endian objects, r_info isn't really a - 64-bit little-endian value: it has a 32-bit little-endian - symbol index followed by four individual byte fields. - Reorder INFO accordingly. */ - if (elf_header.e_machine == EM_MIPS - && elf_header.e_ident[EI_DATA] != ELFDATA2MSB) - rp->r_info = (((rp->r_info & 0xffffffff) << 32) - | ((rp->r_info >> 56) & 0xff) - | ((rp->r_info >> 40) & 0xff00) - | ((rp->r_info >> 24) & 0xff0000) - | ((rp->r_info >> 8) & 0xff000000)); - - sym = symtab + ELF64_R_SYM (rp->r_info); - - if (ELF64_R_SYM (rp->r_info) != 0 - && ELF64_ST_TYPE (sym->st_info) != STT_SECTION - && ELF64_ST_TYPE (sym->st_info) != STT_OBJECT) - { - warn (_("skipping unexpected symbol type %s in relocation in section .rela.%s\n"), - get_symbol_type (ELF64_ST_TYPE (sym->st_info)), - SECTION_NAME (section)); - continue; - } - } - - byte_put (loc, rp->r_addend, reloc_size); - } - - free (symtab); - free (rela); - break; - } - return 1; -} +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 @@ -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; - - 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); 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; } |