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_getabbrev.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_getabbrev.c')
-rw-r--r-- | libdw/dwarf_getabbrev.c | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/libdw/dwarf_getabbrev.c b/libdw/dwarf_getabbrev.c new file mode 100644 index 00000000..0efde45b --- /dev/null +++ b/libdw/dwarf_getabbrev.c @@ -0,0 +1,165 @@ +/* Get abbreviation at given offset. + Copyright (C) 2003, 2004, 2005, 2006, 2014 Red Hat, Inc. + This file is part of elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + 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 <dwarf.h> +#include "libdwP.h" + + +Dwarf_Abbrev * +internal_function +__libdw_getabbrev (dbg, cu, offset, lengthp, result) + Dwarf *dbg; + struct Dwarf_CU *cu; + Dwarf_Off offset; + size_t *lengthp; + Dwarf_Abbrev *result; +{ + /* Don't fail if there is not .debug_abbrev section. */ + if (dbg->sectiondata[IDX_debug_abbrev] == NULL) + return NULL; + + if (offset >= dbg->sectiondata[IDX_debug_abbrev]->d_size) + { + __libdw_seterrno (DWARF_E_INVALID_OFFSET); + return NULL; + } + + const unsigned char *abbrevp + = (unsigned char *) dbg->sectiondata[IDX_debug_abbrev]->d_buf + offset; + + if (*abbrevp == '\0') + /* We are past the last entry. */ + return DWARF_END_ABBREV; + + /* 7.5.3 Abbreviations Tables + + [...] Each declaration begins with an unsigned LEB128 number + representing the abbreviation code itself. [...] The + abbreviation code is followed by another unsigned LEB128 + number that encodes the entry's tag. [...] + + [...] Following the tag encoding is a 1-byte value that + determines whether a debugging information entry using this + abbreviation has child entries or not. [...] + + [...] Finally, the child encoding is followed by a series of + attribute specifications. Each attribute specification + consists of two parts. The first part is an unsigned LEB128 + number representing the attribute's name. The second part is + an unsigned LEB128 number representing the attribute's form. */ + const unsigned char *end = (dbg->sectiondata[IDX_debug_abbrev]->d_buf + + dbg->sectiondata[IDX_debug_abbrev]->d_size); + const unsigned char *start_abbrevp = abbrevp; + unsigned int code; + get_uleb128 (code, abbrevp, end); + + /* Check whether this code is already in the hash table. */ + bool foundit = false; + Dwarf_Abbrev *abb = NULL; + if (cu == NULL + || (abb = Dwarf_Abbrev_Hash_find (&cu->abbrev_hash, code, NULL)) == NULL) + { + if (result == NULL) + abb = libdw_typed_alloc (dbg, Dwarf_Abbrev); + else + abb = result; + } + else + { + foundit = true; + + if (unlikely (abb->offset != offset)) + { + /* A duplicate abbrev code at a different offset, + that should never happen. */ + invalid: + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return NULL; + } + + /* If the caller doesn't need the length we are done. */ + if (lengthp == NULL) + goto out; + } + + /* If there is already a value in the hash table we are going to + overwrite its content. This must not be a problem, since the + content better be the same. */ + abb->code = code; + if (abbrevp >= end) + goto invalid; + get_uleb128 (abb->tag, abbrevp, end); + if (abbrevp + 1 >= end) + goto invalid; + abb->has_children = *abbrevp++ == DW_CHILDREN_yes; + abb->attrp = (unsigned char *) abbrevp; + abb->offset = offset; + + /* Skip over all the attributes and count them while doing so. */ + abb->attrcnt = 0; + unsigned int attrname; + unsigned int attrform; + do + { + if (abbrevp >= end) + goto invalid; + get_uleb128 (attrname, abbrevp, end); + if (abbrevp >= end) + goto invalid; + get_uleb128 (attrform, abbrevp, end); + } + while (attrname != 0 && attrform != 0 && ++abb->attrcnt); + + /* Return the length to the caller if she asked for it. */ + if (lengthp != NULL) + *lengthp = abbrevp - start_abbrevp; + + /* Add the entry to the hash table. */ + if (cu != NULL && ! foundit) + (void) Dwarf_Abbrev_Hash_insert (&cu->abbrev_hash, abb->code, abb); + + out: + return abb; +} + + +Dwarf_Abbrev * +dwarf_getabbrev (die, offset, lengthp) + Dwarf_Die *die; + Dwarf_Off offset; + size_t *lengthp; +{ + return __libdw_getabbrev (die->cu->dbg, die->cu, + die->cu->orig_abbrev_offset + offset, lengthp, + NULL); +} |