summaryrefslogtreecommitdiff
path: root/libdwarf/dwarf_get_abbrev.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdwarf/dwarf_get_abbrev.c')
-rw-r--r--libdwarf/dwarf_get_abbrev.c111
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;
+}