diff options
| -rw-r--r-- | NEWS | 2 | ||||
| -rw-r--r-- | libdw/ChangeLog | 6 | ||||
| -rw-r--r-- | libdw/dwarf_getlocation.c | 60 | ||||
| -rw-r--r-- | libebl/ChangeLog | 8 | ||||
| -rw-r--r-- | libebl/eblsymbolbindingname.c | 8 | ||||
| -rw-r--r-- | libebl/eblsymboltypename.c | 6 | ||||
| -rw-r--r-- | libelf/ChangeLog | 4 | ||||
| -rw-r--r-- | libelf/elf.h | 1 | ||||
| -rw-r--r-- | src/ChangeLog | 11 | ||||
| -rw-r--r-- | src/readelf.c | 93 |
10 files changed, 162 insertions, 37 deletions
@@ -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 = ®s[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 = ®locs[i]; - info->regno = reg; - info->bits = bits; - info->type = type; + info->set = register_info (ebl, reg, ®locs[i], + info->name, &info->bits, &info->type); } qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers); |
