diff options
author | Chih-hung Hsieh <chh@google.com> | 2015-09-25 14:51:48 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2015-09-25 14:51:48 +0000 |
commit | b0121c5547604527aaeea297b54047cd14b234df (patch) | |
tree | 7d9031ee3d5796de4a1825892fc6e04ba6e36ae2 /libdw/dwarf_formref_die.c | |
parent | d03895cf5f8b77c6a85abcd84ea0d80ff56be846 (diff) | |
parent | 5eafdf0f9bfd9a3c5f93414ac16bb399b6da0b7f (diff) | |
download | android_external_elfutils-b0121c5547604527aaeea297b54047cd14b234df.tar.gz android_external_elfutils-b0121c5547604527aaeea297b54047cd14b234df.tar.bz2 android_external_elfutils-b0121c5547604527aaeea297b54047cd14b234df.zip |
Merge "Move files up to match upstream source structure."
Diffstat (limited to 'libdw/dwarf_formref_die.c')
-rw-r--r-- | libdw/dwarf_formref_die.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/libdw/dwarf_formref_die.c b/libdw/dwarf_formref_die.c new file mode 100644 index 00000000..63f66971 --- /dev/null +++ b/libdw/dwarf_formref_die.c @@ -0,0 +1,121 @@ +/* Look up the DIE in a reference-form attribute. + Copyright (C) 2005-2010 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <string.h> +#include "libdwP.h" +#include <dwarf.h> + + +Dwarf_Die * +dwarf_formref_die (attr, result) + Dwarf_Attribute *attr; + Dwarf_Die *result; +{ + if (attr == NULL) + return NULL; + + struct Dwarf_CU *cu = attr->cu; + + Dwarf_Off offset; + if (attr->form == DW_FORM_ref_addr || attr->form == DW_FORM_GNU_ref_alt) + { + /* This has an absolute offset. */ + + uint8_t ref_size = (cu->version == 2 && attr->form == DW_FORM_ref_addr + ? cu->address_size + : cu->offset_size); + + Dwarf *dbg_ret = (attr->form == DW_FORM_GNU_ref_alt + ? cu->dbg->alt_dwarf : cu->dbg); + + if (dbg_ret == NULL) + { + __libdw_seterrno (DWARF_E_NO_ALT_DEBUGLINK); + return NULL; + } + + if (__libdw_read_offset (cu->dbg, dbg_ret, IDX_debug_info, attr->valp, + ref_size, &offset, IDX_debug_info, 0)) + return NULL; + + return INTUSE(dwarf_offdie) (dbg_ret, offset, result); + } + + const unsigned char *datap; + size_t size; + if (attr->form == DW_FORM_ref_sig8) + { + /* This doesn't have an offset, but instead a value we + have to match in the .debug_types type unit headers. */ + + uint64_t sig = read_8ubyte_unaligned (cu->dbg, attr->valp); + cu = Dwarf_Sig8_Hash_find (&cu->dbg->sig8_hash, sig, NULL); + if (cu == NULL) + /* Not seen before. We have to scan through the type units. */ + do + { + cu = __libdw_intern_next_unit (attr->cu->dbg, true); + if (cu == NULL) + { + __libdw_seterrno (INTUSE(dwarf_errno) () + ?: DWARF_E_INVALID_REFERENCE); + return NULL; + } + } + while (cu->type_sig8 != sig); + + datap = cu->dbg->sectiondata[IDX_debug_types]->d_buf; + size = cu->dbg->sectiondata[IDX_debug_types]->d_size; + offset = cu->type_offset; + } + else + { + /* Other forms produce an offset from the CU. */ + if (unlikely (__libdw_formref (attr, &offset) != 0)) + return NULL; + + datap = cu->startp; + size = cu->endp - cu->startp; + } + + if (unlikely (offset >= size)) + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return NULL; + } + + memset (result, '\0', sizeof (Dwarf_Die)); + result->addr = (char *) datap + offset; + result->cu = cu; + return result; +} +INTDEF (dwarf_formref_die) |