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