summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2010-06-15 20:40:59 -0700
committerRoland McGrath <roland@redhat.com>2010-06-15 20:44:43 -0700
commita160261fecbcbe31293cd60f14c0a6dcdb85f5ac (patch)
tree2c71a7ba7dfaf2817dccebfdeb14f0ced948d386
parenta92f1a4edebaaed1878dd5135b67afeb52fc7d0a (diff)
downloadelfutils-roland/addrsym_tls.tar.gz
-rw-r--r--libdw/libdw.map1
-rw-r--r--libdwfl/dwfl_module_addrsym.c46
-rw-r--r--libdwfl/dwfl_module_getsym.c3
-rw-r--r--libdwfl/libdwfl.h5
-rw-r--r--src/readelf.c31
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);