diff --git a/binutils/ChangeLog b/binutils/ChangeLog index cd39f656da..b4f78a0eb7 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,18 @@ +2007-02-06 Nick Clifton + + PR gas/3800 + * readelf.c: Include elf/h8.h twice. The first time in order to + get the reloc numbers, the second time in order to get the reloc + decoder function. + (dump_section): Tell the user if the section being displayed has + unprocessed relocs associated with it. + (get_reloc_size): New function - returns the size of a reloc. + (debug_apply_rela_addends): Use get_reloc_size(). + * dwarf.c (read_and_display_attr_value): Extend number of + languages known for the DW_AT_language attribute. + (process_debug_info): Display the attribute offset before decoding + the attribute, in case there are problems. + 2007-02-05 Dave Brolley * readelf.c (dump_relocations): Don't check for diff --git a/binutils/dwarf.c b/binutils/dwarf.c index fe75b63a51..ad709b97f7 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -1,5 +1,5 @@ /* dwarf.c -- display DWARF contents of a BFD binary file - Copyright 2005, 2006 + Copyright 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of GNU Binutils. @@ -1213,26 +1213,37 @@ read_and_display_attr_value (unsigned long attribute, case DW_AT_language: switch (uvalue) { - case DW_LANG_C: printf ("(non-ANSI C)"); break; + /* Ordered by the numeric value of these constants. */ case DW_LANG_C89: printf ("(ANSI C)"); break; - case DW_LANG_C_plus_plus: printf ("(C++)"); break; - case DW_LANG_Fortran77: printf ("(FORTRAN 77)"); break; - case DW_LANG_Fortran90: printf ("(Fortran 90)"); break; - case DW_LANG_Modula2: printf ("(Modula 2)"); break; - case DW_LANG_Pascal83: printf ("(ANSI Pascal)"); break; + case DW_LANG_C: printf ("(non-ANSI C)"); break; case DW_LANG_Ada83: printf ("(Ada)"); break; + case DW_LANG_C_plus_plus: printf ("(C++)"); break; case DW_LANG_Cobol74: printf ("(Cobol 74)"); break; case DW_LANG_Cobol85: printf ("(Cobol 85)"); break; + case DW_LANG_Fortran77: printf ("(FORTRAN 77)"); break; + case DW_LANG_Fortran90: printf ("(Fortran 90)"); break; + case DW_LANG_Pascal83: printf ("(ANSI Pascal)"); break; + case DW_LANG_Modula2: printf ("(Modula 2)"); break; /* DWARF 2.1 values. */ + case DW_LANG_Java: printf ("(Java)"); break; case DW_LANG_C99: printf ("(ANSI C99)"); break; case DW_LANG_Ada95: printf ("(ADA 95)"); break; case DW_LANG_Fortran95: printf ("(Fortran 95)"); break; + /* DWARF 3 values. */ + case DW_LANG_PLI: printf ("(PLI)"); break; + case DW_LANG_ObjC: printf ("(Objective C)"); break; + case DW_LANG_ObjC_plus_plus: printf ("(Objective C++)"); break; + case DW_LANG_UPC: printf ("(Unified Parallel C)"); break; + case DW_LANG_D: printf ("(D)"); break; /* MIPS extension. */ case DW_LANG_Mips_Assembler: printf ("(MIPS assembler)"); break; /* UPC extension. */ case DW_LANG_Upc: printf ("(Unified Parallel C)"); break; default: - printf ("(Unknown: %lx)", uvalue); + if (uvalue >= DW_LANG_lo_user && uvalue <= DW_LANG_hi_user) + printf ("(implementation defined: %lx)", uvalue); + else + printf ("(Unknown: %lx)", uvalue); break; } break; @@ -1684,6 +1695,13 @@ process_debug_info (struct dwarf_section *section, void *file, continue; } + if (!do_loc) + printf (_(" <%d><%lx>: Abbrev Number: %lu"), + level, + (unsigned long) (tags - section_begin + - bytes_read), + abbrev_number); + /* Scan through the abbreviation list until we reach the correct entry. */ for (entry = first_abbrev; @@ -1693,18 +1711,18 @@ process_debug_info (struct dwarf_section *section, void *file, if (entry == NULL) { + if (!do_loc) + { + printf ("\n"); + fflush (stdout); + } warn (_("Unable to locate entry %lu in the abbreviation table\n"), abbrev_number); return 0; } if (!do_loc) - printf (_(" <%d><%lx>: Abbrev Number: %lu (%s)\n"), - level, - (unsigned long) (tags - section_begin - - bytes_read), - abbrev_number, - get_TAG_name (entry->tag)); + printf (_(" (%s)\n"), get_TAG_name (entry->tag)); switch (entry->tag) { @@ -1724,14 +1742,20 @@ process_debug_info (struct dwarf_section *section, void *file, } for (attr = entry->first_attr; attr; attr = attr->next) - tags = read_and_display_attr (attr->attribute, - attr->form, - tags, cu_offset, - compunit.cu_pointer_size, - offset_size, - compunit.cu_version, - &debug_information [unit], - do_loc); + { + if (! do_loc) + /* Show the offset from where the tag was extracted. */ + printf (" <%2lx>", tags - section_begin); + + tags = read_and_display_attr (attr->attribute, + attr->form, + tags, cu_offset, + compunit.cu_pointer_size, + offset_size, + compunit.cu_version, + &debug_information [unit], + do_loc); + } if (entry->children) ++level; @@ -2507,7 +2531,6 @@ display_debug_str (struct dwarf_section *section, return 1; } - static int display_debug_info (struct dwarf_section *section, void *file) { diff --git a/binutils/readelf.c b/binutils/readelf.c index f1f849fa2a..b1b5c5c717 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -1,5 +1,5 @@ /* readelf.c -- display contents of an ELF format file - Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. Originally developed by Eric Youngdale @@ -80,6 +80,24 @@ #include "elf/external.h" #include "elf/internal.h" + +/* Included here, before RELOC_MACROS_GEN_FUNC is defined, so that + we can obtain the H8 reloc numbers. We need these for the + get_reloc_size() function. We include h8.h again after defining + RELOC_MACROS_GEN_FUNC so that we get the naming function as well. */ + +#include "elf/h8.h" +#undef _ELF_H8_H + +/* Undo the effects of #including reloc-macros.h. */ + +#undef START_RELOC_NUMBERS +#undef RELOC_NUMBER +#undef FAKE_RELOC +#undef EMPTY_RELOC +#undef END_RELOC_NUMBERS +#undef _RELOC_MACROS_H + /* The following headers use the elf/reloc-macros.h file to automatically generate relocation recognition functions such as elf_mips_reloc_type() */ @@ -7644,6 +7662,7 @@ disassemble_section (Elf_Internal_Shdr *section, FILE *file) static int dump_section (Elf_Internal_Shdr *section, FILE *file) { + Elf_Internal_Shdr *relsec; bfd_size_type bytes; bfd_vma addr; unsigned char *data; @@ -7667,6 +7686,26 @@ dump_section (Elf_Internal_Shdr *section, FILE *file) if (!start) return 0; + /* If the section being dumped has relocations against it the user might + be expecting these relocations to have been applied. Check for this + case and issue a warning message in order to avoid confusion. + FIXME: Maybe we ought to have an option that dumps a section with + relocs applied ? */ + for (relsec = section_headers; + relsec < section_headers + elf_header.e_shnum; + ++relsec) + { + 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; + + printf (_(" NOTE: This section has relocations against it, but these have NOT been applied to this dump.\n")); + break; + } + data = start; while (bytes) @@ -7708,9 +7747,47 @@ dump_section (Elf_Internal_Shdr *section, FILE *file) free (start); + putchar ('\n'); return 1; } +/* Return the number of bytes affected by a given reloc. + This information is architecture and reloc dependent. + Returns 4 by default, although this is not always correct. + It should return 0 if a decision cannot be made. + FIXME: This is not the correct way to solve this problem. + The proper way is to have target specific reloc sizing functions + created by the reloc-macros.h header, in the same way that it + already creates the reloc naming functions. */ + +static unsigned int +get_reloc_size (Elf_Internal_Rela * reloc) +{ + switch (elf_header.e_machine) + { + case EM_H8S: + case EM_H8_300: + case EM_H8_300H: + case EM_H8_500: + switch (ELF32_R_TYPE (reloc->r_info)) + { + /* PR gas/3800 - without this information we do not correctly + decode the debug information generated by the h8300 assembler. */ + case R_H8_DIR16: + return 2; + default: + return 4; + } + default: + /* FIXME: We need to extend this switch statement to cope with other + architecture's relocs. (When those relocs are used against debug + sections, and when their size is not 4). But see the multiple + inclusions of for an example of the hoops that we need + to jump through in order to obtain the reloc numbers. */ + return 4; + } +} + /* Apply addends of RELA relocations. */ static int @@ -7720,15 +7797,10 @@ debug_apply_rela_addends (void *file, { 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) @@ -7756,6 +7828,16 @@ debug_apply_rela_addends (void *file, for (rp = rela; rp < rela + nrelas; ++rp) { unsigned char *loc; + unsigned int reloc_size; + + reloc_size = get_reloc_size (rp); + if (reloc_size == 0) + { + warn (_("skipping relocation of unknown size against offset 0x%lx in section %s\n"), + (unsigned long) rp->r_offset, + SECTION_NAME (section)); + continue; + } loc = start + rp->r_offset; if ((loc + reloc_size) > end)