ELF file than is provided by objdump. In particular it can display DWARF
debugging information which (at the moment) objdump cannot. */
\f
+#include "config.h"
#include "sysdep.h"
#include <assert.h>
#include <sys/stat.h>
#include <time.h>
+#ifdef HAVE_ZLIB_H
+#include <zlib.h>
+#endif
/* for PATH_MAX */
#ifdef HAVE_LIMITS_H
#include "safe-ctype.h"
char *program_name = "readelf";
+int do_wide;
static long archive_file_offset;
static unsigned long archive_file_size;
static unsigned long dynamic_addr;
static int do_header;
static int do_dump;
static int do_version;
-static int do_wide;
static int do_histogram;
static int do_debugging;
static int do_arch;
return 0;
}
-/* Display a symbol on stdout. If do_wide is not true then
- format the symbol to be at most WIDTH characters,
- truncating as necessary. If WIDTH is negative then
- format the string to be exactly - WIDTH characters,
- truncating or padding as necessary. */
+/* Display a symbol on stdout. Handles the display of
+ non-printing characters.
+ If DO_WIDE is not true then format the symbol to be
+ at most WIDTH characters, truncating as necessary.
+ If WIDTH is negative then format the string to be
+ exactly - WIDTH characters, truncating or padding
+ as necessary. */
static void
print_symbol (int width, const char *symbol)
{
+ const char * format_string;
+ const char * c;
+
if (do_wide)
- printf ("%s", symbol);
+ {
+ format_string = "%.*s";
+ /* Set the width to a very large value. This simplifies the code below. */
+ width = INT_MAX;
+ }
else if (width < 0)
- printf ("%-*.*s", width, width, symbol);
+ {
+ format_string = "%-*.*2s";
+ /* Keep the width positive. This also helps. */
+ width = - width;
+ }
else
- printf ("%-.*s", width, symbol);
+ {
+ format_string = "%-.*s";
+ }
+
+ while (width)
+ {
+ int len;
+
+ c = symbol;
+
+ /* Look for non-printing symbols inside the symbol's name.
+ This test is triggered in particular by the names generated
+ by the assembler for local labels. */
+ while (ISPRINT (* c))
+ c++;
+
+ len = c - symbol;
+
+ if (len)
+ {
+ if (len > width)
+ len = width;
+
+ printf (format_string, len, symbol);
+
+ width -= len;
+ }
+
+ if (* c == 0 || width == 0)
+ break;
+
+ /* Now display the non-printing character, if
+ there is room left in which to dipslay it. */
+ if (*c < 32)
+ {
+ if (width < 2)
+ break;
+
+ printf ("^%c", *c + 0x40);
+
+ width -= 2;
+ }
+ else
+ {
+ if (width < 6)
+ break;
+
+ printf ("<0x%.2x>", *c);
+
+ width -= 6;
+ }
+
+ symbol = c + 1;
+ }
}
static void
case EM_AVR_OLD:
case EM_BLACKFIN:
case EM_CR16:
+ case EM_CR16_OLD:
case EM_CRIS:
case EM_CRX:
case EM_D30V:
case EM_IP2K:
case EM_IP2K_OLD:
case EM_IQ2000:
+ case EM_M32C_OLD:
case EM_M32C:
case EM_M32R:
case EM_MCORE:
rtype = elf_xtensa_reloc_type (type);
break;
+ case EM_M32C_OLD:
case EM_M32C:
rtype = elf_m32c_reloc_type (type);
break;
break;
case EM_CR16:
+ case EM_CR16_OLD:
rtype = elf_cr16_reloc_type (type);
break;
}
case EM_IQ2000: return "Vitesse IQ2000";
case EM_XTENSA_OLD:
case EM_XTENSA: return "Tensilica Xtensa Processor";
+ case EM_M32C_OLD:
case EM_M32C: return "Renesas M32c";
case EM_MT: return "Morpho Techologies MT processor";
case EM_BLACKFIN: return "Analog Devices Blackfin";
case EM_ALTERA_NIOS2: return "Altera Nios II";
case EM_XC16X: return "Infineon Technologies xc16x";
case EM_CYGNUS_MEP: return "Toshiba MeP Media Engine";
- case EM_CR16: return "National Semiconductor's CR16";
+ case EM_CR16:
+ case EM_CR16_OLD: return "National Semiconductor's CR16";
default:
snprintf (buff, sizeof (buff), _("<unknown>: 0x%x"), e_machine);
return buff;
Dump the contents of section <number|name> as bytes\n\
-p --string-dump=<number|name>\n\
Dump the contents of section <number|name> as strings\n\
- -w[liaprmfFsoR] or\n\
- --debug-dump[=line,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=str,=loc,=Ranges]\n\
+ -w[lLiaprmfFsoR] or\n\
+ --debug-dump[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=str,=loc,=Ranges]\n\
Display the contents of DWARF2 debug sections\n"));
#ifdef SUPPORT_DISASSEMBLY
fprintf (stream, _("\
do_debug_lines = 1;
break;
+ case 'L':
+ do_debug_lines_decoded = 1;
+ break;
+
case 'p':
do_debug_pubnames = 1;
break;
{ "frames", & do_debug_frames },
{ "frames-interp", & do_debug_frames_interp },
{ "info", & do_debug_info },
- { "line", & do_debug_lines },
+ { "line", & do_debug_lines }, /* For backwards compatibility. */
+ { "rawline", & do_debug_lines },
+ { "decodedline", & do_debug_lines_decoded },
{ "loc", & do_debug_loc },
{ "macro", & do_debug_macinfo },
{ "pubnames", & do_debug_pubnames },
Elf_Internal_Shdr *section;
segment = program_headers + i;
- section = section_headers;
+ section = section_headers + 1;
printf (" %2.2d ", i);
}
break;
+ case EM_M32C_OLD:
case EM_M32C:
switch (elf_header.e_flags & EF_M32C_CPU_MASK)
{
else if (section->sh_type == SHT_RELA)
CHECK_ENTSIZE (section, i, Rela);
else if ((do_debugging || do_debug_info || do_debug_abbrevs
- || do_debug_lines || do_debug_pubnames || do_debug_aranges
- || do_debug_frames || do_debug_macinfo || do_debug_str
- || do_debug_loc || do_debug_ranges)
- && const_strneq (name, ".debug_"))
+ || do_debug_lines || do_debug_lines_decoded || do_debug_pubnames
+ || do_debug_aranges || do_debug_frames || do_debug_macinfo
+ || do_debug_str || do_debug_loc || do_debug_ranges)
+ && (const_strneq (name, ".debug_")
+ || const_strneq (name, ".zdebug_")))
{
- name += 7;
+ if (name[1] == 'z')
+ name += sizeof (".zdebug_") - 1;
+ else
+ name += sizeof (".debug_") - 1;
if (do_debugging
|| (do_debug_info && streq (name, "info"))
|| (do_debug_abbrevs && streq (name, "abbrev"))
- || (do_debug_lines && streq (name, "line"))
+ || ((do_debug_lines || do_debug_lines_decoded)
+ && streq (name, "line"))
|| (do_debug_pubnames && streq (name, "pubnames"))
|| (do_debug_aranges && streq (name, "aranges"))
|| (do_debug_ranges && streq (name, "ranges"))
)
request_dump_bynumber (i, DEBUG_DUMP);
}
- /* linkonce section to be combined with .debug_info at link time. */
+ /* Linkonce section to be combined with .debug_info at link time. */
else if ((do_debugging || do_debug_info)
&& const_strneq (name, ".gnu.linkonce.wi."))
request_dump_bynumber (i, DEBUG_DUMP);
case EM_CRIS:
return reloc_type == 3; /* R_CRIS_32. */
case EM_CR16:
+ case EM_CR16_OLD:
return reloc_type == 3; /* R_CR16_NUM32. */
case EM_CRX:
return reloc_type == 15; /* R_CRX_NUM32. */
return reloc_type == 2; /* R_IP2K_32. */
case EM_IQ2000:
return reloc_type == 2; /* R_IQ2000_32. */
+ case EM_M32C_OLD:
case EM_M32C:
return reloc_type == 3; /* R_M32C_32. */
case EM_M32R:
case EM_IP2K_OLD:
case EM_IP2K:
return reloc_type == 1; /* R_IP2K_16. */
+ case EM_M32C_OLD:
case EM_M32C:
return reloc_type == 1; /* R_M32C_16 */
case EM_MSP430_OLD:
}
}
+/* Uncompresses a section that was compressed using zlib, in place.
+ * This is a copy of bfd_uncompress_section_contents, in bfd/compress.c */
+
+static int
+uncompress_section_contents (unsigned char **buffer, dwarf_size_type *size)
+{
+#ifndef HAVE_ZLIB_H
+ /* These are just to quiet gcc. */
+ buffer = 0;
+ size = 0;
+ return FALSE;
+#else
+ dwarf_size_type compressed_size = *size;
+ unsigned char* compressed_buffer = *buffer;
+ dwarf_size_type uncompressed_size;
+ unsigned char* uncompressed_buffer;
+ z_stream strm;
+ int rc;
+ dwarf_size_type header_size = 12;
+
+ /* Read the zlib header. In this case, it should be "ZLIB" followed
+ by the uncompressed section size, 8 bytes in big-endian order. */
+ if (compressed_size < header_size
+ || ! streq ((char*) compressed_buffer, "ZLIB"))
+ return 0;
+ uncompressed_size = compressed_buffer[4]; uncompressed_size <<= 8;
+ uncompressed_size += compressed_buffer[5]; uncompressed_size <<= 8;
+ uncompressed_size += compressed_buffer[6]; uncompressed_size <<= 8;
+ uncompressed_size += compressed_buffer[7]; uncompressed_size <<= 8;
+ uncompressed_size += compressed_buffer[8]; uncompressed_size <<= 8;
+ uncompressed_size += compressed_buffer[9]; uncompressed_size <<= 8;
+ uncompressed_size += compressed_buffer[10]; uncompressed_size <<= 8;
+ uncompressed_size += compressed_buffer[11];
+
+ /* It is possible the section consists of several compressed
+ buffers concatenated together, so we uncompress in a loop. */
+ strm.zalloc = NULL;
+ strm.zfree = NULL;
+ strm.opaque = NULL;
+ strm.avail_in = compressed_size - header_size;
+ strm.next_in = (Bytef*) compressed_buffer + header_size;
+ strm.avail_out = uncompressed_size;
+ uncompressed_buffer = xmalloc (uncompressed_size);
+
+ rc = inflateInit (&strm);
+ while (strm.avail_in > 0)
+ {
+ if (rc != Z_OK)
+ goto fail;
+ strm.next_out = ((Bytef*) uncompressed_buffer
+ + (uncompressed_size - strm.avail_out));
+ rc = inflate (&strm, Z_FINISH);
+ if (rc != Z_STREAM_END)
+ goto fail;
+ rc = inflateReset (&strm);
+ }
+ rc = inflateEnd (&strm);
+ if (rc != Z_OK
+ || strm.avail_out != 0)
+ goto fail;
+
+ free (compressed_buffer);
+ *buffer = uncompressed_buffer;
+ *size = uncompressed_size;
+ return 1;
+
+ fail:
+ free (uncompressed_buffer);
+ return 0;
+#endif /* HAVE_ZLIB_H */
+}
+
/* Apply relocations to a debug section. */
static void
struct dwarf_section *section = &debug_displays [debug].section;
Elf_Internal_Shdr *sec;
char buf [64];
+ int section_is_compressed;
/* If it is already loaded, do nothing. */
if (section->start != NULL)
return 1;
/* Locate the debug section. */
- sec = find_section (section->name);
+ sec = find_section (section->uncompressed_name);
+ if (sec != NULL)
+ section->name = section->uncompressed_name;
+ else
+ {
+ sec = find_section (section->compressed_name);
+ if (sec != NULL)
+ section->name = section->compressed_name;
+ }
if (sec == NULL)
return 0;
+ section_is_compressed = section->name == section->compressed_name;
snprintf (buf, sizeof (buf), _("%s section data"), section->name);
section->address = sec->sh_addr;
section->size = sec->sh_size;
section->start = get_data (NULL, file, sec->sh_offset, 1,
sec->sh_size, buf);
+ if (section->start == NULL)
+ return 0;
+
+ if (section_is_compressed)
+ if (! uncompress_section_contents (§ion->start, §ion->size))
+ return 0;
if (debug_displays [debug].relocate)
debug_apply_relocations (file, sec, section->start);
- return section->start != NULL;
+ return 1;
}
void
/* See if we know how to display the contents of this section. */
for (i = 0; i < max; i++)
- if (streq (debug_displays[i].section.name, name))
+ if (streq (debug_displays[i].section.uncompressed_name, name)
+ || streq (debug_displays[i].section.compressed_name, name))
{
struct dwarf_section *sec = &debug_displays [i].section;
if (pltgot != 0 && local_gotno != 0)
{
bfd_vma entry, local_end, global_end;
- size_t addr_size, i, offset;
+ size_t i, offset;
unsigned char *data;
+ int addr_size;
entry = pltgot;
addr_size = (is_32bit_elf ? 4 : 8);
return _("NT_GNU_HWCAP (DSO-supplied software HWCAP info)");
case NT_GNU_BUILD_ID:
return _("NT_GNU_BUILD_ID (unique build ID bitstring)");
+ case NT_GNU_GOLD_VERSION:
+ return _("NT_GNU_GOLD_VERSION (gold version)");
default:
break;
}