]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Add libdw APIs for relocatable address values.
authorRoland McGrath <roland@redhat.com>
Mon, 21 Jun 2010 10:18:44 +0000 (03:18 -0700)
committerRoland McGrath <roland@redhat.com>
Mon, 21 Jun 2010 10:18:44 +0000 (03:18 -0700)
libdw/ChangeLog
libdw/Makefile.am
libdw/dwarf_form_relocatable.c [new file with mode: 0644]
libdw/dwarf_lineaddr_relocatable.c [new file with mode: 0644]
libdw/libdw.h
libdw/libdw.map
libdw/libdwP.h
libdw/relocate.c

index b6fe88502eb33b7a8fed3aaedc7e332a606c8b79..986427795ee3f0abdd2ac4e9599b0ce33ab8a18a 100644 (file)
@@ -1,5 +1,13 @@
 2010-06-21  Roland McGrath  <roland@redhat.com>
 
+       * relocate.c (__libdw_relocatable): New function.
+       * libdwP.h: Declare it.
+       * dwarf_form_relocatable.c: New file.
+       * dwarf_lineaddr_relocatable.c: New file.
+       * Makefile.am (libdw_a_SOURCES): Add them.
+       * libdw.map (ELFUTILS_0.149): New set; add those.
+       * libdw.h: Declare them.
+
        * libdwP.h (struct Dwarf_Line_s): Replace files with cu.
        (struct Dwarf_Lines_s): New member reloc.
        * dwarf_linesrc.c: Update usage.
index 6b0c0734b569b9dafb6a1f23eebc9a9cce09c141..067eec0d1ceb951b9c94f23c710edc7fca019a24 100644 (file)
@@ -85,7 +85,8 @@ libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \
                  dwarf_cfi_addrframe.c \
                  dwarf_getcfi.c dwarf_getcfi_elf.c dwarf_cfi_end.c \
                  dwarf_aggregate_size.c \
-                 relocate.c
+                 relocate.c \
+                 dwarf_form_relocatable.c dwarf_lineaddr_relocatable.c
 
 if MAINTAINER_MODE
 BUILT_SOURCES = $(srcdir)/known-dwarf.h
diff --git a/libdw/dwarf_form_relocatable.c b/libdw/dwarf_form_relocatable.c
new file mode 100644 (file)
index 0000000..f01b137
--- /dev/null
@@ -0,0 +1,91 @@
+/* Return relocatable address from attribute.
+   Copyright (C) 2010 Red Hat, Inc.
+   This file is part of Red Hat elfutils.
+
+   Red Hat elfutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by the
+   Free Software Foundation; version 2 of the License.
+
+   Red Hat elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Red Hat elfutils; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+   In addition, as a special exception, Red Hat, Inc. gives You the
+   additional right to link the code of Red Hat elfutils with code licensed
+   under any Open Source Initiative certified open source license
+   (http://www.opensource.org/licenses/index.php) which requires the
+   distribution of source code with any binary distribution and to
+   distribute linked combinations of the two.  Non-GPL Code permitted under
+   this exception must only link to the code of Red Hat elfutils through
+   those well defined interfaces identified in the file named EXCEPTION
+   found in the source code files (the "Approved Interfaces").  The files
+   of Non-GPL Code may instantiate templates or use macros or inline
+   functions from the Approved Interfaces without causing the resulting
+   work to be covered by the GNU General Public License.  Only Red Hat,
+   Inc. may make changes or additions to the list of Approved Interfaces.
+   Red Hat's grant of this exception is conditioned upon your not adding
+   any new exceptions.  If you wish to add a new Approved Interface or
+   exception, please contact Red Hat.  You must obey the GNU General Public
+   License in all respects for all of the Red Hat elfutils code and other
+   code used in conjunction with Red Hat elfutils except the Non-GPL Code
+   covered by this exception.  If you modify this file, you may extend this
+   exception to your version of the file, but you are not obligated to do
+   so.  If you do not wish to provide this exception without modification,
+   you must delete this exception statement from your version and license
+   this file solely under the GPL without exception.
+
+   Red Hat elfutils is an included package of the Open Invention Network.
+   An included package of the Open Invention Network is a package for which
+   Open Invention Network licensees cross-license their patents.  No patent
+   license is granted, either expressly or impliedly, by designation as an
+   included package.  Should you wish to participate in the Open Invention
+   Network licensing program, please visit www.openinventionnetwork.com
+   <http://www.openinventionnetwork.com>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include <dwarf.h>
+
+
+int
+dwarf_form_relocatable (attr, sym, name, addend)
+     Dwarf_Attribute *attr;
+     GElf_Sym *sym;
+     const char **name;
+     GElf_Sxword *addend;
+{
+  if (attr == NULL)
+    return -1;
+
+  int width;
+  switch (attr->form)
+    {
+    default:
+      return ((addend != NULL && INTUSE(dwarf_formsdata) (attr, addend)) ? -1
+             : __libdw_relocatable (attr->cu->dbg, IDX_last, NULL, 0,
+                                    sym, name, addend, 0));
+
+    case DW_FORM_addr:
+      width = attr->cu->address_size;
+      break;
+
+    case DW_FORM_data4:
+      width = 4;
+      break;
+
+    case DW_FORM_data8:
+      width = 8;
+      break;
+    }
+
+  return __libdw_relocatable (attr->cu->dbg, cu_sec_idx (attr->cu),
+                             attr->valp, width, sym, name, addend, 0);
+}
diff --git a/libdw/dwarf_lineaddr_relocatable.c b/libdw/dwarf_lineaddr_relocatable.c
new file mode 100644 (file)
index 0000000..2b4a7a6
--- /dev/null
@@ -0,0 +1,73 @@
+/* Return relocatable line address.
+   Copyright (C) 2010 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   Red Hat elfutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by the
+   Free Software Foundation; version 2 of the License.
+
+   Red Hat elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Red Hat elfutils; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+   In addition, as a special exception, Red Hat, Inc. gives You the
+   additional right to link the code of Red Hat elfutils with code licensed
+   under any Open Source Initiative certified open source license
+   (http://www.opensource.org/licenses/index.php) which requires the
+   distribution of source code with any binary distribution and to
+   distribute linked combinations of the two.  Non-GPL Code permitted under
+   this exception must only link to the code of Red Hat elfutils through
+   those well defined interfaces identified in the file named EXCEPTION
+   found in the source code files (the "Approved Interfaces").  The files
+   of Non-GPL Code may instantiate templates or use macros or inline
+   functions from the Approved Interfaces without causing the resulting
+   work to be covered by the GNU General Public License.  Only Red Hat,
+   Inc. may make changes or additions to the list of Approved Interfaces.
+   Red Hat's grant of this exception is conditioned upon your not adding
+   any new exceptions.  If you wish to add a new Approved Interface or
+   exception, please contact Red Hat.  You must obey the GNU General Public
+   License in all respects for all of the Red Hat elfutils code and other
+   code used in conjunction with Red Hat elfutils except the Non-GPL Code
+   covered by this exception.  If you modify this file, you may extend this
+   exception to your version of the file, but you are not obligated to do
+   so.  If you do not wish to provide this exception without modification,
+   you must delete this exception statement from your version and license
+   this file solely under the GPL without exception.
+
+   Red Hat elfutils is an included package of the Open Invention Network.
+   An included package of the Open Invention Network is a package for which
+   Open Invention Network licensees cross-license their patents.  No patent
+   license is granted, either expressly or impliedly, by designation as an
+   included package.  Should you wish to participate in the Open Invention
+   Network licensing program, please visit www.openinventionnetwork.com
+   <http://www.openinventionnetwork.com>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_lineaddr_relocatable (line, sym, name, addend)
+     Dwarf_Line *line;
+     GElf_Sym *sym;
+     const char **name;
+     GElf_Sxword *addend;
+{
+  if (line == NULL)
+    return -1;
+
+  return __libdw_relocatable (line->cu->dbg, IDX_debug_line,
+                             line->cu->lines->reloc == NULL ? NULL
+                             : line->cu->lines->reloc[line
+                                                      - line->cu->lines->info],
+                             line->cu->address_size, sym, name, addend,
+                             line->addr);
+}
index d3e7a5abe028c6e40fafb91ac802f8201462e54e..0ba51972a11a7eda5b7614d35790ded3d0c6b7f4 100644 (file)
@@ -512,6 +512,31 @@ extern int dwarf_arrayorder (Dwarf_Die *die);
 extern int dwarf_srclang (Dwarf_Die *die);
 
 
+/* Relocatable address access functions.
+
+   These retrieve an address that might require relocation in an ET_REL
+   file.  They return -1 for errors.  If successful, they fill in SYM (if
+   not null) with the ELF symbol describing the address fetched.  If NAME
+   is not null, it is filled with the symbol name, or with NULL if there is
+   no named symbol involved.  If ADDEND is not null, it is filled with the
+   offset relative to that symbol.  If the symbol refers to a normal
+   section, the return value is that section index (which might be above
+   SHN_LORESERVE).  If the symbol does not refer to a normal section,
+   the return value is zero and SYM->st_shndx has a special SHN_* value.
+   An address that required no relocation appears as a SHN_ABS symbol
+   with st_value 0 and the whole address in the addend.  */
+
+/* Like dwarf_formaddr, but as described above.  */
+extern int dwarf_form_relocatable (Dwarf_Attribute *attr,
+                                  GElf_Sym *sym, const char **name,
+                                  GElf_Sxword *addend);
+
+/* Like dwarf_lineaddr, but as described above.  */
+extern int dwarf_lineaddr_relocatable (Dwarf_Line *line,
+                                      GElf_Sym *sym, const char **name,
+                                      GElf_Sxword *addend);
+
+
 /* Get abbreviation at given offset for given DIE.  */
 extern Dwarf_Abbrev *dwarf_getabbrev (Dwarf_Die *die, Dwarf_Off offset,
                                      size_t *lengthp);
index 954fff67d922edfe9065a0acc0a8daab0c25f00e..d3d51af3e0b9dbcde1846bb1648135c6e7282f4d 100644 (file)
@@ -249,3 +249,9 @@ ELFUTILS_0.148 {
     dwarf_next_unit;
     dwarf_offdie_types;
 } ELFUTILS_0.146;
+
+ELFUTILS_0.149 {
+  global:
+    dwarf_form_relocatable;
+    dwarf_lineaddr_relocatable;
+} ELFUTILS_0.148;
index 6b22d6ee73cbcf06eba63e38bae441e72645eb74..60ca016bf5bbe2e0ca2589fd14212ae83c24d246 100644 (file)
@@ -619,6 +619,13 @@ __libdw_read_offset (Dwarf *dbg,
                                  ret, sec_ret, size);
 }
 
+extern int __libdw_relocatable (Dwarf *dbg, int sec_idx,
+                               const unsigned char *valp, unsigned int width,
+                               GElf_Sym *sym, const char **name,
+                               GElf_Sxword *addend, GElf_Sxword offset)
+  __nonnull_attribute__ (1) internal_function;
+
+
 static inline size_t
 cu_sec_idx (struct Dwarf_CU *cu)
 {
index a7d57a483c98ad21400850276fdbf9b59b413a8f..27a05eff9909037215e82cae6f0a3b203a671122 100644 (file)
@@ -544,3 +544,56 @@ __libdw_relocate_offset (Dwarf *dbg, int sec_index,
     *val = addend;
   return result;
 }
+\f
+int
+internal_function
+__libdw_relocatable (Dwarf *dbg, int sec_idx,
+                    const unsigned char *valp, unsigned int width,
+                    GElf_Sym *sym, const char **name, GElf_Sxword *addend,
+                    GElf_Sxword offset)
+{
+  struct dwarf_section_reloc *const r = dbg->relocate->sectionrel[sec_idx];
+  int symndx;
+  int result = relocatable_datum (dbg, sec_idx, r, valp, width,
+                                 &symndx, addend);
+  if (result == 0)
+    {
+      if (sym != NULL)
+       *sym = (GElf_Sym) { .st_shndx = SHN_ABS };
+      if (name != NULL)
+       *name = NULL;
+      if (addend != NULL)
+       *addend = offset + (width == 8
+                           ? read_8ubyte_unaligned (dbg, valp)
+                           : read_4ubyte_unaligned (dbg, valp));
+    }
+  else if (likely (result > 0))
+    {
+      GElf_Sym sym_mem;
+      GElf_Word shndx;
+      if (sym == NULL)
+       sym = &sym_mem;
+      result = reloc_getsym (r, symndx, sym, &shndx);
+      if (likely (result > 0))
+       {
+         if (name != NULL)
+           {
+             if (sym->st_name == 0)
+               *name = NULL;
+             else if (unlikely (sym->st_name >= r->symstrdata->d_size))
+               {
+                 __libdw_seterrno (DWARF_E_RELBADSYM);
+                 return -1;
+               }
+             else
+               *name = (const char *) r->symstrdata->d_buf + sym->st_name;
+           }
+         if (addend != NULL)
+           *addend += offset;
+         result = (sym->st_shndx < SHN_LORESERVE ? sym->st_shndx
+                   : sym->st_shndx == SHN_XINDEX ? shndx : SHN_UNDEF);
+       }
+    }
+
+  return result;
+}