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,3 +1,18 @@
2007-02-06 Nick Clifton <nickc@redhat.com>
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 <brolley@redhat.com> 2007-02-05 Dave Brolley <brolley@redhat.com>
* readelf.c (dump_relocations): Don't check for * readelf.c (dump_relocations): Don't check for

View file

@ -1,5 +1,5 @@
/* dwarf.c -- display DWARF contents of a BFD binary file /* dwarf.c -- display DWARF contents of a BFD binary file
Copyright 2005, 2006 Copyright 2005, 2006, 2007
Free Software Foundation, Inc. Free Software Foundation, Inc.
This file is part of GNU Binutils. This file is part of GNU Binutils.
@ -1213,26 +1213,37 @@ read_and_display_attr_value (unsigned long attribute,
case DW_AT_language: case DW_AT_language:
switch (uvalue) 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_C89: printf ("(ANSI C)"); break;
case DW_LANG_C_plus_plus: printf ("(C++)"); break; case DW_LANG_C: printf ("(non-ANSI 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_Ada83: printf ("(Ada)"); 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_Cobol74: printf ("(Cobol 74)"); break;
case DW_LANG_Cobol85: printf ("(Cobol 85)"); 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. */ /* DWARF 2.1 values. */
case DW_LANG_Java: printf ("(Java)"); break;
case DW_LANG_C99: printf ("(ANSI C99)"); break; case DW_LANG_C99: printf ("(ANSI C99)"); break;
case DW_LANG_Ada95: printf ("(ADA 95)"); break; case DW_LANG_Ada95: printf ("(ADA 95)"); break;
case DW_LANG_Fortran95: printf ("(Fortran 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. */ /* MIPS extension. */
case DW_LANG_Mips_Assembler: printf ("(MIPS assembler)"); break; case DW_LANG_Mips_Assembler: printf ("(MIPS assembler)"); break;
/* UPC extension. */ /* UPC extension. */
case DW_LANG_Upc: printf ("(Unified Parallel C)"); break; case DW_LANG_Upc: printf ("(Unified Parallel C)"); break;
default: 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;
} }
break; break;
@ -1684,6 +1695,13 @@ process_debug_info (struct dwarf_section *section, void *file,
continue; 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 /* Scan through the abbreviation list until we reach the
correct entry. */ correct entry. */
for (entry = first_abbrev; for (entry = first_abbrev;
@ -1693,18 +1711,18 @@ process_debug_info (struct dwarf_section *section, void *file,
if (entry == NULL) if (entry == NULL)
{ {
if (!do_loc)
{
printf ("\n");
fflush (stdout);
}
warn (_("Unable to locate entry %lu in the abbreviation table\n"), warn (_("Unable to locate entry %lu in the abbreviation table\n"),
abbrev_number); abbrev_number);
return 0; return 0;
} }
if (!do_loc) if (!do_loc)
printf (_(" <%d><%lx>: Abbrev Number: %lu (%s)\n"), printf (_(" (%s)\n"), get_TAG_name (entry->tag));
level,
(unsigned long) (tags - section_begin
- bytes_read),
abbrev_number,
get_TAG_name (entry->tag));
switch (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) for (attr = entry->first_attr; attr; attr = attr->next)
tags = read_and_display_attr (attr->attribute, {
attr->form, if (! do_loc)
tags, cu_offset, /* Show the offset from where the tag was extracted. */
compunit.cu_pointer_size, printf (" <%2lx>", tags - section_begin);
offset_size,
compunit.cu_version, tags = read_and_display_attr (attr->attribute,
&debug_information [unit], attr->form,
do_loc); tags, cu_offset,
compunit.cu_pointer_size,
offset_size,
compunit.cu_version,
&debug_information [unit],
do_loc);
}
if (entry->children) if (entry->children)
++level; ++level;
@ -2507,7 +2531,6 @@ display_debug_str (struct dwarf_section *section,
return 1; return 1;
} }
static int static int
display_debug_info (struct dwarf_section *section, void *file) display_debug_info (struct dwarf_section *section, void *file)
{ {

View file

@ -1,5 +1,5 @@
/* readelf.c -- display contents of an ELF format file /* 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. Free Software Foundation, Inc.
Originally developed by Eric Youngdale <eric@andante.jic.com> Originally developed by Eric Youngdale <eric@andante.jic.com>
@ -80,6 +80,24 @@
#include "elf/external.h" #include "elf/external.h"
#include "elf/internal.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 /* The following headers use the elf/reloc-macros.h file to
automatically generate relocation recognition functions automatically generate relocation recognition functions
such as elf_mips_reloc_type() */ such as elf_mips_reloc_type() */
@ -7644,6 +7662,7 @@ disassemble_section (Elf_Internal_Shdr *section, FILE *file)
static int static int
dump_section (Elf_Internal_Shdr *section, FILE *file) dump_section (Elf_Internal_Shdr *section, FILE *file)
{ {
Elf_Internal_Shdr *relsec;
bfd_size_type bytes; bfd_size_type bytes;
bfd_vma addr; bfd_vma addr;
unsigned char *data; unsigned char *data;
@ -7667,6 +7686,26 @@ dump_section (Elf_Internal_Shdr *section, FILE *file)
if (!start) if (!start)
return 0; 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; data = start;
while (bytes) while (bytes)
@ -7708,9 +7747,47 @@ dump_section (Elf_Internal_Shdr *section, FILE *file)
free (start); free (start);
putchar ('\n');
return 1; 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. */ /* Apply addends of RELA relocations. */
static int static int
@ -7720,15 +7797,10 @@ debug_apply_rela_addends (void *file,
{ {
Elf_Internal_Shdr *relsec; Elf_Internal_Shdr *relsec;
unsigned char *end = start + section->sh_size; unsigned char *end = start + section->sh_size;
/* FIXME: The relocation field size is relocation type dependent. */
unsigned int reloc_size = 4;
if (!is_relocatable) if (!is_relocatable)
return 1; return 1;
if (section->sh_size < reloc_size)
return 1;
for (relsec = section_headers; for (relsec = section_headers;
relsec < section_headers + elf_header.e_shnum; relsec < section_headers + elf_header.e_shnum;
++relsec) ++relsec)
@ -7756,6 +7828,16 @@ debug_apply_rela_addends (void *file,
for (rp = rela; rp < rela + nrelas; ++rp) for (rp = rela; rp < rela + nrelas; ++rp)
{ {
unsigned char *loc; 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; loc = start + rp->r_offset;
if ((loc + reloc_size) > end) if ((loc + reloc_size) > end)