/* Print information from ELF file in human-readable form.
- Copyright (C) 1999-2015 Red Hat, Inc.
+ Copyright (C) 1999-2017 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 1999.
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
+#include <strings.h>
#include <time.h>
#include <unistd.h>
-#include <sys/param.h>
#include <sys/stat.h>
#include <signal.h>
+#include <libeu.h>
#include <system.h>
+#include <printversion.h>
#include "../libelf/libelfP.h"
#include "../libelf/common.h"
#include "../libebl/libeblP.h"
+#include "../libdwelf/libdwelf.h"
#include "../libdw/libdwP.h"
#include "../libdwfl/libdwflP.h"
#include "../libdw/memory-access.h"
#include "../libdw/known-dwarf.h"
+#ifdef __linux__
+#define CORE_SIGILL SIGILL
+#define CORE_SIGBUS SIGBUS
+#define CORE_SIGFPE SIGFPE
+#define CORE_SIGSEGV SIGSEGV
+#define CORE_SI_USER SI_USER
+#else
+/* We want the linux version of those as that is what shows up in the core files. */
+#define CORE_SIGILL 4 /* Illegal instruction (ANSI). */
+#define CORE_SIGBUS 7 /* BUS error (4.2 BSD). */
+#define CORE_SIGFPE 8 /* Floating-point exception (ANSI). */
+#define CORE_SIGSEGV 11 /* Segmentation violation (ANSI). */
+#define CORE_SI_USER 0 /* Sent by kill, sigsend. */
+#endif
/* Name and version of program. */
-static void print_version (FILE *stream, struct argp_state *state);
ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
/* Bug report address. */
{ "program-headers", 'l', NULL, 0, N_("Display the program headers"), 0 },
{ "segments", 'l', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
{ "relocs", 'r', NULL, 0, N_("Display relocations"), 0 },
+ { "section-groups", 'g', NULL, 0, N_("Display the section groups"), 0 },
{ "section-headers", 'S', NULL, 0, N_("Display the sections' headers"), 0 },
{ "sections", 'S', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
- { "symbols", 's', NULL, 0, N_("Display the symbol table"), 0 },
+ { "symbols", 's', "SECTION", OPTION_ARG_OPTIONAL,
+ N_("Display the symbol table sections"), 0 },
{ "version-info", 'V', NULL, 0, N_("Display versioning information"), 0 },
{ "notes", 'n', NULL, 0, N_("Display the ELF notes"), 0 },
{ "arch-specific", 'A', NULL, 0,
N_("Display just offsets instead of resolving values to addresses in DWARF data"), 0 },
{ "wide", 'W', NULL, 0,
N_("Ignored for compatibility (lines always wide)"), 0 },
+ { "decompress", 'z', NULL, 0,
+ N_("Show compression information for compressed sections (when used with -S); decompress section before dumping data (when used with -p or -x)"), 0 },
{ NULL, 0, NULL, 0, NULL, 0 }
};
/* True if the symbol table should be printed. */
static bool print_symbol_table;
+/* A specific section name, or NULL to print all symbol tables. */
+static char *symbol_table_section;
+
/* True if the version information should be printed. */
static bool print_version_info;
/* True if we should print the .debug_aranges section using libdw. */
static bool decodedline = false;
+/* True if we want to show more information about compressed sections. */
+static bool print_decompress = false;
+
/* Select printing of debugging sections. */
static enum section_e
{
case 's':
print_symbol_table = true;
any_control_option = true;
+ symbol_table_section = arg;
break;
case 'V':
print_version_info = true;
print_string_sections = true;
break;
}
- /* Fall through. */
+ FALLTHROUGH;
case 'x':
add_dump_section (arg, false);
any_control_option = true;
break;
case 'W': /* Ignored. */
break;
+ case 'z':
+ print_decompress = true;
+ break;
case ELF_INPUT_SECTION:
if (arg == NULL)
elf_input_section = ".gnu_debugdata";
}
-/* Print the version information. */
-static void
-print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
-{
- fprintf (stream, "readelf (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
- fprintf (stream, gettext ("\
-Copyright (C) %s Red Hat, Inc.\n\
-This is free software; see the source for copying conditions. There is NO\n\
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2012");
- fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
-}
-
-
/* Create a file descriptor to read the data from the
elf_input_section given a file descriptor to an ELF file. */
static int
dwfl->offline_next_address = 0;
if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd) == NULL)
{
- struct stat64 st;
- if (fstat64 (dwfl_fd, &st) != 0)
+ struct stat st;
+ if (fstat (dwfl_fd, &st) != 0)
error (0, errno, gettext ("cannot stat input file"));
else if (unlikely (st.st_size == 0))
error (0, 0, gettext ("input file is empty"));
close (fd);
}
+/* Check whether there are any compressed sections in the ELF file. */
+static bool
+elf_contains_chdrs (Elf *elf)
+{
+ Elf_Scn *scn = NULL;
+ while ((scn = elf_nextscn (elf, scn)) != NULL)
+ {
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+ if (shdr != NULL && (shdr->sh_flags & SHF_COMPRESSED) != 0)
+ return true;
+ }
+ return false;
+}
/* Process one ELF file. */
static void
gettext ("cannot determine number of program headers: %s"),
elf_errmsg (-1));
- /* For an ET_REL file, libdwfl has adjusted the in-core shdrs
- and may have applied relocation to some sections.
- So we need to get a fresh Elf handle on the file to display those. */
- bool print_unrelocated = (print_section_header
- || print_relocations
- || dump_data_sections != NULL
- || print_notes);
+ /* For an ET_REL file, libdwfl has adjusted the in-core shdrs and
+ may have applied relocation to some sections. If there are any
+ compressed sections, any pass (or libdw/libdwfl) might have
+ uncompressed them. So we need to get a fresh Elf handle on the
+ file to display those. */
+ bool print_unchanged = ((print_section_header
+ || print_relocations
+ || dump_data_sections != NULL
+ || print_notes)
+ && (ehdr->e_type == ET_REL
+ || elf_contains_chdrs (ebl->elf)));
Elf *pure_elf = NULL;
Ebl *pure_ebl = ebl;
- if (ehdr->e_type == ET_REL && print_unrelocated)
+ if (print_unchanged)
{
/* Read the file afresh. */
- off64_t aroff = elf_getaroff (elf);
+ off_t aroff = elf_getaroff (elf);
pure_elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
if (aroff > 0)
{
}
}
+static const char *
+elf_ch_type_name (unsigned int code)
+{
+ if (code == 0)
+ return "NONE";
+
+ if (code == ELFCOMPRESS_ZLIB)
+ return "ZLIB";
+
+ return "UNKNOWN";
+}
/* Print the section headers. */
static void
else
puts (gettext ("[Nr] Name Type Addr Off Size ES Flags Lk Inf Al"));
+ if (print_decompress)
+ {
+ if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
+ puts (gettext (" [Compression Size Al]"));
+ else
+ puts (gettext (" [Compression Size Al]"));
+ }
+
for (cnt = 0; cnt < shnum; ++cnt)
{
Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
*cp++ = 'G';
if (shdr->sh_flags & SHF_TLS)
*cp++ = 'T';
+ if (shdr->sh_flags & SHF_COMPRESSED)
+ *cp++ = 'C';
if (shdr->sh_flags & SHF_ORDERED)
*cp++ = 'O';
if (shdr->sh_flags & SHF_EXCLUDE)
*cp++ = 'E';
*cp = '\0';
+ const char *sname;
char buf[128];
+ sname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name) ?: "<corrupt>";
printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
" %2" PRId64 " %-5s %2" PRId32 " %3" PRId32
" %2" PRId64 "\n",
- cnt,
- elf_strptr (ebl->elf, shstrndx, shdr->sh_name)
- ?: "<corrupt>",
+ cnt, sname,
ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)),
ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr,
ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset,
ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size,
shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info,
shdr->sh_addralign);
+
+ if (print_decompress)
+ {
+ if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+ {
+ GElf_Chdr chdr;
+ if (gelf_getchdr (scn, &chdr) != NULL)
+ printf (" [ELF %s (%" PRId32 ") %0*" PRIx64
+ " %2" PRId64 "]\n",
+ elf_ch_type_name (chdr.ch_type),
+ chdr.ch_type,
+ ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8,
+ chdr.ch_size, chdr.ch_addralign);
+ else
+ error (0, 0,
+ gettext ("bad compression header for section %zd: %s"),
+ elf_ndxscn (scn), elf_errmsg (-1));
+ }
+ else if (strncmp(".zdebug", sname, strlen (".zdebug")) == 0)
+ {
+ ssize_t size;
+ if ((size = dwelf_scn_gnu_compressed_size (scn)) >= 0)
+ printf (" [GNU ZLIB %0*zx ]\n",
+ ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, size);
+ else
+ error (0, 0,
+ gettext ("bad gnu compressed size for section %zd: %s"),
+ elf_ndxscn (scn), elf_errmsg (-1));
+ }
+ }
}
fputc_unlocked ('\n', stdout);
GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
if (shdr != NULL && shdr->sh_type == SHT_GROUP)
- handle_scngrp (ebl, scn, shdr);
+ {
+ if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+ {
+ if (elf_compress (scn, 0, 0) < 0)
+ printf ("WARNING: %s [%zd]\n",
+ gettext ("Couldn't uncompress section"),
+ elf_ndxscn (scn));
+ shdr = gelf_getshdr (scn, &shdr_mem);
+ if (unlikely (shdr == NULL))
+ error (EXIT_FAILURE, 0,
+ gettext ("cannot get section [%zd] header: %s"),
+ elf_ndxscn (scn),
+ elf_errmsg (-1));
+ }
+ handle_scngrp (ebl, scn, shdr);
+ }
}
}
GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
if (shdr != NULL && shdr->sh_type == (GElf_Word) type)
- handle_symtab (ebl, scn, shdr);
+ {
+ if (symbol_table_section != NULL)
+ {
+ /* Get the section header string table index. */
+ size_t shstrndx;
+ const char *sname;
+ if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
+ error (EXIT_FAILURE, 0,
+ gettext ("cannot get section header string table index"));
+ sname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
+ if (sname == NULL || strcmp (sname, symbol_table_section) != 0)
+ continue;
+ }
+
+ if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+ {
+ if (elf_compress (scn, 0, 0) < 0)
+ printf ("WARNING: %s [%zd]\n",
+ gettext ("Couldn't uncompress section"),
+ elf_ndxscn (scn));
+ shdr = gelf_getshdr (scn, &shdr_mem);
+ if (unlikely (shdr == NULL))
+ error (EXIT_FAILURE, 0,
+ gettext ("cannot get section [%zd] header: %s"),
+ elf_ndxscn (scn), elf_errmsg (-1));
+ }
+ handle_symtab (ebl, scn, shdr);
+ }
}
}
++nsyms;
if (maxlength < ++lengths[cnt])
++maxlength;
- if (inner > max_nsyms)
+ if (inner >= max_nsyms)
goto invalid_data;
}
while ((chain[inner++] & 1) == 0);
if (likely (shdr != NULL))
{
+ if ((shdr->sh_type == SHT_HASH || shdr->sh_type == SHT_GNU_HASH)
+ && (shdr->sh_flags & SHF_COMPRESSED) != 0)
+ {
+ if (elf_compress (scn, 0, 0) < 0)
+ printf ("WARNING: %s [%zd]\n",
+ gettext ("Couldn't uncompress section"),
+ elf_ndxscn (scn));
+ shdr = gelf_getshdr (scn, &shdr_mem);
+ if (unlikely (shdr == NULL))
+ error (EXIT_FAILURE, 0,
+ gettext ("cannot get section [%zd] header: %s"),
+ elf_ndxscn (scn), elf_errmsg (-1));
+ }
+
if (shdr->sh_type == SHT_HASH)
{
if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
static const char *
+dwarf_defaulted_string (unsigned int code)
+{
+ static const char *const known[] =
+ {
+#define DWARF_ONE_KNOWN_DW_DEFAULTED(NAME, CODE) [CODE] = #NAME,
+ DWARF_ALL_KNOWN_DW_DEFAULTED
+#undef DWARF_ONE_KNOWN_DW_DEFAULTED
+ };
+
+ if (likely (code < sizeof (known) / sizeof (known[0])))
+ return known[code];
+
+ return NULL;
+}
+
+
+static const char *
dwarf_visibility_string (unsigned int code)
{
static const char *const known[] =
}
+static const char *
+dwarf_unit_string (unsigned int type)
+{
+ switch (type)
+ {
+#define DWARF_ONE_KNOWN_DW_UT(NAME, CODE) case CODE: return #NAME;
+ DWARF_ALL_KNOWN_DW_UT
+#undef DWARF_ONE_KNOWN_DW_UT
+ default:
+ return NULL;
+ }
+}
+
+
/* Used by all dwarf_foo_name functions. */
static const char *
string_or_unknown (const char *known, unsigned int code,
static const char *
+dwarf_defaulted_name (unsigned int code)
+{
+ const char *ret = dwarf_defaulted_string (code);
+ return string_or_unknown (ret, code, 0, 0, false);
+}
+
+
+static const char *
dwarf_visibility_name (unsigned int code)
{
const char *ret = dwarf_visibility_string (code);
}
+static const char *
+dwarf_unit_name (unsigned int type)
+{
+ const char *ret = dwarf_unit_string (type);
+ return string_or_unknown (ret, type, DW_UT_lo_user, DW_UT_hi_user, true);
+}
+
+
static void
print_block (size_t n, const void *block)
{
CONSUME (addrsize);
char *a = format_dwarf_addr (dwflmod, 0, addr, addr);
- printf ("%*s[%4" PRIuMAX "] %s %s\n",
+ printf ("%*s[%2" PRIuMAX "] %s %s\n",
indent, "", (uintmax_t) offset, op_name, a);
free (a);
break;
case DW_OP_call_ref:
+ case DW_OP_GNU_variable_value:
/* Offset operand. */
if (ref_size != 4 && ref_size != 8)
goto invalid; /* Cannot be used in CFA. */
addr = read_8ubyte_unaligned (dbg, data);
data += ref_size;
CONSUME (ref_size);
-
- printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX "\n",
+ /* addr is a DIE offset, so format it as one. */
+ printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
indent, "", (uintmax_t) offset,
op_name, (uintmax_t) addr);
offset += 1 + ref_size;
case DW_OP_const1u:
// XXX value might be modified by relocation
NEED (1);
- printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 "\n",
+ printf ("%*s[%2" PRIuMAX "] %s %" PRIu8 "\n",
indent, "", (uintmax_t) offset,
op_name, *((uint8_t *) data));
++data;
case DW_OP_const2u:
NEED (2);
// XXX value might be modified by relocation
- printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
+ printf ("%*s[%2" PRIuMAX "] %s %" PRIu16 "\n",
indent, "", (uintmax_t) offset,
op_name, read_2ubyte_unaligned (dbg, data));
CONSUME (2);
case DW_OP_const4u:
NEED (4);
// XXX value might be modified by relocation
- printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
+ printf ("%*s[%2" PRIuMAX "] %s %" PRIu32 "\n",
indent, "", (uintmax_t) offset,
op_name, read_4ubyte_unaligned (dbg, data));
CONSUME (4);
case DW_OP_const8u:
NEED (8);
// XXX value might be modified by relocation
- printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
+ printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 "\n",
indent, "", (uintmax_t) offset,
op_name, (uint64_t) read_8ubyte_unaligned (dbg, data));
CONSUME (8);
case DW_OP_const1s:
NEED (1);
// XXX value might be modified by relocation
- printf ("%*s[%4" PRIuMAX "] %s %" PRId8 "\n",
+ printf ("%*s[%2" PRIuMAX "] %s %" PRId8 "\n",
indent, "", (uintmax_t) offset,
op_name, *((int8_t *) data));
++data;
case DW_OP_const2s:
NEED (2);
// XXX value might be modified by relocation
- printf ("%*s[%4" PRIuMAX "] %s %" PRId16 "\n",
+ printf ("%*s[%2" PRIuMAX "] %s %" PRId16 "\n",
indent, "", (uintmax_t) offset,
op_name, read_2sbyte_unaligned (dbg, data));
CONSUME (2);
case DW_OP_const4s:
NEED (4);
// XXX value might be modified by relocation
- printf ("%*s[%4" PRIuMAX "] %s %" PRId32 "\n",
+ printf ("%*s[%2" PRIuMAX "] %s %" PRId32 "\n",
indent, "", (uintmax_t) offset,
op_name, read_4sbyte_unaligned (dbg, data));
CONSUME (4);
case DW_OP_const8s:
NEED (8);
// XXX value might be modified by relocation
- printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
+ printf ("%*s[%2" PRIuMAX "] %s %" PRId64 "\n",
indent, "", (uintmax_t) offset,
op_name, read_8sbyte_unaligned (dbg, data));
CONSUME (8);
uint64_t uleb;
NEED (1);
get_uleb128 (uleb, data, data + len);
- printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
+ printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 "\n",
indent, "", (uintmax_t) offset, op_name, uleb);
CONSUME (data - start);
offset += 1 + (data - start);
get_uleb128 (uleb, data, data + len);
NEED (1);
get_uleb128 (uleb2, data, data + len);
- printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n",
+ printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n",
indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
CONSUME (data - start);
offset += 1 + (data - start);
int64_t sleb;
NEED (1);
get_sleb128 (sleb, data, data + len);
- printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
+ printf ("%*s[%2" PRIuMAX "] %s %" PRId64 "\n",
indent, "", (uintmax_t) offset, op_name, sleb);
CONSUME (data - start);
offset += 1 + (data - start);
get_uleb128 (uleb, data, data + len);
NEED (1);
get_sleb128 (sleb, data, data + len);
- printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n",
+ printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n",
indent, "", (uintmax_t) offset, op_name, uleb, sleb);
CONSUME (data - start);
offset += 1 + (data - start);
case DW_OP_call2:
NEED (2);
- printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
+ printf ("%*s[%2" PRIuMAX "] %s [%6" PRIx16 "]\n",
indent, "", (uintmax_t) offset, op_name,
read_2ubyte_unaligned (dbg, data));
CONSUME (2);
+ data += 2;
offset += 3;
break;
case DW_OP_call4:
NEED (4);
- printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
+ printf ("%*s[%2" PRIuMAX "] %s [%6" PRIx32 "]\n",
indent, "", (uintmax_t) offset, op_name,
read_4ubyte_unaligned (dbg, data));
CONSUME (4);
+ data += 4;
offset += 5;
break;
case DW_OP_skip:
case DW_OP_bra:
NEED (2);
- printf ("%*s[%4" PRIuMAX "] %s %" PRIuMAX "\n",
+ printf ("%*s[%2" PRIuMAX "] %s %" PRIuMAX "\n",
indent, "", (uintmax_t) offset, op_name,
(uintmax_t) (offset + read_2sbyte_unaligned (dbg, data) + 3));
CONSUME (2);
start = data;
NEED (1);
get_uleb128 (uleb, data, data + len);
- printf ("%*s[%4" PRIuMAX "] %s: ",
+ printf ("%*s[%2" PRIuMAX "] %s: ",
indent, "", (uintmax_t) offset, op_name);
NEED (uleb);
print_block (uleb, data);
NEED (1);
get_sleb128 (sleb, data, data + len);
- printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "] %+" PRId64 "\n",
+ printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "] %+" PRId64 "\n",
indent, "", (intmax_t) offset,
op_name, (uintmax_t) addr, sleb);
CONSUME (data - start);
start = data;
NEED (1);
get_uleb128 (uleb, data, data + len);
- printf ("%*s[%4" PRIuMAX "] %s:\n",
+ printf ("%*s[%2" PRIuMAX "] %s:\n",
indent, "", (uintmax_t) offset, op_name);
NEED (uleb);
- print_ops (dwflmod, dbg, indent + 6, indent + 6, vers,
+ print_ops (dwflmod, dbg, indent + 5, indent + 5, vers,
addrsize, offset_size, cu, uleb, data);
data += uleb;
CONSUME (data - start);
NEED (1);
uint8_t usize = *(uint8_t *) data++;
NEED (usize);
- printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "] ",
+ printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "] ",
indent, "", (uintmax_t) offset, op_name, uleb);
print_block (usize, data);
data += usize;
get_uleb128 (uleb2, data, data + len);
if (! print_unresolved_addresses && cu != NULL)
uleb2 += cu->start;
- printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " [%6" PRIx64 "]\n",
+ printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 " [%6" PRIx64 "]\n",
indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
CONSUME (data - start);
offset += 1 + (data - start);
get_uleb128 (uleb, data, data + len);
if (! print_unresolved_addresses && cu != NULL)
uleb += cu->start;
- printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
+ printf ("%*s[%2" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
indent, "", (uintmax_t) offset,
op_name, usize, uleb);
CONSUME (data - start);
get_uleb128 (uleb, data, data + len);
if (uleb != 0 && ! print_unresolved_addresses && cu != NULL)
uleb += cu->start;
- printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n",
+ printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
indent, "", (uintmax_t) offset, op_name, uleb);
CONSUME (data - start);
offset += 1 + (data - start);
uintmax_t param_off = (uintmax_t) read_4ubyte_unaligned (dbg, data);
if (! print_unresolved_addresses && cu != NULL)
param_off += cu->start;
- printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n",
+ printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
indent, "", (uintmax_t) offset, op_name, param_off);
CONSUME (4);
data += 4;
default:
/* No Operand. */
- printf ("%*s[%4" PRIuMAX "] %s\n",
+ printf ("%*s[%2" PRIuMAX "] %s\n",
indent, "", (uintmax_t) offset, op_name);
++offset;
break;
continue;
invalid:
- printf (gettext ("%*s[%4" PRIuMAX "] %s <TRUNCATED>\n"),
+ printf (gettext ("%*s[%2" PRIuMAX "] %s <TRUNCATED>\n"),
indent, "", (uintmax_t) offset, op_name);
break;
}
size_t cnt = 0;
unsigned int name;
unsigned int form;
+ Dwarf_Sword data;
Dwarf_Off enoffset;
- while (dwarf_getabbrevattr (&abbrev, cnt,
- &name, &form, &enoffset) == 0)
+ while (dwarf_getabbrevattr_data (&abbrev, cnt, &name, &form,
+ &data, &enoffset) == 0)
{
- printf (" attr: %s, form: %s, offset: %#" PRIx64 "\n",
- dwarf_attr_name (name), dwarf_form_name (form),
- (uint64_t) enoffset);
-
+ printf (" attr: %s, form: %s",
+ dwarf_attr_name (name), dwarf_form_name (form));
+ if (form == DW_FORM_implicit_const)
+ printf (" (%" PRId64 ")", data);
+ printf (", offset: %#" PRIx64 "\n", (uint64_t) enoffset);
++cnt;
}
Dwarf_Addr base = 0;
unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
unsigned char *readp = data->d_buf;
+ Dwarf_CU *last_cu = NULL;
while (readp < endp)
{
ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
+ Dwarf_CU *cu = last_cu;
if (first && skip_listptr_hole (&known_rangelistptr, &listptr_idx,
- &address_size, NULL, &base, NULL,
+ &address_size, NULL, &base, &cu,
offset, &readp, endp))
continue;
+ if (last_cu != cu)
+ {
+ char *basestr = format_dwarf_addr (dwflmod, address_size,
+ base, base);
+ Dwarf_Die cudie;
+ if (dwarf_cu_die (cu, &cudie,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL) == NULL)
+ printf (gettext ("\n Unknown CU base: %s\n"), basestr);
+ else
+ printf (gettext ("\n CU [%6" PRIx64 "] base: %s\n"),
+ dwarf_dieoffset (&cudie), basestr);
+ free (basestr);
+ }
+ last_cu = cu;
+
if (unlikely (data->d_size - offset < (size_t) address_size * 2))
{
printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
if (begin == (Dwarf_Addr) -1l) /* Base address entry. */
{
char *b = format_dwarf_addr (dwflmod, address_size, end, end);
- printf (gettext (" [%6tx] base address %s\n"), offset, b);
+ printf (gettext (" [%6tx] base address\n %s\n"), offset, b);
free (b);
base = end;
}
else if (begin == 0 && end == 0) /* End of list entry. */
{
if (first)
- printf (gettext (" [%6tx] empty list\n"), offset);
+ printf (gettext (" [%6tx] empty list\n"), offset);
first = true;
}
else
{
- char *b = format_dwarf_addr (dwflmod, address_size, base + begin,
- begin);
- char *e = format_dwarf_addr (dwflmod, address_size, base + end,
- end);
/* We have an address range entry. */
if (first) /* First address range entry in a list. */
- printf (gettext (" [%6tx] %s..%s\n"), offset, b, e);
+ printf (" [%6tx] ", offset);
else
- printf (gettext (" %s..%s\n"), b, e);
- free (b);
- free (e);
+ printf (" ");
+
+ printf ("range %" PRIx64 ", %" PRIx64 "\n", begin, end);
+ if (! print_unresolved_addresses)
+ {
+ char *b = format_dwarf_addr (dwflmod, address_size, base + begin,
+ base + begin);
+ char *e = format_dwarf_addr (dwflmod, address_size,
+ base + end - 1, base + end);
+ printf (" %s..\n", b);
+ printf (" %s\n", e);
+ free (b);
+ free (e);
+ }
first = false;
}
return set;
}
+static const unsigned char *
+read_encoded (unsigned int encoding, const unsigned char *readp,
+ const unsigned char *const endp, uint64_t *res, Dwarf *dbg)
+{
+ if ((encoding & 0xf) == DW_EH_PE_absptr)
+ encoding = gelf_getclass (dbg->elf) == ELFCLASS32
+ ? DW_EH_PE_udata4 : DW_EH_PE_udata8;
+
+ switch (encoding & 0xf)
+ {
+ case DW_EH_PE_uleb128:
+ get_uleb128 (*res, readp, endp);
+ break;
+ case DW_EH_PE_sleb128:
+ get_sleb128 (*res, readp, endp);
+ break;
+ case DW_EH_PE_udata2:
+ if (readp + 2 > endp)
+ goto invalid;
+ *res = read_2ubyte_unaligned_inc (dbg, readp);
+ break;
+ case DW_EH_PE_udata4:
+ if (readp + 4 > endp)
+ goto invalid;
+ *res = read_4ubyte_unaligned_inc (dbg, readp);
+ break;
+ case DW_EH_PE_udata8:
+ if (readp + 8 > endp)
+ goto invalid;
+ *res = read_8ubyte_unaligned_inc (dbg, readp);
+ break;
+ case DW_EH_PE_sdata2:
+ if (readp + 2 > endp)
+ goto invalid;
+ *res = read_2sbyte_unaligned_inc (dbg, readp);
+ break;
+ case DW_EH_PE_sdata4:
+ if (readp + 4 > endp)
+ goto invalid;
+ *res = read_4sbyte_unaligned_inc (dbg, readp);
+ break;
+ case DW_EH_PE_sdata8:
+ if (readp + 8 > endp)
+ goto invalid;
+ *res = read_8sbyte_unaligned_inc (dbg, readp);
+ break;
+ default:
+ invalid:
+ error (1, 0,
+ gettext ("invalid encoding"));
+ }
+
+ return readp;
+}
+
+
static void
print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
Dwarf_Word vma_base, unsigned int code_align,
int data_align,
unsigned int version, unsigned int ptr_size,
+ unsigned int encoding,
Dwfl_Module *dwflmod, Ebl *ebl, Dwarf *dbg)
{
char regnamebuf[REGNAMESZ];
case DW_CFA_set_loc:
if ((uint64_t) (endp - readp) < 1)
goto invalid;
- get_uleb128 (op1, readp, endp);
- op1 += vma_base;
- printf (" set_loc %" PRIu64 "\n", op1 * code_align);
+ readp = read_encoded (encoding, readp, endp, &op1, dbg);
+ printf (" set_loc %#" PRIx64 " to %#" PRIx64 "\n",
+ op1, pc = vma_base + op1);
break;
case DW_CFA_advance_loc1:
if ((uint64_t) (endp - readp) < 1)
}
-static const unsigned char *
-read_encoded (unsigned int encoding, const unsigned char *readp,
- const unsigned char *const endp, uint64_t *res, Dwarf *dbg)
-{
- if ((encoding & 0xf) == DW_EH_PE_absptr)
- encoding = gelf_getclass (dbg->elf) == ELFCLASS32
- ? DW_EH_PE_udata4 : DW_EH_PE_udata8;
-
- switch (encoding & 0xf)
- {
- case DW_EH_PE_uleb128:
- get_uleb128 (*res, readp, endp);
- break;
- case DW_EH_PE_sleb128:
- get_sleb128 (*res, readp, endp);
- break;
- case DW_EH_PE_udata2:
- if (readp + 2 > endp)
- goto invalid;
- *res = read_2ubyte_unaligned_inc (dbg, readp);
- break;
- case DW_EH_PE_udata4:
- if (readp + 4 > endp)
- goto invalid;
- *res = read_4ubyte_unaligned_inc (dbg, readp);
- break;
- case DW_EH_PE_udata8:
- if (readp + 8 > endp)
- goto invalid;
- *res = read_8ubyte_unaligned_inc (dbg, readp);
- break;
- case DW_EH_PE_sdata2:
- if (readp + 2 > endp)
- goto invalid;
- *res = read_2sbyte_unaligned_inc (dbg, readp);
- break;
- case DW_EH_PE_sdata4:
- if (readp + 4 > endp)
- goto invalid;
- *res = read_4sbyte_unaligned_inc (dbg, readp);
- break;
- case DW_EH_PE_sdata8:
- if (readp + 8 > endp)
- goto invalid;
- *res = read_8sbyte_unaligned_inc (dbg, readp);
- break;
- default:
- invalid:
- error (1, 0,
- gettext ("invalid encoding"));
- }
-
- return readp;
-}
-
-
static void
print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
else
print_cfa_program (readp, cieend, vma_base, code_alignment_factor,
data_alignment_factor, version, ptr_size,
- dwflmod, ebl, dbg);
+ fde_encoding, dwflmod, ebl, dbg);
readp = cieend;
}
}
{
struct attrcb_args *cbargs = (struct attrcb_args *) arg;
const int level = cbargs->level;
+ Dwarf_Die *die = cbargs->die;
unsigned int attr = dwarf_whatattr (attrp);
if (unlikely (attr == 0))
{
if (!cbargs->silent)
- error (0, 0, gettext ("cannot get attribute code: %s"),
- dwarf_errmsg (-1));
+ error (0, 0, gettext ("DIE [%" PRIx64 "] "
+ "cannot get attribute code: %s"),
+ dwarf_dieoffset (die), dwarf_errmsg (-1));
return DWARF_CB_ABORT;
}
if (unlikely (form == 0))
{
if (!cbargs->silent)
- error (0, 0, gettext ("cannot get attribute form: %s"),
- dwarf_errmsg (-1));
+ error (0, 0, gettext ("DIE [%" PRIx64 "] "
+ "cannot get attribute form: %s"),
+ dwarf_dieoffset (die), dwarf_errmsg (-1));
return DWARF_CB_ABORT;
}
{
attrval_out:
if (!cbargs->silent)
- error (0, 0, gettext ("cannot get attribute value: %s"),
+ error (0, 0, gettext ("DIE [%" PRIx64 "] "
+ "cannot get attribute '%s' (%s) value: "
+ "%s"),
+ dwarf_dieoffset (die),
+ dwarf_attr_name (attr),
+ dwarf_form_name (form),
dwarf_errmsg (-1));
- return DWARF_CB_ABORT;
+ /* Don't ABORT, it might be other attributes can be resolved. */
+ return DWARF_CB_OK;
}
char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize,
addr, addr);
break;
case DW_FORM_sec_offset:
+ case DW_FORM_implicit_const:
case DW_FORM_udata:
case DW_FORM_sdata:
- case DW_FORM_data8:
+ case DW_FORM_data8: /* Note no data16 here, we see that as block. */
case DW_FORM_data4:
case DW_FORM_data2:
case DW_FORM_data1:;
dwarf_form_name (form), (uintmax_t) num);
return DWARF_CB_OK;
}
- /* else fallthrough */
+ FALLTHROUGH;
/* These cases always take a loclistptr and no constant. */
case DW_AT_location:
case DW_AT_accessibility:
valuestr = dwarf_access_name (num);
break;
+ case DW_AT_defaulted:
+ valuestr = dwarf_defaulted_name (num);
+ break;
case DW_AT_visibility:
valuestr = dwarf_visibility_name (num);
break;
case DW_AT_discr_list:
valuestr = dwarf_discr_list_name (num);
break;
+ case DW_AT_decl_file:
+ case DW_AT_call_file:
+ {
+ /* Try to get the actual file, the current interface only
+ gives us full paths, but we only want to show the file
+ name for now. */
+ Dwarf_Die cudie;
+ if (dwarf_cu_die (cbargs->cu, &cudie,
+ NULL, NULL, NULL, NULL, NULL, NULL) != NULL)
+ {
+ Dwarf_Files *files;
+ size_t nfiles;
+ if (dwarf_getsrcfiles (&cudie, &files, &nfiles) == 0)
+ {
+ valuestr = dwarf_filesrc (files, num, NULL, NULL);
+ char *filename = strrchr (valuestr, '/');
+ if (filename != NULL)
+ valuestr = filename + 1;
+ }
+ }
+ }
+ break;
default:
/* Nothing. */
break;
printf (" %*s%-20s (%s) %s\n",
(int) (level * 2), "", dwarf_attr_name (attr),
- dwarf_form_name (form), nl_langinfo (flag ? YESSTR : NOSTR));
+ dwarf_form_name (form), flag ? gettext ("yes") : gettext ("no"));
break;
case DW_FORM_flag_present:
break;
printf (" %*s%-20s (%s) %s\n",
(int) (level * 2), "", dwarf_attr_name (attr),
- dwarf_form_name (form), nl_langinfo (YESSTR));
+ dwarf_form_name (form), gettext ("yes"));
break;
case DW_FORM_exprloc:
case DW_FORM_block2:
case DW_FORM_block1:
case DW_FORM_block:
+ case DW_FORM_data16: /* DWARF5 calls this a constant class. */
if (cbargs->silent)
break;
Dwarf_Block block;
print_block (block.length, block.data);
break;
}
- /* Fall through. */
+ FALLTHROUGH;
case DW_AT_location:
case DW_AT_data_location:
default:
if (cbargs->silent)
break;
- printf (" %*s%-20s (form: %#x) ???\n",
+ printf (" %*s%-20s (%s) ???\n",
(int) (level * 2), "", dwarf_attr_name (attr),
- (int) form);
+ dwarf_form_name (form));
break;
}
int maxdies = 20;
Dwarf_Die *dies = (Dwarf_Die *) xmalloc (maxdies * sizeof (Dwarf_Die));
- Dwarf_Off offset = 0;
-
/* New compilation unit. */
- size_t cuhl;
Dwarf_Half version;
+
+ Dwarf_Die result;
Dwarf_Off abbroffset;
uint8_t addrsize;
uint8_t offsize;
- Dwarf_Off nextcu;
- uint64_t typesig;
- Dwarf_Off typeoff;
+ uint64_t unit_id;
+ Dwarf_Off subdie_off;
+
+ int unit_res;
+ Dwarf_CU *cu;
+ Dwarf_CU cu_mem;
+ uint8_t unit_type;
+ Dwarf_Die cudie;
+ Dwarf_Die subdie;
+
+ /* We cheat a little because we want to see only the CUs from .debug_info
+ or .debug_types. We know the Dwarf_CU struct layout. Set it up at
+ the end of .debug_info if we want .debug_types only. Check the returned
+ Dwarf_CU is still in the expected section. */
+ if (debug_types)
+ {
+ cu_mem.dbg = dbg;
+ cu_mem.end = dbg->sectiondata[IDX_debug_info]->d_size;
+ cu_mem.sec_idx = IDX_debug_info;
+ cu = &cu_mem;
+ }
+ else
+ cu = NULL;
+
next_cu:
- if (dwarf_next_unit (dbg, offset, &nextcu, &cuhl, &version,
- &abbroffset, &addrsize, &offsize,
- debug_types ? &typesig : NULL,
- debug_types ? &typeoff : NULL) != 0)
+ unit_res = dwarf_get_units (dbg, cu, &cu, &version, &unit_type,
+ &cudie, &subdie);
+ if (unit_res == 1)
+ goto do_return;
+
+ if (unit_res == -1)
+ {
+ if (!silent)
+ error (0, 0, gettext ("cannot get next unit: %s"), dwarf_errmsg (-1));
+ goto do_return;
+ }
+
+ if (cu->sec_idx != (size_t) (debug_types ? IDX_debug_types : IDX_debug_info))
goto do_return;
+ dwarf_cu_die (cu, &result, NULL, &abbroffset, &addrsize, &offsize,
+ &unit_id, &subdie_off);
+
if (!silent)
{
- if (debug_types)
+ Dwarf_Off offset = cu->start;
+ if (debug_types && version < 5)
printf (gettext (" Type unit at offset %" PRIu64 ":\n"
" Version: %" PRIu16 ", Abbreviation section offset: %"
PRIu64 ", Address size: %" PRIu8
", Offset size: %" PRIu8
"\n Type signature: %#" PRIx64
- ", Type offset: %#" PRIx64 "\n"),
+ ", Type offset: %#" PRIx64 " [%" PRIx64 "]\n"),
(uint64_t) offset, version, abbroffset, addrsize, offsize,
- typesig, (uint64_t) typeoff);
+ unit_id, (uint64_t) subdie_off, dwarf_dieoffset (&subdie));
else
- printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
- " Version: %" PRIu16 ", Abbreviation section offset: %"
- PRIu64 ", Address size: %" PRIu8
- ", Offset size: %" PRIu8 "\n"),
- (uint64_t) offset, version, abbroffset, addrsize, offsize);
+ {
+ printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
+ " Version: %" PRIu16
+ ", Abbreviation section offset: %" PRIu64
+ ", Address size: %" PRIu8
+ ", Offset size: %" PRIu8 "\n"),
+ (uint64_t) offset, version, abbroffset, addrsize, offsize);
+
+ if (version >= 5)
+ {
+ printf (gettext (" Unit type: %s (%" PRIu8 ")"),
+ dwarf_unit_name (unit_type), unit_type);
+ if (unit_type == DW_UT_type
+ || unit_type == DW_UT_skeleton
+ || unit_type == DW_UT_split_compile
+ || unit_type == DW_UT_split_type)
+ printf (", Unit id: 0x%.16" PRIx64 "", unit_id);
+ if (unit_type == DW_UT_type
+ || unit_type == DW_UT_split_type)
+ printf (", Unit DIE off: %#" PRIx64 " [%" PRIx64 "]",
+ subdie_off, dwarf_dieoffset (&subdie));
+ printf ("\n");
+ }
+ }
+ }
+
+ if (version < 2 || version > 5
+ || unit_type < DW_UT_compile || unit_type > DW_UT_split_type)
+ {
+ if (!silent)
+ error (0, 0, gettext ("unknown version (%d) or unit type (%d)"),
+ version, unit_type);
+ goto next_cu;
}
struct attrcb_args args =
.offset_size = offsize
};
- offset += cuhl;
-
int level = 0;
-
- if (unlikely ((debug_types ? dwarf_offdie_types : dwarf_offdie)
- (dbg, offset, &dies[level]) == NULL))
- {
- if (!silent)
- error (0, 0, gettext ("cannot get DIE at offset %" PRIu64
- " in section '%s': %s"),
- (uint64_t) offset, secname, dwarf_errmsg (-1));
- goto do_return;
- }
-
+ dies[0] = cudie;
args.cu = dies[0].cu;
do
{
- offset = dwarf_dieoffset (&dies[level]);
+ Dwarf_Off offset = dwarf_dieoffset (&dies[level]);
if (unlikely (offset == ~0ul))
{
if (!silent)
if (unlikely (tag == DW_TAG_invalid))
{
if (!silent)
- error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIu64
- " in section '%s': %s"),
+ error (0, 0, gettext ("cannot get tag of DIE at offset [%" PRIx64
+ "] in section '%s': %s"),
(uint64_t) offset, secname, dwarf_errmsg (-1));
goto do_return;
}
if (!silent)
- printf (" [%6" PRIx64 "] %*s%s\n",
- (uint64_t) offset, (int) (level * 2), "",
- dwarf_tag_name (tag));
+ {
+ unsigned int code = dwarf_getabbrevcode (dies[level].abbrev);
+ printf (" [%6" PRIx64 "] %*s%-20s abbrev: %u\n",
+ (uint64_t) offset, (int) (level * 2), "",
+ dwarf_tag_name (tag), code);
+ }
/* Print the attribute values. */
args.level = level;
}
while (level >= 0);
- offset = nextcu;
- if (offset != 0)
- goto next_cu;
+ /* And again... */
+ goto next_cu;
do_return:
free (dies);
uint_fast8_t offset_size = 4;
bool first = true;
- struct Dwarf_CU *cu = NULL;
Dwarf_Addr base = 0;
unsigned char *readp = data->d_buf;
unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
+ Dwarf_CU *last_cu = NULL;
while (readp < endp)
{
ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
+ Dwarf_CU *cu = last_cu;
if (first && skip_listptr_hole (&known_loclistptr, &listptr_idx,
&address_size, &offset_size, &base,
&cu, offset, &readp, endp))
continue;
+ if (last_cu != cu)
+ {
+ char *basestr = format_dwarf_addr (dwflmod, address_size,
+ base, base);
+ Dwarf_Die cudie;
+ if (dwarf_cu_die (cu, &cudie,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL) == NULL)
+ printf (gettext ("\n Unknown CU base: %s\n"), basestr);
+ else
+ printf (gettext ("\n CU [%6" PRIx64 "] base: %s\n"),
+ dwarf_dieoffset (&cudie), basestr);
+ free (basestr);
+ }
+ last_cu = cu;
+
if (unlikely (data->d_size - offset < (size_t) address_size * 2))
{
printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
if (begin == (Dwarf_Addr) -1l) /* Base address entry. */
{
char *b = format_dwarf_addr (dwflmod, address_size, end, end);
- printf (gettext (" [%6tx] base address %s\n"), offset, b);
+ printf (gettext (" [%6tx] base address\n %s\n"), offset, b);
free (b);
base = end;
}
else if (begin == 0 && end == 0) /* End of list entry. */
{
if (first)
- printf (gettext (" [%6tx] empty list\n"), offset);
+ printf (gettext (" [%6tx] empty list\n"), offset);
first = true;
}
else
/* We have a location expression entry. */
uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
- char *b = format_dwarf_addr (dwflmod, address_size, base + begin,
- begin);
- char *e = format_dwarf_addr (dwflmod, address_size, base + end,
- end);
-
if (first) /* First entry in a list. */
- printf (gettext (" [%6tx] %s..%s"), offset, b, e);
+ printf (" [%6tx] ", offset);
else
- printf (gettext (" %s..%s"), b, e);
+ printf (" ");
- free (b);
- free (e);
+ printf ("range %" PRIx64 ", %" PRIx64 "\n", begin, end);
+ if (! print_unresolved_addresses)
+ {
+ char *b = format_dwarf_addr (dwflmod, address_size, base + begin,
+ base + begin);
+ char *e = format_dwarf_addr (dwflmod, address_size,
+ base + end - 1, base + end);
+ printf (" %s..\n", b);
+ printf (" %s\n", e);
+ free (b);
+ free (e);
+ }
if (endp - readp <= (ptrdiff_t) len)
{
break;
}
- print_ops (dwflmod, dbg, 1, 18 + (address_size * 4),
- 3 /*XXX*/, address_size, offset_size, cu, len, readp);
+ print_ops (dwflmod, dbg, 11, 11,
+ cu != NULL ? cu->version : 3,
+ address_size, offset_size, cu, len, readp);
first = false;
readp += len;
// Version 4 is the GNU extension for DWARF4. DWARF5 will use version
// 5 when it gets standardized.
- if (vers != 4)
+ if (vers != 4 && vers != 5)
{
printf (gettext (" unknown version, cannot parse section\n"));
return;
line_offset);
}
- const unsigned char *vendor[DW_MACRO_GNU_hi_user - DW_MACRO_GNU_lo_user];
+ const unsigned char *vendor[DW_MACRO_hi_user - DW_MACRO_lo_user];
memset (vendor, 0, sizeof vendor);
if (flag & 0x04)
{
goto invalid_data;
unsigned int opcode = *readp++;
printf (gettext (" [%" PRIx8 "]"), opcode);
- if (opcode < DW_MACRO_GNU_lo_user
- || opcode > DW_MACRO_GNU_hi_user)
+ if (opcode < DW_MACRO_lo_user
+ || opcode > DW_MACRO_hi_user)
goto invalid_data;
// Record the start of description for this vendor opcode.
// uleb128 nr args, 1 byte per arg form.
- vendor[opcode - DW_MACRO_GNU_lo_user] = readp;
+ vendor[opcode - DW_MACRO_lo_user] = readp;
if (readp + 1 > readendp)
goto invalid_data;
unsigned int args = *readp++;
if (readp + 1 > readendp)
goto invalid_data;
unsigned int form = *readp++;
- printf (" %s", dwarf_form_string (form));
+ printf (" %s", dwarf_form_name (form));
if (form != DW_FORM_data1
&& form != DW_FORM_data2
&& form != DW_FORM_data4
switch (opcode)
{
- case DW_MACRO_GNU_start_file:
+ case DW_MACRO_start_file:
get_uleb128 (u128, readp, readendp);
if (readp >= readendp)
goto invalid_data;
++level;
break;
- case DW_MACRO_GNU_end_file:
+ case DW_MACRO_end_file:
--level;
printf ("%*send_file\n", level, "");
break;
- case DW_MACRO_GNU_define:
+ case DW_MACRO_define:
get_uleb128 (u128, readp, readendp);
endp = memchr (readp, '\0', readendp - readp);
if (endp == NULL)
readp = endp + 1;
break;
- case DW_MACRO_GNU_undef:
+ case DW_MACRO_undef:
get_uleb128 (u128, readp, readendp);
endp = memchr (readp, '\0', readendp - readp);
if (endp == NULL)
readp = endp + 1;
break;
- case DW_MACRO_GNU_define_indirect:
+ case DW_MACRO_define_strp:
get_uleb128 (u128, readp, readendp);
if (readp + offset_len > readendp)
goto invalid_data;
level, "", dwarf_getstring (dbg, off, NULL), u128);
break;
- case DW_MACRO_GNU_undef_indirect:
+ case DW_MACRO_undef_strp:
get_uleb128 (u128, readp, readendp);
if (readp + offset_len > readendp)
goto invalid_data;
level, "", dwarf_getstring (dbg, off, NULL), u128);
break;
- case DW_MACRO_GNU_transparent_include:
+ case DW_MACRO_import:
if (readp + offset_len > readendp)
goto invalid_data;
if (offset_len == 8)
level, "", off);
break;
+ case DW_MACRO_define_sup:
+ get_uleb128 (u128, readp, readendp);
+ if (readp + offset_len > readendp)
+ goto invalid_data;
+ if (offset_len == 8)
+ off = read_8ubyte_unaligned_inc (dbg, readp);
+ else
+ off = read_4ubyte_unaligned_inc (dbg, readp);
+ // Needs support for reading from supplementary object file.
+ printf ("%*s#define <str-at-0x%" PRIx64 ">, line %u (sup)\n",
+ level, "", off, u128);
+ break;
+
+ case DW_MACRO_undef_sup:
+ get_uleb128 (u128, readp, readendp);
+ if (readp + offset_len > readendp)
+ goto invalid_data;
+ if (offset_len == 8)
+ off = read_8ubyte_unaligned_inc (dbg, readp);
+ else
+ off = read_4ubyte_unaligned_inc (dbg, readp);
+ // Needs support for reading from supplementary object file.
+ printf ("%*s#undef <str-at-0x%" PRIx64 ">, line %u (sup)\n",
+ level, "", off, u128);
+ break;
+
+ case DW_MACRO_import_sup:
+ if (readp + offset_len > readendp)
+ goto invalid_data;
+ if (offset_len == 8)
+ off = read_8ubyte_unaligned_inc (dbg, readp);
+ else
+ off = read_4ubyte_unaligned_inc (dbg, readp);
+ printf ("%*s#include offset 0x%" PRIx64 " (sup)\n",
+ level, "", off);
+ break;
+
+ case DW_MACRO_define_strx:
+ get_uleb128 (u128, readp, readendp);
+ if (readp + offset_len > readendp)
+ goto invalid_data;
+ if (offset_len == 8)
+ off = read_8ubyte_unaligned_inc (dbg, readp);
+ else
+ off = read_4ubyte_unaligned_inc (dbg, readp);
+ // Needs support for reading indirect string offset table
+ printf ("%*s#define <str-at-0x%" PRIx64 ">, line %u (strx)\n",
+ level, "", off, u128);
+ break;
+
+ case DW_MACRO_undef_strx:
+ get_uleb128 (u128, readp, readendp);
+ if (readp + offset_len > readendp)
+ goto invalid_data;
+ if (offset_len == 8)
+ off = read_8ubyte_unaligned_inc (dbg, readp);
+ else
+ off = read_4ubyte_unaligned_inc (dbg, readp);
+ // Needs support for reading indirect string offset table.
+ printf ("%*s#undef <str-at-0x%" PRIx64 ">, line %u (strx)\n",
+ level, "", off, u128);
+ break;
+
default:
printf ("%*svendor opcode 0x%" PRIx8, level, "", opcode);
- if (opcode < DW_MACRO_GNU_lo_user
- || opcode > DW_MACRO_GNU_lo_user
- || vendor[opcode - DW_MACRO_GNU_lo_user] == NULL)
+ if (opcode < DW_MACRO_lo_user
+ || opcode > DW_MACRO_lo_user
+ || vendor[opcode - DW_MACRO_lo_user] == NULL)
goto invalid_data;
const unsigned char *op_desc;
- op_desc = vendor[opcode - DW_MACRO_GNU_lo_user];
+ op_desc = vendor[opcode - DW_MACRO_lo_user];
// Just skip the arguments, we cannot really interpret them,
// but print as much as we can.
if (readp + 1 > readendp)
goto invalid_data;
val = *readp++;
- printf (" %s", nl_langinfo (val != 0 ? YESSTR : NOSTR));
+ printf (" %s", val != 0 ? gettext ("yes") : gettext ("no"));
break;
case DW_FORM_string:
dsize = 8;
break;
default:
+ dsize = 0;
error (1, 0, gettext ("invalid TType encoding"));
}
int n;
for (n = 0; n < ndebug_sections; ++n)
if (strcmp (name, debug_sections[n].name) == 0
-#if USE_ZLIB
|| (name[0] == '.' && name[1] == 'z'
&& debug_sections[n].name[1] == 'd'
&& strcmp (&name[2], &debug_sections[n].name[1]) == 0)
-#endif
)
{
if ((print_debug_sections | implicit_debug_sections)
unsigned int colno, size_t *repeated_size)
{
uint_fast16_t count = item->count ?: 1;
+ /* Ebl_Core_Item count is always a small number.
+ Make sure the backend didn't put in some large bogus value. */
+ assert (count < 128);
#define TYPES \
DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8); \
DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64); \
DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64)
-#define DO_TYPE(NAME, Name, hex, dec) GElf_##Name Name[count]
- union { TYPES; } value;
+#define DO_TYPE(NAME, Name, hex, dec) GElf_##Name Name
+ typedef union { TYPES; } value_t;
+ void *data = alloca (count * sizeof (value_t));
+#undef DO_TYPE
+
+#define DO_TYPE(NAME, Name, hex, dec) \
+ GElf_##Name *value_##Name __attribute__((unused)) = data
+ TYPES;
#undef DO_TYPE
- void *data = &value;
size_t size = gelf_fsize (core, item->type, count, EV_CURRENT);
size_t convsize = size;
if (repeated_size != NULL)
#define DO_TYPE(NAME, Name, hex, dec) \
case ELF_T_##NAME: \
colno = print_core_item (colno, ',', WRAP_COLUMN, \
- 0, item->name, dec, value.Name[0]); \
+ 0, item->name, dec, value_##Name[0]); \
break
TYPES;
#undef DO_TYPE
#define DO_TYPE(NAME, Name, hex, dec) \
case ELF_T_##NAME: \
colno = print_core_item (colno, ',', WRAP_COLUMN, \
- 0, item->name, hex, value.Name[0]); \
+ 0, item->name, hex, value_##Name[0]); \
break
TYPES;
#undef DO_TYPE
{
#define DO_TYPE(NAME, Name, hex, dec) \
case ELF_T_##NAME: \
- sec = value.Name[0]; \
- usec = value.Name[1]; \
+ sec = value_##Name[0]; \
+ usec = value_##Name[1]; \
break
TYPES;
#undef DO_TYPE
case 'c':
assert (count == 1);
colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
- "%c", value.Byte[0]);
+ "%c", value_Byte[0]);
break;
case 's':
colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
- "%.*s", (int) count, value.Byte);
+ "%.*s", (int) count, value_Byte);
break;
case '\n':
printf (" %s\n", name);
break;
}
- /* Fall through */
+ FALLTHROUGH;
case 'x': /* hex */
case 'p': /* address */
case 's': /* address of string */
if (si_code > 0)
switch (si_signo)
{
- case SIGILL:
- case SIGFPE:
- case SIGSEGV:
- case SIGBUS:
+ case CORE_SIGILL:
+ case CORE_SIGFPE:
+ case CORE_SIGSEGV:
+ case CORE_SIGBUS:
{
uint64_t addr;
if (! buf_read_ulong (core, &ptr, end, &addr))
default:
;
}
- else if (si_code == SI_USER)
+ else if (si_code == CORE_SI_USER)
{
int pid, uid;
if (! buf_read_int (core, &ptr, end, &pid)
&& (offset = gelf_getnote (data, offset,
&nhdr, &name_offset, &desc_offset)) > 0)
{
- const char *name = data->d_buf + name_offset;
+ const char *name = nhdr.n_namesz == 0 ? "" : data->d_buf + name_offset;
const char *desc = data->d_buf + desc_offset;
char buf[100];
return;
bad_note:
- error (EXIT_FAILURE, 0,
- gettext ("cannot get content of note section: %s"),
- elf_errmsg (-1));
+ error (0, 0,
+ gettext ("cannot get content of note: %s"),
+ data != NULL ? "garbage data" : elf_errmsg (-1));
}
static void
elf_ndxscn (scn), name);
else
{
+ if (print_decompress)
+ {
+ /* We try to decompress the section, but keep the old shdr around
+ so we can show both the original shdr size and the uncompressed
+ data size. */
+ if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+ {
+ if (elf_compress (scn, 0, 0) < 0)
+ printf ("WARNING: %s [%zd]\n",
+ gettext ("Couldn't uncompress section"),
+ elf_ndxscn (scn));
+ }
+ else if (strncmp (name, ".zdebug", strlen (".zdebug")) == 0)
+ {
+ if (elf_compress_gnu (scn, 0, 0) < 0)
+ printf ("WARNING: %s [%zd]\n",
+ gettext ("Couldn't uncompress section"),
+ elf_ndxscn (scn));
+ }
+ }
+
Elf_Data *data = elf_rawdata (scn, NULL);
if (data == NULL)
error (0, 0, gettext ("cannot get data for section [%zu] '%s': %s"),
elf_ndxscn (scn), name, elf_errmsg (-1));
else
{
- printf (gettext ("\nHex dump of section [%zu] '%s', %" PRIu64
- " bytes at offset %#0" PRIx64 ":\n"),
- elf_ndxscn (scn), name,
- shdr->sh_size, shdr->sh_offset);
+ if (data->d_size == shdr->sh_size)
+ printf (gettext ("\nHex dump of section [%zu] '%s', %" PRIu64
+ " bytes at offset %#0" PRIx64 ":\n"),
+ elf_ndxscn (scn), name,
+ shdr->sh_size, shdr->sh_offset);
+ else
+ printf (gettext ("\nHex dump of section [%zu] '%s', %" PRIu64
+ " bytes (%zd uncompressed) at offset %#0"
+ PRIx64 ":\n"),
+ elf_ndxscn (scn), name,
+ shdr->sh_size, data->d_size, shdr->sh_offset);
hex_dump (data->d_buf, data->d_size);
}
}
elf_ndxscn (scn), name);
else
{
+ if (print_decompress)
+ {
+ /* We try to decompress the section, but keep the old shdr around
+ so we can show both the original shdr size and the uncompressed
+ data size. */
+ if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+ {
+ if (elf_compress (scn, 0, 0) < 0)
+ printf ("WARNING: %s [%zd]\n",
+ gettext ("Couldn't uncompress section"),
+ elf_ndxscn (scn));
+ }
+ else if (strncmp (name, ".zdebug", strlen (".zdebug")) == 0)
+ {
+ if (elf_compress_gnu (scn, 0, 0) < 0)
+ printf ("WARNING: %s [%zd]\n",
+ gettext ("Couldn't uncompress section"),
+ elf_ndxscn (scn));
+ }
+ }
+
Elf_Data *data = elf_rawdata (scn, NULL);
if (data == NULL)
error (0, 0, gettext ("cannot get data for section [%zu] '%s': %s"),
elf_ndxscn (scn), name, elf_errmsg (-1));
else
{
- printf (gettext ("\nString section [%zu] '%s' contains %" PRIu64
- " bytes at offset %#0" PRIx64 ":\n"),
- elf_ndxscn (scn), name,
- shdr->sh_size, shdr->sh_offset);
+ if (data->d_size == shdr->sh_size)
+ printf (gettext ("\nString section [%zu] '%s' contains %" PRIu64
+ " bytes at offset %#0" PRIx64 ":\n"),
+ elf_ndxscn (scn), name,
+ shdr->sh_size, shdr->sh_offset);
+ else
+ printf (gettext ("\nString section [%zu] '%s' contains %" PRIu64
+ " bytes (%zd uncompressed) at offset %#0"
+ PRIx64 ":\n"),
+ elf_ndxscn (scn), name,
+ shdr->sh_size, data->d_size, shdr->sh_offset);
const char *start = data->d_buf;
const char *const limit = start + data->d_size;
{
as_off = s->as_off;
- Elf *subelf;
+ Elf *subelf = NULL;
if (unlikely (elf_rand (elf, as_off) == 0)
|| unlikely ((subelf = elf_begin (-1, ELF_C_READ_MMAP, elf))
== NULL))