summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoland McGrath <[email protected]>2009-07-08 14:07:20 -0700
committerRoland McGrath <[email protected]>2009-07-08 14:07:20 -0700
commitbdb2e5030de6a36bc696aa031619cf9509015a83 (patch)
treef625265b990a9b2bfeca99dee61f3638d2c3fee7
parentae3028b6ddc4143d592f94d2fb1a86e81411e884 (diff)
parent714f66a60f55dada62ac808cd5cffeddd1f4ad39 (diff)
Merge commit 'origin/master' into dwarf
Conflicts: libdw/ChangeLog src/ChangeLog
-rw-r--r--NEWS2
-rw-r--r--libdw/ChangeLog6
-rw-r--r--libdw/dwarf_getlocation.c60
-rw-r--r--libebl/ChangeLog8
-rw-r--r--libebl/eblsymbolbindingname.c8
-rw-r--r--libebl/eblsymboltypename.c6
-rw-r--r--libelf/ChangeLog4
-rw-r--r--libelf/elf.h1
-rw-r--r--src/ChangeLog11
-rw-r--r--src/readelf.c93
10 files changed, 162 insertions, 37 deletions
diff --git a/NEWS b/NEWS
index 2933d35a..1b73645f 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,8 @@ libelf: Add elf_getshdrnum alias for elf_getshnum and elf_getshdrstrndx alias
for elf_getshstrndx and deprecate original names. Sun screwed up
their implementation and asked for a solution.
+libebl: Add support for STB_GNU_UNIQUE.
+
readelf: Add -N option, speeds up DWARF printing without address->name lookups.
Version 0.141:
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index a13136c7..deb3817b 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -141,6 +141,12 @@
* c++/dwarf: New file.
* Makefile.am (pkginclude_HEADERS): Add it.
+2009-07-08 Roland McGrath <[email protected]>
+
+ * dwarf_getlocation.c (check_constant_offset): New function.
+ (dwarf_getlocation, dwarf_getlocation_addr): Call it to
+ handle DW_AT_data_member_location of data[48] as constant offset.
+
2009-06-18 Roland McGrath <[email protected]>
* libdwP.h (__libdw_read_address_inc): Constify.
diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c
index 504db376..62106ce3 100644
--- a/libdw/dwarf_getlocation.c
+++ b/libdw/dwarf_getlocation.c
@@ -55,6 +55,7 @@
#include <dwarf.h>
#include <search.h>
#include <stdlib.h>
+#include <assert.h>
#include <libdwP.h>
@@ -111,6 +112,57 @@ loc_compare (const void *p1, const void *p2)
return 0;
}
+/* DW_AT_data_member_location can be a constant as well as a loclistptr.
+ Only data[48] indicate a loclistptr. */
+static int
+check_constant_offset (Dwarf_Attribute *attr,
+ Dwarf_Op **llbuf, size_t *listlen)
+{
+ if (attr->code != DW_AT_data_member_location
+ || attr->form == DW_FORM_data4
+ || attr->form == DW_FORM_data8)
+ return 1;
+
+ /* Check whether we already cached this location. */
+ struct loc_s fake = { .addr = attr->valp };
+ struct loc_s **found = tfind (&fake, &attr->cu->locs, loc_compare);
+
+ if (found == NULL)
+ {
+ Dwarf_Word offset;
+ if (INTUSE(dwarf_formudata) (attr, &offset) != 0)
+ return -1;
+
+ Dwarf_Op *result = libdw_alloc (attr->cu->dbg,
+ Dwarf_Op, sizeof (Dwarf_Op), 1);
+
+ result->atom = DW_OP_plus_uconst;
+ result->number = offset;
+ result->number2 = 0;
+ result->offset = 0;
+
+ /* Insert a record in the search tree so we can find it again later. */
+ struct loc_s *newp = libdw_alloc (attr->cu->dbg,
+ struct loc_s, sizeof (struct loc_s),
+ 1);
+ newp->addr = attr->valp;
+ newp->loc = result;
+ newp->nloc = 1;
+
+ found = tsearch (newp, &attr->cu->locs, loc_compare);
+ }
+
+ assert ((*found)->nloc == 1);
+
+ if (llbuf != NULL)
+ {
+ *llbuf = (*found)->loc;
+ *listlen = 1;
+ }
+
+ return 0;
+}
+
static int
getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block,
Dwarf_Op **llbuf, size_t *listlen, int sec_index)
@@ -333,6 +385,10 @@ dwarf_getlocation (attr, llbuf, listlen)
Dwarf_Op **llbuf;
size_t *listlen;
{
+ int result = check_constant_offset (attr, llbuf, listlen);
+ if (result != 1)
+ return result;
+
if (! attr_ok (attr))
return -1;
@@ -378,6 +434,10 @@ dwarf_getlocation_addr (attr, address, llbufs, listlens, maxlocs)
return -1;
}
+ int result = check_constant_offset (attr, &llbufs[0], &listlens[0]);
+ if (result != 1)
+ return result ?: 1;
+
unsigned char *endp;
unsigned char *readp = __libdw_formptr (attr, IDX_debug_loc,
DWARF_E_NO_LOCLIST, &endp, NULL);
diff --git a/libebl/ChangeLog b/libebl/ChangeLog
index 83319c70..12e94f42 100644
--- a/libebl/ChangeLog
+++ b/libebl/ChangeLog
@@ -1,3 +1,11 @@
+2009-07-08 Ulrich Drepper <[email protected]>
+
+ * eblsymbolbindingname.c (ebl_symbol_binding_name): Handle
+ STB_GNU_UNIQUE.
+
+ * eblsymboltypename.c (ebl_symbol_type_name): Only handle STT_GNU_IFUNC
+ if the binary is marked as being for Linux.
+
2009-04-01 Roland McGrath <[email protected]>
* eblsymboltypename.c (ebl_symbol_type_name): Add STT_GNU_IFUNC.
diff --git a/libebl/eblsymbolbindingname.c b/libebl/eblsymbolbindingname.c
index c4412c9e..334a9c3e 100644
--- a/libebl/eblsymbolbindingname.c
+++ b/libebl/eblsymbolbindingname.c
@@ -1,5 +1,5 @@
/* Return symbol binding name.
- Copyright (C) 2001, 2002 Red Hat, Inc.
+ Copyright (C) 2001, 2002, 2009 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <[email protected]>, 2001.
@@ -78,8 +78,14 @@ ebl_symbol_binding_name (ebl, binding, buf, len)
res = stb_names[binding];
else
{
+ char *ident;
+
if (binding >= STB_LOPROC && binding <= STB_HIPROC)
snprintf (buf, len, "LOPROC+%d", binding - STB_LOPROC);
+ else if (binding == STB_GNU_UNIQUE
+ && (ident = elf_getident (ebl->elf, NULL)) != NULL
+ && ident[EI_OSABI] == ELFOSABI_LINUX)
+ return "GNU_UNIQUE";
else if (binding >= STB_LOOS && binding <= STB_HIOS)
snprintf (buf, len, "LOOS+%d", binding - STB_LOOS);
else
diff --git a/libebl/eblsymboltypename.c b/libebl/eblsymboltypename.c
index 6aae13ee..f2ac6222 100644
--- a/libebl/eblsymboltypename.c
+++ b/libebl/eblsymboltypename.c
@@ -84,9 +84,13 @@ ebl_symbol_type_name (ebl, symbol, buf, len)
res = stt_names[symbol];
else
{
+ char *ident;
+
if (symbol >= STT_LOPROC && symbol <= STT_HIPROC)
snprintf (buf, len, "LOPROC+%d", symbol - STT_LOPROC);
- else if (symbol == STT_GNU_IFUNC)
+ else if (symbol == STT_GNU_IFUNC
+ && (ident = elf_getident (ebl->elf, NULL)) != NULL
+ && ident[EI_OSABI] == ELFOSABI_LINUX)
return "GNU_IFUNC";
else if (symbol >= STT_LOOS && symbol <= STT_HIOS)
snprintf (buf, len, "LOOS+%d", symbol - STT_LOOS);
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index a0163db1..5d8ac8ae 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,7 @@
+2009-07-08 Ulrich Drepper <[email protected]>
+
+ * elf.h: Update from glibc.
+
2009-06-13 Ulrich Drepper <[email protected]>
* Makefile.am (libelf_a_SOURCES): Replace elf_getshnum.c and
diff --git a/libelf/elf.h b/libelf/elf.h
index 8fdf74b0..7efdedef 100644
--- a/libelf/elf.h
+++ b/libelf/elf.h
@@ -444,6 +444,7 @@ typedef struct
#define STB_WEAK 2 /* Weak symbol */
#define STB_NUM 3 /* Number of defined types. */
#define STB_LOOS 10 /* Start of OS-specific */
+#define STB_GNU_UNIQUE 10 /* Unique symbol. */
#define STB_HIOS 12 /* End of OS-specific */
#define STB_LOPROC 13 /* Start of processor-specific */
#define STB_HIPROC 15 /* End of processor-specific */
diff --git a/src/ChangeLog b/src/ChangeLog
index 2ef1e42c..58198a8b 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -203,6 +203,17 @@
* dwarflint.c: Checking for zero padding and unreferenced bytes.
CU size and padding at the end of CU are now checked.
+2009-07-08 Mark Wielaard <[email protected]>
+
+ * readelf.c (attr_callback): Handle DW_Form constants for
+ DW_AT_data_member_location.
+
+2009-07-06 Roland McGrath <[email protected]>
+
+ * readelf.c (register_info): New function. Handle unknown register #s.
+ (print_cfa_program): Use it.
+ (handle_core_register, handle_core_registers): Likewise.
+
2009-06-28 Roland McGrath <[email protected]>
* readelf.c (print_address_names): New static variable.
diff --git a/src/readelf.c b/src/readelf.c
index e925565b..28c73feb 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -3732,6 +3732,35 @@ print_debug_ranges_section (Dwfl_Module *dwflmod,
}
}
+#define REGNAMESZ 16
+static const char *
+register_info (Ebl *ebl, unsigned int regno, const Ebl_Register_Location *loc,
+ char name[REGNAMESZ], int *bits, int *type)
+{
+ const char *set;
+ const char *pfx;
+ int ignore;
+ ssize_t n = ebl_register_info (ebl, regno, name, REGNAMESZ, &pfx, &set,
+ bits ?: &ignore, type ?: &ignore);
+ if (n <= 0)
+ {
+ snprintf (name, sizeof name, "reg%u", loc->regno);
+ if (bits != NULL)
+ *bits = loc->bits;
+ if (type != NULL)
+ *type = DW_ATE_unsigned;
+ set = "??? unrecognized";
+ }
+ else
+ {
+ if (bits != NULL && *bits <= 0)
+ *bits = loc->bits;
+ if (type != NULL && *type == DW_ATE_void)
+ *type = DW_ATE_unsigned;
+
+ }
+ return set;
+}
static void
print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
@@ -3739,14 +3768,11 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
int data_align, unsigned int ptr_size, Dwfl_Module *dwflmod,
Ebl *ebl, Dwarf *dbg)
{
- char regnamebuf[16];
+ char regnamebuf[REGNAMESZ];
const char *regname (unsigned int regno)
{
- const char *str;
- int i;
- return (ebl_register_info (ebl, regno, regnamebuf, sizeof (regnamebuf),
- &str, &str, &i, &i) < 0
- ? "???" : regnamebuf);
+ register_info (ebl, regno, NULL, regnamebuf, NULL, NULL);
+ return regnamebuf;
}
puts ("\n Program:");
@@ -4526,9 +4552,20 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
const char *valuestr = NULL;
switch (attr)
{
+ /* This case can take either a constant or a loclistptr. */
+ case DW_AT_data_member_location:
+ if (form != DW_FORM_data4 && form != DW_FORM_data8)
+ {
+ printf (" %*s%-20s %" PRIxMAX "\n",
+ (int) (level * 2), "", dwarf_attr_string (attr),
+ (uintmax_t) num);
+ return DWARF_CB_OK;
+ }
+ /* else fallthrough */
+
+ /* These cases always take a loclistptr and no constant. */
case DW_AT_location:
case DW_AT_data_location:
- case DW_AT_data_member_location:
case DW_AT_vtable_elem_location:
case DW_AT_string_length:
case DW_AT_use_location:
@@ -6284,17 +6321,10 @@ handle_core_register (Ebl *ebl, Elf *core, int maxregname,
for (int reg = regloc->regno; reg < regloc->regno + regloc->count; ++reg)
{
- const char *pfx;
- const char *set;
- char name[16];
+ char name[REGNAMESZ];
int bits;
int type;
- ssize_t n = ebl_register_info (ebl, reg, name, sizeof name,
- &pfx, &set, &bits, &type);
- if (n <= 0)
- error (EXIT_FAILURE, 0,
- gettext ("unable to handle register number %d"),
- regloc->regno);
+ register_info (ebl, reg, regloc, name, &bits, &type);
#define TYPES \
BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8, 4); \
@@ -6382,10 +6412,10 @@ struct register_info
{
const Ebl_Register_Location *regloc;
const char *set;
- char name[16];
- Dwarf_Half regno;
- uint8_t bits;
- uint8_t type;
+ char name[REGNAMESZ];
+ int regno;
+ int bits;
+ int type;
};
static int
@@ -6439,8 +6469,12 @@ handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL);
if (maxnreg <= 0)
- error (EXIT_FAILURE, 0,
- gettext ("cannot get register info: %s"), elf_errmsg (-1));
+ {
+ for (size_t i = 0; i < nregloc; ++i)
+ if (maxnreg < reglocs[i].regno + reglocs[i].count)
+ maxnreg = reglocs[i].regno + reglocs[i].count;
+ assert (maxnreg > 0);
+ }
struct register_info regs[maxnreg];
memset (regs, 0, sizeof regs);
@@ -6456,20 +6490,9 @@ handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
if (reg > maxreg)
maxreg = reg;
struct register_info *info = &regs[reg];
-
- const char *pfx;
- int bits;
- int type;
- ssize_t n = ebl_register_info (ebl, reg, info->name, sizeof info->name,
- &pfx, &info->set, &bits, &type);
- if (n <= 0)
- error (EXIT_FAILURE, 0,
- gettext ("cannot register info: %s"), elf_errmsg (-1));
-
info->regloc = &reglocs[i];
- info->regno = reg;
- info->bits = bits;
- info->type = type;
+ info->set = register_info (ebl, reg, &reglocs[i],
+ info->name, &info->bits, &info->type);
}
qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers);