Handle DW_OP_GNU_implicit_pointer.
authorRoland McGrath <roland@redhat.com>
Sat, 8 May 2010 11:01:14 +0000 (04:01 -0700)
committerRoland McGrath <roland@redhat.com>
Mon, 30 Aug 2010 11:10:41 +0000 (04:10 -0700)
12 files changed:
NEWS
libdw/ChangeLog
libdw/Makefile.am
libdw/dwarf.h
libdw/dwarf_getlocation.c
libdw/dwarf_getlocation_implicit_pointer.c [new file with mode: 0644]
libdw/dwarf_offdie.c
libdw/libdw.h
libdw/libdw.map
libdw/libdwP.h
src/ChangeLog
src/readelf.c

diff --git a/NEWS b/NEWS
index 599ea32..898cb81 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,8 @@
 Version 0.149:
 
+libdw: Decode new DW_OP_GNU_implicit_pointer operation;
+       new function dwarf_getlocation_implicit_pointer.
+
 libdwfl: New function dwfl_dwarf_line.
 
 addr2line: New flag -F/--flags to print DWARF more line information details.
index dc1a7f3..da6ed05 100644 (file)
@@ -1,3 +1,18 @@
+2010-07-26  Roland McGrath  <roland@redhat.com>
+
+       * dwarf_getlocation_implicit_pointer.c: New file.
+       * Makefile.am (libdw_a_SOURCES): Add it.
+       * libdw.map (ELFUTILS_0.149): New set.
+       Add dwarf_getlocation_implicit_pointer.
+       * libdw.h: Declare it.
+
+       * dwarf_offdie.c (do_offdie): Renamed to __libdw_offdie, made global.
+       (dwarf_offdie, dwarf_offdie_types): Update callers.
+       * libdwP.h: Declare it.
+
+       * dwarf.h: Add DW_OP_GNU_implicit_pointer.
+       * dwarf_getlocation.c (__libdw_intern_expression): Handle it.
+
 2010-08-24  Roland McGrath  <roland@redhat.com>
 
        * libdw.map (ELFUTILS_0.149): New set.  Add dwfl_dwarf_line.
index 530cbf4..598bdd1 100644 (file)
@@ -84,7 +84,7 @@ libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \
                  dwarf_frame_info.c dwarf_frame_cfa.c dwarf_frame_register.c \
                  dwarf_cfi_addrframe.c \
                  dwarf_getcfi.c dwarf_getcfi_elf.c dwarf_cfi_end.c \
-                 dwarf_aggregate_size.c
+                 dwarf_aggregate_size.c dwarf_getlocation_implicit_pointer.c
 
 if MAINTAINER_MODE
 BUILT_SOURCES = $(srcdir)/known-dwarf.h
index dbf56e9..edf57b4 100644 (file)
@@ -475,6 +475,7 @@ enum
     DW_OP_GNU_push_tls_address = 0xe0,
     DW_OP_GNU_uninit = 0xf0,
     DW_OP_GNU_encoded_addr = 0xf1,
+    DW_OP_GNU_implicit_pointer = 0xf2,
 
     DW_OP_lo_user = 0xe0,      /* Implementation-defined range start.  */
     DW_OP_hi_user = 0xff       /* Implementation-defined range end.  */
index e960ef9..f7a60f9 100644 (file)
@@ -420,6 +420,15 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
          data += newloc->number;               /* Skip the block.  */
          break;
 
+       case DW_OP_GNU_implicit_pointer:
+         /* DW_FORM_ref_addr, depends on offset size of CU.  */
+         if (__libdw_read_offset_inc (dbg, sec_index, &data, ref_size,
+                                      &newloc->number, IDX_debug_info, 0))
+           return -1;
+         /* XXX Check size.  */
+         get_uleb128 (newloc->number2, data); /* Byte offset.  */
+         break;
+
        default:
          goto invalid;
        }
diff --git a/libdw/dwarf_getlocation_implicit_pointer.c b/libdw/dwarf_getlocation_implicit_pointer.c
new file mode 100644 (file)
index 0000000..4d9f6b9
--- /dev/null
@@ -0,0 +1,86 @@
+/* Return associated attribute for DW_OP_GNU_implicit_pointer.
+   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_getlocation_implicit_pointer (attr, op, result)
+     Dwarf_Attribute *attr;
+     const Dwarf_Op *op;
+     Dwarf_Attribute *result;
+{
+  if (attr == NULL)
+    return -1;
+
+  if (unlikely (op->atom != DW_OP_GNU_implicit_pointer))
+    {
+      __libdw_seterrno (DWARF_E_INVALID_ACCESS);
+      return -1;
+    }
+
+  Dwarf_Die die;
+  if (__libdw_offdie (attr->cu->dbg, op->number, &die,
+                     attr->cu->type_offset != 0) == NULL)
+    return -1;
+
+  if (INTUSE(dwarf_attr) (&die, DW_AT_location, result) == NULL
+      && INTUSE(dwarf_attr) (&die, DW_AT_const_value, result) == NULL)
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return -1;
+    }
+
+  return 0;
+}
index 925fe51..4c650cf 100644 (file)
 #include "libdwP.h"
 
 
-static Dwarf_Die *
-do_offdie (Dwarf *dbg, Dwarf_Off offset, Dwarf_Die *result, bool debug_types)
+Dwarf_Die *
+internal_function
+__libdw_offdie (Dwarf *dbg, Dwarf_Off offset, Dwarf_Die *result,
+               bool debug_types)
 {
   if (dbg == NULL)
     return NULL;
@@ -95,7 +97,7 @@ dwarf_offdie (dbg, offset, result)
      Dwarf_Off offset;
      Dwarf_Die *result;
 {
-  return do_offdie (dbg, offset, result, false);
+  return __libdw_offdie (dbg, offset, result, false);
 }
 INTDEF(dwarf_offdie)
 
@@ -105,5 +107,5 @@ dwarf_offdie_types (dbg, offset, result)
      Dwarf_Off offset;
      Dwarf_Die *result;
 {
-  return do_offdie (dbg, offset, result, true);
+  return __libdw_offdie (dbg, offset, result, true);
 }
index 9202136..d36238e 100644 (file)
@@ -659,6 +659,16 @@ extern int dwarf_getlocation_implicit_value (Dwarf_Attribute *attr,
                                             Dwarf_Block *return_block)
   __nonnull_attribute__ (2, 3);
 
+/* Return the attribute indicated by a DW_OP_GNU_implicit_pointer operation.
+   The OP pointer must point into an expression that dwarf_getlocation
+   or dwarf_getlocation_addr has returned given the same ATTR.
+   The result is the DW_AT_location or DW_AT_const_value attribute
+   of the OP->number DIE.  */
+extern int dwarf_getlocation_implicit_pointer (Dwarf_Attribute *attr,
+                                              const Dwarf_Op *op,
+                                              Dwarf_Attribute *result)
+  __nonnull_attribute__ (2, 3);
+
 
 /* Compute the byte-size of a type DIE according to DWARF rules.
    For most types, this is just DW_AT_byte_size.
index 6d6b365..1f71d03 100644 (file)
@@ -250,5 +250,7 @@ ELFUTILS_0.148 {
 
 ELFUTILS_0.149 {
   global:
+    dwarf_getlocation_implicit_pointer;
+
     dwfl_dwarf_line;
 } ELFUTILS_0.148;
index bb0ae1d..da6efc5 100644 (file)
@@ -456,6 +456,10 @@ extern int __libdw_intern_expression (Dwarf *dbg,
                                      int sec_index)
   __nonnull_attribute__ (5, 6, 9, 10) internal_function;
 
+extern Dwarf_Die *__libdw_offdie (Dwarf *dbg, Dwarf_Off offset,
+                                 Dwarf_Die *result, bool debug_types)
+  internal_function;
+
 
 /* Return error code of last failing function call.  This value is kept
    separately for each thread.  */
index 3010ce5..4fff276 100644 (file)
@@ -1,3 +1,7 @@
+2010-07-26  Roland McGrath  <roland@redhat.com>
+
+       * readelf.c (print_ops): Handle DW_OP_GNU_implicit_pointer.
+
 2010-08-30  Roland McGrath  <roland@redhat.com>
 
        * readelf.c (print_debug_loc_section): Check for bogus length
        (struct attrcb_args): Add offset_size field.
        (attr_callback): Use it for print_ops call.
        (print_debug_info_section): Initialize it.
+       (print_ops): Likewise.
 
 2010-04-14  Roland McGrath  <roland@redhat.com>
 
index fd9f9a5..8c5e815 100644 (file)
@@ -3969,6 +3969,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
       [DW_OP_bit_piece] = "bit_piece",
       [DW_OP_implicit_value] = "implicit_value",
       [DW_OP_stack_value] = "stack_value",
+      [DW_OP_GNU_implicit_pointer] = "GNU_implicit_pointer",
     };
 
   if (len == 0)
@@ -4211,6 +4212,28 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
          offset += 1 + (data - start);
          break;
 
+       case DW_OP_GNU_implicit_pointer:
+         /* DIE offset operand.  */
+         start = data;
+         NEED (ref_size + 1);
+         if (ref_size == 4)
+           addr = read_4ubyte_unaligned (dbg, data);
+         else
+           {
+             assert (ref_size == 8);
+             addr = read_8ubyte_unaligned (dbg, data);
+           }
+         data += ref_size;
+         /* Byte offset operand.  */
+         get_sleb128 (sleb, data); /* XXX check overrun */
+
+         printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX ", %+" PRId64 "\n",
+                 indent, "", (intmax_t) offset,
+                 known[op], (uintmax_t) addr, sleb);
+         CONSUME (data - start);
+         offset += 1 + (data - start);
+         break;
+
        default:
          /* No Operand.  */
          if (op < sizeof known / sizeof known[0] && known[op] != NULL)