diff options
Diffstat (limited to 'libdwarf/dwarf_get_abbrev.c')
-rw-r--r-- | libdwarf/dwarf_get_abbrev.c | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/libdwarf/dwarf_get_abbrev.c b/libdwarf/dwarf_get_abbrev.c new file mode 100644 index 00000000..0295f9bd --- /dev/null +++ b/libdwarf/dwarf_get_abbrev.c @@ -0,0 +1,111 @@ +/* Get abbreviation record. + Copyright (C) 2000, 2001, 2002 Red Hat, Inc. + Written by Ulrich Drepper <drepper@redhat.com>, 2000. + + This program is Open Source software; you can redistribute it and/or + modify it under the terms of the Open Software License version 1.0 as + published by the Open Source Initiative. + + You should have received a copy of the Open Software License along + with this program; if not, you may obtain a copy of the Open Software + License version 1.0 from http://www.opensource.org/licenses/osl.php or + by writing the Open Source Initiative c/o Lawrence Rosen, Esq., + 3001 King Ranch Road, Ukiah, CA 95482. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include <stdlib.h> + +#include <libdwarfP.h> + + +int +dwarf_get_abbrev (dbg, offset, return_abbrev, length, attr_count, error) + Dwarf_Debug dbg; + Dwarf_Unsigned offset; + Dwarf_Abbrev *return_abbrev; + Dwarf_Unsigned *length; + Dwarf_Unsigned *attr_count; + Dwarf_Error *error; +{ + Dwarf_Abbrev ent; + Dwarf_Small *abbrevp; + Dwarf_Small *start_abbrevp; + + /* Address in memory. */ + abbrevp = (Dwarf_Small *) dbg->sections[IDX_debug_abbrev].addr + offset; + + /* Remember where we started. */ + start_abbrevp = abbrevp; + + if (*abbrevp != '\0') + { + /* 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. */ + Dwarf_Word abbrev_code; + Dwarf_Word abbrev_tag; + Dwarf_Word attr_name; + Dwarf_Word attr_form; + Dwarf_Unsigned attrcnt; + + /* XXX We have no tests for crossing the section boundary here. + We should compare with dbg->sections[IDX_debug_abbrev].size. */ + get_uleb128 (abbrev_code, abbrevp); + get_uleb128 (abbrev_tag, abbrevp); + + /* Get memory for the result. */ + ent = (Dwarf_Abbrev) malloc (sizeof (struct Dwarf_Abbrev_s)); + if (ent == NULL) + { + __libdwarf_error (dbg, error, DW_E_NOMEM); + return DW_DLV_ERROR; + } + + ent->code = abbrev_code; + ent->tag = abbrev_tag; + ent->has_children = *abbrevp++ == DW_CHILDREN_yes; + ent->attrp = abbrevp; + ent->offset = offset; + + /* Skip over all the attributes. */ + attrcnt = 0; + do + { + get_uleb128 (attr_name, abbrevp); + get_uleb128 (attr_form, abbrevp); + } + while (attr_name != 0 && attr_form != 0 && ++attrcnt); + + /* Number of attributes. */ + *attr_count = ent->attrcnt = attrcnt; + + /* Store the actual abbreviation record. */ + *return_abbrev = ent; + } + else + /* Read over the NUL byte. */ + ++abbrevp; + + /* Length of the entry. */ + *length = abbrevp - start_abbrevp; + + /* If we come here we haven't found anything. */ + return DW_DLV_OK; +} |