]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
unfinished roland/addrsym_tls
authorRoland McGrath <roland@redhat.com>
Wed, 16 Jun 2010 03:40:59 +0000 (20:40 -0700)
committerRoland McGrath <roland@redhat.com>
Wed, 16 Jun 2010 03:44:43 +0000 (20:44 -0700)
libdw/libdw.map
libdwfl/dwfl_module_addrsym.c
libdwfl/dwfl_module_getsym.c
libdwfl/libdwfl.h
src/readelf.c

index 1a9afb135cf81fb5e00978df7dfae23e57a1d88d..0e1513f6a8cece87833979b6bd241ea13caf7b31 100644 (file)
@@ -226,6 +226,7 @@ ELFUTILS_0.143 {
     dwarf_decl_line;
     dwarf_srclang;
 
+    dwfl_module_addrsym_tls;
 } ELFUTILS_0.142;
 
 ELFUTILS_0.144 {
index 72280d118c8418fe1ad029b3bcfff20183ef6f74..46621182eb42923579fe52c31e6057ee27a2ae1a 100644 (file)
@@ -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
 
 #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);
+}
index f78e6ec03fdcf3fc3296705d5bf319dbd8974b94..701c35ad9e85a3c798f3e523cdcb996b37509177 100644 (file)
@@ -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
index 51e98187bcd6573e538e43cd84cdb9d9a76c4947..4256d243f5be0e6097db2072655763f14c2faad5 100644 (file)
@@ -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
index 1d8da26835b26ed9c3af2c1d1dc4f818fa8795e0..69ebea6c34c672545ad5ab286cc2634e3bcae3dc 100644 (file)
@@ -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);