diff options
author | Roland McGrath <roland@redhat.com> | 2010-06-15 20:40:59 -0700 |
---|---|---|
committer | Roland McGrath <roland@redhat.com> | 2010-06-15 20:44:43 -0700 |
commit | a160261fecbcbe31293cd60f14c0a6dcdb85f5ac (patch) | |
tree | 2c71a7ba7dfaf2817dccebfdeb14f0ced948d386 | |
parent | a92f1a4edebaaed1878dd5135b67afeb52fc7d0a (diff) |
unfinishedupstream/roland/addrsym_tls
-rw-r--r-- | libdw/libdw.map | 1 | ||||
-rw-r--r-- | libdwfl/dwfl_module_addrsym.c | 46 | ||||
-rw-r--r-- | libdwfl/dwfl_module_getsym.c | 3 | ||||
-rw-r--r-- | libdwfl/libdwfl.h | 5 | ||||
-rw-r--r-- | src/readelf.c | 31 |
5 files changed, 64 insertions, 22 deletions
diff --git a/libdw/libdw.map b/libdw/libdw.map index 1a9afb13..0e1513f6 100644 --- a/libdw/libdw.map +++ b/libdw/libdw.map @@ -226,6 +226,7 @@ ELFUTILS_0.143 { dwarf_decl_line; dwarf_srclang; + dwfl_module_addrsym_tls; } ELFUTILS_0.142; ELFUTILS_0.144 { diff --git a/libdwfl/dwfl_module_addrsym.c b/libdwfl/dwfl_module_addrsym.c index 72280d11..46621182 100644 --- a/libdwfl/dwfl_module_addrsym.c +++ b/libdwfl/dwfl_module_addrsym.c @@ -1,5 +1,5 @@ /* Find debugging and symbol information for a module in libdwfl. - Copyright (C) 2005, 2006, 2007, 2008 Red Hat, Inc. + Copyright (C) 2005-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 @@ -49,12 +49,31 @@ #include "libdwflP.h" +static inline bool +want_symbol (GElf_Sym *sym, bool tls, GElf_Addr addr) +{ + if (tls) + { + if (GELF_ST_TYPE (sym->st_info) != STT_TLS) + return false; + + // XXX ... + return sym->st_value <= addr; + } + + return (sym->st_value <= addr + && GELF_ST_TYPE (sym->st_info) != STT_SECTION + && GELF_ST_TYPE (sym->st_info) != STT_FILE + && GELF_ST_TYPE (sym->st_info) != STT_TLS); +} + /* Returns the name of the symbol "closest" to ADDR. Never returns symbols at addresses above ADDR. */ -const char * -dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr, - GElf_Sym *closest_sym, GElf_Word *shndxp) +static const char * +find_symbol (Dwfl_Module *mod, GElf_Addr addr, + GElf_Sym *closest_sym, GElf_Word *shndxp, + bool tls) { int syments = INTUSE(dwfl_module_getsymtab) (mod); if (syments < 0) @@ -112,10 +131,7 @@ dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr, const char *name = INTUSE(dwfl_module_getsym) (mod, i, &sym, &shndx); if (name != NULL && name[0] != '\0' && sym.st_shndx != SHN_UNDEF - && sym.st_value <= addr - && GELF_ST_TYPE (sym.st_info) != STT_SECTION - && GELF_ST_TYPE (sym.st_info) != STT_FILE - && GELF_ST_TYPE (sym.st_info) != STT_TLS) + && want_symbol (&sym, tls, addr)) { /* Even if we don't choose this symbol, its existence excludes any sizeless symbol (assembly label) that is below its upper @@ -180,4 +196,18 @@ dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr, *shndxp = closest_shndx; return closest_name; } + +const char * +dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr, + GElf_Sym *closest_sym, GElf_Word *shndxp) +{ + return find_symbol (mod, addr, closest_sym, shndxp, false); +} INTDEF (dwfl_module_addrsym) + +const char * +dwfl_module_addrsym_tls (Dwfl_Module *mod, GElf_Addr addr, + GElf_Sym *closest_sym, GElf_Word *shndxp) +{ + return find_symbol (mod, addr, closest_sym, shndxp, true); +} diff --git a/libdwfl/dwfl_module_getsym.c b/libdwfl/dwfl_module_getsym.c index f78e6ec0..701c35ad 100644 --- a/libdwfl/dwfl_module_getsym.c +++ b/libdwfl/dwfl_module_getsym.c @@ -98,6 +98,9 @@ dwfl_module_getsym (Dwfl_Module *mod, int ndx, break; default: + if (GELF_ST_TYPE (sym->st_info) == STT_TLS) /* XXX */ + break; + if (mod->e_type == ET_REL) { /* In an ET_REL file, the symbol table values are relative diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h index 51e98187..4256d243 100644 --- a/libdwfl/libdwfl.h +++ b/libdwfl/libdwfl.h @@ -450,6 +450,11 @@ extern const char *dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr address, GElf_Sym *sym, GElf_Word *shndxp) __nonnull_attribute__ (3); +/* Like dwfl_module_addrsym, but ADDRESS is relative to MOD's TLS segment. */ +extern const char *dwfl_module_addrsym_tls (Dwfl_Module *mod, GElf_Addr address, + GElf_Sym *sym, GElf_Word *shndxp) + __nonnull_attribute__ (3); + /* Find the ELF section that *ADDRESS lies inside and return it. On success, adjusts *ADDRESS to be relative to the section, and sets *BIAS to the difference between addresses used in diff --git a/src/readelf.c b/src/readelf.c index 1d8da268..69ebea6c 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -3091,12 +3091,14 @@ print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr) static char * format_dwarf_addr (Dwfl_Module *dwflmod, - int address_size, Dwarf_Addr address) + int address_size, Dwarf_Addr address, bool tls) { /* See if there is a name we can give for this address. */ GElf_Sym sym; const char *name = print_address_names - ? dwfl_module_addrsym (dwflmod, address, &sym, NULL) : NULL; + ? ((tls ? dwfl_module_addrsym_tls : dwfl_module_addrsym) + (dwflmod, address, &sym, NULL)) + : NULL; if (name != NULL) sym.st_value = address - sym.st_value; @@ -4373,7 +4375,7 @@ print_debug_ranges_section (Dwfl_Module *dwflmod, if (begin == (Dwarf_Addr) -1l) /* Base address entry. */ { - char *b = format_dwarf_addr (dwflmod, address_size, end); + char *b = format_dwarf_addr (dwflmod, address_size, end, false); printf (gettext (" [%6tx] base address %s\n"), offset, b); free (b); } @@ -4381,8 +4383,8 @@ print_debug_ranges_section (Dwfl_Module *dwflmod, first = true; else { - char *b = format_dwarf_addr (dwflmod, address_size, begin); - char *e = format_dwarf_addr (dwflmod, address_size, end); + char *b = format_dwarf_addr (dwflmod, address_size, begin, false); + char *e = format_dwarf_addr (dwflmod, address_size, end, false); /* We have an address range entry. */ if (first) /* First address range entry in a list. */ printf (gettext (" [%6tx] %s..%s\n"), offset, b, e); @@ -5154,7 +5156,8 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) dwarf_errmsg (-1)); return DWARF_CB_ABORT; } - char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr); + char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, + addr, false); printf (" %*s%-20s (%s) %s\n", (int) (level * 2), "", dwarf_attr_string (attr), dwarf_form_string (form), a); @@ -5721,7 +5724,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, line += line_increment; address += address_increment; - char *a = format_dwarf_addr (dwflmod, 0, address); + char *a = format_dwarf_addr (dwflmod, 0, address, false); printf (gettext ("\ special opcode %u: address+%u = %s, line%+d = %zu\n"), opcode, address_increment, a, line_increment, line); @@ -5761,7 +5764,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, else address = read_8ubyte_unaligned_inc (dbg, linep); { - char *a = format_dwarf_addr (dwflmod, 0, address); + char *a = format_dwarf_addr (dwflmod, 0, address, false); printf (gettext ("set address to %s\n"), a); free (a); } @@ -5813,7 +5816,7 @@ define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"), get_uleb128 (u128, linep); address += minimum_instr_len * u128; { - char *a = format_dwarf_addr (dwflmod, 0, address); + char *a = format_dwarf_addr (dwflmod, 0, address, false); printf (gettext ("advance address by %u to %s\n"), u128, a); free (a); @@ -5865,7 +5868,7 @@ define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"), * ((255 - opcode_base) / line_range)); address += u128; { - char *a = format_dwarf_addr (dwflmod, 0, address); + char *a = format_dwarf_addr (dwflmod, 0, address, false); printf (gettext ("advance address by constant %u to %s\n"), u128, a); free (a); @@ -5881,7 +5884,7 @@ define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"), u128 = read_2ubyte_unaligned_inc (dbg, linep); address += u128; { - char *a = format_dwarf_addr (dwflmod, 0, address); + char *a = format_dwarf_addr (dwflmod, 0, address, false); printf (gettext ("\ advance address by fixed value %u to %s\n"), u128, a); @@ -5981,7 +5984,7 @@ print_debug_loc_section (Dwfl_Module *dwflmod, if (begin == (Dwarf_Addr) -1l) /* Base address entry. */ { - char *b = format_dwarf_addr (dwflmod, address_size, end); + char *b = format_dwarf_addr (dwflmod, address_size, end, false); printf (gettext (" [%6tx] base address %s\n"), offset, b); free (b); } @@ -5992,8 +5995,8 @@ print_debug_loc_section (Dwfl_Module *dwflmod, /* We have a location expression entry. */ uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp); - char *b = format_dwarf_addr (dwflmod, address_size, begin); - char *e = format_dwarf_addr (dwflmod, address_size, end); + char *b = format_dwarf_addr (dwflmod, address_size, begin, false); + char *e = format_dwarf_addr (dwflmod, address_size, end, false); if (first) /* First entry in a list. */ printf (gettext (" [%6tx] %s..%s"), offset, b, e); |