diff options
author | Roland McGrath <[email protected]> | 2007-10-23 13:07:39 +0000 |
---|---|---|
committer | Roland McGrath <[email protected]> | 2007-10-23 13:07:39 +0000 |
commit | e4c22ea004c02a58f5db5eb53794275344c17958 (patch) | |
tree | ec3713d305f8e9f05b15d29240accc71e98998c5 /libdw | |
parent | 98c5ead4ad9fbf96ad3b54d8ca26e354ddc3398d (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/ChangeLog | 19 | ||||
-rw-r--r-- | libdw/dwarf_child.c | 11 | ||||
-rw-r--r-- | libdw/dwarf_formref.c | 22 | ||||
-rw-r--r-- | libdw/dwarf_formref_die.c | 36 | ||||
-rw-r--r-- | libdw/dwarf_siblingof.c | 4 | ||||
-rw-r--r-- | libdw/libdw.h | 8 | ||||
-rw-r--r-- | libdw/libdwP.h | 7 | ||||
-rw-r--r-- | libdw/libdw_findcu.c | 13 | ||||
-rw-r--r-- | libdw/libdw_form.c | 7 |
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; |