dwarf_form.c revision 261246
1/*-
2 * Copyright (c) 2007 John Birrell (jb@freebsd.org)
3 * Copyright (c) 2009,2010 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_form.c 2073 2011-10-27 03:30:47Z jkoshy $");
31
32int
33dwarf_hasform(Dwarf_Attribute at, Dwarf_Half form, Dwarf_Bool *return_hasform,
34    Dwarf_Error *error)
35{
36	Dwarf_Debug dbg;
37
38	dbg = at != NULL ? at->at_die->die_dbg : NULL;
39
40	if (at == NULL || return_hasform == NULL) {
41		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
42		return (DW_DLV_ERROR);
43	}
44
45	*return_hasform = (at->at_form == form);
46
47	return (DW_DLV_OK);
48}
49
50int
51dwarf_whatform(Dwarf_Attribute at, Dwarf_Half *return_form, Dwarf_Error *error)
52{
53	Dwarf_Debug dbg;
54
55	dbg = at != NULL ? at->at_die->die_dbg : NULL;
56
57	if (at == NULL || return_form == NULL) {
58		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
59		return (DW_DLV_ERROR);
60	}
61
62	*return_form = at->at_form;
63
64	return (DW_DLV_OK);
65}
66
67int
68dwarf_whatform_direct(Dwarf_Attribute at, Dwarf_Half *return_form,
69    Dwarf_Error *error)
70{
71	Dwarf_Debug dbg;
72
73	dbg = at != NULL ? at->at_die->die_dbg : NULL;
74
75	if (at == NULL || return_form == NULL) {
76		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
77		return (DW_DLV_ERROR);
78	}
79
80	if (at->at_indirect)
81		*return_form = DW_FORM_indirect;
82	else
83		*return_form = (Dwarf_Half) at->at_form;
84
85	return (DW_DLV_OK);
86}
87
88int
89dwarf_whatattr(Dwarf_Attribute at, Dwarf_Half *return_attr, Dwarf_Error *error)
90{
91	Dwarf_Debug dbg;
92
93	dbg = at != NULL ? at->at_die->die_dbg : NULL;
94
95	if (at == NULL || return_attr == NULL) {
96		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
97		return (DW_DLV_ERROR);
98	}
99
100	*return_attr = (Dwarf_Half) at->at_attrib;
101
102	return (DW_DLV_OK);
103}
104
105int
106dwarf_formref(Dwarf_Attribute at, Dwarf_Off *return_offset, Dwarf_Error *error)
107{
108	int ret;
109	Dwarf_Debug dbg;
110
111	dbg = at != NULL ? at->at_die->die_dbg : NULL;
112
113	if (at == NULL || return_offset == NULL) {
114		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
115		return (DW_DLV_ERROR);
116	}
117
118	switch (at->at_form) {
119	case DW_FORM_ref1:
120	case DW_FORM_ref2:
121	case DW_FORM_ref4:
122	case DW_FORM_ref8:
123	case DW_FORM_ref_udata:
124		*return_offset = (Dwarf_Off) at->u[0].u64;
125		ret = DW_DLV_OK;
126		break;
127	default:
128		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
129		ret = DW_DLV_ERROR;
130	}
131
132	return (ret);
133}
134
135int
136dwarf_global_formref(Dwarf_Attribute at, Dwarf_Off *return_offset,
137    Dwarf_Error *error)
138{
139	int ret;
140	Dwarf_Debug dbg;
141
142	dbg = at != NULL ? at->at_die->die_dbg : NULL;
143
144	if (at == NULL || return_offset == NULL) {
145		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
146		return (DW_DLV_ERROR);
147	}
148
149	switch (at->at_form) {
150	case DW_FORM_ref_addr:
151	case DW_FORM_sec_offset:
152		*return_offset = (Dwarf_Off) at->u[0].u64;
153		ret = DW_DLV_OK;
154		break;
155	case DW_FORM_ref1:
156	case DW_FORM_ref2:
157	case DW_FORM_ref4:
158	case DW_FORM_ref8:
159	case DW_FORM_ref_udata:
160		*return_offset = (Dwarf_Off) at->u[0].u64 +
161			at->at_die->die_cu->cu_offset;
162		ret = DW_DLV_OK;
163		break;
164	default:
165		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
166		ret = DW_DLV_ERROR;
167	}
168
169	return (ret);
170}
171
172int
173dwarf_formaddr(Dwarf_Attribute at, Dwarf_Addr *return_addr, Dwarf_Error *error)
174{
175	int ret;
176	Dwarf_Debug dbg;
177
178	dbg = at != NULL ? at->at_die->die_dbg : NULL;
179
180	if (at == NULL || return_addr == NULL) {
181		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
182		return (DW_DLV_ERROR);
183	}
184
185	if (at->at_form == DW_FORM_addr) {
186		*return_addr = at->u[0].u64;
187		ret = DW_DLV_OK;
188	} else {
189		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
190		ret = DW_DLV_ERROR;
191	}
192
193	return (ret);
194}
195
196int
197dwarf_formflag(Dwarf_Attribute at, Dwarf_Bool *return_bool, Dwarf_Error *error)
198{
199	int ret;
200	Dwarf_Debug dbg;
201
202	dbg = at != NULL ? at->at_die->die_dbg : NULL;
203
204	if (at == NULL || return_bool == NULL) {
205		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
206		return (DW_DLV_ERROR);
207	}
208
209	if (at->at_form == DW_FORM_flag ||
210	    at->at_form == DW_FORM_flag_present) {
211		*return_bool = (Dwarf_Bool) (!!at->u[0].u64);
212		ret = DW_DLV_OK;
213	} else {
214		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
215		ret = DW_DLV_ERROR;
216	}
217
218	return (ret);
219}
220
221int
222dwarf_formudata(Dwarf_Attribute at, Dwarf_Unsigned *return_uvalue,
223    Dwarf_Error *error)
224{
225	int ret;
226	Dwarf_Debug dbg;
227
228	dbg = at != NULL ? at->at_die->die_dbg : NULL;
229
230	if (at == NULL || return_uvalue == NULL) {
231		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
232		return (DW_DLV_ERROR);
233	}
234
235	switch (at->at_form) {
236	case DW_FORM_data1:
237	case DW_FORM_data2:
238	case DW_FORM_data4:
239	case DW_FORM_data8:
240	case DW_FORM_udata:
241		*return_uvalue = at->u[0].u64;
242		ret = DW_DLV_OK;
243		break;
244	default:
245		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
246		ret = DW_DLV_ERROR;
247	}
248
249	return (ret);
250}
251
252int
253dwarf_formsdata(Dwarf_Attribute at, Dwarf_Signed *return_svalue,
254    Dwarf_Error *error)
255{
256	int ret;
257	Dwarf_Debug dbg;
258
259	dbg = at != NULL ? at->at_die->die_dbg : NULL;
260
261	if (at == NULL || return_svalue == NULL) {
262		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
263		return (DW_DLV_ERROR);
264	}
265
266	switch (at->at_form) {
267	case DW_FORM_data1:
268		*return_svalue = (int8_t) at->u[0].s64;
269		ret = DW_DLV_OK;
270		break;
271	case DW_FORM_data2:
272		*return_svalue = (int16_t) at->u[0].s64;
273		ret = DW_DLV_OK;
274		break;
275	case DW_FORM_data4:
276		*return_svalue = (int32_t) at->u[0].s64;
277		ret = DW_DLV_OK;
278		break;
279	case DW_FORM_data8:
280	case DW_FORM_sdata:
281		*return_svalue = at->u[0].s64;
282		ret = DW_DLV_OK;
283		break;
284	default:
285		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
286		ret = DW_DLV_ERROR;
287	}
288
289	return (ret);
290}
291
292int
293dwarf_formblock(Dwarf_Attribute at, Dwarf_Block **return_block,
294    Dwarf_Error *error)
295{
296	int ret;
297	Dwarf_Debug dbg;
298
299	dbg = at != NULL ? at->at_die->die_dbg : NULL;
300
301	if (at == NULL || return_block == NULL) {
302		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
303		return (DW_DLV_ERROR);
304	}
305
306	switch (at->at_form) {
307	case DW_FORM_block:
308	case DW_FORM_block1:
309	case DW_FORM_block2:
310	case DW_FORM_block4:
311		*return_block = &at->at_block;
312		ret = DW_DLV_OK;
313		break;
314	default:
315		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
316		ret = DW_DLV_ERROR;
317	}
318
319	return (ret);
320}
321
322int
323dwarf_formsig8(Dwarf_Attribute at, Dwarf_Sig8 *return_sig8, Dwarf_Error *error)
324{
325	Dwarf_Debug dbg;
326
327	dbg = at != NULL ? at->at_die->die_dbg : NULL;
328
329	if (at == NULL || return_sig8 == NULL) {
330		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
331		return (DW_DLV_ERROR);
332	}
333
334	if (at->at_form != DW_FORM_ref_sig8) {
335		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
336		return (DW_DLV_ERROR);
337	}
338
339	assert(at->u[0].u64 == 8);
340	memcpy(return_sig8->signature, at->u[1].u8p, at->u[0].u64);
341
342	return (DW_DLV_OK);
343}
344
345int
346dwarf_formexprloc(Dwarf_Attribute at, Dwarf_Unsigned *return_exprlen,
347    Dwarf_Ptr *return_expr, Dwarf_Error *error)
348{
349
350	Dwarf_Debug dbg;
351
352	dbg = at != NULL ? at->at_die->die_dbg : NULL;
353
354	if (at == NULL || return_exprlen == NULL || return_expr == NULL) {
355		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
356		return (DW_DLV_ERROR);
357	}
358
359	if (at->at_form != DW_FORM_exprloc) {
360		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
361		return (DW_DLV_ERROR);
362	}
363
364	*return_exprlen = at->u[0].u64;
365	*return_expr = (void *) at->u[1].u8p;
366
367	return (DW_DLV_OK);
368}
369
370int
371dwarf_formstring(Dwarf_Attribute at, char **return_string,
372    Dwarf_Error *error)
373{
374	int ret;
375	Dwarf_Debug dbg;
376
377	dbg = at != NULL ? at->at_die->die_dbg : NULL;
378
379	if (at == NULL || return_string == NULL) {
380		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
381		return (DW_DLV_ERROR);
382	}
383
384	switch (at->at_form) {
385	case DW_FORM_string:
386		*return_string = (char *) at->u[0].s;
387		ret = DW_DLV_OK;
388		break;
389	case DW_FORM_strp:
390		*return_string = (char *) at->u[1].s;
391		ret = DW_DLV_OK;
392		break;
393	default:
394		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
395		ret = DW_DLV_ERROR;
396	}
397
398	return (ret);
399}
400
401enum Dwarf_Form_Class
402dwarf_get_form_class(Dwarf_Half dwversion, Dwarf_Half attr,
403    Dwarf_Half offset_size, Dwarf_Half form)
404{
405
406	switch (form) {
407	case DW_FORM_addr:
408		return (DW_FORM_CLASS_ADDRESS);
409	case DW_FORM_block:
410	case DW_FORM_block1:
411	case DW_FORM_block2:
412	case DW_FORM_block4:
413		return (DW_FORM_CLASS_BLOCK);
414	case DW_FORM_string:
415	case DW_FORM_strp:
416		return (DW_FORM_CLASS_STRING);
417	case DW_FORM_flag:
418	case DW_FORM_flag_present:
419		return (DW_FORM_CLASS_FLAG);
420	case DW_FORM_ref_addr:
421	case DW_FORM_ref_sig8:
422	case DW_FORM_ref_udata:
423	case DW_FORM_ref1:
424	case DW_FORM_ref2:
425	case DW_FORM_ref4:
426	case DW_FORM_ref8:
427		return (DW_FORM_CLASS_REFERENCE);
428	case DW_FORM_exprloc:
429		return (DW_FORM_CLASS_EXPRLOC);
430	case DW_FORM_data1:
431	case DW_FORM_data2:
432	case DW_FORM_sdata:
433	case DW_FORM_udata:
434		return (DW_FORM_CLASS_CONSTANT);
435	case DW_FORM_data4:
436	case DW_FORM_data8:
437		if (dwversion > 3)
438			return (DW_FORM_CLASS_CONSTANT);
439		if (form == DW_FORM_data4 && offset_size != 4)
440			return (DW_FORM_CLASS_CONSTANT);
441		if (form == DW_FORM_data8 && offset_size != 8)
442			return (DW_FORM_CLASS_CONSTANT);
443		/* FALLTHROUGH */
444	case DW_FORM_sec_offset:
445		/*
446		 * DW_FORM_data4 and DW_FORM_data8 can be used as
447		 * offset/pointer before DWARF4. Newly added
448		 * DWARF4 form DW_FORM_sec_offset intents to replace
449		 * DW_FORM_data{4,8} for this purpose. Anyway, to
450		 * determine the actual class for these forms, we need
451		 * to also look at the attribute number.
452		 */
453		switch (attr) {
454		case DW_AT_location:
455		case DW_AT_string_length:
456		case DW_AT_return_addr:
457		case DW_AT_data_member_location:
458		case DW_AT_frame_base:
459		case DW_AT_segment:
460		case DW_AT_static_link:
461		case DW_AT_use_location:
462		case DW_AT_vtable_elem_location:
463			return (DW_FORM_CLASS_LOCLISTPTR);
464		case DW_AT_stmt_list:
465			return (DW_FORM_CLASS_LINEPTR);
466		case DW_AT_start_scope:
467		case DW_AT_ranges:
468			return (DW_FORM_CLASS_RANGELISTPTR);
469		case DW_AT_macro_info:
470			return (DW_FORM_CLASS_MACPTR);
471		default:
472			if (form == DW_FORM_data4 || form == DW_FORM_data8)
473				return (DW_FORM_CLASS_CONSTANT);
474			else
475				return (DW_FORM_CLASS_UNKNOWN);
476		}
477	default:
478		return (DW_FORM_CLASS_UNKNOWN);
479	}
480}
481