1260684Skaiw/*-
2260684Skaiw * Copyright (c) 2007 John Birrell (jb@freebsd.org)
3260684Skaiw * Copyright (c) 2009 Kai Wang
4260684Skaiw * All rights reserved.
5260684Skaiw *
6260684Skaiw * Redistribution and use in source and binary forms, with or without
7260684Skaiw * modification, are permitted provided that the following conditions
8260684Skaiw * are met:
9260684Skaiw * 1. Redistributions of source code must retain the above copyright
10260684Skaiw *    notice, this list of conditions and the following disclaimer.
11260684Skaiw * 2. Redistributions in binary form must reproduce the above copyright
12260684Skaiw *    notice, this list of conditions and the following disclaimer in the
13260684Skaiw *    documentation and/or other materials provided with the distribution.
14260684Skaiw *
15260684Skaiw * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16260684Skaiw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17260684Skaiw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18260684Skaiw * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19260684Skaiw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20260684Skaiw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21260684Skaiw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22260684Skaiw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23260684Skaiw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24260684Skaiw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25260684Skaiw * SUCH DAMAGE.
26260684Skaiw */
27260684Skaiw
28260684Skaiw#include "_libdwarf.h"
29260684Skaiw
30276371SemasteELFTC_VCSID("$Id: dwarf_attr.c 3064 2014-06-06 19:35:55Z kaiwang27 $");
31260684Skaiw
32260684Skaiwint
33260684Skaiwdwarf_attr(Dwarf_Die die, Dwarf_Half attr, Dwarf_Attribute *atp,
34260684Skaiw    Dwarf_Error *error)
35260684Skaiw{
36260684Skaiw	Dwarf_Debug dbg;
37260684Skaiw	Dwarf_Attribute at;
38260684Skaiw
39260684Skaiw	dbg = die != NULL ? die->die_dbg : NULL;
40260684Skaiw
41260684Skaiw	if (die == NULL || atp == NULL) {
42260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
43260684Skaiw		return (DW_DLV_ERROR);
44260684Skaiw	}
45260684Skaiw
46260684Skaiw	if ((at = _dwarf_attr_find(die, attr)) == NULL) {
47260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
48260684Skaiw		return (DW_DLV_NO_ENTRY);
49260684Skaiw	}
50260684Skaiw
51260684Skaiw	*atp = at;
52260684Skaiw
53260684Skaiw	return (DW_DLV_OK);
54260684Skaiw}
55260684Skaiw
56260684Skaiwint
57260684Skaiwdwarf_attrlist(Dwarf_Die die, Dwarf_Attribute **attrbuf,
58260684Skaiw    Dwarf_Signed *attrcount, Dwarf_Error *error)
59260684Skaiw{
60260684Skaiw	Dwarf_Attribute at;
61260684Skaiw	Dwarf_Debug dbg;
62260684Skaiw	int i;
63260684Skaiw
64260684Skaiw	dbg = die != NULL ? die->die_dbg : NULL;
65260684Skaiw
66260684Skaiw	if (die == NULL || attrbuf == NULL || attrcount == NULL) {
67260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
68260684Skaiw		return (DW_DLV_ERROR);
69260684Skaiw	}
70260684Skaiw
71260684Skaiw	if (die->die_ab->ab_atnum == 0) {
72260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
73260684Skaiw		return (DW_DLV_NO_ENTRY);
74260684Skaiw	}
75260684Skaiw
76260684Skaiw	*attrcount = die->die_ab->ab_atnum;
77260684Skaiw
78260684Skaiw	if (die->die_attrarray != NULL) {
79260684Skaiw		*attrbuf = die->die_attrarray;
80260684Skaiw		return (DW_DLV_OK);
81260684Skaiw	}
82260684Skaiw
83260684Skaiw	if ((die->die_attrarray = malloc(*attrcount * sizeof(Dwarf_Attribute)))
84260684Skaiw	    == NULL) {
85260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
86260684Skaiw		return (DW_DLV_ERROR);
87260684Skaiw	}
88260684Skaiw
89260684Skaiw	for (i = 0, at = STAILQ_FIRST(&die->die_attr);
90260684Skaiw	     i < *attrcount && at != NULL; i++, at = STAILQ_NEXT(at, at_next))
91260684Skaiw		die->die_attrarray[i] = at;
92260684Skaiw
93260684Skaiw	*attrbuf = die->die_attrarray;
94260684Skaiw
95260684Skaiw	return (DW_DLV_OK);
96260684Skaiw}
97260684Skaiw
98260684Skaiwint
99260684Skaiwdwarf_hasattr(Dwarf_Die die, Dwarf_Half attr, Dwarf_Bool *ret_bool,
100260684Skaiw    Dwarf_Error *error)
101260684Skaiw{
102260684Skaiw	Dwarf_Debug dbg;
103260684Skaiw
104260684Skaiw	dbg = die != NULL ? die->die_dbg : NULL;
105260684Skaiw
106260684Skaiw	if (die == NULL || ret_bool == NULL) {
107260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
108260684Skaiw		return (DW_DLV_ERROR);
109260684Skaiw	}
110260684Skaiw
111260684Skaiw	*ret_bool = (_dwarf_attr_find(die, attr) != NULL);
112260684Skaiw
113260684Skaiw	return (DW_DLV_OK);
114260684Skaiw}
115260684Skaiw
116260684Skaiwint
117276371Semastedwarf_attroffset(Dwarf_Attribute at, Dwarf_Off *ret_off, Dwarf_Error *error)
118276371Semaste{
119276371Semaste	Dwarf_Debug dbg;
120276371Semaste
121276371Semaste	dbg = at != NULL ? at->at_die->die_dbg : NULL;
122276371Semaste
123276371Semaste	if (at == NULL || ret_off == NULL) {
124276371Semaste		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
125276371Semaste		return (DW_DLV_ERROR);
126276371Semaste	}
127276371Semaste
128276371Semaste	*ret_off = at->at_offset;
129276371Semaste
130276371Semaste	return (DW_DLV_OK);
131276371Semaste}
132276371Semaste
133276371Semasteint
134260684Skaiwdwarf_lowpc(Dwarf_Die die, Dwarf_Addr *ret_lowpc, Dwarf_Error *error)
135260684Skaiw{
136260684Skaiw	Dwarf_Attribute at;
137260684Skaiw	Dwarf_Debug dbg;
138260684Skaiw
139260684Skaiw	dbg = die != NULL ? die->die_dbg : NULL;
140260684Skaiw
141260684Skaiw	if (die == NULL || ret_lowpc == NULL) {
142260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
143260684Skaiw		return (DW_DLV_ERROR);
144260684Skaiw	}
145260684Skaiw
146260684Skaiw	if ((at = _dwarf_attr_find(die, DW_AT_low_pc)) == NULL) {
147260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
148260684Skaiw		return (DW_DLV_NO_ENTRY);
149260684Skaiw	}
150260684Skaiw
151260684Skaiw	*ret_lowpc = at->u[0].u64;
152260684Skaiw
153260684Skaiw	return (DW_DLV_OK);
154260684Skaiw}
155260684Skaiw
156260684Skaiwint
157260684Skaiwdwarf_highpc(Dwarf_Die die, Dwarf_Addr *ret_highpc, Dwarf_Error *error)
158260684Skaiw{
159276371Semaste
160276371Semaste	return (dwarf_highpc_b(die, ret_highpc, NULL, NULL, error));
161276371Semaste}
162276371Semaste
163276371Semasteint
164276371Semastedwarf_highpc_b(Dwarf_Die die, Dwarf_Addr *ret_highpc, Dwarf_Half *ret_form,
165276371Semaste    enum Dwarf_Form_Class *ret_class, Dwarf_Error *error)
166276371Semaste{
167260684Skaiw	Dwarf_Attribute at;
168260684Skaiw	Dwarf_Debug dbg;
169276371Semaste	Dwarf_CU cu;
170260684Skaiw
171260684Skaiw	dbg = die != NULL ? die->die_dbg : NULL;
172260684Skaiw
173260684Skaiw	if (die == NULL || ret_highpc == NULL) {
174260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
175260684Skaiw		return (DW_DLV_ERROR);
176260684Skaiw	}
177260684Skaiw
178260684Skaiw	if ((at = _dwarf_attr_find(die, DW_AT_high_pc)) == NULL) {
179260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
180260684Skaiw		return (DW_DLV_NO_ENTRY);
181260684Skaiw	}
182260684Skaiw
183260684Skaiw	*ret_highpc = at->u[0].u64;
184260684Skaiw
185276371Semaste	if (ret_form != NULL) {
186276371Semaste		*ret_form = at->at_form;
187276371Semaste	}
188276371Semaste
189276371Semaste	if (ret_class != NULL) {
190276371Semaste		cu = die->die_cu;
191276371Semaste		*ret_class = dwarf_get_form_class(cu->cu_version,
192276371Semaste		    DW_AT_high_pc, cu->cu_length_size == 4 ? 4 : 8,
193276371Semaste		    at->at_form);
194276371Semaste	}
195276371Semaste
196260684Skaiw	return (DW_DLV_OK);
197260684Skaiw}
198260684Skaiw
199260684Skaiwint
200260684Skaiwdwarf_bytesize(Dwarf_Die die, Dwarf_Unsigned *ret_size, Dwarf_Error *error)
201260684Skaiw{
202260684Skaiw	Dwarf_Attribute at;
203260684Skaiw	Dwarf_Debug dbg;
204260684Skaiw
205260684Skaiw	dbg = die != NULL ? die->die_dbg : NULL;
206260684Skaiw
207260684Skaiw	if (die == NULL || ret_size == NULL) {
208260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
209260684Skaiw		return (DW_DLV_ERROR);
210260684Skaiw	}
211260684Skaiw
212260684Skaiw	if ((at = _dwarf_attr_find(die, DW_AT_byte_size)) == NULL) {
213260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
214260684Skaiw		return (DW_DLV_NO_ENTRY);
215260684Skaiw	}
216260684Skaiw
217260684Skaiw	*ret_size = at->u[0].u64;
218260684Skaiw
219260684Skaiw	return (DW_DLV_OK);
220260684Skaiw}
221260684Skaiw
222260684Skaiwint
223260684Skaiwdwarf_bitsize(Dwarf_Die die, Dwarf_Unsigned *ret_size, Dwarf_Error *error)
224260684Skaiw{
225260684Skaiw	Dwarf_Attribute at;
226260684Skaiw	Dwarf_Debug dbg;
227260684Skaiw
228260684Skaiw	dbg = die != NULL ? die->die_dbg : NULL;
229260684Skaiw
230260684Skaiw	if (die == NULL || ret_size == NULL) {
231260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
232260684Skaiw		return (DW_DLV_ERROR);
233260684Skaiw	}
234260684Skaiw
235260684Skaiw	if ((at = _dwarf_attr_find(die, DW_AT_bit_size)) == NULL) {
236260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
237260684Skaiw		return (DW_DLV_NO_ENTRY);
238260684Skaiw	}
239260684Skaiw
240260684Skaiw	*ret_size = at->u[0].u64;
241260684Skaiw
242260684Skaiw	return (DW_DLV_OK);
243260684Skaiw}
244260684Skaiw
245260684Skaiwint
246260684Skaiwdwarf_bitoffset(Dwarf_Die die, Dwarf_Unsigned *ret_size, Dwarf_Error *error)
247260684Skaiw{
248260684Skaiw	Dwarf_Attribute at;
249260684Skaiw	Dwarf_Debug dbg;
250260684Skaiw
251260684Skaiw	dbg = die != NULL ? die->die_dbg : NULL;
252260684Skaiw
253260684Skaiw	if (die == NULL || ret_size == NULL) {
254260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
255260684Skaiw		return (DW_DLV_ERROR);
256260684Skaiw	}
257260684Skaiw
258260684Skaiw	if ((at = _dwarf_attr_find(die, DW_AT_bit_offset)) == NULL) {
259260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
260260684Skaiw		return (DW_DLV_NO_ENTRY);
261260684Skaiw	}
262260684Skaiw
263260684Skaiw	*ret_size = at->u[0].u64;
264260684Skaiw
265260684Skaiw	return (DW_DLV_OK);
266260684Skaiw}
267260684Skaiw
268260684Skaiwint
269260684Skaiwdwarf_srclang(Dwarf_Die die, Dwarf_Unsigned *ret_lang, Dwarf_Error *error)
270260684Skaiw{
271260684Skaiw	Dwarf_Attribute at;
272260684Skaiw	Dwarf_Debug dbg;
273260684Skaiw
274260684Skaiw	dbg = die != NULL ? die->die_dbg : NULL;
275260684Skaiw
276260684Skaiw	if (die == NULL || ret_lang == NULL) {
277260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
278260684Skaiw		return (DW_DLV_ERROR);
279260684Skaiw	}
280260684Skaiw
281260684Skaiw	if ((at = _dwarf_attr_find(die, DW_AT_language)) == NULL) {
282260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
283260684Skaiw		return (DW_DLV_NO_ENTRY);
284260684Skaiw	}
285260684Skaiw
286260684Skaiw	*ret_lang = at->u[0].u64;
287260684Skaiw
288260684Skaiw	return (DW_DLV_OK);
289260684Skaiw}
290260684Skaiw
291260684Skaiwint
292260684Skaiwdwarf_arrayorder(Dwarf_Die die, Dwarf_Unsigned *ret_order, Dwarf_Error *error)
293260684Skaiw{
294260684Skaiw	Dwarf_Attribute at;
295260684Skaiw	Dwarf_Debug dbg;
296260684Skaiw
297260684Skaiw	dbg = die != NULL ? die->die_dbg : NULL;
298260684Skaiw
299260684Skaiw	if (die == NULL || ret_order == NULL) {
300260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
301260684Skaiw		return (DW_DLV_ERROR);
302260684Skaiw	}
303260684Skaiw
304260684Skaiw	if ((at = _dwarf_attr_find(die, DW_AT_ordering)) == NULL) {
305260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
306260684Skaiw		return (DW_DLV_NO_ENTRY);
307260684Skaiw	}
308260684Skaiw
309260684Skaiw	*ret_order = at->u[0].u64;
310260684Skaiw
311260684Skaiw	return (DW_DLV_OK);
312260684Skaiw}
313