xref: /netbsd-src/external/bsd/elftoolchain/dist/libdwarf/libdwarf_attr.c (revision 5ac3bc719ce6e70593039505b491894133237d12)
1 /*	$NetBSD: libdwarf_attr.c,v 1.5 2024/03/03 17:37:32 christos Exp $	*/
2 
3 /*-
4  * Copyright (c) 2007 John Birrell (jb@freebsd.org)
5  * Copyright (c) 2009-2011,2023 Kai Wang
6  * All rights reserved.
7  *
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.
16  *
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.
28  */
29 
30 #include "_libdwarf.h"
31 
32 __RCSID("$NetBSD: libdwarf_attr.c,v 1.5 2024/03/03 17:37:32 christos Exp $");
33 ELFTC_VCSID("Id: libdwarf_attr.c 4019 2023-10-22 03:06:17Z kaiwang27");
34 
35 int
_dwarf_attr_alloc(Dwarf_Die die,Dwarf_Attribute * atp,Dwarf_Error * error)36 _dwarf_attr_alloc(Dwarf_Die die, Dwarf_Attribute *atp, Dwarf_Error *error)
37 {
38 	Dwarf_Attribute at;
39 
40 	assert(die != NULL);
41 	assert(atp != NULL);
42 
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);
46 	}
47 
48 	*atp = at;
49 
50 	return (DW_DLE_NONE);
51 }
52 
53 static int
_dwarf_attr_add(Dwarf_Die die,Dwarf_Attribute atref,Dwarf_Attribute * atp,Dwarf_Error * error)54 _dwarf_attr_add(Dwarf_Die die, Dwarf_Attribute atref, Dwarf_Attribute *atp,
55     Dwarf_Error *error)
56 {
57 	Dwarf_Attribute at;
58 	int ret;
59 
60 	if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
61 		return (ret);
62 
63 	memcpy(at, atref, sizeof(struct _Dwarf_Attribute));
64 
65 	STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
66 
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;
78 		}
79 	}
80 
81 	if (atp != NULL)
82 		*atp = at;
83 
84 	return (DW_DLE_NONE);
85 }
86 
87 Dwarf_Attribute
_dwarf_attr_find(Dwarf_Die die,Dwarf_Half attr)88 _dwarf_attr_find(Dwarf_Die die, Dwarf_Half attr)
89 {
90 	Dwarf_Attribute at;
91 
92 	STAILQ_FOREACH(at, &die->die_attr, at_next) {
93 		if (at->at_attrib == attr)
94 			break;
95 	}
96 
97 	return (at);
98 }
99 
100 int
_dwarf_attr_init(Dwarf_Debug dbg,Dwarf_Section * ds,uint64_t * offsetp,int dwarf_size,Dwarf_CU cu,Dwarf_Die die,Dwarf_AttrDef ad,uint64_t form,int indirect,Dwarf_Error * error)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)
104 {
105 	struct _Dwarf_Attribute atref;
106 	int ret;
107 
108 	ret = DW_DLE_NONE;
109 	memset(&atref, 0, sizeof(atref));
110 	atref.at_die = die;
111 	atref.at_offset = *offsetp;
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;
116 
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 	case DW_FORM_ref_sup4:
155 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 4);
156 		break;
157 	case DW_FORM_data8:
158 	case DW_FORM_ref8:
159 	case DW_FORM_ref_sup8:
160 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 8);
161 		break;
162 	case DW_FORM_indirect:
163 		form = _dwarf_read_uleb128(ds->ds_data, offsetp);
164 		return (_dwarf_attr_init(dbg, ds, offsetp, dwarf_size, cu, die,
165 		    ad, form, 1, error));
166 	case DW_FORM_ref_addr:
167 		if (cu->cu_version == 2)
168 			atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
169 			    cu->cu_pointer_size);
170 		else
171 			atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
172 			    dwarf_size);
173 		break;
174 	case DW_FORM_ref_udata:
175 	case DW_FORM_udata:
176 	case DW_FORM_loclistx:
177 	case DW_FORM_rnglistx:
178 		atref.u[0].u64 = _dwarf_read_uleb128(ds->ds_data, offsetp);
179 		break;
180 	case DW_FORM_sdata:
181 		atref.u[0].s64 = _dwarf_read_sleb128(ds->ds_data, offsetp);
182 		break;
183 	case DW_FORM_sec_offset:
184 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size);
185 		break;
186 	case DW_FORM_string:
187 		atref.u[0].s = _dwarf_read_string(ds->ds_data, ds->ds_size,
188 		    offsetp);
189 		break;
190 	case DW_FORM_strp:
191 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size);
192 		atref.u[1].s = _dwarf_strtab_get_table(dbg) + atref.u[0].u64;
193 		break;
194 	case DW_FORM_ref_sig8:
195 		atref.u[0].u64 = 8;
196 		atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
197 		    atref.u[0].u64);
198 		break;
199 	case DW_FORM_flag_present:
200 		/* This form has no value encoded in the DIE. */
201 		atref.u[0].u64 = 1;
202 		break;
203 	case DW_FORM_strx:
204 		atref.u[0].u64 = _dwarf_read_uleb128(ds->ds_data, offsetp);
205 		/* TODO: .debug_str_offsets */
206 		break;
207 	case DW_FORM_addrx:
208 		atref.u[0].u64 = _dwarf_read_uleb128(ds->ds_data, offsetp);
209 		/* TODO: .debug_addr */
210 		break;
211 	case DW_FORM_strp_sup:
212 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size);
213 		/* TODO: supplementary object file. */
214 		break;
215 	case DW_FORM_data16:
216 		atref.u[0].u64 = 16;
217 		atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
218 		    atref.u[0].u64);
219 		break;
220 	case DW_FORM_line_strp:
221 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size);
222 		atref.u[1].s = _dwarf_strtab_get_line_table(dbg) +
223 		    atref.u[0].u64;
224 		break;
225 	case DW_FORM_implicit_const:
226 		/* DWARF5 7.5.3 Implicit constant stored in attrdef.
227 		   This form has no value encoded in the DIE. */
228 		atref.u[0].s64 = ad->ad_const;
229 		break;
230 	case DW_FORM_strx1:
231 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 1);
232 		/* TODO: .debug_str_offsets */
233 		break;
234 	case DW_FORM_strx2:
235 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 1);
236 		/* TODO: .debug_str_offsets */
237 		break;
238 	case DW_FORM_strx3:
239 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 3);
240 		/* TODO: .debug_str_offsets */
241 		break;
242 	case DW_FORM_strx4:
243 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 4);
244 		/* TODO: .debug_str_offsets */
245 		break;
246 	case DW_FORM_addrx1:
247 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 1);
248 		/* TODO: .debug_addr */
249 		break;
250 	case DW_FORM_addrx2:
251 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 2);
252 		/* TODO: .debug_addr */
253 		break;
254 	case DW_FORM_addrx3:
255 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 3);
256 		/* TODO: .debug_addr */
257 		break;
258 	case DW_FORM_addrx4:
259 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 4);
260 		/* TODO: .debug_addr */
261 		break;
262 
263 	default:
264 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
265 		ret = DW_DLE_ATTR_FORM_BAD;
266 		break;
267 	}
268 
269 	if (ret == DW_DLE_NONE) {
270 		if (form == DW_FORM_block || form == DW_FORM_block1 ||
271 		    form == DW_FORM_block2 || form == DW_FORM_block4) {
272 			atref.at_block.bl_len = atref.u[0].u64;
273 			atref.at_block.bl_data = atref.u[1].u8p;
274 		}
275 		ret = _dwarf_attr_add(die, &atref, NULL, error);
276 	}
277 
278 	return (ret);
279 }
280 
281 static int
_dwarf_attr_write(Dwarf_P_Debug dbg,Dwarf_P_Section ds,Dwarf_Rel_Section drs,Dwarf_CU cu,Dwarf_Attribute at,int pass2,Dwarf_Error * error)282 _dwarf_attr_write(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_Rel_Section drs,
283     Dwarf_CU cu, Dwarf_Attribute at, int pass2, Dwarf_Error *error)
284 {
285 	struct _Dwarf_P_Expr_Entry *ee;
286 	uint64_t value, offset, bs;
287 	int ret;
288 
289 	assert(dbg != NULL && ds != NULL && cu != NULL && at != NULL);
290 
291 	/* Fill in reference to other DIE in the second pass. */
292 	if (pass2) {
293 		if (at->at_form != DW_FORM_ref4 && at->at_form != DW_FORM_ref8)
294 			return (DW_DLE_NONE);
295 		if (at->at_refdie == NULL || at->at_offset == 0)
296 			return (DW_DLE_NONE);
297 		offset = at->at_offset;
298 		dbg->write(ds->ds_data, &offset, at->at_refdie->die_offset,
299 		    at->at_form == DW_FORM_ref4 ? 4 : 8);
300 		return (DW_DLE_NONE);
301 	}
302 
303 	switch (at->at_form) {
304 	case DW_FORM_addr:
305 		if (at->at_relsym)
306 			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
307 			    dwarf_drt_data_reloc, cu->cu_pointer_size,
308 			    ds->ds_size, at->at_relsym, at->u[0].u64, NULL,
309 			    error);
310 		else
311 			ret = WRITE_VALUE(at->u[0].u64, cu->cu_pointer_size);
312 		break;
313 	case DW_FORM_block:
314 	case DW_FORM_block1:
315 	case DW_FORM_block2:
316 	case DW_FORM_block4:
317 		/* Write block size. */
318 		if (at->at_form == DW_FORM_block) {
319 			ret = _dwarf_write_uleb128_alloc(&ds->ds_data,
320 			    &ds->ds_cap, &ds->ds_size, at->u[0].u64, error);
321 			if (ret != DW_DLE_NONE)
322 				break;
323 		} else {
324 			if (at->at_form == DW_FORM_block1)
325 				bs = 1;
326 			else if (at->at_form == DW_FORM_block2)
327 				bs = 2;
328 			else
329 				bs = 4;
330 			ret = WRITE_VALUE(at->u[0].u64, bs);
331 			if (ret != DW_DLE_NONE)
332 				break;
333 		}
334 
335 		/* Keep block data offset for later use. */
336 		offset = ds->ds_size;
337 
338 		/* Write block data. */
339 		ret = WRITE_BLOCK(at->u[1].u8p, at->u[0].u64);
340 		if (ret != DW_DLE_NONE)
341 			break;
342 		if (at->at_expr == NULL)
343 			break;
344 
345 		/* Generate relocation entry for DW_OP_addr expressions. */
346 		STAILQ_FOREACH(ee, &at->at_expr->pe_eelist, ee_next) {
347 			if (ee->ee_loc.lr_atom != DW_OP_addr || ee->ee_sym == 0)
348 				continue;
349 			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
350 			    dwarf_drt_data_reloc, dbg->dbg_pointer_size,
351 			    offset + ee->ee_loc.lr_offset + 1, ee->ee_sym,
352 			    ee->ee_loc.lr_number, NULL, error);
353 			if (ret != DW_DLE_NONE)
354 				break;
355 		}
356 		break;
357 	case DW_FORM_data1:
358 	case DW_FORM_flag:
359 	case DW_FORM_ref1:
360 		ret = WRITE_VALUE(at->u[0].u64, 1);
361 		break;
362 	case DW_FORM_data2:
363 	case DW_FORM_ref2:
364 		ret = WRITE_VALUE(at->u[0].u64, 2);
365 		break;
366 	case DW_FORM_data4:
367 		if (at->at_relsym || at->at_relsec != NULL)
368 			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
369 			    dwarf_drt_data_reloc, 4, ds->ds_size, at->at_relsym,
370 			    at->u[0].u64, at->at_relsec, error);
371 		else
372 			ret = WRITE_VALUE(at->u[0].u64, 4);
373 		break;
374 	case DW_FORM_data8:
375 		if (at->at_relsym || at->at_relsec != NULL)
376 			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
377 			    dwarf_drt_data_reloc, 8, ds->ds_size, at->at_relsym,
378 			    at->u[0].u64, at->at_relsec, error);
379 		else
380 			ret = WRITE_VALUE(at->u[0].u64, 8);
381 		break;
382 	case DW_FORM_ref4:
383 	case DW_FORM_ref8:
384 		/*
385 		 * The value of ref4 and ref8 could be a reference to another
386 		 * DIE within the CU. And if we don't know the ref DIE's
387 		 * offset at the moement, then we remember at_offset and fill
388 		 * it in the second pass.
389 		 */
390 		if (at->at_refdie) {
391 			value = at->at_refdie->die_offset;
392 			if (value == 0) {
393 				cu->cu_pass2 = 1;
394 				at->at_offset = ds->ds_size;
395 			}
396 		} else
397 			value = at->u[0].u64;
398 		ret = WRITE_VALUE(value, at->at_form == DW_FORM_ref4 ? 4 : 8);
399 		break;
400 	case DW_FORM_indirect:
401 		/* TODO. */
402 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
403 		ret = DW_DLE_ATTR_FORM_BAD;
404 		break;
405 	case DW_FORM_ref_addr:
406 		/* DWARF2 format. */
407 		if (at->at_relsym)
408 			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
409 			    dwarf_drt_data_reloc, cu->cu_pointer_size,
410 			    ds->ds_size, at->at_relsym, at->u[0].u64, NULL,
411 			    error);
412 		else
413 			ret = WRITE_VALUE(at->u[0].u64, cu->cu_pointer_size);
414 		break;
415 	case DW_FORM_ref_udata:
416 	case DW_FORM_udata:
417 		ret = WRITE_ULEB128(at->u[0].u64);
418 		break;
419 	case DW_FORM_sdata:
420 		ret = WRITE_SLEB128(at->u[0].s64);
421 		break;
422 	case DW_FORM_string:
423 		assert(at->u[0].s != NULL);
424 		ret = WRITE_STRING(at->u[0].s);
425 		break;
426 	case DW_FORM_strp:
427 		ret = _dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc,
428 		    4, ds->ds_size, 0, at->u[0].u64, ".debug_str", error);
429 		break;
430 	default:
431 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
432 		ret = DW_DLE_ATTR_FORM_BAD;
433 		break;
434 	}
435 
436 	return (ret);
437 }
438 
439 int
_dwarf_add_AT_dataref(Dwarf_P_Debug dbg,Dwarf_P_Die die,Dwarf_Half attr,Dwarf_Unsigned pc_value,Dwarf_Unsigned sym_index,const char * secname,Dwarf_P_Attribute * atp,Dwarf_Error * error)440 _dwarf_add_AT_dataref(Dwarf_P_Debug dbg, Dwarf_P_Die die, Dwarf_Half attr,
441     Dwarf_Unsigned pc_value, Dwarf_Unsigned sym_index, const char *secname,
442     Dwarf_P_Attribute *atp, Dwarf_Error *error)
443 {
444 	Dwarf_Attribute at;
445 	int ret;
446 
447 	assert(dbg != NULL && die != NULL);
448 
449 	if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
450 		return (ret);
451 
452 	at->at_die = die;
453 	at->at_attrib = attr;
454 	if (dbg->dbg_pointer_size == 4)
455 		at->at_form = DW_FORM_data4;
456 	else
457 		at->at_form = DW_FORM_data8;
458 	at->at_relsym = sym_index;
459 	at->at_relsec = secname;
460 	at->u[0].u64 = pc_value;
461 
462 	STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
463 
464 	if (atp)
465 		*atp = at;
466 
467 	return (DW_DLE_NONE);
468 }
469 
470 int
_dwarf_add_string_attr(Dwarf_P_Die die,Dwarf_P_Attribute * atp,Dwarf_Half attr,char * string,Dwarf_Error * error)471 _dwarf_add_string_attr(Dwarf_P_Die die, Dwarf_P_Attribute *atp, Dwarf_Half attr,
472     char *string, Dwarf_Error *error)
473 {
474 	Dwarf_Attribute at;
475 	Dwarf_Debug dbg;
476 	int ret;
477 
478 	dbg = die != NULL ? die->die_dbg : NULL;
479 
480 	assert(atp != NULL);
481 
482 	if (die == NULL || string == NULL) {
483 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
484 		return (DW_DLE_ARGUMENT);
485 	}
486 
487 	if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
488 		return (ret);
489 
490 	at->at_die = die;
491 	at->at_attrib = attr;
492 	at->at_form = DW_FORM_strp;
493 	if ((ret = _dwarf_strtab_add(dbg, string, &at->u[0].u64,
494 	    error)) != DW_DLE_NONE) {
495 		free(at);
496 		return (ret);
497 	}
498 	at->u[1].s = _dwarf_strtab_get_table(dbg) + at->u[0].u64;
499 
500 	*atp = at;
501 
502 	STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
503 
504 	return (DW_DLE_NONE);
505 }
506 
507 int
_dwarf_attr_gen(Dwarf_P_Debug dbg,Dwarf_P_Section ds,Dwarf_Rel_Section drs,Dwarf_CU cu,Dwarf_Die die,int pass2,Dwarf_Error * error)508 _dwarf_attr_gen(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_Rel_Section drs,
509     Dwarf_CU cu, Dwarf_Die die, int pass2, Dwarf_Error *error)
510 {
511 	Dwarf_Attribute at;
512 	int ret;
513 
514 	assert(dbg != NULL && ds != NULL && cu != NULL && die != NULL);
515 
516 	STAILQ_FOREACH(at, &die->die_attr, at_next) {
517 		ret = _dwarf_attr_write(dbg, ds, drs, cu, at, pass2, error);
518 		if (ret != DW_DLE_NONE)
519 			return (ret);
520 	}
521 
522 	return (DW_DLE_NONE);
523 }
524