diff options
Diffstat (limited to 'binutils/readelf.c')
-rw-r--r-- | binutils/readelf.c | 94 |
1 files changed, 88 insertions, 6 deletions
diff --git a/binutils/readelf.c b/binutils/readelf.c index f1f849f..b1b5c5c 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 <eric@andante.jic.com> @@ -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 <elf/h8.h> 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) |