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.
This commit is contained in:
Nick Clifton 2007-02-06 15:15:13 +00:00
parent 7b5030c061
commit 4b78141aa2
3 changed files with 149 additions and 29 deletions

View file

@ -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)