aboutsummaryrefslogtreecommitdiff
path: root/binutils
diff options
context:
space:
mode:
Diffstat (limited to 'binutils')
-rw-r--r--binutils/ChangeLog15
-rw-r--r--binutils/readelf.c326
2 files changed, 169 insertions, 172 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index d2a65c6..f26615d 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,18 @@
+2004-01-07 Nick Clifton <nickc@redhat.com>
+
+ * readelf.c (find_section): New function. Locates a named
+ section.
+ (get_debug_line_pointer_sizes): New function: Initialises the
+ debug_line_pointer_sizes array.
+ (display_debug_lines): Call get_debug_line_pointer_sizes.
+ (display_debug_loc): Likewise.
+ (load_debug_loc): Use find_section.
+ (load_debug_str): Likewise.
+ (display_debug_info): Likewise.
+ (prescan_debug_info): Delete.
+ (debug_displays): Remove prescan field.
+ (process_section_contents): Do not perform prescans.
+
2004-01-03 Alan Modra <amodra@bigpond.net.au>
* objcopy.c (filter_bytes): Delete. Move code to..
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 67c4816..6604cad 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -6271,16 +6271,137 @@ process_extended_line_op (unsigned char *data, int is_stmt, int pointer_size)
return len;
}
+/* Finds section NAME inside FILE and returns a
+ pointer to it, or NULL upon failure. */
+
+static Elf_Internal_Shdr *
+find_section (const char * name)
+{
+ Elf_Internal_Shdr *sec;
+ unsigned int i;
+
+ for (i = elf_header.e_shnum, sec = section_headers + i - 1;
+ i; --i, --sec)
+ if (strcmp (SECTION_NAME (sec), name) == 0)
+ break;
+
+ if (i && sec && sec->sh_size != 0)
+ return sec;
+
+ return NULL;
+}
+
/* Size of pointers in the .debug_line section. This information is not
really present in that section. It's obtained before dumping the debug
sections by doing some pre-scan of the .debug_info section. */
static unsigned int * debug_line_pointer_sizes = NULL;
static unsigned int num_debug_line_pointer_sizes = 0;
+/* Locate and scan the .debug_info section in the file and record the pointer
+ sizes for the compilation units in it. Usually an executable will have
+ just one pointer size, but this is not guaranteed, and so we try not to
+ make any assumptions. Returns zero upon failure, or the number of
+ compilation units upon success. */
+
+static unsigned int
+get_debug_line_pointer_sizes (FILE * file)
+{
+ Elf_Internal_Shdr * section;
+ unsigned char * start;
+ unsigned char * end;
+ unsigned char * begin;
+ unsigned long length;
+ unsigned int num_units;
+ unsigned int unit;
+
+ section = find_section (".debug_info");
+ if (section == NULL)
+ return 0;
+
+ length = section->sh_size;
+ start = get_data (NULL, file, section->sh_offset, section->sh_size,
+ _("extracting pointer sizes from .debug_info section"));
+ if (start == NULL)
+ return 0;
+
+ end = start + section->sh_size;
+ /* First scan the section to get the number of comp units. */
+ for (begin = start, num_units = 0; begin < end; num_units++)
+ {
+ /* Read the first 4 bytes. For a 32-bit DWARF section, this will
+ be the length. For a 64-bit DWARF section, it'll be the escape
+ code 0xffffffff followed by an 8 byte length. */
+ length = byte_get (begin, 4);
+
+ if (length == 0xffffffff)
+ {
+ length = byte_get (begin + 4, 8);
+ begin += length + 12;
+ }
+ else
+ begin += length + 4;
+ }
+
+ if (num_units == 0)
+ {
+ error (_("No comp units in .debug_info section ?"));
+ free (start);
+ return 0;
+ }
+
+ /* Then allocate an array to hold the pointer sizes. */
+ debug_line_pointer_sizes = malloc (num_units * sizeof * debug_line_pointer_sizes);
+ if (debug_line_pointer_sizes == NULL)
+ {
+ error (_("Not enough memory for a pointer size array of %u entries"),
+ num_units);
+ free (start);
+ return 0;
+ }
+
+ /* Populate the array. */
+ for (begin = start, unit = 0; begin < end; unit++)
+ {
+ length = byte_get (begin, 4);
+ if (length == 0xffffffff)
+ {
+ /* For 64-bit DWARF, the 1-byte address_size field is 22 bytes
+ from the start of the section. This is computed as follows:
+
+ unit_length: 12 bytes
+ version: 2 bytes
+ debug_abbrev_offset: 8 bytes
+ -----------------------------
+ Total: 22 bytes */
+
+ debug_line_pointer_sizes [unit] = byte_get (begin + 22, 1);
+ length = byte_get (begin + 4, 8);
+ begin += length + 12;
+ }
+ else
+ {
+ /* For 32-bit DWARF, the 1-byte address_size field is 10 bytes from
+ the start of the section:
+
+ unit_length: 4 bytes
+ version: 2 bytes
+ debug_abbrev_offset: 4 bytes
+ -----------------------------
+ Total: 10 bytes */
+
+ debug_line_pointer_sizes [unit] = byte_get (begin + 10, 1);
+ begin += length + 4;
+ }
+ }
+
+ free (start);
+ num_debug_line_pointer_sizes = num_units;
+ return num_units;
+}
+
static int
display_debug_lines (Elf_Internal_Shdr *section,
- unsigned char * start,
- FILE *file ATTRIBUTE_UNUSED)
+ unsigned char *start, FILE *file)
{
unsigned char *hdrptr;
DWARF2_Internal_LineInfo info;
@@ -6296,6 +6417,9 @@ display_debug_lines (Elf_Internal_Shdr *section,
printf (_("\nDump of debug contents of section %s:\n\n"),
SECTION_NAME (section));
+ if (num_debug_line_pointer_sizes == 0)
+ get_debug_line_pointer_sizes (file);
+
while (data < end)
{
unsigned int pointer_size;
@@ -7506,20 +7630,14 @@ static void
load_debug_loc (FILE *file)
{
Elf_Internal_Shdr *sec;
- unsigned int i;
/* If it is already loaded, do nothing. */
if (debug_loc_contents != NULL)
return;
/* Locate the .debug_loc section. */
- for (i = 0, sec = section_headers;
- i < elf_header.e_shnum;
- i++, sec++)
- if (strcmp (SECTION_NAME (sec), ".debug_loc") == 0)
- break;
-
- if (i == elf_header.e_shnum || sec->sh_size == 0)
+ sec = find_section (".debug_loc");
+ if (sec == NULL)
return;
debug_loc_size = sec->sh_size;
@@ -7542,8 +7660,7 @@ free_debug_loc (void)
static int
display_debug_loc (Elf_Internal_Shdr *section,
- unsigned char *start,
- FILE *file ATTRIBUTE_UNUSED)
+ unsigned char *start, FILE *file)
{
unsigned char *section_end;
unsigned long bytes;
@@ -7561,6 +7678,9 @@ display_debug_loc (Elf_Internal_Shdr *section,
return 0;
}
+ if (num_debug_line_pointer_sizes == 0)
+ get_debug_line_pointer_sizes (file);
+
printf (_("Contents of the .debug_loc section:\n\n"));
printf (_("\n Offset Begin End Expression\n"));
@@ -7625,20 +7745,14 @@ static void
load_debug_str (FILE *file)
{
Elf_Internal_Shdr *sec;
- unsigned int i;
/* If it is already loaded, do nothing. */
if (debug_str_contents != NULL)
return;
/* Locate the .debug_str section. */
- for (i = 0, sec = section_headers;
- i < elf_header.e_shnum;
- i++, sec++)
- if (strcmp (SECTION_NAME (sec), ".debug_str") == 0)
- break;
-
- if (i == elf_header.e_shnum || sec->sh_size == 0)
+ sec = find_section (".debug_str");
+ if (sec == NULL)
return;
debug_str_size = sec->sh_size;
@@ -8100,7 +8214,6 @@ display_debug_info (Elf_Internal_Shdr *section,
unsigned char *hdrptr;
unsigned char *cu_abbrev_offset_ptr;
unsigned char *tags;
- unsigned int i;
int level;
unsigned long cu_offset;
int offset_size;
@@ -8224,13 +8337,8 @@ display_debug_info (Elf_Internal_Shdr *section,
unsigned char *begin;
/* Locate the .debug_abbrev section and process it. */
- for (i = 0, sec = section_headers;
- i < elf_header.e_shnum;
- i++, sec++)
- if (strcmp (SECTION_NAME (sec), ".debug_abbrev") == 0)
- break;
-
- if (i == elf_header.e_shnum || sec->sh_size == 0)
+ sec = find_section (".debug_abbrev");
+ if (sec == NULL)
{
warn (_("Unable to locate .debug_abbrev section!\n"));
return 0;
@@ -9194,121 +9302,31 @@ display_debug_not_supported (Elf_Internal_Shdr *section,
return 1;
}
-/* Pre-scan the .debug_info section to record the pointer sizes for the
- compilation units. Usually an executable will have just one pointer
- size, but this is not guaranteed, and so we try not to make any
- assumptions. Returns zero upon failure, or the number of compilation
- units upon success. */
-
-static unsigned int
-prescan_debug_info (Elf_Internal_Shdr *section, unsigned char *start,
- FILE *file ATTRIBUTE_UNUSED)
-{
- unsigned char *begin;
- unsigned char *end = start + section->sh_size;
- unsigned long length;
- unsigned int num_units;
- unsigned int unit;
-
- /* First scan the section to compute the number of comp units. */
- for (begin = start, num_units = 0; begin < end; num_units++)
- {
- /* Read the first 4 bytes. For a 32-bit DWARF section, this will
- be the length. For a 64-bit DWARF section, it'll be the escape
- code 0xffffffff followed by an 8 byte length. */
- length = byte_get (begin, 4);
-
- if (length == 0xffffffff)
- {
- length = byte_get (begin + 4, 8);
- begin += length + 12;
- }
- else
- begin += length + 4;
- }
-
- if (num_units == 0)
- {
- error (_("No comp units in .debug_info section ?"));
- return 0;
- }
-
- /* Then allocate an array to hold the pointer sizes. */
- debug_line_pointer_sizes = malloc (num_units * sizeof * debug_line_pointer_sizes);
- if (debug_line_pointer_sizes == NULL)
- {
- error (_("Not enough memory for a pointer size array of %u entries"),
- num_units);
- return 0;
- }
-
- /* Populate the array. */
- for (begin = start, unit = 0; begin < end; unit++)
- {
- length = byte_get (begin, 4);
- if (length == 0xffffffff)
- {
- /* For 64-bit DWARF, the 1-byte address_size field is 22 bytes
- from the start of the section. This is computed as follows:
-
- unit_length: 12 bytes
- version: 2 bytes
- debug_abbrev_offset: 8 bytes
- -----------------------------
- Total: 22 bytes */
-
- debug_line_pointer_sizes [unit] = byte_get (begin + 22, 1);
- length = byte_get (begin + 4, 8);
- begin += length + 12;
- }
- else
- {
- /* For 32-bit DWARF, the 1-byte address_size field is 10 bytes from
- the start of the section:
-
- unit_length: 4 bytes
- version: 2 bytes
- debug_abbrev_offset: 4 bytes
- -----------------------------
- Total: 10 bytes */
-
- debug_line_pointer_sizes [unit] = byte_get (begin + 10, 1);
- begin += length + 4;
- }
- }
-
- num_debug_line_pointer_sizes = num_units;
- return num_units;
-}
-
-/* A structure containing the name of a debug section and a pointer
- to a function that can decode it. The third field is a prescan
- function to be run over the section before displaying any of the
- sections. */
+/* A structure containing the name of a debug section
+ and a pointer to a function that can decode it. */
struct
{
const char *const name;
int (*display) (Elf_Internal_Shdr *, unsigned char *, FILE *);
- int (*prescan) (Elf_Internal_Shdr *, unsigned char *, FILE *);
}
debug_displays[] =
{
- { ".debug_abbrev", display_debug_abbrev, NULL },
- { ".debug_aranges", display_debug_aranges, NULL },
- { ".debug_frame", display_debug_frames, NULL },
- { ".debug_info", display_debug_info, prescan_debug_info },
- { ".debug_line", display_debug_lines, NULL },
- { ".debug_pubnames", display_debug_pubnames, NULL },
- { ".eh_frame", display_debug_frames, NULL },
- { ".debug_macinfo", display_debug_macinfo, NULL },
- { ".debug_str", display_debug_str, NULL },
- { ".debug_loc", display_debug_loc, NULL },
- { ".debug_pubtypes", display_debug_not_supported, NULL },
- { ".debug_ranges", display_debug_not_supported, NULL },
- { ".debug_static_func", display_debug_not_supported, NULL },
- { ".debug_static_vars", display_debug_not_supported, NULL },
- { ".debug_types", display_debug_not_supported, NULL },
- { ".debug_weaknames", display_debug_not_supported, NULL }
+ { ".debug_abbrev", display_debug_abbrev },
+ { ".debug_aranges", display_debug_aranges },
+ { ".debug_frame", display_debug_frames },
+ { ".debug_info", display_debug_info },
+ { ".debug_line", display_debug_lines },
+ { ".debug_pubnames", display_debug_pubnames },
+ { ".eh_frame", display_debug_frames },
+ { ".debug_macinfo", display_debug_macinfo },
+ { ".debug_str", display_debug_str },
+ { ".debug_loc", display_debug_loc },
+ { ".debug_pubtypes", display_debug_not_supported },
+ { ".debug_ranges", display_debug_not_supported },
+ { ".debug_static_func", display_debug_not_supported },
+ { ".debug_static_vars", display_debug_not_supported },
+ { ".debug_types", display_debug_not_supported },
+ { ".debug_weaknames", display_debug_not_supported }
};
static int
@@ -9363,42 +9381,6 @@ process_section_contents (FILE *file)
if (! do_dump)
return 1;
- /* Pre-scan the debug sections to find some debug information not
- present in some of them. For the .debug_line, we must find out the
- size of address (specified in .debug_info and .debug_aranges). */
- for (i = 0, section = section_headers;
- i < elf_header.e_shnum && i < num_dump_sects;
- i++, section++)
- {
- char *name = SECTION_NAME (section);
- int j;
-
- if (section->sh_size == 0)
- continue;
-
- /* See if there is some pre-scan operation for this section. */
- for (j = NUM_ELEM (debug_displays); j--;)
- if (strcmp (debug_displays[j].name, name) == 0)
- {
- if (debug_displays[j].prescan != NULL)
- {
- bfd_size_type length;
- unsigned char *start;
-
- length = section->sh_size;
- start = get_data (NULL, file, section->sh_offset, length,
- _("debug section data"));
- if (!start)
- return 0;
-
- debug_displays[j].prescan (section, start, file);
- free (start);
- }
-
- break;
- }
- }
-
for (i = 0, section = section_headers;
i < elf_header.e_shnum && i < num_dump_sects;
i++, section++)