Remove building with NOCRYPTO option
[minix3.git] / external / bsd / elftoolchain / dist / libdwarf / libdwarf_attr.c
blob531aa6e0fa6425c47a16eb9b49b96a7bb35c487b
1 /* $NetBSD: libdwarf_attr.c,v 1.2 2014/03/09 16:58:04 christos Exp $ */
3 /*-
4 * Copyright (c) 2007 John Birrell (jb@freebsd.org)
5 * Copyright (c) 2009-2011 Kai Wang
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
30 #include "_libdwarf.h"
32 __RCSID("$NetBSD: libdwarf_attr.c,v 1.2 2014/03/09 16:58:04 christos Exp $");
33 ELFTC_VCSID("Id: libdwarf_attr.c 2966 2013-09-21 14:40:14Z kaiwang27 ");
35 int
36 _dwarf_attr_alloc(Dwarf_Die die, Dwarf_Attribute *atp, Dwarf_Error *error)
38 Dwarf_Attribute at;
40 assert(die != NULL);
41 assert(atp != NULL);
43 if ((at = calloc(1, sizeof(struct _Dwarf_Attribute))) == NULL) {
44 DWARF_SET_ERROR(die->die_dbg, error, DW_DLE_MEMORY);
45 return (DW_DLE_MEMORY);
48 *atp = at;
50 return (DW_DLE_NONE);
53 static int
54 _dwarf_attr_add(Dwarf_Die die, Dwarf_Attribute atref, Dwarf_Attribute *atp,
55 Dwarf_Error *error)
57 Dwarf_Attribute at;
58 int ret;
60 if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
61 return (ret);
63 memcpy(at, atref, sizeof(struct _Dwarf_Attribute));
65 STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
67 /* Save a pointer to the attribute name if this is one. */
68 if (at->at_attrib == DW_AT_name) {
69 switch (at->at_form) {
70 case DW_FORM_strp:
71 die->die_name = at->u[1].s;
72 break;
73 case DW_FORM_string:
74 die->die_name = at->u[0].s;
75 break;
76 default:
77 break;
81 if (atp != NULL)
82 *atp = at;
84 return (DW_DLE_NONE);
87 Dwarf_Attribute
88 _dwarf_attr_find(Dwarf_Die die, Dwarf_Half attr)
90 Dwarf_Attribute at;
92 STAILQ_FOREACH(at, &die->die_attr, at_next) {
93 if (at->at_attrib == attr)
94 break;
97 return (at);
101 _dwarf_attr_init(Dwarf_Debug dbg, Dwarf_Section *ds, uint64_t *offsetp,
102 int dwarf_size, Dwarf_CU cu, Dwarf_Die die, Dwarf_AttrDef ad,
103 uint64_t form, int indirect, Dwarf_Error *error)
105 struct _Dwarf_Attribute atref;
106 Dwarf_Section *str;
107 int ret;
109 ret = DW_DLE_NONE;
110 memset(&atref, 0, sizeof(atref));
111 atref.at_die = die;
112 atref.at_attrib = ad->ad_attrib;
113 atref.at_form = indirect ? form : ad->ad_form;
114 atref.at_indirect = indirect;
115 atref.at_ld = NULL;
117 switch (form) {
118 case DW_FORM_addr:
119 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
120 cu->cu_pointer_size);
121 break;
122 case DW_FORM_block:
123 case DW_FORM_exprloc:
124 atref.u[0].u64 = _dwarf_read_uleb128(ds->ds_data, offsetp);
125 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
126 atref.u[0].u64);
127 break;
128 case DW_FORM_block1:
129 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 1);
130 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
131 atref.u[0].u64);
132 break;
133 case DW_FORM_block2:
134 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 2);
135 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
136 atref.u[0].u64);
137 break;
138 case DW_FORM_block4:
139 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 4);
140 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
141 atref.u[0].u64);
142 break;
143 case DW_FORM_data1:
144 case DW_FORM_flag:
145 case DW_FORM_ref1:
146 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 1);
147 break;
148 case DW_FORM_data2:
149 case DW_FORM_ref2:
150 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 2);
151 break;
152 case DW_FORM_data4:
153 case DW_FORM_ref4:
154 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 4);
155 break;
156 case DW_FORM_data8:
157 case DW_FORM_ref8:
158 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 8);
159 break;
160 case DW_FORM_indirect:
161 form = _dwarf_read_uleb128(ds->ds_data, offsetp);
162 return (_dwarf_attr_init(dbg, ds, offsetp, dwarf_size, cu, die,
163 ad, form, 1, error));
164 case DW_FORM_ref_addr:
165 if (cu->cu_version == 2)
166 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
167 cu->cu_pointer_size);
168 else if (cu->cu_version == 3)
169 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
170 dwarf_size);
171 break;
172 case DW_FORM_ref_udata:
173 case DW_FORM_udata:
174 atref.u[0].u64 = _dwarf_read_uleb128(ds->ds_data, offsetp);
175 break;
176 case DW_FORM_sdata:
177 atref.u[0].s64 = _dwarf_read_sleb128(ds->ds_data, offsetp);
178 break;
179 case DW_FORM_sec_offset:
180 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size);
181 break;
182 case DW_FORM_string:
183 atref.u[0].s = _dwarf_read_string(ds->ds_data, ds->ds_size,
184 offsetp);
185 break;
186 case DW_FORM_strp:
187 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size);
188 str = _dwarf_find_section(dbg, ".debug_str");
189 assert(str != NULL);
190 atref.u[1].s = (char *) str->ds_data + atref.u[0].u64;
191 break;
192 case DW_FORM_ref_sig8:
193 atref.u[0].u64 = 8;
194 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
195 atref.u[0].u64);
196 break;
197 case DW_FORM_flag_present:
198 /* This form has no value encoded in the DIE. */
199 atref.u[0].u64 = 1;
200 break;
201 default:
202 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
203 ret = DW_DLE_ATTR_FORM_BAD;
204 break;
207 if (ret == DW_DLE_NONE) {
208 if (form == DW_FORM_block || form == DW_FORM_block1 ||
209 form == DW_FORM_block2 || form == DW_FORM_block4) {
210 atref.at_block.bl_len = atref.u[0].u64;
211 atref.at_block.bl_data = atref.u[1].u8p;
213 ret = _dwarf_attr_add(die, &atref, NULL, error);
216 return (ret);
219 static int
220 _dwarf_attr_write(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_Rel_Section drs,
221 Dwarf_CU cu, Dwarf_Attribute at, int pass2, Dwarf_Error *error)
223 struct _Dwarf_P_Expr_Entry *ee;
224 uint64_t value, offset, bs;
225 int ret;
227 assert(dbg != NULL && ds != NULL && cu != NULL && at != NULL);
229 /* Fill in reference to other DIE in the second pass. */
230 if (pass2) {
231 if (at->at_form != DW_FORM_ref4 && at->at_form != DW_FORM_ref8)
232 return (DW_DLE_NONE);
233 if (at->at_refdie == NULL || at->at_offset == 0)
234 return (DW_DLE_NONE);
235 offset = at->at_offset;
236 dbg->write(ds->ds_data, &offset, at->at_refdie->die_offset,
237 at->at_form == DW_FORM_ref4 ? 4 : 8);
238 return (DW_DLE_NONE);
241 switch (at->at_form) {
242 case DW_FORM_addr:
243 if (at->at_relsym)
244 ret = _dwarf_reloc_entry_add(dbg, drs, ds,
245 dwarf_drt_data_reloc, cu->cu_pointer_size,
246 ds->ds_size, at->at_relsym, at->u[0].u64, NULL,
247 error);
248 else
249 ret = WRITE_VALUE(at->u[0].u64, cu->cu_pointer_size);
250 break;
251 case DW_FORM_block:
252 case DW_FORM_block1:
253 case DW_FORM_block2:
254 case DW_FORM_block4:
255 /* Write block size. */
256 if (at->at_form == DW_FORM_block) {
257 ret = _dwarf_write_uleb128_alloc(&ds->ds_data,
258 &ds->ds_cap, &ds->ds_size, at->u[0].u64, error);
259 if (ret != DW_DLE_NONE)
260 break;
261 } else {
262 if (at->at_form == DW_FORM_block1)
263 bs = 1;
264 else if (at->at_form == DW_FORM_block2)
265 bs = 2;
266 else
267 bs = 4;
268 ret = WRITE_VALUE(at->u[0].u64, bs);
269 if (ret != DW_DLE_NONE)
270 break;
273 /* Keep block data offset for later use. */
274 offset = ds->ds_size;
276 /* Write block data. */
277 ret = WRITE_BLOCK(at->u[1].u8p, at->u[0].u64);
278 if (ret != DW_DLE_NONE)
279 break;
280 if (at->at_expr == NULL)
281 break;
283 /* Generate relocation entry for DW_OP_addr expressions. */
284 STAILQ_FOREACH(ee, &at->at_expr->pe_eelist, ee_next) {
285 if (ee->ee_loc.lr_atom != DW_OP_addr || ee->ee_sym == 0)
286 continue;
287 ret = _dwarf_reloc_entry_add(dbg, drs, ds,
288 dwarf_drt_data_reloc, dbg->dbg_pointer_size,
289 offset + ee->ee_loc.lr_offset + 1, ee->ee_sym,
290 ee->ee_loc.lr_number, NULL, error);
291 if (ret != DW_DLE_NONE)
292 break;
294 break;
295 case DW_FORM_data1:
296 case DW_FORM_flag:
297 case DW_FORM_ref1:
298 ret = WRITE_VALUE(at->u[0].u64, 1);
299 break;
300 case DW_FORM_data2:
301 case DW_FORM_ref2:
302 ret = WRITE_VALUE(at->u[0].u64, 2);
303 break;
304 case DW_FORM_data4:
305 if (at->at_relsym || at->at_relsec != NULL)
306 ret = _dwarf_reloc_entry_add(dbg, drs, ds,
307 dwarf_drt_data_reloc, 4, ds->ds_size, at->at_relsym,
308 at->u[0].u64, at->at_relsec, error);
309 else
310 ret = WRITE_VALUE(at->u[0].u64, 4);
311 break;
312 case DW_FORM_data8:
313 if (at->at_relsym || at->at_relsec != NULL)
314 ret = _dwarf_reloc_entry_add(dbg, drs, ds,
315 dwarf_drt_data_reloc, 8, ds->ds_size, at->at_relsym,
316 at->u[0].u64, at->at_relsec, error);
317 else
318 ret = WRITE_VALUE(at->u[0].u64, 8);
319 break;
320 case DW_FORM_ref4:
321 case DW_FORM_ref8:
323 * The value of ref4 and ref8 could be a reference to another
324 * DIE within the CU. And if we don't know the ref DIE's
325 * offset at the moement, then we remember at_offset and fill
326 * it in the second pass.
328 if (at->at_refdie) {
329 value = at->at_refdie->die_offset;
330 if (value == 0) {
331 cu->cu_pass2 = 1;
332 at->at_offset = ds->ds_size;
334 } else
335 value = at->u[0].u64;
336 ret = WRITE_VALUE(value, at->at_form == DW_FORM_ref4 ? 4 : 8);
337 break;
338 case DW_FORM_indirect:
339 /* TODO. */
340 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
341 ret = DW_DLE_ATTR_FORM_BAD;
342 break;
343 case DW_FORM_ref_addr:
344 /* DWARF2 format. */
345 if (at->at_relsym)
346 ret = _dwarf_reloc_entry_add(dbg, drs, ds,
347 dwarf_drt_data_reloc, cu->cu_pointer_size,
348 ds->ds_size, at->at_relsym, at->u[0].u64, NULL,
349 error);
350 else
351 ret = WRITE_VALUE(at->u[0].u64, cu->cu_pointer_size);
352 break;
353 case DW_FORM_ref_udata:
354 case DW_FORM_udata:
355 ret = WRITE_ULEB128(at->u[0].u64);
356 break;
357 case DW_FORM_sdata:
358 ret = WRITE_SLEB128(at->u[0].s64);
359 break;
360 case DW_FORM_string:
361 assert(at->u[0].s != NULL);
362 ret = WRITE_STRING(at->u[0].s);
363 break;
364 case DW_FORM_strp:
365 ret = _dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc,
366 4, ds->ds_size, 0, at->u[0].u64, ".debug_str", error);
367 break;
368 default:
369 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
370 ret = DW_DLE_ATTR_FORM_BAD;
371 break;
374 return (ret);
378 _dwarf_add_AT_dataref(Dwarf_P_Debug dbg, Dwarf_P_Die die, Dwarf_Half attr,
379 Dwarf_Unsigned pc_value, Dwarf_Unsigned sym_index, const char *secname,
380 Dwarf_P_Attribute *atp, Dwarf_Error *error)
382 Dwarf_Attribute at;
383 int ret;
385 assert(dbg != NULL && die != NULL);
387 if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
388 return (ret);
390 at->at_die = die;
391 at->at_attrib = attr;
392 if (dbg->dbg_pointer_size == 4)
393 at->at_form = DW_FORM_data4;
394 else
395 at->at_form = DW_FORM_data8;
396 at->at_relsym = sym_index;
397 at->at_relsec = secname;
398 at->u[0].u64 = pc_value;
400 STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
402 if (atp)
403 *atp = at;
405 return (DW_DLE_NONE);
409 _dwarf_add_string_attr(Dwarf_P_Die die, Dwarf_P_Attribute *atp, Dwarf_Half attr,
410 char *string, Dwarf_Error *error)
412 Dwarf_Attribute at;
413 Dwarf_Debug dbg;
414 int ret;
416 dbg = die != NULL ? die->die_dbg : NULL;
418 assert(atp != NULL);
420 if (die == NULL || string == NULL) {
421 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
422 return (DW_DLE_ARGUMENT);
425 if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
426 return (ret);
428 at->at_die = die;
429 at->at_attrib = attr;
430 at->at_form = DW_FORM_strp;
431 if ((ret = _dwarf_strtab_add(dbg, string, &at->u[0].u64,
432 error)) != DW_DLE_NONE) {
433 free(at);
434 return (ret);
436 at->u[1].s = _dwarf_strtab_get_table(dbg) + at->u[0].u64;
438 *atp = at;
440 STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
442 return (DW_DLE_NONE);
446 _dwarf_attr_gen(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_Rel_Section drs,
447 Dwarf_CU cu, Dwarf_Die die, int pass2, Dwarf_Error *error)
449 Dwarf_Attribute at;
450 int ret;
452 assert(dbg != NULL && ds != NULL && cu != NULL && die != NULL);
454 STAILQ_FOREACH(at, &die->die_attr, at_next) {
455 ret = _dwarf_attr_write(dbg, ds, drs, cu, at, pass2, error);
456 if (ret != DW_DLE_NONE)
457 return (ret);
460 return (DW_DLE_NONE);