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 
30 ELFTC_VCSID("$Id: dwarf_form.c 2073 2011-10-27 03:30:47Z jkoshy $");
31 
32 int
dwarf_hasform(Dwarf_Attribute at,Dwarf_Half form,Dwarf_Bool * return_hasform,Dwarf_Error * error)33 dwarf_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 
50 int
dwarf_whatform(Dwarf_Attribute at,Dwarf_Half * return_form,Dwarf_Error * error)51 dwarf_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 
67 int
dwarf_whatform_direct(Dwarf_Attribute at,Dwarf_Half * return_form,Dwarf_Error * error)68 dwarf_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 
88 int
dwarf_whatattr(Dwarf_Attribute at,Dwarf_Half * return_attr,Dwarf_Error * error)89 dwarf_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 
105 int
dwarf_formref(Dwarf_Attribute at,Dwarf_Off * return_offset,Dwarf_Error * error)106 dwarf_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 
135 int
dwarf_global_formref(Dwarf_Attribute at,Dwarf_Off * return_offset,Dwarf_Error * error)136 dwarf_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 
172 int
dwarf_formaddr(Dwarf_Attribute at,Dwarf_Addr * return_addr,Dwarf_Error * error)173 dwarf_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 
196 int
dwarf_formflag(Dwarf_Attribute at,Dwarf_Bool * return_bool,Dwarf_Error * error)197 dwarf_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 
221 int
dwarf_formudata(Dwarf_Attribute at,Dwarf_Unsigned * return_uvalue,Dwarf_Error * error)222 dwarf_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 
252 int
dwarf_formsdata(Dwarf_Attribute at,Dwarf_Signed * return_svalue,Dwarf_Error * error)253 dwarf_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 
292 int
dwarf_formblock(Dwarf_Attribute at,Dwarf_Block ** return_block,Dwarf_Error * error)293 dwarf_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 
322 int
dwarf_formsig8(Dwarf_Attribute at,Dwarf_Sig8 * return_sig8,Dwarf_Error * error)323 dwarf_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 
345 int
dwarf_formexprloc(Dwarf_Attribute at,Dwarf_Unsigned * return_exprlen,Dwarf_Ptr * return_expr,Dwarf_Error * error)346 dwarf_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 
370 int
dwarf_formstring(Dwarf_Attribute at,char ** return_string,Dwarf_Error * error)371 dwarf_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 
401 enum Dwarf_Form_Class
dwarf_get_form_class(Dwarf_Half dwversion,Dwarf_Half attr,Dwarf_Half offset_size,Dwarf_Half form)402 dwarf_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