dwarf_attr.c revision 302408
1/*-
2 * Copyright (c) 2007 John Birrell (jb@freebsd.org)
3 * Copyright (c) 2009 Kai Wang
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include "_libdwarf.h"
29
30ELFTC_VCSID("$Id: dwarf_attr.c 3064 2014-06-06 19:35:55Z kaiwang27 $");
31
32int
33dwarf_attr(Dwarf_Die die, Dwarf_Half attr, Dwarf_Attribute *atp,
34    Dwarf_Error *error)
35{
36	Dwarf_Debug dbg;
37	Dwarf_Attribute at;
38
39	dbg = die != NULL ? die->die_dbg : NULL;
40
41	if (die == NULL || atp == NULL) {
42		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
43		return (DW_DLV_ERROR);
44	}
45
46	if ((at = _dwarf_attr_find(die, attr)) == NULL) {
47		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
48		return (DW_DLV_NO_ENTRY);
49	}
50
51	*atp = at;
52
53	return (DW_DLV_OK);
54}
55
56int
57dwarf_attrlist(Dwarf_Die die, Dwarf_Attribute **attrbuf,
58    Dwarf_Signed *attrcount, Dwarf_Error *error)
59{
60	Dwarf_Attribute at;
61	Dwarf_Debug dbg;
62	int i;
63
64	dbg = die != NULL ? die->die_dbg : NULL;
65
66	if (die == NULL || attrbuf == NULL || attrcount == NULL) {
67		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
68		return (DW_DLV_ERROR);
69	}
70
71	if (die->die_ab->ab_atnum == 0) {
72		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
73		return (DW_DLV_NO_ENTRY);
74	}
75
76	*attrcount = die->die_ab->ab_atnum;
77
78	if (die->die_attrarray != NULL) {
79		*attrbuf = die->die_attrarray;
80		return (DW_DLV_OK);
81	}
82
83	if ((die->die_attrarray = malloc(*attrcount * sizeof(Dwarf_Attribute)))
84	    == NULL) {
85		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
86		return (DW_DLV_ERROR);
87	}
88
89	for (i = 0, at = STAILQ_FIRST(&die->die_attr);
90	     i < *attrcount && at != NULL; i++, at = STAILQ_NEXT(at, at_next))
91		die->die_attrarray[i] = at;
92
93	*attrbuf = die->die_attrarray;
94
95	return (DW_DLV_OK);
96}
97
98int
99dwarf_hasattr(Dwarf_Die die, Dwarf_Half attr, Dwarf_Bool *ret_bool,
100    Dwarf_Error *error)
101{
102	Dwarf_Debug dbg;
103
104	dbg = die != NULL ? die->die_dbg : NULL;
105
106	if (die == NULL || ret_bool == NULL) {
107		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
108		return (DW_DLV_ERROR);
109	}
110
111	*ret_bool = (_dwarf_attr_find(die, attr) != NULL);
112
113	return (DW_DLV_OK);
114}
115
116int
117dwarf_attroffset(Dwarf_Attribute at, Dwarf_Off *ret_off, Dwarf_Error *error)
118{
119	Dwarf_Debug dbg;
120
121	dbg = at != NULL ? at->at_die->die_dbg : NULL;
122
123	if (at == NULL || ret_off == NULL) {
124		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
125		return (DW_DLV_ERROR);
126	}
127
128	*ret_off = at->at_offset;
129
130	return (DW_DLV_OK);
131}
132
133int
134dwarf_lowpc(Dwarf_Die die, Dwarf_Addr *ret_lowpc, Dwarf_Error *error)
135{
136	Dwarf_Attribute at;
137	Dwarf_Debug dbg;
138
139	dbg = die != NULL ? die->die_dbg : NULL;
140
141	if (die == NULL || ret_lowpc == NULL) {
142		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
143		return (DW_DLV_ERROR);
144	}
145
146	if ((at = _dwarf_attr_find(die, DW_AT_low_pc)) == NULL) {
147		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
148		return (DW_DLV_NO_ENTRY);
149	}
150
151	*ret_lowpc = at->u[0].u64;
152
153	return (DW_DLV_OK);
154}
155
156int
157dwarf_highpc(Dwarf_Die die, Dwarf_Addr *ret_highpc, Dwarf_Error *error)
158{
159
160	return (dwarf_highpc_b(die, ret_highpc, NULL, NULL, error));
161}
162
163int
164dwarf_highpc_b(Dwarf_Die die, Dwarf_Addr *ret_highpc, Dwarf_Half *ret_form,
165    enum Dwarf_Form_Class *ret_class, Dwarf_Error *error)
166{
167	Dwarf_Attribute at;
168	Dwarf_Debug dbg;
169	Dwarf_CU cu;
170
171	dbg = die != NULL ? die->die_dbg : NULL;
172
173	if (die == NULL || ret_highpc == NULL) {
174		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
175		return (DW_DLV_ERROR);
176	}
177
178	if ((at = _dwarf_attr_find(die, DW_AT_high_pc)) == NULL) {
179		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
180		return (DW_DLV_NO_ENTRY);
181	}
182
183	*ret_highpc = at->u[0].u64;
184
185	if (ret_form != NULL) {
186		*ret_form = at->at_form;
187	}
188
189	if (ret_class != NULL) {
190		cu = die->die_cu;
191		*ret_class = dwarf_get_form_class(cu->cu_version,
192		    DW_AT_high_pc, cu->cu_length_size == 4 ? 4 : 8,
193		    at->at_form);
194	}
195
196	return (DW_DLV_OK);
197}
198
199int
200dwarf_bytesize(Dwarf_Die die, Dwarf_Unsigned *ret_size, Dwarf_Error *error)
201{
202	Dwarf_Attribute at;
203	Dwarf_Debug dbg;
204
205	dbg = die != NULL ? die->die_dbg : NULL;
206
207	if (die == NULL || ret_size == NULL) {
208		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
209		return (DW_DLV_ERROR);
210	}
211
212	if ((at = _dwarf_attr_find(die, DW_AT_byte_size)) == NULL) {
213		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
214		return (DW_DLV_NO_ENTRY);
215	}
216
217	*ret_size = at->u[0].u64;
218
219	return (DW_DLV_OK);
220}
221
222int
223dwarf_bitsize(Dwarf_Die die, Dwarf_Unsigned *ret_size, Dwarf_Error *error)
224{
225	Dwarf_Attribute at;
226	Dwarf_Debug dbg;
227
228	dbg = die != NULL ? die->die_dbg : NULL;
229
230	if (die == NULL || ret_size == NULL) {
231		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
232		return (DW_DLV_ERROR);
233	}
234
235	if ((at = _dwarf_attr_find(die, DW_AT_bit_size)) == NULL) {
236		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
237		return (DW_DLV_NO_ENTRY);
238	}
239
240	*ret_size = at->u[0].u64;
241
242	return (DW_DLV_OK);
243}
244
245int
246dwarf_bitoffset(Dwarf_Die die, Dwarf_Unsigned *ret_size, Dwarf_Error *error)
247{
248	Dwarf_Attribute at;
249	Dwarf_Debug dbg;
250
251	dbg = die != NULL ? die->die_dbg : NULL;
252
253	if (die == NULL || ret_size == NULL) {
254		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
255		return (DW_DLV_ERROR);
256	}
257
258	if ((at = _dwarf_attr_find(die, DW_AT_bit_offset)) == NULL) {
259		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
260		return (DW_DLV_NO_ENTRY);
261	}
262
263	*ret_size = at->u[0].u64;
264
265	return (DW_DLV_OK);
266}
267
268int
269dwarf_srclang(Dwarf_Die die, Dwarf_Unsigned *ret_lang, Dwarf_Error *error)
270{
271	Dwarf_Attribute at;
272	Dwarf_Debug dbg;
273
274	dbg = die != NULL ? die->die_dbg : NULL;
275
276	if (die == NULL || ret_lang == NULL) {
277		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
278		return (DW_DLV_ERROR);
279	}
280
281	if ((at = _dwarf_attr_find(die, DW_AT_language)) == NULL) {
282		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
283		return (DW_DLV_NO_ENTRY);
284	}
285
286	*ret_lang = at->u[0].u64;
287
288	return (DW_DLV_OK);
289}
290
291int
292dwarf_arrayorder(Dwarf_Die die, Dwarf_Unsigned *ret_order, Dwarf_Error *error)
293{
294	Dwarf_Attribute at;
295	Dwarf_Debug dbg;
296
297	dbg = die != NULL ? die->die_dbg : NULL;
298
299	if (die == NULL || ret_order == NULL) {
300		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
301		return (DW_DLV_ERROR);
302	}
303
304	if ((at = _dwarf_attr_find(die, DW_AT_ordering)) == NULL) {
305		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
306		return (DW_DLV_NO_ENTRY);
307	}
308
309	*ret_order = at->u[0].u64;
310
311	return (DW_DLV_OK);
312}
313