2007-10-23 Roland McGrath <roland@redhat.com>
* linux-kernel-modules.c (report_kernel_archive): Reorder the kernel
module to appear first.
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index d21f5d6..b7cd628 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,22 @@
+2007-10-17 Roland McGrath <roland@redhat.com>
+
+ * 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 <roland@redhat.com>
* dwarf_begin_elf.c (check_section): Punt on SHT_NOBITS sections.
diff --git a/libdw/dwarf_child.c b/libdw/dwarf_child.c
index 42b3813..b22b010 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 <drepper@redhat.com>, 2003.
@@ -177,6 +177,15 @@
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 ac905c8..7c4fb71 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 <drepper@redhat.com>, 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 @@
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 18ffe2f..90a4b2d 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 00e5a1c..a6cca39 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 <drepper@redhat.com>, 2003.
@@ -92,7 +92,7 @@
{
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 70a35b0..6242d04 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_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 f069075..78fd5ce 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -267,6 +267,7 @@
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 @@
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_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 e6259d4..afff6d3 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 <drepper@redhat.com>, 2003.
@@ -97,6 +97,7 @@
if (start < dbg->next_cu_offset)
{
+ invalid:
__libdw_seterrno (DWARF_E_INVALID_DWARF);
return NULL;
}
@@ -115,6 +116,15 @@
/* 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 @@
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 779b6c0..ad78f4b 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 <drepper@redhat.com>, 2003.
@@ -73,8 +73,11 @@
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;