summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS5
-rw-r--r--TODO4
-rw-r--r--lib/ChangeLog5
-rw-r--r--lib/system.h14
-rw-r--r--libdw/ChangeLog8
-rw-r--r--libdw/Makefile.am6
-rw-r--r--libdw/dwarf.h4
-rw-r--r--libdwfl/ChangeLog5
-rw-r--r--libdwfl/gzip.c115
-rw-r--r--src/ChangeLog58
-rw-r--r--src/addr2line.c6
-rw-r--r--src/ar.c5
-rw-r--r--src/elfcmp.c5
-rw-r--r--src/elflint.c42
-rw-r--r--src/findtextrel.c6
-rw-r--r--src/ld.c4
-rw-r--r--src/nm.c4
-rw-r--r--src/objdump.c4
-rw-r--r--src/ranlib.c4
-rw-r--r--src/readelf.c724
-rw-r--r--src/size.c4
-rw-r--r--src/strings.c4
-rw-r--r--src/strip.c4
-rw-r--r--src/unstrip.c5
24 files changed, 819 insertions, 226 deletions
diff --git a/NEWS b/NEWS
index b48aeed5..07d80a45 100644
--- a/NEWS
+++ b/NEWS
@@ -2,7 +2,10 @@ Version 0.139:
libcpu: Add Intel SSE4 disassembler support
-readelf: Implement call frame information dumping.
+readelf: Implement call frame information and exception handling dumping.
+ Add -e option. Enable it implicitly for -a.
+
+elflint: Check PT_GNU_EH_FRAME program header entry.
libdwfl: Support automatic gzip/bzip2 decompression of ELF files.
diff --git a/TODO b/TODO
index bc374146..c884c2c1 100644
--- a/TODO
+++ b/TODO
@@ -1,7 +1,7 @@
ToDo list for elfutils -*-outline-*-
----------------------
-Time-stamp: <2009-01-01 16:56:38 drepper>
+Time-stamp: <2009-01-16 20:55:06 drepper>
* mkinstalldirs
@@ -118,6 +118,8 @@ Time-stamp: <2009-01-01 16:56:38 drepper>
check TLS relocation depencies
+ Check content of .eh_frame_hdr, .eh_frame, .gcc_except_table
+
*** for x86
check that R_386_TLS_GD is followed by R_386_PLT32 for __tls_get_addr
diff --git a/lib/ChangeLog b/lib/ChangeLog
index 8791640b..0774524c 100644
--- a/lib/ChangeLog
+++ b/lib/ChangeLog
@@ -1,3 +1,8 @@
+2009-01-17 Ulrich Drepper <[email protected]>
+
+ * system.h (ARGP_PROGRAM_VERSION_HOOK_DEF): Define.
+ (ARGP_PROGRAM_BUG_ADDRESS_DEF): Define.
+
2009-01-10 Ulrich Drepper <[email protected]>
* eu-config.h: Remove tls_key_t, key_create, getspecific, setspecific,
diff --git a/lib/system.h b/lib/system.h
index 23c666ad..10b4734a 100644
--- a/lib/system.h
+++ b/lib/system.h
@@ -1,5 +1,5 @@
/* Declarations for common convenience functions.
- Copyright (C) 2006 Red Hat, Inc.
+ Copyright (C) 2006, 2009 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -78,4 +78,16 @@ extern int crc32_file (int fd, uint32_t *resp);
#define pread_retry(fd, buf, len, off) \
TEMP_FAILURE_RETRY (pread (fd, buf, len, off))
+
+/* We need define two variables, argp_program_version_hook and
+ argp_program_bug_address, in all programs. argp.h declares these
+ variables as non-const (which is correct in general). But we can
+ do better, it is not going to change. So we want to move them into
+ the .rodata section. Define macros to do the trick. */
+#define ARGP_PROGRAM_VERSION_HOOK_DEF \
+ void (*const apvh) (FILE *, struct argp_state *) \
+ __asm ("argp_program_version_hook")
+#define ARGP_PROGRAM_BUG_ADDRESS_DEF \
+ const char *const apba__ __asm ("argp_program_bug_address")
+
#endif /* system.h */
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 9b9be90c..51ab6e94 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,4 +1,8 @@
-2009-01-11 Roland McGrath <[email protected]>
+2009-01-17 Roland McGrath <[email protected]>
+
+ * Makefile.am (known-dwarf.h): Target renamed, not in $(srcdir).
+ Make it unconditional.
+ (BUILT_SOURCES): Updated.
* dwarf.h: Add description comments for DW_LANG_* values.
@@ -6,6 +10,8 @@
($(srcdir)/known-dwarf.h): New target.
(BUILT_SOURCES): Add it.
+ * dwarf.h: Add DW_OP_GNU_push_tls_address, DW_OP_GNU_uninit.
+
2009-01-10 Ulrich Drepper <[email protected]>
* dwarf_error.c: Always use __thread. Remove all !USE_TLS code.
diff --git a/libdw/Makefile.am b/libdw/Makefile.am
index 6dda8eef..5f84abd8 100644
--- a/libdw/Makefile.am
+++ b/libdw/Makefile.am
@@ -85,12 +85,10 @@ libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \
libdw_visit_scopes.c \
dwarf_entry_breakpoints.c
-if MAINTAINER_MODE
-BUILT_SOURCES = $(srcdir)/known-dwarf.h
-$(srcdir)/known-dwarf.h: $(top_srcdir)/config/known-dwarf.awk $(srcdir)/dwarf.h
+BUILT_SOURCES = known-dwarf.h
+known-dwarf.h: $(top_srcdir)/config/known-dwarf.awk $(srcdir)/dwarf.h
$(AWK) -f $^ > [email protected]
-endif
if !MUDFLAP
libdw_pic_a_SOURCES =
diff --git a/libdw/dwarf.h b/libdw/dwarf.h
index bdd16d93..cce46304 100644
--- a/libdw/dwarf.h
+++ b/libdw/dwarf.h
@@ -432,6 +432,10 @@ enum
DW_OP_call_frame_cfa = 0x9c,/* CFA as determined by CFI. */
DW_OP_bit_piece = 0x9d, /* ULEB128 size and ULEB128 offset in bits. */
+ /* GNU extensions. */
+ DW_OP_GNU_push_tls_address = 0xe0,
+ DW_OP_GNU_uninit = 0xf0,
+
DW_OP_lo_user = 0xe0, /* Implementation-defined range start. */
DW_OP_hi_user = 0xff /* Implementation-defined range end. */
};
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index f0ab1acf..ef00a0cf 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,8 @@
+2009-01-14 Roland McGrath <[email protected]>
+
+ * gzip.c [!BZLIB] (mapped_zImage): New function.
+ (unzip) [!BZLIB]: Grok Linux kernel zImage format.
+
2009-01-10 Ulrich Drepper <[email protected]>
* dwfl_error.c: Always use __thread. Remove all !USE_TLS code.
diff --git a/libdwfl/gzip.c b/libdwfl/gzip.c
index ed602a66..66445254 100644
--- a/libdwfl/gzip.c
+++ b/libdwfl/gzip.c
@@ -53,6 +53,7 @@
#ifdef BZLIB
# define inflate_groks_header true
+# define mapped_zImage(...) false
# include <bzlib.h>
# define unzip __libdw_bunzip2
# define DWFL_E_ZLIB DWFL_E_BZLIB
@@ -66,12 +67,41 @@
# define gzdopen BZ2_bzdopen
# define gzread BZ2_bzread
# define gzclose BZ2_bzclose
+# define gzerror BZ2_bzerror
#else
# define inflate_groks_header false
# include <zlib.h>
# define unzip __libdw_gunzip
# define MAGIC "\037\213"
# define Z(what) Z_##what
+
+/* We can also handle Linux kernel zImage format in a very hackish way.
+ If it looks like one, we actually just scan the image for the gzip
+ magic bytes to figure out where the gzip image starts. */
+
+# define LINUX_MAGIC_OFFSET 514
+# define LINUX_MAGIC "HdrS"
+
+static bool
+mapped_zImage (off64_t *start_offset, void **mapped, size_t *mapped_size)
+{
+ const size_t pos = LINUX_MAGIC_OFFSET + sizeof LINUX_MAGIC;
+ if (*mapped_size > pos
+ && !memcmp (*mapped + LINUX_MAGIC_OFFSET,
+ LINUX_MAGIC, sizeof LINUX_MAGIC - 1))
+ {
+ void *p = memmem (*mapped + pos, *mapped_size - pos,
+ MAGIC, sizeof MAGIC - 1);
+ if (p != NULL)
+ {
+ *start_offset += p - *mapped;
+ *mapped_size = *mapped + *mapped_size - p,
+ *mapped = p;
+ return true;
+ }
+ }
+ return false;
+}
#endif
/* If this is not a compressed image, return DWFL_E_BADELF.
@@ -120,7 +150,8 @@ unzip (int fd, off64_t start_offset,
/* If the file is already mapped in, look at the header. */
if (mapped != NULL
&& (mapped_size <= sizeof MAGIC
- || memcmp (mapped, MAGIC, sizeof MAGIC - 1)))
+ || memcmp (mapped, MAGIC, sizeof MAGIC - 1))
+ && !mapped_zImage (&start_offset, &mapped, &mapped_size))
/* Not a compressed file. */
return DWFL_E_BADELF;
@@ -165,35 +196,69 @@ unzip (int fd, off64_t start_offset,
{
/* Let the decompression library read the file directly. */
- int d = dup (fd);
- if (unlikely (d < 0))
- return DWFL_E_BADELF;
- if (start_offset != 0)
- {
- off64_t off = lseek (d, start_offset, SEEK_SET);
- if (off != start_offset)
- {
- close (d);
- return DWFL_E_BADELF;
- }
- }
- gzFile zf = gzdopen (d, "r");
- if (unlikely (zf == NULL))
- {
- close (d);
- return zlib_fail (Z (MEM_ERROR));
- }
+ gzFile zf;
+ Dwfl_Error open_stream (void)
+ {
+ int d = dup (fd);
+ if (unlikely (d < 0))
+ return DWFL_E_BADELF;
+ if (start_offset != 0)
+ {
+ off64_t off = lseek (d, start_offset, SEEK_SET);
+ if (off != start_offset)
+ {
+ close (d);
+ return DWFL_E_BADELF;
+ }
+ }
+ zf = gzdopen (d, "r");
+ if (unlikely (zf == NULL))
+ {
+ close (d);
+ return zlib_fail (Z (MEM_ERROR));
+ }
+
+ /* From here on, zlib will close D. */
+
+ return DWFL_E_NOERROR;
+ }
- /* From here on, zlib will close D. */
+ Dwfl_Error result = open_stream ();
#ifndef BZLIB
- if (gzdirect (zf))
+ if (result == DWFL_E_NOERROR && gzdirect (zf))
{
+ bool found = false;
+ char buf[sizeof LINUX_MAGIC - 1];
+ gzseek (zf, start_offset + LINUX_MAGIC_OFFSET, SEEK_SET);
+ int n = gzread (zf, buf, sizeof buf);
+ if (n == sizeof buf
+ && !memcmp (buf, LINUX_MAGIC, sizeof LINUX_MAGIC - 1))
+ while (gzread (zf, buf, sizeof MAGIC - 1) == sizeof MAGIC - 1)
+ if (!memcmp (buf, MAGIC, sizeof MAGIC - 1))
+ {
+ start_offset = gztell (zf) - 2;
+ found = true;
+ break;
+ }
gzclose (zf);
- return DWFL_E_BADELF;
+ if (found)
+ {
+ result = open_stream ();
+ if (result == DWFL_E_NOERROR && unlikely (gzdirect (zf)))
+ {
+ gzclose (zf);
+ result = DWFL_E_BADELF;
+ }
+ }
+ else
+ result = DWFL_E_BADELF;
}
#endif
+ if (result != DWFL_E_NOERROR)
+ return result;
+
ptrdiff_t pos = 0;
while (1)
{
@@ -205,9 +270,9 @@ unzip (int fd, off64_t start_offset,
int n = gzread (zf, buffer + pos, size - pos);
if (n < 0)
{
-#ifdef BZLIB
int code;
- BZ2_bzerror (zf, &code);
+ gzerror (zf, &code);
+#ifdef BZLIB
if (code == BZ_DATA_ERROR_MAGIC)
{
gzclose (zf);
@@ -216,7 +281,7 @@ unzip (int fd, off64_t start_offset,
}
#endif
gzclose (zf);
- return zlib_fail (Z (DATA_ERROR));
+ return zlib_fail (code);
}
if (n == 0)
break;
diff --git a/src/ChangeLog b/src/ChangeLog
index 854ad699..97fd4495 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,61 @@
+2009-01-17 Ulrich Drepper <[email protected]>
+
+ * addr2line.c: Use ARGP_PROGRAM_VERSION_HOOK_DEF and
+ ARGP_PROGRAM_BUG_ADDRESS_DEF.
+ * ar.c: Likewise.
+ * elfcmp.c: Likewise.
+ * elflint.c: Likewise.
+ * findtextrel.c: Likewise.
+ * ld.c: Likewise.
+ * nm.c: Likewise.
+ * objdump.c: Likewise.
+ * ranlib.c: Likewise.
+ * readelf.c: Likewise.
+ * size.c: Likewise.
+ * strings.c: Likewise.
+ * strip.c: Likewise.
+ * unstrip.c: Likewise.
+
+2009-01-16 Ulrich Drepper <[email protected]>
+
+ * elflint.c (check_program_header): Check that PT_GNU_EH_FRAME entry
+ matches .eh_frame_hdr section, if it is available. Also check that
+ the segment is allocated, not writable, not executable.
+
+ * readelf.c: Add -e option. Dump exception and unwind related
+ sections. Add -e to -a.
+ (print_encoding_base): Handle DW_EH_PE_omit.
+ (print_debug_exception_table): Beginning of support.
+ (print_debug): Hook up print_debug_exception_table for
+ .gcc_except_table sections.
+
+ * readelf.c (print_debug_frame_section): Some fixes for last change.
+
+2009-01-15 Ulrich Drepper <[email protected]>
+
+ * readelf.c (print_encoding): Now a toplevel function.
+ (print_relinfo): Likewise.
+ (print_encoding_base): Broken out of print_debug_frame_section.
+ (print_debug_frame_section): Print different header for .eh_frame
+ sections. Fix recognition of matching CIEs in .debug_frame sections.
+ Print absolute offset for PC-relative FDE locations. Don't print
+ table header for FDEs if the table is empty.
+ (read_encoded): New function.
+ (print_debug_frame_hdr_section): New function.
+ (print_debug): Hook up print_debug_frame_hdr_section for .eh_frame_hdr
+ sections.
+
+ * readelf.c (handle_relocs_rel): Print section number.
+ (print_debug_abbrev_section): Likewise.
+ (print_debug_aranges_section): Likewise.
+ (print_debug_ranges_section): Likewise.
+ (print_debug_info_section): Likewise.
+ (print_debug_line_section): Likewise.
+ (print_debug_loc_section): Likewise.
+ (print_debug_macinfo_section): Likewise.
+ (print_debug_pubnames_section): Likewise.
+ (print_debug_str_section): Likewise.
+
2009-01-10 Ulrich Drepper <[email protected]>
* strings.c (read_block): Fix typo in error message string.
diff --git a/src/addr2line.c b/src/addr2line.c
index 7141e269..5a7b0456 100644
--- a/src/addr2line.c
+++ b/src/addr2line.c
@@ -46,13 +46,15 @@
#include <string.h>
#include <unistd.h>
+#include <system.h>
+
/* Name and version of program. */
static void print_version (FILE *stream, struct argp_state *state);
-void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
/* Bug report address. */
-const char *argp_program_bug_address = PACKAGE_BUGREPORT;
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
/* Values for the parameters which have no short form. */
diff --git a/src/ar.c b/src/ar.c
index 961db241..a7a12329 100644
--- a/src/ar.c
+++ b/src/ar.c
@@ -55,7 +55,8 @@
/* Name and version of program. */
static void print_version (FILE *stream, struct argp_state *state);
-void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
+
/* Prototypes for local functions. */
static int do_oper_extract (int oper, const char *arfname, char **argv,
int argc, long int instance);
@@ -66,7 +67,7 @@ static int do_oper_insert (int oper, const char *arfname, char **argv,
/* Bug report address. */
-const char *argp_program_bug_address = PACKAGE_BUGREPORT;
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
/* Definitions of arguments for argp functions. */
diff --git a/src/elfcmp.c b/src/elfcmp.c
index 8903efb1..a1596365 100644
--- a/src/elfcmp.c
+++ b/src/elfcmp.c
@@ -41,6 +41,7 @@
#include <string.h>
#include <unistd.h>
+#include <system.h>
#include "../libelf/elf-knowledge.h"
#include "../libebl/libeblP.h"
@@ -53,10 +54,10 @@ static int regioncompare (const void *p1, const void *p2);
/* Name and version of program. */
static void print_version (FILE *stream, struct argp_state *state);
-void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
/* Bug report address. */
-const char *argp_program_bug_address = PACKAGE_BUGREPORT;
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
/* Values for the parameters which have no short form. */
#define OPT_GAPS 0x100
diff --git a/src/elflint.c b/src/elflint.c
index 23b0f496..1c508c47 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -56,10 +56,10 @@
/* Name and version of program. */
static void print_version (FILE *stream, struct argp_state *state);
-void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
/* Bug report address. */
-const char *argp_program_bug_address = PACKAGE_BUGREPORT;
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
#define ARGP_strict 300
#define ARGP_gnuld 301
@@ -67,7 +67,6 @@ const char *argp_program_bug_address = PACKAGE_BUGREPORT;
/* Definitions of arguments for argp functions. */
static const struct argp_option options[] =
{
-
{ "strict", ARGP_strict, NULL, 0,
N_("Be extremely strict, flag level 2 features."), 0 },
{ "quiet", 'q', NULL, 0, N_("Do not print anything if successful"), 0 },
@@ -4132,7 +4131,7 @@ more than one GNU_RELRO entry in program header\n"));
if ((phdr2->p_flags & PF_W) == 0)
ERROR (gettext ("\
loadable segment GNU_RELRO applies to is not writable\n"));
- if ((phdr2->p_flags &~ PF_W) != (phdr->p_flags &~ PF_W))
+ if ((phdr2->p_flags & ~PF_W) != (phdr->p_flags & ~PF_W))
ERROR (gettext ("\
loadable segment [%u] flags do not match GNU_RELRO [%u] flags\n"),
cnt, inner);
@@ -4173,6 +4172,41 @@ loadable segment [%u] flags do not match GNU_RELRO [%u] flags\n"),
ERROR (gettext ("\
program header offset in ELF header and PHDR entry do not match"));
}
+ else if (phdr->p_type == PT_GNU_EH_FRAME)
+ {
+ /* If there is an .eh_frame_hdr section it must be
+ referenced by this program header entry. */
+ Elf_Scn *scn = NULL;
+ while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+ {
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+ if (shdr != NULL && shdr->sh_type == SHT_PROGBITS
+ && ! strcmp (".eh_frame_hdr",
+ elf_strptr (ebl->elf, shstrndx, shdr->sh_name)))
+ {
+ if (phdr->p_offset != shdr->sh_offset)
+ ERROR (gettext ("\
+call frame search table reference in program header has wrong offset\n"));
+ if (phdr->p_memsz != shdr->sh_size)
+ ERROR (gettext ("\
+call frame search table size mismatch in program and section header\n"));
+ break;
+ }
+ }
+
+ /* The section must be allocated and not be writable and
+ executable. */
+ if ((phdr->p_flags & PF_R) == 0)
+ ERROR (gettext ("\
+call frame search table must be allocated\n"));
+ if ((phdr->p_flags & PF_W) != 0)
+ ERROR (gettext ("\
+call frame search table must not be writable\n"));
+ if ((phdr->p_flags & PF_X) != 0)
+ ERROR (gettext ("\
+call frame search table must not be executable\n"));
+ }
if (phdr->p_filesz > phdr->p_memsz
&& (phdr->p_memsz != 0 || phdr->p_type != PT_NOTE))
diff --git a/src/findtextrel.c b/src/findtextrel.c
index 2fd99c96..9d10982f 100644
--- a/src/findtextrel.c
+++ b/src/findtextrel.c
@@ -44,6 +44,8 @@
#include <string.h>
#include <unistd.h>
+#include <system.h>
+
struct segments
{
@@ -54,10 +56,10 @@ struct segments
/* Name and version of program. */
static void print_version (FILE *stream, struct argp_state *state);
-void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
/* Bug report address. */
-const char *argp_program_bug_address = PACKAGE_BUGREPORT;
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
/* Values for the parameters which have no short form. */
#define OPT_DEBUGINFO 0x100
diff --git a/src/ld.c b/src/ld.c
index b4cc6cc7..989bfaba 100644
--- a/src/ld.c
+++ b/src/ld.c
@@ -48,10 +48,10 @@
/* Name and version of program. */
static void print_version (FILE *stream, struct argp_state *state);
-void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
/* Bug report address. */
-const char *argp_program_bug_address = PACKAGE_BUGREPORT;
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
/* Values for the various options. */
diff --git a/src/nm.c b/src/nm.c
index 8b8f547f..8833948a 100644
--- a/src/nm.c
+++ b/src/nm.c
@@ -58,10 +58,10 @@
/* Name and version of program. */
static void print_version (FILE *stream, struct argp_state *state);
-void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
/* Bug report address. */
-const char *argp_program_bug_address = PACKAGE_BUGREPORT;
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
/* Values for the parameters which have no short form. */
diff --git a/src/objdump.c b/src/objdump.c
index 55d3ae2e..7f639410 100644
--- a/src/objdump.c
+++ b/src/objdump.c
@@ -49,10 +49,10 @@
/* Name and version of program. */
static void print_version (FILE *stream, struct argp_state *state);
-void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
/* Bug report address. */
-const char *argp_program_bug_address = PACKAGE_BUGREPORT;
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
/* Definitions of arguments for argp functions. */
diff --git a/src/ranlib.c b/src/ranlib.c
index f456b997..e92dc89b 100644
--- a/src/ranlib.c
+++ b/src/ranlib.c
@@ -58,10 +58,10 @@ static int handle_file (const char *fname);
/* Name and version of program. */
static void print_version (FILE *stream, struct argp_state *state);
-void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
/* Bug report address. */
-const char *argp_program_bug_address = PACKAGE_BUGREPORT;
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
/* Definitions of arguments for argp functions. */
diff --git a/src/readelf.c b/src/readelf.c
index 2041983d..a3223eb4 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -61,16 +61,16 @@
/* Name and version of program. */
static void print_version (FILE *stream, struct argp_state *state);
-void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
/* Bug report address. */
-const char *argp_program_bug_address = PACKAGE_BUGREPORT;
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
/* Definitions of arguments for argp functions. */
static const struct argp_option options[] =
{
{ NULL, 0, NULL, 0, N_("Output selection:"), 0 },
- { "all", 'a', NULL, 0, N_("Equivalent to: -h -l"), 0 },
+ { "all", 'a', NULL, 0, N_("Equivalent to: -e -h -l"), 0 },
{ "dynamic", 'd', NULL, 0, N_("Display the dynamic segment"), 0 },
{ "file-header", 'h', NULL, 0, N_("Display the ELF file header"), 0 },
{ "histogram", 'I', NULL, 0,
@@ -84,8 +84,8 @@ static const struct argp_option options[] =
{ "version-info", 'V', NULL, 0, N_("Display versioning information"), 0 },
{ "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL,
N_("Display DWARF section content. SECTION can be one of abbrev, "
- "aranges, frame, info, loc, line, ranges, pubnames, str, or macinfo."),
- 0 },
+ "aranges, frame, info, loc, line, ranges, pubnames, str, macinfo, "
+ "or exception"), 0 },
{ "notes", 'n', NULL, 0, N_("Display the core notes"), 0 },
{ "arch-specific", 'A', NULL, 0,
N_("Display architecture specific information (if any)"), 0 },
@@ -96,6 +96,8 @@ static const struct argp_option options[] =
{ "string-dump", 'p', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
{ "archive-index", 'c', NULL, 0,
N_("Display the symbol index of an archive"), 0 },
+ { "exception", 'e', NULL, 0, N_("Display sections for exception handling"),
+ 0 },
{ NULL, 0, NULL, 0, N_("Output control:"), 0 },
@@ -166,20 +168,21 @@ static bool any_control_option;
/* Select printing of debugging sections. */
static enum section_e
{
- section_abbrev = 1, /* .debug_abbrev */
- section_aranges = 2, /* .debug_aranges */
- section_frame = 4, /* .debug_frame or .eh_frame */
- section_info = 8, /* .debug_info */
- section_line = 16, /* .debug_line */
- section_loc = 32, /* .debug_loc */
- section_pubnames = 64,/* .debug_pubnames */
- section_str = 128, /* .debug_str */
- section_macinfo = 256,/* .debug_macinfo */
- section_ranges = 512, /* .debug_ranges */
+ section_abbrev = 1, /* .debug_abbrev */
+ section_aranges = 2, /* .debug_aranges */
+ section_frame = 4, /* .debug_frame or .eh_frame & al. */
+ section_info = 8, /* .debug_info */
+ section_line = 16, /* .debug_line */
+ section_loc = 32, /* .debug_loc */
+ section_pubnames = 64, /* .debug_pubnames */
+ section_str = 128, /* .debug_str */
+ section_macinfo = 256, /* .debug_macinfo */
+ section_ranges = 512, /* .debug_ranges */
+ section_exception = 1024, /* .eh_frame & al. */
section_all = (section_abbrev | section_aranges | section_frame
| section_info | section_line | section_loc
| section_pubnames | section_str | section_macinfo
- | section_ranges)
+ | section_ranges | section_exception)
} print_debug_sections;
/* Select hex dumping of sections. */
@@ -286,6 +289,7 @@ parse_opt (int key, char *arg,
print_histogram = true;
print_arch = true;
print_notes = true;
+ print_debug_sections |= section_exception;
any_control_option = true;
break;
case 'A':
@@ -296,6 +300,10 @@ parse_opt (int key, char *arg,
print_dynamic_table = true;
any_control_option = true;
break;
+ case 'e':
+ print_debug_sections |= section_exception;
+ any_control_option = true;
+ break;
case 'g':
print_section_groups = true;
any_control_option = true;
@@ -358,6 +366,8 @@ parse_opt (int key, char *arg,
print_debug_sections |= section_str;
else if (strcmp (arg, "macinfo") == 0)
print_debug_sections |= section_macinfo;
+ else if (strcmp (arg, "exception") == 0)
+ print_debug_sections |= section_exception;
else
{
fprintf (stderr, gettext ("Unknown DWARF debug section `%s'.\n"),
@@ -1495,11 +1505,11 @@ handle_relocs_rel (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
if (shdr->sh_info != 0)
printf (ngettext ("\
-\nRelocation section [%2u] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
+\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
"\
-\nRelocation section [%2u] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
+\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
nentries),
- (unsigned int) elf_ndxscn (scn),
+ elf_ndxscn (scn),
elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
(unsigned int) shdr->sh_info,
elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
@@ -3962,12 +3972,11 @@ static void
print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
Ebl *ebl __attribute__ ((unused)),
GElf_Ehdr *ehdr __attribute__ ((unused)),
- Elf_Scn *scn __attribute__ ((unused)),
- GElf_Shdr *shdr, Dwarf *dbg)
+ Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
{
- printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"
+ printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
" [ Code]\n"),
- ".debug_abbrev", (uint64_t) shdr->sh_offset);
+ elf_ndxscn (scn), ".debug_abbrev", (uint64_t) shdr->sh_offset);
Dwarf_Off offset = 0;
while (offset < shdr->sh_size)
@@ -4033,8 +4042,7 @@ print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
static void
print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
Ebl *ebl __attribute__ ((unused)),
- GElf_Ehdr *ehdr __attribute__ ((unused)),
- Elf_Scn *scn __attribute__ ((unused)),
+ GElf_Ehdr *ehdr, Elf_Scn *scn,
GElf_Shdr *shdr, Dwarf *dbg)
{
Dwarf_Aranges *aranges;
@@ -4047,11 +4055,11 @@ print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
}
printf (ngettext ("\
-\nDWARF section '%s' at offset %#" PRIx64 " contains %zu entry:\n",
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entry:\n",
"\
-\nDWARF section '%s' at offset %#" PRIx64 " contains %zu entries:\n",
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entries:\n",
cnt),
- ".debug_aranges", (uint64_t) shdr->sh_offset, cnt);
+ elf_ndxscn (scn), ".debug_aranges", (uint64_t) shdr->sh_offset, cnt);
/* Compute floor(log16(cnt)). */
size_t tmp = cnt;
@@ -4103,8 +4111,8 @@ print_debug_ranges_section (Dwfl_Module *dwflmod,
}
printf (gettext ("\
-\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
- ".debug_ranges", (uint64_t) shdr->sh_offset);
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
+ elf_ndxscn (scn), ".debug_ranges", (uint64_t) shdr->sh_offset);
size_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
@@ -4381,6 +4389,159 @@ encoded_ptr_size (int encoding, unsigned int ptr_size)
}
+static unsigned int
+print_encoding (unsigned int val)
+{
+ switch (val & 0xf)
+ {
+ case DW_EH_PE_absptr:
+ fputs ("absptr", stdout);
+ break;
+ case DW_EH_PE_uleb128:
+ fputs ("uleb128", stdout);
+ break;
+ case DW_EH_PE_udata2:
+ fputs ("udata2", stdout);
+ break;
+ case DW_EH_PE_udata4:
+ fputs ("udata4", stdout);
+ break;
+ case DW_EH_PE_udata8:
+ fputs ("udata8", stdout);
+ break;
+ case DW_EH_PE_sleb128:
+ fputs ("sleb128", stdout);
+ break;
+ case DW_EH_PE_sdata2:
+ fputs ("sdata2", stdout);
+ break;
+ case DW_EH_PE_sdata4:
+ fputs ("sdata4", stdout);
+ break;
+ case DW_EH_PE_sdata8:
+ fputs ("sdata8", stdout);
+ break;
+ default:
+ /* We did not use any of the bits after all. */
+ return val;
+ }
+
+ return val & ~0xf;
+}
+
+
+static unsigned int
+print_relinfo (unsigned int val)
+{
+ switch (val & 0x70)
+ {
+ case DW_EH_PE_pcrel:
+ fputs ("pcrel", stdout);
+ break;
+ case DW_EH_PE_textrel:
+ fputs ("textrel", stdout);
+ break;
+ case DW_EH_PE_datarel:
+ fputs ("datarel", stdout);
+ break;
+ case DW_EH_PE_funcrel:
+ fputs ("funcrel", stdout);
+ break;
+ case DW_EH_PE_aligned:
+ fputs ("aligned", stdout);
+ break;
+ default:
+ return val;
+ }
+
+ return val & ~0x70;
+}
+
+
+static void
+print_encoding_base (const char *pfx, unsigned int fde_encoding)
+{
+ printf ("(%s", pfx);
+
+ if (fde_encoding == DW_EH_PE_omit)
+ puts ("omit)");
+ else
+ {
+ unsigned int w = fde_encoding;
+
+ if (w & 0xf)
+ w = print_encoding (w);
+
+ if (w & 0x70)
+ {
+ if (w != fde_encoding)
+ fputc_unlocked (' ', stdout);
+
+ w = print_relinfo (w);
+ }
+
+ if (w != 0)
+ printf ("%s%x", w != fde_encoding ? " " : "", w);
+
+ puts (")");
+ }
+}
+
+
+static const unsigned char *
+read_encoded (unsigned int encoding, const unsigned char *readp,
+ const unsigned char *const endp, uint64_t *res, Dwarf *dbg)
+{
+ switch (encoding & 0xf)
+ {
+ case DW_EH_PE_uleb128:
+ // XXX buffer overrun check
+ get_uleb128 (*res, readp);
+ break;
+ case DW_EH_PE_sleb128:
+ // XXX buffer overrun check
+ get_sleb128 (*res, readp);
+ 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)
@@ -4398,10 +4559,16 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
scnname, elf_errmsg (-1));
return;
}
+ bool is_eh_frame = strcmp (scnname, ".eh_frame") == 0;
- printf (gettext ("\
-\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
- scnname, (uint64_t) shdr->sh_offset);
+ if (is_eh_frame)
+ printf (gettext ("\
+\nCall frame information section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
+ elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
+ else
+ printf (gettext ("\
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
+ elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
struct cieinfo
{
@@ -4410,20 +4577,16 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
unsigned int code_alignment_factor;
unsigned int data_alignment_factor;
unsigned int fde_encoding;
+ unsigned int lsda_encoding;
struct cieinfo *next;
} *cies = NULL;
const unsigned char *readp = data->d_buf;
const unsigned char *const dataend = ((unsigned char *) data->d_buf
+ data->d_size);
- bool is_eh_frame = strcmp (scnname, ".eh_frame") == 0;
while (readp < dataend)
{
- /* At the beginning there must be a CIE. There can be multiple,
- hence we test tis in a loop. */
- ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
-
- if (unlikely (readp + 12 > dataend))
+ if (unlikely (readp + 4 > dataend))
{
invalid_data:
error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
@@ -4431,21 +4594,32 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
return;
}
- unsigned int ptr_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+ /* At the beginning there must be a CIE. There can be multiple,
+ hence we test tis in a loop. */
+ ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, readp);
unsigned int length = 4;
if (unlikely (unit_length == 0xffffffff))
{
+ if (unlikely (readp + 8 > dataend))
+ goto invalid_data;
+
unit_length = read_8ubyte_unaligned_inc (dbg, readp);
length = 8;
+ }
- if (unlikely (readp + 12 > dataend))
- goto invalid_data;
+ if (unlikely (unit_length == 0))
+ {
+ printf (gettext ("\n [%6jx] Zero terminator\n"), offset);
+ continue;
}
+
+ unsigned int ptr_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+
ptrdiff_t start = readp - (unsigned char *) data->d_buf;
const unsigned char *const cieend = readp + unit_length;
- if (unlikely (cieend > dataend))
+ if (unlikely (cieend > dataend || readp + 8 > dataend))
goto invalid_data;
Dwarf_Word cie_id;
@@ -4457,10 +4631,10 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
unsigned int code_alignment_factor;
int data_alignment_factor;
unsigned int fde_encoding = 0;
+ unsigned int lsda_encoding = 0;
Dwarf_Word initial_location = 0;
- if ((is_eh_frame && cie_id == 0)
- || (! is_eh_frame && cie_id == DW_CIE_ID))
+ if (cie_id == (is_eh_frame ? 0 : DW_CIE_ID))
{
uint_fast8_t version = *readp++;
const char *const augmentation = (const char *) readp;
@@ -4484,7 +4658,7 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
// XXX Check overflow
get_uleb128 (return_address_register, readp);
- printf (" [%6jx] CIE length=%" PRIu64 "\n"
+ printf ("\n [%6jx] CIE length=%" PRIu64 "\n"
" CIE_id: %" PRIu64 "\n"
" version: %u\n"
" augmentation: \"%s\"\n"
@@ -4497,71 +4671,6 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
if (augmentation[0] == 'z')
{
- unsigned int print_encoding (unsigned int val)
- {
- switch (val & 0xf)
- {
- case DW_EH_PE_absptr:
- fputs ("absptr", stdout);
- break;
- case DW_EH_PE_uleb128:
- fputs ("uleb128", stdout);
- break;
- case DW_EH_PE_udata2:
- fputs ("udata2", stdout);
- break;
- case DW_EH_PE_udata4:
- fputs ("udata4", stdout);
- break;
- case DW_EH_PE_udata8:
- fputs ("udata8", stdout);
- break;
- case DW_EH_PE_sleb128:
- fputs ("sleb128", stdout);
- break;
- case DW_EH_PE_sdata2:
- fputs ("sdata2", stdout);
- break;
- case DW_EH_PE_sdata4:
- fputs ("sdata4", stdout);
- break;
- case DW_EH_PE_sdata8:
- fputs ("sdata8", stdout);
- break;
- default:
- /* We did not use any of the bits after all. */
- return val;
- }
-
- return val & ~0xf;
- }
-
- unsigned int print_relinfo (unsigned int val)
- {
- switch (val & 0x70)
- {
- case DW_EH_PE_pcrel:
- fputs ("pcrel", stdout);
- break;
- case DW_EH_PE_textrel:
- fputs ("textrel", stdout);
- break;
- case DW_EH_PE_datarel:
- fputs ("datarel", stdout);
- break;
- case DW_EH_PE_funcrel:
- fputs ("funcrel", stdout);
- break;
- case DW_EH_PE_aligned:
- fputs ("aligned", stdout);
- break;
- default:
- return val;
- }
-
- return val & ~0x70;
- }
-
unsigned int augmentationlen;
get_uleb128 (augmentationlen, readp);
@@ -4574,28 +4683,20 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
if (*cp == 'R')
{
- putchar_unlocked ('(');
-
- unsigned int w = fde_encoding = *readp++;
-
- if (w & 0xf)
- w = print_encoding (w);
-
- if (w & 0x70)
- {
- if (w != fde_encoding)
- fputc_unlocked (' ', stdout);
-
- w = print_relinfo (w);
- }
-
- if (w != 0)
- printf ("(%s%x", w != fde_encoding ? " " : "", w);
-
- puts (")");
+ fde_encoding = *readp++;
+ print_encoding_base (gettext ("FDE address encoding: "),
+ fde_encoding);
+ }
+ else if (*cp == 'L')
+ {
+ lsda_encoding = *readp++;
+ print_encoding_base (gettext ("LSDA pointer encoding: "),
+ lsda_encoding);
}
else if (*cp == 'P')
{
+ /* Personality. This field usually has a relocation
+ attached pointing to __gcc_personality_v0. */
const unsigned char *startp = readp;
unsigned int encoding = *readp++;
uint64_t val = 0;
@@ -4654,13 +4755,13 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
++cp;
}
- readp += augmentationlen;
}
struct cieinfo *newp = alloca (sizeof (*newp));
newp->cie_offset = offset;
newp->augmentation = augmentation;
newp->fde_encoding = fde_encoding;
+ newp->lsda_encoding = lsda_encoding;
newp->code_alignment_factor = code_alignment_factor;
newp->data_alignment_factor = data_alignment_factor;
newp->next = cies;
@@ -4670,7 +4771,9 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
{
struct cieinfo *cie = cies;
while (cie != NULL)
- if (start - (ptrdiff_t) cie_id == cie->cie_offset)
+ if (is_eh_frame
+ ? start - (ptrdiff_t) cie_id == cie->cie_offset
+ : (ptrdiff_t) cie_id == cie->cie_offset)
break;
else
cie = cie->next;
@@ -4681,35 +4784,72 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
}
/* Initialize from CIE data. */
- ptr_size = encoded_ptr_size (cie->fde_encoding, ptr_size);
+ fde_encoding = cie->fde_encoding;
+ lsda_encoding = cie->lsda_encoding;
+ ptr_size = encoded_ptr_size (fde_encoding, ptr_size);
code_alignment_factor = cie->code_alignment_factor;
data_alignment_factor = cie->data_alignment_factor;
- fde_encoding = cie->fde_encoding;
+ const unsigned char *base = readp;
+ // XXX There are sometimes relocations for this value
initial_location = read_ubyte_unaligned_inc (ptr_size, dbg, readp);
Dwarf_Word address_range
= read_ubyte_unaligned_inc (ptr_size, dbg, readp);
printf ("\n [%6jx] FDE length=%" PRIu64 " cie=[%6jx]\n"
" CIE_pointer: %" PRIu64 "\n"
- " initial_location: %#" PRIx64 "\n"
- " address_range: %#" PRIx64 "\n",
+ " initial_location: %#" PRIx64,
offset, (uint64_t) unit_length,
cie->cie_offset, (uint64_t) cie_id,
- (uint64_t) initial_location, (uint64_t) address_range);
+ (uint64_t) initial_location);
+ if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
+ printf (gettext (" (offset: %#" PRIx64 ")"),
+ ((uint64_t) shdr->sh_offset
+ + (base - (const unsigned char *) data->d_buf)
+ + (uint64_t) initial_location)
+ & (ptr_size == 4
+ ? UINT64_C (0xffffffff)
+ : UINT64_C (0xffffffffffffffff)));
+
+ printf ("\n address_range: %#" PRIx64 "\n",
+ (uint64_t) address_range);
if (cie->augmentation[0] == 'z')
{
unsigned int augmentationlen;
get_uleb128 (augmentationlen, readp);
- const char *hdr = "Augmentation data:";
- const char *cp = cie->augmentation + 1;
- for (unsigned int u = 0; u < augmentationlen; ++cp, ++u)
+ if (augmentationlen > 0)
{
- printf (" %-26s%#x (", hdr, readp[u]);
- hdr = "";
+ const char *hdr = "Augmentation data:";
+ const char *cp = cie->augmentation + 1;
+ unsigned int u = 0;
+ while (*cp != '\0')
+ {
+ if (*cp == 'L')
+ {
+ uint64_t lsda_pointer;
+ const unsigned char *p
+ = read_encoded (lsda_encoding, &readp[u],
+ &readp[augmentationlen],
+ &lsda_pointer, dbg);
+ u = p - readp;
+ printf (gettext ("\
+ %-26sLSDA pointer: %#" PRIx64 "\n"),
+ hdr, lsda_pointer);
+ hdr = "";
+ }
+ ++cp;
+ }
+
+ while (u < augmentationlen)
+ {
+ printf (" %-26s%#x\n", hdr, readp[u++]);
+ hdr = "";
+ }
}
+
+ readp += augmentationlen;
}
}
@@ -4947,12 +5087,12 @@ static void
print_debug_info_section (Dwfl_Module *dwflmod,
Ebl *ebl __attribute__ ((unused)),
GElf_Ehdr *ehdr __attribute__ ((unused)),
- Elf_Scn *scn __attribute__ ((unused)),
+ Elf_Scn *scn,
GElf_Shdr *shdr, Dwarf *dbg)
{
printf (gettext ("\
-\nDWARF section '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
- ".debug_info", (uint64_t) shdr->sh_offset);
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
+ elf_ndxscn (scn), ".debug_info", (uint64_t) shdr->sh_offset);
/* If the section is empty we don't have to do anything. */
if (shdr->sh_size == 0)
@@ -5072,8 +5212,8 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
{
printf (gettext ("\
-\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
- ".debug_line", (uint64_t) shdr->sh_offset);
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
+ elf_ndxscn (scn), ".debug_line", (uint64_t) shdr->sh_offset);
if (shdr->sh_size == 0)
return;
@@ -5504,11 +5644,8 @@ advance address by fixed value %u to %s\n"),
static void
print_debug_loc_section (Dwfl_Module *dwflmod,
- Ebl *ebl __attribute__ ((unused)),
- GElf_Ehdr *ehdr __attribute__ ((unused)),
- Elf_Scn *scn __attribute__ ((unused)),
- GElf_Shdr *shdr,
- Dwarf *dbg __attribute__ ((unused)))
+ Ebl *ebl __attribute__ ((unused)), GElf_Ehdr *ehdr,
+ Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
{
Elf_Data *data = elf_rawdata (scn, NULL);
@@ -5520,8 +5657,8 @@ print_debug_loc_section (Dwfl_Module *dwflmod,
}
printf (gettext ("\
-\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
- ".debug_loc", (uint64_t) shdr->sh_offset);
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
+ elf_ndxscn (scn), ".debug_loc", (uint64_t) shdr->sh_offset);
size_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
@@ -5615,8 +5752,8 @@ print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
{
printf (gettext ("\
-\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
- ".debug_macinfo", (uint64_t) shdr->sh_offset);
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
+ elf_ndxscn (scn), ".debug_macinfo", (uint64_t) shdr->sh_offset);
putc_unlocked ('\n', stdout);
/* There is no function in libdw to iterate over the raw content of
@@ -5784,11 +5921,10 @@ static void
print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
Ebl *ebl __attribute__ ((unused)),
GElf_Ehdr *ehdr __attribute__ ((unused)),
- Elf_Scn *scn __attribute__ ((unused)),
- GElf_Shdr *shdr, Dwarf *dbg)
+ Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
{
- printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
- ".debug_pubnames", (uint64_t) shdr->sh_offset);
+ printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
+ elf_ndxscn (scn), ".debug_pubnames", (uint64_t) shdr->sh_offset);
int n = 0;
(void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
@@ -5799,8 +5935,7 @@ static void
print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
Ebl *ebl __attribute__ ((unused)),
GElf_Ehdr *ehdr __attribute__ ((unused)),
- Elf_Scn *scn __attribute__ ((unused)),
- GElf_Shdr *shdr, Dwarf *dbg)
+ Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
{
/* Compute floor(log16(shdr->sh_size)). */
GElf_Addr tmp = shdr->sh_size;
@@ -5812,8 +5947,9 @@ print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
}
digits = MAX (4, digits);
- printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"
+ printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
" %*s String\n"),
+ elf_ndxscn (scn),
".debug_str", (uint64_t) shdr->sh_offset,
/* TRANS: the debugstr| prefix makes the string unique. */
digits + 2, sgettext ("debugstr|Offset"));
@@ -5836,6 +5972,261 @@ print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
}
}
+
+/* Print the content of the call frame search table section
+ '.eh_frame_hdr'. */
+static void
+print_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
+ Ebl *ebl __attribute__ ((unused)),
+ GElf_Ehdr *ehdr __attribute__ ((unused)),
+ Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+{
+ printf (gettext ("\
+\nCall frame search table section [%2zu] '.eh_frame_hdr':\n"),
+ elf_ndxscn (scn));
+
+ Elf_Data *data = elf_rawdata (scn, NULL);
+
+ if (unlikely (data == NULL))
+ {
+ error (0, 0, gettext ("cannot get %s content: %s"),
+ ".eh_frame_hdr", elf_errmsg (-1));
+ return;
+ }
+
+ const unsigned char *readp = data->d_buf;
+ const unsigned char *const dataend = ((unsigned char *) data->d_buf
+ + data->d_size);
+
+ if (unlikely (readp + 4 > dataend))
+ {
+ invalid_data:
+ error (0, 0, gettext ("invalid data"));
+ return;
+ }
+
+ unsigned int version = *readp++;
+ unsigned int eh_frame_ptr_enc = *readp++;
+ unsigned int fde_count_enc = *readp++;
+ unsigned int table_enc = *readp++;
+
+ printf (" version: %u\n"
+ " eh_frame_ptr_enc: %#x ",
+ version, eh_frame_ptr_enc);
+ print_encoding_base ("", eh_frame_ptr_enc);
+ printf (" fde_count_enc: %#x ", fde_count_enc);
+ print_encoding_base ("", fde_count_enc);
+ printf (" table_enc: %#x ", table_enc);
+ print_encoding_base ("", table_enc);
+
+ uint64_t eh_frame_ptr = 0;
+ if (eh_frame_ptr_enc != DW_EH_PE_omit)
+ {
+ readp = read_encoded (eh_frame_ptr_enc, readp, dataend, &eh_frame_ptr,
+ dbg);
+ if (unlikely (readp == NULL))
+ goto invalid_data;
+
+ printf (" eh_frame_ptr: %#" PRIx64, eh_frame_ptr);
+ if ((eh_frame_ptr_enc & 0x70) == DW_EH_PE_pcrel)
+ printf (" (offset: %#" PRIx64 ")",
+ /* +4 because of the 4 byte header of the section. */
+ (uint64_t) shdr->sh_offset + 4 + eh_frame_ptr);
+
+ putchar_unlocked ('\n');
+ }
+
+ uint64_t fde_count = 0;
+ if (fde_count_enc != DW_EH_PE_omit)
+ {
+ readp = read_encoded (fde_count_enc, readp, dataend, &fde_count, dbg);
+ if (unlikely (readp == NULL))
+ goto invalid_data;
+
+ printf (" fde_count: %" PRIu64 "\n", fde_count);
+ }
+
+ if (fde_count == 0 || table_enc == DW_EH_PE_omit)
+ return;
+
+ puts (" Table:");
+
+ /* Optimize for the most common case. */
+ if (table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4))
+ while (fde_count > 0 && readp + 8 <= dataend)
+ {
+ int32_t initial_location = read_4sbyte_unaligned_inc (dbg, readp);
+ uint64_t initial_offset = ((uint64_t) shdr->sh_offset
+ + (int64_t) initial_location);
+ int32_t address = read_4sbyte_unaligned_inc (dbg, readp);
+ // XXX Possibly print symbol name or section offset for initial_offset
+ printf (" %#" PRIx32 " (offset: %#6" PRIx64 ") -> %#" PRIx32
+ " fde=[%6" PRIx64 "]\n",
+ initial_location, initial_offset,
+ address, address - (eh_frame_ptr + 4));
+ }
+ else
+ while (0 && readp < dataend)
+ {
+
+ }
+}
+
+
+/* Print the content of the exception handling table section
+ '.eh_frame_hdr'. */
+static void
+print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
+ Ebl *ebl __attribute__ ((unused)),
+ GElf_Ehdr *ehdr __attribute__ ((unused)),
+ Elf_Scn *scn,
+ GElf_Shdr *shdr __attribute__ ((unused)),
+ Dwarf *dbg __attribute__ ((unused)))
+{
+ printf (gettext ("\
+\nException handling table section [%2zu] '.gcc_except_table':\n"),
+ elf_ndxscn (scn));
+
+ Elf_Data *data = elf_rawdata (scn, NULL);
+
+ if (unlikely (data == NULL))
+ {
+ error (0, 0, gettext ("cannot get %s content: %s"),
+ ".gcc_except_table", elf_errmsg (-1));
+ return;
+ }
+
+ const unsigned char *readp = data->d_buf;
+ const unsigned char *const dataend = readp + data->d_size;
+
+ if (unlikely (readp + 1 > dataend))
+ {
+ invalid_data:
+ error (0, 0, gettext ("invalid data"));
+ return;
+ }
+ unsigned int lpstart_encoding = *readp++;
+ printf (gettext (" LPStart encoding: %#x "), lpstart_encoding);
+ print_encoding_base ("", lpstart_encoding);
+ if (lpstart_encoding != DW_EH_PE_omit)
+ {
+ uint64_t lpstart;
+ readp = read_encoded (lpstart_encoding, readp, dataend, &lpstart, dbg);
+ printf (" LPStart: %#" PRIx64 "\n", lpstart);
+ }
+
+ if (unlikely (readp + 1 > dataend))
+ goto invalid_data;
+ unsigned int ttype_encoding = *readp++;
+ printf (gettext (" TType encoding: %#x "), ttype_encoding);
+ print_encoding_base ("", ttype_encoding);
+ const unsigned char *ttype_base = NULL;
+ if (ttype_encoding != DW_EH_PE_omit)
+ {
+ unsigned int ttype_base_offset;
+ get_uleb128 (ttype_base_offset, readp);
+ printf (" TType base offset: %#x\n", ttype_base_offset);
+ ttype_base = readp + ttype_base_offset;
+ }
+
+ if (unlikely (readp + 1 > dataend))
+ goto invalid_data;
+ unsigned int call_site_encoding = *readp++;
+ printf (gettext (" Call site encoding: %#x "), call_site_encoding);
+ print_encoding_base ("", call_site_encoding);
+ unsigned int call_site_table_len;
+ get_uleb128 (call_site_table_len, readp);
+
+ const unsigned char *const action_table = readp + call_site_table_len;
+ if (unlikely (action_table > dataend))
+ goto invalid_data;
+ unsigned int u = 0;
+ unsigned int max_action = 0;
+ while (readp < action_table)
+ {
+ if (u == 0)
+ puts (gettext ("\n Call site table:"));
+
+ uint64_t call_site_start;
+ readp = read_encoded (call_site_encoding, readp, dataend,
+ &call_site_start, dbg);
+ uint64_t call_site_length;
+ readp = read_encoded (call_site_encoding, readp, dataend,
+ &call_site_length, dbg);
+ uint64_t landing_pad;
+ readp = read_encoded (call_site_encoding, readp, dataend,
+ &landing_pad, dbg);
+ unsigned int action;
+ get_uleb128 (action, readp);
+ max_action = MAX (action, max_action);
+ printf (gettext (" [%4u] Call site start: %#" PRIx64 "\n"
+ " Call site length: %" PRIu64 "\n"
+ " Landing pad: %#" PRIx64 "\n"
+ " Action: %u\n"),
+ u++, call_site_start, call_site_length, landing_pad, action);
+ }
+ assert (readp == action_table);
+
+ unsigned int max_ar_filter = 0;
+ if (max_action > 0)
+ {
+ puts ("\n Action table:");
+
+ const unsigned char *const action_table_end
+ = action_table + max_action + 1;
+
+ u = 0;
+ do
+ {
+ int ar_filter;
+ get_sleb128 (ar_filter, readp);
+ if (ar_filter > 0 && (unsigned int) ar_filter > max_ar_filter)
+ max_ar_filter = ar_filter;
+ int ar_disp;
+ get_sleb128 (ar_disp, readp);
+
+ printf (" [%4u] ar_filter: %d\n"
+ " ar_disp: %d\n",
+ u++, ar_filter, ar_disp);
+ }
+ while (readp < action_table_end);
+ }
+
+ if (max_ar_filter > 0)
+ {
+ puts ("\n TType table:");
+
+ // XXX Not *4, size of encoding;
+ switch (ttype_encoding & 7)
+ {
+ case DW_EH_PE_udata2:
+ case DW_EH_PE_sdata2:
+ readp = ttype_base - max_ar_filter * 2;
+ break;
+ case DW_EH_PE_udata4:
+ case DW_EH_PE_sdata4:
+ readp = ttype_base - max_ar_filter * 4;
+ break;
+ case DW_EH_PE_udata8:
+ case DW_EH_PE_sdata8:
+ readp = ttype_base - max_ar_filter * 8;
+ break;
+ default:
+ error (1, 0, gettext ("invalid TType encoding"));
+ }
+
+ do
+ {
+ uint64_t ttype;
+ readp = read_encoded (ttype_encoding, readp, ttype_base, &ttype,
+ dbg);
+ printf (" [%4u] %#" PRIx64 "\n", max_ar_filter--, ttype);
+ }
+ while (readp < ttype_base);
+ }
+}
+
+
static void
print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
{
@@ -5884,7 +6275,12 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
NEW_SECTION (str),
NEW_SECTION (macinfo),
NEW_SECTION (ranges),
- { ".eh_frame", section_frame, print_debug_frame_section }
+ { ".eh_frame", section_frame | section_exception,
+ print_debug_frame_section },
+ { ".eh_frame_hdr", section_frame | section_exception,
+ print_debug_frame_hdr_section },
+ { ".gcc_except_table", section_frame | section_exception,
+ print_debug_exception_table }
};
const int ndebug_sections = (sizeof (debug_sections)
/ sizeof (debug_sections[0]));
diff --git a/src/size.c b/src/size.c
index 9f59cceb..f6f23d55 100644
--- a/src/size.c
+++ b/src/size.c
@@ -50,10 +50,10 @@
/* Name and version of program. */
static void print_version (FILE *stream, struct argp_state *state);
-void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
/* Bug report address. */
-const char *argp_program_bug_address = PACKAGE_BUGREPORT;
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
/* Values for the parameters which have no short form. */
diff --git a/src/strings.c b/src/strings.c
index aebf07bd..b69f2ad2 100644
--- a/src/strings.c
+++ b/src/strings.c
@@ -59,10 +59,10 @@ static int read_elf (Elf *elf, int fd, const char *fname, off64_t fdlen);
/* Name and version of program. */
static void print_version (FILE *stream, struct argp_state *state);
-void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
/* Bug report address. */
-const char *argp_program_bug_address = PACKAGE_BUGREPORT;
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
/* Definitions of arguments for argp functions. */
static const struct argp_option options[] =
diff --git a/src/strip.c b/src/strip.c
index 3ca047af..1958bb51 100644
--- a/src/strip.c
+++ b/src/strip.c
@@ -55,10 +55,10 @@
/* Name and version of program. */
static void print_version (FILE *stream, struct argp_state *state);
-void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
/* Bug report address. */
-const char *argp_program_bug_address = PACKAGE_BUGREPORT;
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
/* Values for the parameters which have no short form. */
diff --git a/src/unstrip.c b/src/unstrip.c
index 4a6fd197..97b73c6f 100644
--- a/src/unstrip.c
+++ b/src/unstrip.c
@@ -64,11 +64,10 @@
/* Name and version of program. */
static void print_version (FILE *stream, struct argp_state *state);
-void (*argp_program_version_hook) (FILE *, struct argp_state *)
- = print_version;
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
/* Bug report address. */
-const char *argp_program_bug_address = PACKAGE_BUGREPORT;
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
/* Definitions of arguments for argp functions. */
static const struct argp_option options[] =