merge of 0bdc7517571447282c23ea28a69147eabf574048
and b0183df71043735ade5c882809fed6c7ca571b2a
diff --git a/NEWS b/NEWS
index d03953a..803b605 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,8 @@
DSO versions also for symbols in nobits sections. Allow .rodata section
to have STRINGS and MERGE flag set.
+strip: add some more compatibility with binutils.
+
Version 0.112:
elfcmp: some more relaxation.
@@ -27,7 +29,7 @@
Version 0.110:
-libelf: fix a numbe rof problems with elf_update
+libelf: fix a number of problems with elf_update
elfcmp: fix a few bugs. Compare gaps.
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 010deda..c5d1503 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,7 +1,7 @@
-2005-08-10 Roland McGrath <roland@redhat.com>
+2005-08-10 Ulrich Drepper <drepper@redhat.com>
- * dwarf_getsrclines.c (dwarf_getsrclines): Update
- DW_LNS_set_epilogue_begin use to correct misspelling.
+ * dwarf_getsrclines.c (dwarf_getsrclines): Correct fallout of renaming
+ of DW_LNS_set_epilog_begin.
2005-08-09 Roland McGrath <roland@redhat.com>
diff --git a/src/ChangeLog b/src/ChangeLog
index 701c219..7aae3f9 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,7 +1,25 @@
-2005-08-10 Roland McGrath <roland@redhat.com>
+2005-07-28 Roland McGrath <roland@redhat.com>
- * readelf.c (print_debug_line_section): Update
- DW_LNS_set_epilogue_begin use to correct misspelling.
+ * addr2line.c (options, parse_opt): Don't handle -e here.
+ (executable): Variable removed.
+ (argp_children): New static variable.
+ (argp): Use it. Make const.
+ (main): Fill in argp_children from dwfl_standard_argp ().
+ Let libdwfl handle file selection, pass Dwfl handle to handle_address.
+ (print_dwarf_function): New function. Try to figure out inline chain.
+ (elf_getname): Function removed, libdwfl does it for us.
+ (handle_address): Take Dwfl handle instead of Elf, Dwarf handles.
+ Use dwfl_module_addrname instead of elf_getname.
+ Use dwfl_module_getsrc and dwfl_lineinfo instead of libdw calls.
+ * Makefile.am (INCLUDES): Add libdwfl directory to path.
+
+2005-08-10 Ulrich Drepper <drepper@redhat.com>
+
+ * strip.c (parse_opt): STATE parameter is now used.
+ Various little cleanups.
+
+ * readelf.c (print_debug_line_section): Correct fallout of renaming
+ of DW_LNS_set_epilog_begin.
2005-08-08 Roland McGrath <roland@redhat.com>
diff --git a/src/Makefile.am b/src/Makefile.am
index 73c82dc..3f1c756 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -24,7 +24,9 @@
$(if $($(*F)_no_Wunused),,-Wunused -Wextra) \
$(if $($(*F)_no_Wformat),,-Wformat=2)
-INCLUDES = -I$(srcdir) -I$(srcdir)/../libelf -I$(srcdir)/../libebl -I$(srcdir)/../lib -I$(srcdir)/../libdw -I..
+INCLUDES = -I$(srcdir) -I$(srcdir)/../libelf -I$(srcdir)/../libebl \
+ -I$(srcdir)/../libdw -I$(srcdir)/../libdwfl \
+ -I$(srcdir)/../lib -I..
YACC = @YACC@ -d
AM_YFLAGS = -pld
@@ -90,7 +92,7 @@
ld_LDFLAGS = -rdynamic
elflint_LDADD = $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl
findtextrel_LDADD = $(libdw) $(libelf) $(libmudflap)
-addr2line_LDADD = $(libdw) $(libelf) $(libmudflap)
+addr2line_LDADD = $(libdw) $(libmudflap)
elfcmp_LDADD = $(libebl) $(libelf) $(libmudflap) -ldl
objdump_LDADD = $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl
diff --git a/src/addr2line.c b/src/addr2line.c
index 60fcdf6..97eaed1 100644
--- a/src/addr2line.c
+++ b/src/addr2line.c
@@ -21,9 +21,9 @@
#include <errno.h>
#include <error.h>
#include <fcntl.h>
-#include <gelf.h>
#include <inttypes.h>
-#include <libdw.h>
+#include <libdwfl.h>
+#include <dwarf.h>
#include <libintl.h>
#include <locale.h>
#include <mcheck.h>
@@ -49,9 +49,6 @@
/* Definitions of arguments for argp functions. */
static const struct argp_option options[] =
{
- { NULL, 0, NULL, 0, N_("Input Selection:"), 0 },
- { "exe", 'e', "FILE", 0, N_("Find addresses in FILE"), 0 },
-
{ NULL, 0, NULL, 0, N_("Output Selection:"), 0 },
{ "basenames", 's', NULL, 0, N_("Show only base names of source files"), 0 },
{ "functions", 'f', NULL, 0, N_("Additional show function names"), 0 },
@@ -74,20 +71,19 @@
/* Prototype for option handler. */
static error_t parse_opt (int key, char *arg, struct argp_state *state);
+static struct argp_child argp_children[2]; /* [0] is set in main. */
+
/* Data structure to communicate with argp functions. */
-static struct argp argp =
+static const struct argp argp =
{
- options, parse_opt, args_doc, doc, NULL, NULL, NULL
+ options, parse_opt, args_doc, doc, argp_children, NULL, NULL
};
/* Handle ADDR. */
-static void handle_address (GElf_Addr addr, Elf *elf, Dwarf *dw);
+static void handle_address (GElf_Addr addr, Dwfl *dwfl);
-/* Name of the executable. */
-static const char *executable = "a.out";
-
/* True if only base names of files should be shown. */
static bool only_basenames;
@@ -116,55 +112,11 @@
/* Initialize the message catalog. */
(void) textdomain (PACKAGE);
- /* Parse and process arguments. */
- (void) argp_parse (&argp, argc, argv, 0, &remaining, NULL);
-
- /* Tell the library which version we are expecting. */
- elf_version (EV_CURRENT);
-
- /* Open the file. */
- int fd = open64 (executable, O_RDONLY);
- if (fd == -1)
- error (1, errno, gettext ("cannot open '%s'"), executable);
-
- /* Create the ELF descriptor. */
- Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
- if (elf == NULL)
- {
- close (fd);
- error (1, 0, gettext ("cannot create ELF descriptor: %s"),
- elf_errmsg (-1));
- }
-
- /* Try to get a DWARF descriptor. If it fails, we try to locate the
- debuginfo file. */
- Dwarf *dw = dwarf_begin_elf (elf, DWARF_C_READ, NULL);
- int fd2 = -1;
- Elf *elf2 = NULL;
- if (dw == NULL)
- {
- char *canon = canonicalize_file_name (executable);
- GElf_Ehdr ehdr_mem;
- GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
-
- if (canon != NULL && ehdr != NULL)
- {
- const char *debuginfo_dir;
- if (ehdr->e_ident[EI_CLASS] == ELFCLASS32
- || ehdr->e_machine == EM_IA_64 || ehdr->e_machine == EM_ALPHA)
- debuginfo_dir = "/usr/lib/debug";
- else
- debuginfo_dir = "/usr/lib64/debug";
-
- char *difname = alloca (strlen (debuginfo_dir) + strlen (canon) + 1);
- strcpy (stpcpy (difname, debuginfo_dir), canon);
- fd2 = open64 (difname, O_RDONLY);
- if (fd2 != -1)
- dw = dwarf_begin_elf (elf2, DWARF_C_READ, NULL);
- }
-
- free (canon);
- }
+ /* Parse and process arguments. This includes opening the modules. */
+ argp_children[0].argp = dwfl_standard_argp ();
+ Dwfl *dwfl = NULL;
+ (void) argp_parse (&argp, argc, argv, 0, &remaining, &dwfl);
+ assert (dwfl != NULL);
/* Now handle the addresses. In case none are given on the command
line, read from stdin. */
@@ -183,7 +135,7 @@
char *endp;
uintmax_t addr = strtoumax (buf, &endp, 0);
if (endp != buf)
- handle_address (addr, elf2 ?: elf, dw);
+ handle_address (addr, dwfl);
else
result = 1;
}
@@ -197,7 +149,7 @@
char *endp;
uintmax_t addr = strtoumax (argv[remaining], &endp, 0);
if (endp != argv[remaining])
- handle_address (addr, elf2 ?: elf, dw);
+ handle_address (addr, dwfl);
else
result = 1;
}
@@ -224,21 +176,21 @@
/* Handle program arguments. */
static error_t
-parse_opt (int key, char *arg,
- struct argp_state *state __attribute__ ((unused)))
+parse_opt (int key, char *arg __attribute__ ((unused)),
+ struct argp_state *state)
{
switch (key)
{
+ case ARGP_KEY_INIT:
+ state->child_inputs[0] = state->input;
+ break;
+
case 'b':
case 'C':
case OPT_DEMANGLER:
/* Ignored for compatibility. */
break;
- case 'e':
- executable = arg;
- break;
-
case 's':
only_basenames = true;
break;
@@ -254,118 +206,108 @@
}
-struct func_arg
-{
- GElf_Addr addr;
- const char *name;
-};
-
-
-static int
-match_func (Dwarf_Func *func, void *arg)
-{
- struct func_arg *func_arg = (struct func_arg *) arg;
- Dwarf_Addr addr;
-
- if (dwarf_func_lowpc (func, &addr) == 0 && addr <= func_arg->addr
- && dwarf_func_highpc (func, &addr) == 0 && func_arg->addr < addr)
- {
- func_arg->name = dwarf_func_name (func);
- return DWARF_CB_ABORT;
- }
-
- return DWARF_CB_OK;
-}
-
-
static const char *
-elf_getname (GElf_Addr addr, Elf *elf)
+dwarf_diename_integrate (Dwarf_Die *die)
{
- /* The DWARF information is not available. Use the ELF
- symbol table. */
- Elf_Scn *scn = NULL;
- Elf_Scn *dynscn = NULL;
-
- while ((scn = elf_nextscn (elf, scn)) != NULL)
- {
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
- if (shdr != NULL)
- {
- if (shdr->sh_type == SHT_SYMTAB)
- break;
- if (shdr->sh_type == SHT_DYNSYM)
- dynscn = scn;
- }
- }
- if (scn == NULL)
- scn = dynscn;
-
- if (scn != NULL)
- {
- /* Look through the symbol table for a matching symbol. */
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
- assert (shdr != NULL);
-
- Elf_Data *data = elf_getdata (scn, NULL);
- if (data != NULL)
- for (int cnt = 1; cnt < (int) (shdr->sh_size / shdr->sh_entsize);
- ++cnt)
- {
- GElf_Sym sym_mem;
- GElf_Sym *sym = gelf_getsym (data, cnt, &sym_mem);
- if (sym != NULL
- && sym->st_value <= addr
- && addr < sym->st_value + sym->st_size)
- return elf_strptr (elf, shdr->sh_link, sym->st_name);
- }
- }
-
- return NULL;
+ Dwarf_Attribute attr_mem;
+ return dwarf_formstring (dwarf_attr_integrate (die, DW_AT_name, &attr_mem));
}
+static bool
+print_dwarf_function (Dwfl_Module *mod, Dwarf_Addr addr)
+{
+ Dwarf_Addr bias = 0;
+ Dwarf_Die *cudie = dwfl_module_addrdie (mod, addr, &bias);
+
+ Dwarf_Die *scopes;
+ int nscopes = dwarf_getscopes (cudie, addr - bias, &scopes);
+ if (nscopes <= 0)
+ return false;
+
+ for (int i = 0; i < nscopes; ++i)
+ switch (dwarf_tag (&scopes[i]))
+ {
+ case DW_TAG_subprogram:
+ {
+ const char *name = dwarf_diename_integrate (&scopes[i]);
+ if (name == NULL)
+ return false;
+ puts (name);
+ return true;
+ }
+
+ case DW_TAG_inlined_subroutine:
+ {
+ const char *name = dwarf_diename_integrate (&scopes[i]);
+ if (name == NULL)
+ return false;
+ printf ("%s inlined", name);
+
+ Dwarf_Files *files;
+ if (dwarf_getsrcfiles (cudie, &files, NULL) == 0)
+ {
+ Dwarf_Attribute attr_mem;
+ Dwarf_Word val;
+ if (dwarf_formudata (dwarf_attr (&scopes[i],
+ DW_AT_call_file,
+ &attr_mem), &val) == 0)
+ {
+ const char *file = dwarf_filesrc (files, val, NULL, NULL);
+ int lineno = 0, colno = 0;
+ if (dwarf_formudata (dwarf_attr (&scopes[i],
+ DW_AT_call_line,
+ &attr_mem), &val) == 0)
+ lineno = val;
+ if (dwarf_formudata (dwarf_attr (&scopes[i],
+ DW_AT_call_column,
+ &attr_mem), &val) == 0)
+ colno = val;
+ if (lineno == 0)
+ {
+ if (file != NULL)
+ printf (" from %s", file);
+ }
+ else if (colno == 0)
+ printf (" at %s:%u", file, lineno);
+ else
+ printf (" at %s:%u:%u", file, lineno, colno);
+ }
+ }
+ printf (" in ");
+ continue;
+ }
+ }
+
+ return false;
+}
static void
-handle_address (GElf_Addr addr, Elf *elf, Dwarf *dw)
+handle_address (GElf_Addr addr, Dwfl *dwfl)
{
- Dwarf_Die die_mem;
- Dwarf_Die *die = dwarf_addrdie (dw, addr, &die_mem);
+ Dwfl_Module *mod = dwfl_addrmodule (dwfl, addr);
if (show_functions)
{
/* First determine the function name. Use the DWARF information if
possible. */
- struct func_arg arg;
- arg.addr = addr;
- arg.name = NULL;
-
- if (dwarf_getfuncs (die, match_func, &arg, 0) <= 0)
- arg.name = elf_getname (addr, elf);
-
- puts (arg.name ?: "??");
+ if (! print_dwarf_function (mod, addr))
+ puts (dwfl_module_addrname (mod, addr) ?: "??");
}
+ Dwfl_Line *line = dwfl_module_getsrc (mod, addr);
- Dwarf_Line *line;
const char *src;
- if ((line = dwarf_getsrc_die (die, addr)) != NULL
- && (src = dwarf_linesrc (line, NULL, NULL)) != NULL)
+ int lineno, linecol;
+ if (line != NULL && (src = dwfl_lineinfo (line, &addr, &lineno, &linecol,
+ NULL, NULL)) != NULL)
{
if (only_basenames)
src = basename (src);
- int lineno;
- if (dwarf_lineno (line, &lineno) != -1)
- {
- int linecol;
- if (dwarf_linecol (line, &linecol) != -1 && linecol != 0)
- printf ("%s:%d:%d\n", src, lineno, linecol);
- else
- printf ("%s:%d\n", src, lineno);
- }
+ if (linecol != 0)
+ printf ("%s:%d:%d\n", src, lineno, linecol);
else
- printf ("%s:0\n", src);
+ printf ("%s:%d\n", src, lineno);
}
else
puts ("??:0");
diff --git a/src/strip.c b/src/strip.c
index 37f9eb0..42e13b4 100644
--- a/src/strip.c
+++ b/src/strip.c
@@ -199,8 +199,7 @@
/* Handle program arguments. */
static error_t
-parse_opt (int key, char *arg,
- struct argp_state *state __attribute__ ((unused)))
+parse_opt (int key, char *arg, struct argp_state *state)
{
switch (key)
{
@@ -369,14 +368,10 @@
size_t fname_len = strlen (fname) + 1;
char *fullname = alloca (prefix_len + 1 + fname_len);
char *cp = fullname;
- Elf *newelf;
Elf *debugelf = NULL;
char *tmp_debug_fname = NULL;
int result = 0;
- GElf_Ehdr ehdr_mem;
- GElf_Ehdr *ehdr;
size_t shstrndx;
- size_t shnum;
struct shdr_info
{
Elf_Scn *scn;
@@ -462,7 +457,8 @@
}
/* Get the information from the old file. */
- ehdr = gelf_getehdr (elf, &ehdr_mem);
+ GElf_Ehdr ehdr_mem;
+ GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
if (ehdr == NULL)
INTERNAL_ERROR (fname);
@@ -474,6 +470,7 @@
/* We now create a new ELF descriptor for the same file. We
construct it almost exactly in the same way with some information
dropped. */
+ Elf *newelf;
if (output_fname != NULL)
newelf = elf_begin (fd, ELF_C_WRITE_MMAP, NULL);
else
@@ -493,9 +490,7 @@
for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
{
GElf_Phdr phdr_mem;
- GElf_Phdr *phdr;
-
- phdr = gelf_getphdr (elf, cnt, &phdr_mem);
+ GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem);
if (phdr == NULL
|| unlikely (gelf_update_phdr (newelf, cnt, phdr) == 0))
INTERNAL_ERROR (fname);
@@ -519,9 +514,7 @@
for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
{
GElf_Phdr phdr_mem;
- GElf_Phdr *phdr;
-
- phdr = gelf_getphdr (elf, cnt, &phdr_mem);
+ GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem);
if (phdr == NULL
|| unlikely (gelf_update_phdr (debugelf, cnt, phdr) == 0))
INTERNAL_ERROR (fname);
@@ -529,6 +522,7 @@
}
/* Number of sections. */
+ size_t shnum;
if (unlikely (elf_getshnum (elf, &shnum) < 0))
{
error (0, 0, gettext ("cannot determine number of sections: %s"),
@@ -596,9 +590,6 @@
}
else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GROUP))
{
- Elf32_Word *grpref;
- size_t inner;
-
/* Cross-reference the sections contained in the section
group. */
shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
@@ -606,7 +597,8 @@
INTERNAL_ERROR (fname);
/* XXX Fix for unaligned access. */
- grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
+ Elf32_Word *grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
+ size_t inner;
for (inner = 1;
inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
++inner)
@@ -665,16 +657,14 @@
idx = shdr_info[cnt].group_idx;
while (idx != 0)
{
- /* If the references section group is a normal section
- group and has one element remaining, or if it is an
- empty COMDAT section group it is removed. */
- bool is_comdat;
-
/* The section group data is already loaded. */
assert (shdr_info[idx].data != NULL);
- is_comdat = (((Elf32_Word *) shdr_info[idx].data->d_buf)[0]
- & GRP_COMDAT) != 0;
+ /* If the references section group is a normal section
+ group and has one element remaining, or if it is an
+ empty COMDAT section group it is removed. */
+ bool is_comdat = (((Elf32_Word *) shdr_info[idx].data->d_buf)[0]
+ & GRP_COMDAT) != 0;
--shdr_info[idx].group_cnt;
if ((!is_comdat && shdr_info[idx].group_cnt == 1)
@@ -720,10 +710,6 @@
if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
|| shdr_info[cnt].shdr.sh_type == SHT_SYMTAB)
{
- Elf_Data *symdata;
- Elf_Data *xndxdata;
- size_t elsize;
-
/* Make sure the data is loaded. */
if (shdr_info[cnt].data == NULL)
{
@@ -732,7 +718,7 @@
if (shdr_info[cnt].data == NULL)
INTERNAL_ERROR (fname);
}
- symdata = shdr_info[cnt].data;
+ Elf_Data *symdata = shdr_info[cnt].data;
/* If there is an extended section index table load it
as well. */
@@ -747,11 +733,13 @@
if (shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
INTERNAL_ERROR (fname);
}
- xndxdata = shdr_info[shdr_info[cnt].symtab_idx].data;
+ Elf_Data *xndxdata
+ = shdr_info[shdr_info[cnt].symtab_idx].data;
/* Go through all symbols and make sure the section they
reference is not removed. */
- elsize = gelf_fsize (elf, ELF_T_SYM, 1, ehdr->e_version);
+ size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
+ ehdr->e_version);
for (size_t inner = 0;
inner < shdr_info[cnt].data->d_size / elsize;
@@ -759,15 +747,13 @@
{
GElf_Sym sym_mem;
Elf32_Word xndx;
- GElf_Sym *sym;
- size_t scnidx;
-
- sym = gelf_getsymshndx (symdata, xndxdata, inner,
- &sym_mem, &xndx);
+ GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
+ inner, &sym_mem,
+ &xndx);
if (sym == NULL)
INTERNAL_ERROR (fname);
- scnidx = sym->st_shndx;
+ size_t scnidx = sym->st_shndx;
if (scnidx == SHN_UNDEF || scnidx >= shnum
|| (scnidx >= SHN_LORESERVE
&& scnidx <= SHN_HIRESERVE
@@ -830,20 +816,17 @@
{
for (cnt = 1; cnt < shnum; ++cnt)
{
- Elf_Data *debugdata;
- GElf_Shdr debugshdr;
- bool discard_section;
-
scn = elf_newscn (debugelf);
if (scn == NULL)
error (EXIT_FAILURE, 0,
gettext ("while generating output file: %s"),
elf_errmsg (-1));
- discard_section = shdr_info[cnt].idx > 0 && cnt != ehdr->e_shstrndx;
+ bool discard_section = (shdr_info[cnt].idx > 0
+ && cnt != ehdr->e_shstrndx);
/* Set the section header in the new file. */
- debugshdr = shdr_info[cnt].shdr;
+ GElf_Shdr debugshdr = shdr_info[cnt].shdr;
if (discard_section)
debugshdr.sh_type = SHT_NOBITS;
@@ -860,7 +843,7 @@
}
/* Set the data. This is done by copying from the old file. */
- debugdata = elf_newdata (scn);
+ Elf_Data *debugdata = elf_newdata (scn);
if (debugdata == NULL)
INTERNAL_ERROR (fname);
@@ -931,9 +914,6 @@
/* Create the reference to the file with the debug info. */
if (debug_fname != NULL)
{
- char *debug_basename;
- off_t crc_offset;
-
/* Add the section header string table section name. */
shdr_info[cnt].se = ebl_strtabadd (shst, ".gnu_debuglink", 15);
shdr_info[cnt].idx = idx++;
@@ -964,8 +944,8 @@
error (EXIT_FAILURE, 0, gettext ("cannot allocate section data: %s"),
elf_errmsg (-1));
- debug_basename = basename (debug_fname_embed ?: debug_fname);
- crc_offset = strlen (debug_basename) + 1;
+ char *debug_basename = basename (debug_fname_embed ?: debug_fname);
+ off_t crc_offset = strlen (debug_basename) + 1;
/* Align to 4 byte boundary */
crc_offset = ((crc_offset - 1) & ~3) + 4;