summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2010-09-09 23:16:18 -0700
committerRoland McGrath <roland@redhat.com>2010-09-09 23:16:18 -0700
commita4e6b968146b9b2e9879dc4bc0c1f0510f3abf40 (patch)
treea125ac30eb7a0b7f2be77dd3241b274d9d36b560
parent4f167992ce148c3a075f1a88ec90a922ab334f7a (diff)
parent932585d2385c9d4e5686e4ddc9ba30c68172d7f3 (diff)
downloadelfutils-a4e6b968146b9b2e9879dc4bc0c1f0510f3abf40.tar.gz
Merge branch 'roland/implicit-ptr'
-rw-r--r--NEWS3
-rw-r--r--libdw/ChangeLog15
-rw-r--r--libdw/Makefile.am2
-rw-r--r--libdw/dwarf.h1
-rw-r--r--libdw/dwarf_getlocation.c9
-rw-r--r--libdw/dwarf_getlocation_implicit_pointer.c86
-rw-r--r--libdw/dwarf_offdie.c10
-rw-r--r--libdw/libdw.h10
-rw-r--r--libdw/libdw.map2
-rw-r--r--libdw/libdwP.h4
-rw-r--r--src/ChangeLog5
-rw-r--r--src/readelf.c23
12 files changed, 165 insertions, 5 deletions
diff --git a/NEWS b/NEWS
index 599ea321..898cb81d 100644
--- 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.
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index dc1a7f38..da6ed056 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -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.
diff --git a/libdw/Makefile.am b/libdw/Makefile.am
index 530cbf4b..598bdd1f 100644
--- a/libdw/Makefile.am
+++ b/libdw/Makefile.am
@@ -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
diff --git a/libdw/dwarf.h b/libdw/dwarf.h
index dbf56e91..edf57b49 100644
--- a/libdw/dwarf.h
+++ b/libdw/dwarf.h
@@ -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. */
diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c
index e960ef9e..f7a60f9f 100644
--- a/libdw/dwarf_getlocation.c
+++ b/libdw/dwarf_getlocation.c
@@ -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
index 00000000..4d9f6b99
--- /dev/null
+++ b/libdw/dwarf_getlocation_implicit_pointer.c
@@ -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;
+}
diff --git a/libdw/dwarf_offdie.c b/libdw/dwarf_offdie.c
index 925fe512..4c650cfd 100644
--- a/libdw/dwarf_offdie.c
+++ b/libdw/dwarf_offdie.c
@@ -56,8 +56,10 @@
#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);
}
diff --git a/libdw/libdw.h b/libdw/libdw.h
index 92021366..d36238ed 100644
--- a/libdw/libdw.h
+++ b/libdw/libdw.h
@@ -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.
diff --git a/libdw/libdw.map b/libdw/libdw.map
index 6d6b365f..1f71d03b 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -250,5 +250,7 @@ ELFUTILS_0.148 {
ELFUTILS_0.149 {
global:
+ dwarf_getlocation_implicit_pointer;
+
dwfl_dwarf_line;
} ELFUTILS_0.148;
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index bb0ae1d1..da6efc53 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -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. */
diff --git a/src/ChangeLog b/src/ChangeLog
index 060e9df7..716e7313 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -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>
Print .debug_loc/.debug_ranges with cognizance of actual DIE uses.
@@ -114,6 +118,7 @@
(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>
diff --git a/src/readelf.c b/src/readelf.c
index 2b7f9f2f..81ef6a9f 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -3975,6 +3975,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)
@@ -4217,6 +4218,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)