summaryrefslogtreecommitdiffstats
path: root/libdw
diff options
context:
space:
mode:
authorRoland McGrath <[email protected]>2007-10-23 13:07:39 +0000
committerRoland McGrath <[email protected]>2007-10-23 13:07:39 +0000
commite4c22ea004c02a58f5db5eb53794275344c17958 (patch)
treeec3713d305f8e9f05b15d29240accc71e98998c5 /libdw
parent98c5ead4ad9fbf96ad3b54d8ca26e354ddc3398d (diff)
2007-10-23 Roland McGrath <[email protected]>
* linux-kernel-modules.c (report_kernel_archive): Reorder the kernel module to appear first.
Diffstat (limited to 'libdw')
-rw-r--r--libdw/ChangeLog19
-rw-r--r--libdw/dwarf_child.c11
-rw-r--r--libdw/dwarf_formref.c22
-rw-r--r--libdw/dwarf_formref_die.c36
-rw-r--r--libdw/dwarf_siblingof.c4
-rw-r--r--libdw/libdw.h8
-rw-r--r--libdw/libdwP.h7
-rw-r--r--libdw/libdw_findcu.c13
-rw-r--r--libdw/libdw_form.c7
9 files changed, 106 insertions, 21 deletions
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index d21f5d64..b7cd6285 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,22 @@
+2007-10-17 Roland McGrath <[email protected]>
+
+ * libdw.h (__deprecated_attribute__): New macro.
+ (dwarf_formref): Mark it deprecated.
+ * dwarf_formref.c (__libdw_formref): New function, broken out of ...
+ (dwarf_formref): ... here. Call it. Remove INTDEF.
+ * libdwP.h: Remove INTDECL.
+ Declare __libdw_formref.
+ * dwarf_siblingof.c (dwarf_siblingof): Call __libdw_formref instead.
+ * dwarf_formref_die.c: Likewise. Handle DW_FORM_ref_addr here.
+
+ * libdw_form.c (__libdw_form_val_len): Fix DW_FORM_ref_addr result,
+ needs to check CU->version.
+
+ * libdwP.h (struct Dwarf_CU): New member `version'.
+ * libdw_findcu.c (__libdw_findcu): Initialize it.
+
+ * dwarf_child.c: Return 1 for null entry as first child.
+
2007-10-05 Roland McGrath <[email protected]>
* dwarf_begin_elf.c (check_section): Punt on SHT_NOBITS sections.
diff --git a/libdw/dwarf_child.c b/libdw/dwarf_child.c
index 42b38137..b22b010e 100644
--- a/libdw/dwarf_child.c
+++ b/libdw/dwarf_child.c
@@ -1,5 +1,5 @@
/* Return vhild of current DIE.
- Copyright (C) 2003, 2004, 2005, 2006 Red Hat, Inc.
+ Copyright (C) 2003, 2004, 2005, 2006, 2007 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <[email protected]>, 2003.
@@ -177,6 +177,15 @@ dwarf_child (die, result)
if (addr == NULL)
return -1;
+ /* It's kosher (just suboptimal) to have a null entry first thing (7.5.3).
+ So if this starts with ULEB128 of 0 (even with silly encoding of 0),
+ it is a kosher null entry and we do not really have any children. */
+ const unsigned char *code = addr;
+ while (unlikely (*code == 0x80))
+ ++code;
+ if (unlikely (*code == '\0'))
+ return 1;
+
/* RESULT can be the same as DIE. So preserve what we need. */
struct Dwarf_CU *cu = die->cu;
diff --git a/libdw/dwarf_formref.c b/libdw/dwarf_formref.c
index ac905c82..7c4fb71a 100644
--- a/libdw/dwarf_formref.c
+++ b/libdw/dwarf_formref.c
@@ -1,5 +1,5 @@
/* Return reference offset represented by attribute.
- Copyright (C) 2003, 2005 Red Hat, Inc.
+ Copyright (C) 2003, 2005, 2007 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <[email protected]>, 2003.
@@ -55,15 +55,11 @@
#include <dwarf.h>
#include "libdwP.h"
-
int
-dwarf_formref (attr, return_offset)
+__libdw_formref (attr, return_offset)
Dwarf_Attribute *attr;
Dwarf_Off *return_offset;
{
- if (attr == NULL)
- return -1;
-
const unsigned char *datap;
switch (attr->form)
@@ -100,4 +96,16 @@ dwarf_formref (attr, return_offset)
return 0;
}
-INTDEF(dwarf_formref)
+
+/* This is the old public entry point.
+ It is now deprecated in favor of dwarf_formref_die. */
+int
+dwarf_formref (attr, return_offset)
+ Dwarf_Attribute *attr;
+ Dwarf_Off *return_offset;
+{
+ if (attr == NULL)
+ return -1;
+
+ return __libdw_formref (attr, return_offset);
+}
diff --git a/libdw/dwarf_formref_die.c b/libdw/dwarf_formref_die.c
index 18ffe2fb..90a4b2d3 100644
--- a/libdw/dwarf_formref_die.c
+++ b/libdw/dwarf_formref_die.c
@@ -1,5 +1,5 @@
/* Look up the DIE in a reference-form attribute.
- Copyright (C) 2005 Red Hat, Inc.
+ Copyright (C) 2005, 2007 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -52,13 +52,39 @@
#endif
#include "libdwP.h"
+#include <dwarf.h>
+
Dwarf_Die *
-dwarf_formref_die (Dwarf_Attribute *attr, Dwarf_Die *die_mem)
+dwarf_formref_die (attr, die_mem)
+ Dwarf_Attribute *attr;
+ Dwarf_Die *die_mem;
{
+ if (attr == NULL)
+ return NULL;
+
Dwarf_Off offset;
- return (unlikely (INTUSE(dwarf_formref) (attr, &offset) != 0) ? NULL
- : INTUSE(dwarf_offdie) (attr->cu->dbg, attr->cu->start + offset,
- die_mem));
+ if (attr->form == DW_FORM_ref_addr)
+ {
+ /* This has an absolute offset. */
+
+ uint8_t ref_size = (attr->cu->version == 2
+ ? attr->cu->address_size
+ : attr->cu->offset_size);
+
+ if (ref_size == 8)
+ offset = read_8ubyte_unaligned (attr->cu->dbg, attr->valp);
+ else
+ offset = read_4ubyte_unaligned (attr->cu->dbg, attr->valp);
+ }
+ else
+ {
+ /* Other forms produce an offset from the CU. */
+ if (unlikely (__libdw_formref (attr, &offset) != 0))
+ return NULL;
+ offset += attr->cu->start;
+ }
+
+ return INTUSE(dwarf_offdie) (attr->cu->dbg, offset, die_mem);
}
INTDEF (dwarf_formref_die)
diff --git a/libdw/dwarf_siblingof.c b/libdw/dwarf_siblingof.c
index 00e5a1c7..a6cca394 100644
--- a/libdw/dwarf_siblingof.c
+++ b/libdw/dwarf_siblingof.c
@@ -1,5 +1,5 @@
/* Return sibling of given DIE.
- Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
+ Copyright (C) 2003, 2004, 2005, 2007 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <[email protected]>, 2003.
@@ -92,7 +92,7 @@ dwarf_siblingof (die, result)
{
Dwarf_Off offset;
sibattr.valp = addr;
- if (INTUSE(dwarf_formref) (&sibattr, &offset) != 0)
+ if (__libdw_formref (&sibattr, &offset) != 0)
/* Something went wrong. */
return -1;
diff --git a/libdw/libdw.h b/libdw/libdw.h
index 70a35b04..6242d04f 100644
--- a/libdw/libdw.h
+++ b/libdw/libdw.h
@@ -57,10 +57,13 @@
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
# define __nonnull_attribute__(...) __attribute__ ((__nonnull__ (__VA_ARGS__)))
+# define __deprecated_attribute__ __attribute__ ((__deprecated__))
#else
# define __nonnull_attribute__(args...)
+# define __deprecated_attribute__
#endif
+
#ifdef __GNUC_STDC_INLINE__
# define __libdw_extern_inline extern __inline __attribute__ ((__gnu_inline__))
#else
@@ -310,9 +313,10 @@ extern int dwarf_formsdata (Dwarf_Attribute *attr, Dwarf_Sword *return_uval)
extern int dwarf_formaddr (Dwarf_Attribute *attr, Dwarf_Addr *return_addr)
__nonnull_attribute__ (2);
-/* Return reference offset represented by attribute. */
+/* This function is deprecated. Always use dwarf_formref_die instead.
+ Return reference offset represented by attribute. */
extern int dwarf_formref (Dwarf_Attribute *attr, Dwarf_Off *return_offset)
- __nonnull_attribute__ (2);
+ __nonnull_attribute__ (2) __deprecated_attribute__;
/* Look up the DIE in a reference-form attribute. */
extern Dwarf_Die *dwarf_formref_die (Dwarf_Attribute *attr, Dwarf_Die *die_mem)
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index f069075b..78fd5ce7 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -267,6 +267,7 @@ struct Dwarf_CU
Dwarf_Off end;
uint8_t address_size;
uint8_t offset_size;
+ uint16_t version;
/* Hash table for the abbreviations. */
Dwarf_Abbrev_Hash abbrev_hash;
@@ -365,6 +366,11 @@ extern size_t __libdw_form_val_len (Dwarf *dbg, struct Dwarf_CU *cu,
const unsigned char *valp)
__nonnull_attribute__ (1, 2, 4) internal_function;
+/* Helper function for DW_FORM_ref* handling. */
+extern int __libdw_formref (Dwarf_Attribute *attr, Dwarf_Off *return_offset)
+ __nonnull_attribute__ (1, 2) internal_function;
+
+
/* Helper function to locate attribute. */
extern unsigned char *__libdw_find_attr (Dwarf_Die *die,
unsigned int search_name,
@@ -411,7 +417,6 @@ INTDECL (dwarf_entrypc)
INTDECL (dwarf_errmsg)
INTDECL (dwarf_formaddr)
INTDECL (dwarf_formblock)
-INTDECL (dwarf_formref)
INTDECL (dwarf_formref_die)
INTDECL (dwarf_formsdata)
INTDECL (dwarf_formstring)
diff --git a/libdw/libdw_findcu.c b/libdw/libdw_findcu.c
index e6259d49..afff6d3a 100644
--- a/libdw/libdw_findcu.c
+++ b/libdw/libdw_findcu.c
@@ -1,5 +1,5 @@
/* Find CU for given offset.
- Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
+ Copyright (C) 2003, 2004, 2005, 2007 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <[email protected]>, 2003.
@@ -97,6 +97,7 @@ __libdw_findcu (dbg, start)
if (start < dbg->next_cu_offset)
{
+ invalid:
__libdw_seterrno (DWARF_E_INVALID_DWARF);
return NULL;
}
@@ -115,6 +116,15 @@ __libdw_findcu (dbg, start)
/* No more entries. */
return NULL;
+ /* XXX We need the version number but dwarf_nextcu swallows it. */
+ const char *bytes = (dbg->sectiondata[IDX_debug_info]->d_buf + oldoff
+ + (2 * offset_size - 4));
+ uint16_t version = read_2ubyte_unaligned (dbg, bytes);
+
+ /* We only know how to handle the DWARF version 2 and 3 formats. */
+ if (unlikely (version != 2) && unlikely (version != 3))
+ goto invalid;
+
/* Create an entry for this CU. */
struct Dwarf_CU *newp = libdw_typed_alloc (dbg, struct Dwarf_CU);
@@ -123,6 +133,7 @@ __libdw_findcu (dbg, start)
newp->end = dbg->next_cu_offset;
newp->address_size = address_size;
newp->offset_size = offset_size;
+ newp->version = version;
Dwarf_Abbrev_Hash_init (&newp->abbrev_hash, 41);
newp->orig_abbrev_offset = newp->last_abbrev_offset = abbrev_offset;
newp->lines = NULL;
diff --git a/libdw/libdw_form.c b/libdw/libdw_form.c
index 779b6c0e..ad78f4b4 100644
--- a/libdw/libdw_form.c
+++ b/libdw/libdw_form.c
@@ -1,5 +1,5 @@
/* Helper functions for form handling.
- Copyright (C) 2003, 2004, 2006 Red Hat, Inc.
+ Copyright (C) 2003, 2004, 2006, 2007 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <[email protected]>, 2003.
@@ -73,8 +73,11 @@ __libdw_form_val_len (Dwarf *dbg, struct Dwarf_CU *cu, unsigned int form,
result = cu->address_size;
break;
- case DW_FORM_strp:
case DW_FORM_ref_addr:
+ result = cu->version == 2 ? cu->address_size : cu->offset_size;
+ break;
+
+ case DW_FORM_strp:
result = cu->offset_size;
break;