blob: bef5a1129b8c46742ff4ce1790ae3b9e0510e131 [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Return attribute list for die.
2 Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
3 Written by Ulrich Drepper <drepper@redhat.com>, 2000.
4
5 This program is Open Source software; you can redistribute it and/or
6 modify it under the terms of the Open Software License version 1.0 as
7 published by the Open Source Initiative.
8
9 You should have received a copy of the Open Software License along
10 with this program; if not, you may obtain a copy of the Open Software
11 License version 1.0 from http://www.opensource.org/licenses/osl.php or
12 by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
13 3001 King Ranch Road, Ukiah, CA 95482. */
14
15#ifdef HAVE_CONFIG_H
16# include <config.h>
17#endif
18
19#include <stdlib.h>
20
21#include <libdwarfP.h>
22
23
24struct attrlist
25{
26 struct attrlist *next;
27 Dwarf_Attribute attr;
28};
29
30
31int
32dwarf_attrlist (die, attrbuf, attrcount, error)
33 Dwarf_Die die;
34 Dwarf_Attribute **attrbuf;
35 Dwarf_Signed *attrcount;
36 Dwarf_Error *error;
37{
38 Dwarf_Debug dbg = die->cu->dbg;
39 Dwarf_Small *die_addr;
40 Dwarf_Word u128;
41 Dwarf_Abbrev abbrev;
42 Dwarf_Small *attrp;
43 struct attrlist *alist;
44 int nattr;
45 Dwarf_Attribute *result;
46
47 /* Address of the given die. */
48 die_addr = die->addr;
49
50 /* Get abbrev code. */
51 get_uleb128 (u128, die_addr);
52 /* And get the abbreviation itself. */
53 abbrev = __libdwarf_get_abbrev (dbg, die->cu, u128, error);
54 if (abbrev == NULL)
55 return DW_DLV_ERROR;
56
57 /* This is where the attributes start. */
58 attrp = abbrev->attrp;
59
60 /* Initialize the list. We create one because we don't know yet how
61 many attributes there will be. */
62 alist = NULL;
63 nattr = 0;
64
65 /* Go over the list of attributes. */
66 while (1)
67 {
68 Dwarf_Word attr_name;
69 Dwarf_Word attr_form;
70 Dwarf_Attribute new_attr;
71 struct attrlist *new_alist;
72
73 /* Are we still in bounds? */
74 if (unlikely (attrp
75 >= ((Dwarf_Small *) dbg->sections[IDX_debug_abbrev].addr
76 + dbg->sections[IDX_debug_abbrev].size)))
77 {
78 while (alist != NULL)
79 {
80 free (alist->attr);
81 alist = alist->next;
82 }
83
84 __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
85 return DW_DLV_ERROR;
86 }
87
88 /* Get attribute name and form.
89
90 XXX We don't check whether this reads beyond the end of the
91 section. */
92 get_uleb128 (attr_name, attrp);
93 get_uleb128 (attr_form, attrp);
94
95 /* We can stop if we found the attribute with value zero. */
96 if (attr_name == 0 && attr_form == 0)
97 break;
98
99 /* Allocate the attribute data structure. */
100 new_attr = (Dwarf_Attribute) malloc (sizeof (struct Dwarf_Attribute_s));
101 if (new_attr == NULL)
102 {
103 while (alist != NULL)
104 {
105 free (alist->attr);
106 alist = alist->next;
107 }
108
109 __libdwarf_error (dbg, error, DW_E_NOMEM);
110 return DW_DLV_ERROR;
111 }
112
113 /* Fill in the values. */
114 new_attr->code = attr_name;
115 new_attr->form = attr_form;
116 new_attr->valp = die_addr;
117 new_attr->cu = die->cu;
118
119 /* Enqueue. */
120 new_alist = (struct attrlist *) alloca (sizeof (struct attrlist));
121 new_alist->attr = new_attr;
122 new_alist->next = alist;
123 alist = new_alist;
124 ++nattr;
125
126 /* Skip over the rest of this attribute (if there is any). */
127 if (attr_form != 0)
128 {
129 size_t len;
130
131 if (unlikely (__libdwarf_form_val_len (dbg, die->cu, attr_form,
132 die_addr, &len, error)
133 != DW_DLV_OK))
134 {
135 while (alist != NULL)
136 {
137 free (alist->attr);
138 alist = alist->next;
139 }
140
141 return DW_DLV_ERROR;
142 }
143
144 die_addr += len;
145 }
146 }
147
148 if (nattr == 0)
149 {
150 *attrcount = 0;
151 *attrbuf = NULL;
152 return DW_DLV_NO_ENTRY;
153 }
154
155 /* Allocate the array for the result. */
156 result = (Dwarf_Attribute *) malloc (nattr * sizeof (Dwarf_Attribute));
157 if (result == NULL)
158 {
159 while (alist != NULL)
160 {
161 free (alist->attr);
162 alist = alist->next;
163 }
164
165 __libdwarf_error (dbg, error, DW_E_NOMEM);
166 return DW_DLV_ERROR;
167 }
168
169 /* Store the number of attributes and the result pointer. */
170 *attrcount = nattr;
171 *attrbuf = result;
172
173 /* Put the attribute entries in the array (in the right order). */
174 do
175 {
176 result[--nattr] = alist->attr;
177 alist = alist->next;
178 }
179 while (nattr > 0);
180
181 return DW_DLV_OK;
182}