xref: /netbsd-src/external/bsd/elftoolchain/dist/libdwarf/libdwarf_attr.c (revision 5ac3bc719ce6e70593039505b491894133237d12)
1*5ac3bc71Schristos /*	$NetBSD: libdwarf_attr.c,v 1.5 2024/03/03 17:37:32 christos Exp $	*/
2e81373b4Schristos 
39dd9d0cfSchristos /*-
49dd9d0cfSchristos  * Copyright (c) 2007 John Birrell (jb@freebsd.org)
5*5ac3bc71Schristos  * Copyright (c) 2009-2011,2023 Kai Wang
69dd9d0cfSchristos  * All rights reserved.
79dd9d0cfSchristos  *
89dd9d0cfSchristos  * Redistribution and use in source and binary forms, with or without
99dd9d0cfSchristos  * modification, are permitted provided that the following conditions
109dd9d0cfSchristos  * are met:
119dd9d0cfSchristos  * 1. Redistributions of source code must retain the above copyright
129dd9d0cfSchristos  *    notice, this list of conditions and the following disclaimer.
139dd9d0cfSchristos  * 2. Redistributions in binary form must reproduce the above copyright
149dd9d0cfSchristos  *    notice, this list of conditions and the following disclaimer in the
159dd9d0cfSchristos  *    documentation and/or other materials provided with the distribution.
169dd9d0cfSchristos  *
179dd9d0cfSchristos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
189dd9d0cfSchristos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
199dd9d0cfSchristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
209dd9d0cfSchristos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
219dd9d0cfSchristos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
229dd9d0cfSchristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
239dd9d0cfSchristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
249dd9d0cfSchristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
259dd9d0cfSchristos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
269dd9d0cfSchristos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
279dd9d0cfSchristos  * SUCH DAMAGE.
289dd9d0cfSchristos  */
299dd9d0cfSchristos 
309dd9d0cfSchristos #include "_libdwarf.h"
319dd9d0cfSchristos 
32*5ac3bc71Schristos __RCSID("$NetBSD: libdwarf_attr.c,v 1.5 2024/03/03 17:37:32 christos Exp $");
33*5ac3bc71Schristos ELFTC_VCSID("Id: libdwarf_attr.c 4019 2023-10-22 03:06:17Z kaiwang27");
349dd9d0cfSchristos 
359dd9d0cfSchristos int
_dwarf_attr_alloc(Dwarf_Die die,Dwarf_Attribute * atp,Dwarf_Error * error)369dd9d0cfSchristos _dwarf_attr_alloc(Dwarf_Die die, Dwarf_Attribute *atp, Dwarf_Error *error)
379dd9d0cfSchristos {
389dd9d0cfSchristos 	Dwarf_Attribute at;
399dd9d0cfSchristos 
409dd9d0cfSchristos 	assert(die != NULL);
419dd9d0cfSchristos 	assert(atp != NULL);
429dd9d0cfSchristos 
439dd9d0cfSchristos 	if ((at = calloc(1, sizeof(struct _Dwarf_Attribute))) == NULL) {
449dd9d0cfSchristos 		DWARF_SET_ERROR(die->die_dbg, error, DW_DLE_MEMORY);
459dd9d0cfSchristos 		return (DW_DLE_MEMORY);
469dd9d0cfSchristos 	}
479dd9d0cfSchristos 
489dd9d0cfSchristos 	*atp = at;
499dd9d0cfSchristos 
509dd9d0cfSchristos 	return (DW_DLE_NONE);
519dd9d0cfSchristos }
529dd9d0cfSchristos 
539dd9d0cfSchristos static int
_dwarf_attr_add(Dwarf_Die die,Dwarf_Attribute atref,Dwarf_Attribute * atp,Dwarf_Error * error)549dd9d0cfSchristos _dwarf_attr_add(Dwarf_Die die, Dwarf_Attribute atref, Dwarf_Attribute *atp,
559dd9d0cfSchristos     Dwarf_Error *error)
569dd9d0cfSchristos {
579dd9d0cfSchristos 	Dwarf_Attribute at;
589dd9d0cfSchristos 	int ret;
599dd9d0cfSchristos 
609dd9d0cfSchristos 	if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
619dd9d0cfSchristos 		return (ret);
629dd9d0cfSchristos 
639dd9d0cfSchristos 	memcpy(at, atref, sizeof(struct _Dwarf_Attribute));
649dd9d0cfSchristos 
659dd9d0cfSchristos 	STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
669dd9d0cfSchristos 
679dd9d0cfSchristos 	/* Save a pointer to the attribute name if this is one. */
689dd9d0cfSchristos 	if (at->at_attrib == DW_AT_name) {
699dd9d0cfSchristos 		switch (at->at_form) {
709dd9d0cfSchristos 		case DW_FORM_strp:
719dd9d0cfSchristos 			die->die_name = at->u[1].s;
729dd9d0cfSchristos 			break;
739dd9d0cfSchristos 		case DW_FORM_string:
749dd9d0cfSchristos 			die->die_name = at->u[0].s;
759dd9d0cfSchristos 			break;
769dd9d0cfSchristos 		default:
779dd9d0cfSchristos 			break;
789dd9d0cfSchristos 		}
799dd9d0cfSchristos 	}
809dd9d0cfSchristos 
819dd9d0cfSchristos 	if (atp != NULL)
829dd9d0cfSchristos 		*atp = at;
839dd9d0cfSchristos 
849dd9d0cfSchristos 	return (DW_DLE_NONE);
859dd9d0cfSchristos }
869dd9d0cfSchristos 
879dd9d0cfSchristos Dwarf_Attribute
_dwarf_attr_find(Dwarf_Die die,Dwarf_Half attr)889dd9d0cfSchristos _dwarf_attr_find(Dwarf_Die die, Dwarf_Half attr)
899dd9d0cfSchristos {
909dd9d0cfSchristos 	Dwarf_Attribute at;
919dd9d0cfSchristos 
929dd9d0cfSchristos 	STAILQ_FOREACH(at, &die->die_attr, at_next) {
939dd9d0cfSchristos 		if (at->at_attrib == attr)
949dd9d0cfSchristos 			break;
959dd9d0cfSchristos 	}
969dd9d0cfSchristos 
979dd9d0cfSchristos 	return (at);
989dd9d0cfSchristos }
999dd9d0cfSchristos 
1009dd9d0cfSchristos 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)1019dd9d0cfSchristos _dwarf_attr_init(Dwarf_Debug dbg, Dwarf_Section *ds, uint64_t *offsetp,
1029dd9d0cfSchristos     int dwarf_size, Dwarf_CU cu, Dwarf_Die die, Dwarf_AttrDef ad,
1039dd9d0cfSchristos     uint64_t form, int indirect, Dwarf_Error *error)
1049dd9d0cfSchristos {
1059dd9d0cfSchristos 	struct _Dwarf_Attribute atref;
1069dd9d0cfSchristos 	int ret;
1079dd9d0cfSchristos 
1089dd9d0cfSchristos 	ret = DW_DLE_NONE;
1099dd9d0cfSchristos 	memset(&atref, 0, sizeof(atref));
1109dd9d0cfSchristos 	atref.at_die = die;
11142bd3019Schristos 	atref.at_offset = *offsetp;
1129dd9d0cfSchristos 	atref.at_attrib = ad->ad_attrib;
1139dd9d0cfSchristos 	atref.at_form = indirect ? form : ad->ad_form;
1149dd9d0cfSchristos 	atref.at_indirect = indirect;
1159dd9d0cfSchristos 	atref.at_ld = NULL;
1169dd9d0cfSchristos 
1179dd9d0cfSchristos 	switch (form) {
1189dd9d0cfSchristos 	case DW_FORM_addr:
1199dd9d0cfSchristos 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
1209dd9d0cfSchristos 		    cu->cu_pointer_size);
1219dd9d0cfSchristos 		break;
1229dd9d0cfSchristos 	case DW_FORM_block:
1239dd9d0cfSchristos 	case DW_FORM_exprloc:
1249dd9d0cfSchristos 		atref.u[0].u64 = _dwarf_read_uleb128(ds->ds_data, offsetp);
1259dd9d0cfSchristos 		atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
1269dd9d0cfSchristos 		    atref.u[0].u64);
1279dd9d0cfSchristos 		break;
1289dd9d0cfSchristos 	case DW_FORM_block1:
1299dd9d0cfSchristos 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 1);
1309dd9d0cfSchristos 		atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
1319dd9d0cfSchristos 		    atref.u[0].u64);
1329dd9d0cfSchristos 		break;
1339dd9d0cfSchristos 	case DW_FORM_block2:
1349dd9d0cfSchristos 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 2);
1359dd9d0cfSchristos 		atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
1369dd9d0cfSchristos 		    atref.u[0].u64);
1379dd9d0cfSchristos 		break;
1389dd9d0cfSchristos 	case DW_FORM_block4:
1399dd9d0cfSchristos 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 4);
1409dd9d0cfSchristos 		atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
1419dd9d0cfSchristos 		    atref.u[0].u64);
1429dd9d0cfSchristos 		break;
1439dd9d0cfSchristos 	case DW_FORM_data1:
1449dd9d0cfSchristos 	case DW_FORM_flag:
1459dd9d0cfSchristos 	case DW_FORM_ref1:
1469dd9d0cfSchristos 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 1);
1479dd9d0cfSchristos 		break;
1489dd9d0cfSchristos 	case DW_FORM_data2:
1499dd9d0cfSchristos 	case DW_FORM_ref2:
1509dd9d0cfSchristos 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 2);
1519dd9d0cfSchristos 		break;
1529dd9d0cfSchristos 	case DW_FORM_data4:
1539dd9d0cfSchristos 	case DW_FORM_ref4:
154*5ac3bc71Schristos 	case DW_FORM_ref_sup4:
1559dd9d0cfSchristos 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 4);
1569dd9d0cfSchristos 		break;
1579dd9d0cfSchristos 	case DW_FORM_data8:
1589dd9d0cfSchristos 	case DW_FORM_ref8:
159*5ac3bc71Schristos 	case DW_FORM_ref_sup8:
1609dd9d0cfSchristos 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 8);
1619dd9d0cfSchristos 		break;
1629dd9d0cfSchristos 	case DW_FORM_indirect:
1639dd9d0cfSchristos 		form = _dwarf_read_uleb128(ds->ds_data, offsetp);
1649dd9d0cfSchristos 		return (_dwarf_attr_init(dbg, ds, offsetp, dwarf_size, cu, die,
1659dd9d0cfSchristos 		    ad, form, 1, error));
1669dd9d0cfSchristos 	case DW_FORM_ref_addr:
1679dd9d0cfSchristos 		if (cu->cu_version == 2)
1689dd9d0cfSchristos 			atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
1699dd9d0cfSchristos 			    cu->cu_pointer_size);
17042bd3019Schristos 		else
1719dd9d0cfSchristos 			atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
1729dd9d0cfSchristos 			    dwarf_size);
1739dd9d0cfSchristos 		break;
1749dd9d0cfSchristos 	case DW_FORM_ref_udata:
1759dd9d0cfSchristos 	case DW_FORM_udata:
176*5ac3bc71Schristos 	case DW_FORM_loclistx:
177*5ac3bc71Schristos 	case DW_FORM_rnglistx:
1789dd9d0cfSchristos 		atref.u[0].u64 = _dwarf_read_uleb128(ds->ds_data, offsetp);
1799dd9d0cfSchristos 		break;
1809dd9d0cfSchristos 	case DW_FORM_sdata:
1819dd9d0cfSchristos 		atref.u[0].s64 = _dwarf_read_sleb128(ds->ds_data, offsetp);
1829dd9d0cfSchristos 		break;
1839dd9d0cfSchristos 	case DW_FORM_sec_offset:
1849dd9d0cfSchristos 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size);
1859dd9d0cfSchristos 		break;
1869dd9d0cfSchristos 	case DW_FORM_string:
1879dd9d0cfSchristos 		atref.u[0].s = _dwarf_read_string(ds->ds_data, ds->ds_size,
1889dd9d0cfSchristos 		    offsetp);
1899dd9d0cfSchristos 		break;
1909dd9d0cfSchristos 	case DW_FORM_strp:
1919dd9d0cfSchristos 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size);
192*5ac3bc71Schristos 		atref.u[1].s = _dwarf_strtab_get_table(dbg) + atref.u[0].u64;
1939dd9d0cfSchristos 		break;
1949dd9d0cfSchristos 	case DW_FORM_ref_sig8:
1959dd9d0cfSchristos 		atref.u[0].u64 = 8;
1969dd9d0cfSchristos 		atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
1979dd9d0cfSchristos 		    atref.u[0].u64);
1989dd9d0cfSchristos 		break;
1999dd9d0cfSchristos 	case DW_FORM_flag_present:
2009dd9d0cfSchristos 		/* This form has no value encoded in the DIE. */
2019dd9d0cfSchristos 		atref.u[0].u64 = 1;
2029dd9d0cfSchristos 		break;
203*5ac3bc71Schristos 	case DW_FORM_strx:
204*5ac3bc71Schristos 		atref.u[0].u64 = _dwarf_read_uleb128(ds->ds_data, offsetp);
205*5ac3bc71Schristos 		/* TODO: .debug_str_offsets */
206*5ac3bc71Schristos 		break;
207*5ac3bc71Schristos 	case DW_FORM_addrx:
208*5ac3bc71Schristos 		atref.u[0].u64 = _dwarf_read_uleb128(ds->ds_data, offsetp);
209*5ac3bc71Schristos 		/* TODO: .debug_addr */
210*5ac3bc71Schristos 		break;
211*5ac3bc71Schristos 	case DW_FORM_strp_sup:
212*5ac3bc71Schristos 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size);
213*5ac3bc71Schristos 		/* TODO: supplementary object file. */
214*5ac3bc71Schristos 		break;
215*5ac3bc71Schristos 	case DW_FORM_data16:
216*5ac3bc71Schristos 		atref.u[0].u64 = 16;
217*5ac3bc71Schristos 		atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
218*5ac3bc71Schristos 		    atref.u[0].u64);
219*5ac3bc71Schristos 		break;
220*5ac3bc71Schristos 	case DW_FORM_line_strp:
221*5ac3bc71Schristos 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size);
222*5ac3bc71Schristos 		atref.u[1].s = _dwarf_strtab_get_line_table(dbg) +
223*5ac3bc71Schristos 		    atref.u[0].u64;
224*5ac3bc71Schristos 		break;
225*5ac3bc71Schristos 	case DW_FORM_implicit_const:
226*5ac3bc71Schristos 		/* DWARF5 7.5.3 Implicit constant stored in attrdef.
227*5ac3bc71Schristos 		   This form has no value encoded in the DIE. */
228*5ac3bc71Schristos 		atref.u[0].s64 = ad->ad_const;
229*5ac3bc71Schristos 		break;
230*5ac3bc71Schristos 	case DW_FORM_strx1:
231*5ac3bc71Schristos 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 1);
232*5ac3bc71Schristos 		/* TODO: .debug_str_offsets */
233*5ac3bc71Schristos 		break;
234*5ac3bc71Schristos 	case DW_FORM_strx2:
235*5ac3bc71Schristos 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 1);
236*5ac3bc71Schristos 		/* TODO: .debug_str_offsets */
237*5ac3bc71Schristos 		break;
238*5ac3bc71Schristos 	case DW_FORM_strx3:
239*5ac3bc71Schristos 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 3);
240*5ac3bc71Schristos 		/* TODO: .debug_str_offsets */
241*5ac3bc71Schristos 		break;
242*5ac3bc71Schristos 	case DW_FORM_strx4:
243*5ac3bc71Schristos 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 4);
244*5ac3bc71Schristos 		/* TODO: .debug_str_offsets */
245*5ac3bc71Schristos 		break;
246*5ac3bc71Schristos 	case DW_FORM_addrx1:
247*5ac3bc71Schristos 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 1);
248*5ac3bc71Schristos 		/* TODO: .debug_addr */
249*5ac3bc71Schristos 		break;
250*5ac3bc71Schristos 	case DW_FORM_addrx2:
251*5ac3bc71Schristos 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 2);
252*5ac3bc71Schristos 		/* TODO: .debug_addr */
253*5ac3bc71Schristos 		break;
254*5ac3bc71Schristos 	case DW_FORM_addrx3:
255*5ac3bc71Schristos 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 3);
256*5ac3bc71Schristos 		/* TODO: .debug_addr */
257*5ac3bc71Schristos 		break;
258*5ac3bc71Schristos 	case DW_FORM_addrx4:
259*5ac3bc71Schristos 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 4);
260*5ac3bc71Schristos 		/* TODO: .debug_addr */
261*5ac3bc71Schristos 		break;
262*5ac3bc71Schristos 
2639dd9d0cfSchristos 	default:
2649dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
2659dd9d0cfSchristos 		ret = DW_DLE_ATTR_FORM_BAD;
2669dd9d0cfSchristos 		break;
2679dd9d0cfSchristos 	}
2689dd9d0cfSchristos 
2699dd9d0cfSchristos 	if (ret == DW_DLE_NONE) {
2709dd9d0cfSchristos 		if (form == DW_FORM_block || form == DW_FORM_block1 ||
2719dd9d0cfSchristos 		    form == DW_FORM_block2 || form == DW_FORM_block4) {
2729dd9d0cfSchristos 			atref.at_block.bl_len = atref.u[0].u64;
2739dd9d0cfSchristos 			atref.at_block.bl_data = atref.u[1].u8p;
2749dd9d0cfSchristos 		}
2759dd9d0cfSchristos 		ret = _dwarf_attr_add(die, &atref, NULL, error);
2769dd9d0cfSchristos 	}
2779dd9d0cfSchristos 
2789dd9d0cfSchristos 	return (ret);
2799dd9d0cfSchristos }
2809dd9d0cfSchristos 
2819dd9d0cfSchristos 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)2829dd9d0cfSchristos _dwarf_attr_write(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_Rel_Section drs,
2839dd9d0cfSchristos     Dwarf_CU cu, Dwarf_Attribute at, int pass2, Dwarf_Error *error)
2849dd9d0cfSchristos {
2859dd9d0cfSchristos 	struct _Dwarf_P_Expr_Entry *ee;
2869dd9d0cfSchristos 	uint64_t value, offset, bs;
2879dd9d0cfSchristos 	int ret;
2889dd9d0cfSchristos 
2899dd9d0cfSchristos 	assert(dbg != NULL && ds != NULL && cu != NULL && at != NULL);
2909dd9d0cfSchristos 
2919dd9d0cfSchristos 	/* Fill in reference to other DIE in the second pass. */
2929dd9d0cfSchristos 	if (pass2) {
2939dd9d0cfSchristos 		if (at->at_form != DW_FORM_ref4 && at->at_form != DW_FORM_ref8)
2949dd9d0cfSchristos 			return (DW_DLE_NONE);
2959dd9d0cfSchristos 		if (at->at_refdie == NULL || at->at_offset == 0)
2969dd9d0cfSchristos 			return (DW_DLE_NONE);
2979dd9d0cfSchristos 		offset = at->at_offset;
2989dd9d0cfSchristos 		dbg->write(ds->ds_data, &offset, at->at_refdie->die_offset,
2999dd9d0cfSchristos 		    at->at_form == DW_FORM_ref4 ? 4 : 8);
3009dd9d0cfSchristos 		return (DW_DLE_NONE);
3019dd9d0cfSchristos 	}
3029dd9d0cfSchristos 
3039dd9d0cfSchristos 	switch (at->at_form) {
3049dd9d0cfSchristos 	case DW_FORM_addr:
3059dd9d0cfSchristos 		if (at->at_relsym)
3069dd9d0cfSchristos 			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
3079dd9d0cfSchristos 			    dwarf_drt_data_reloc, cu->cu_pointer_size,
3089dd9d0cfSchristos 			    ds->ds_size, at->at_relsym, at->u[0].u64, NULL,
3099dd9d0cfSchristos 			    error);
3109dd9d0cfSchristos 		else
3119dd9d0cfSchristos 			ret = WRITE_VALUE(at->u[0].u64, cu->cu_pointer_size);
3129dd9d0cfSchristos 		break;
3139dd9d0cfSchristos 	case DW_FORM_block:
3149dd9d0cfSchristos 	case DW_FORM_block1:
3159dd9d0cfSchristos 	case DW_FORM_block2:
3169dd9d0cfSchristos 	case DW_FORM_block4:
3179dd9d0cfSchristos 		/* Write block size. */
3189dd9d0cfSchristos 		if (at->at_form == DW_FORM_block) {
3199dd9d0cfSchristos 			ret = _dwarf_write_uleb128_alloc(&ds->ds_data,
3209dd9d0cfSchristos 			    &ds->ds_cap, &ds->ds_size, at->u[0].u64, error);
3219dd9d0cfSchristos 			if (ret != DW_DLE_NONE)
3229dd9d0cfSchristos 				break;
3239dd9d0cfSchristos 		} else {
3249dd9d0cfSchristos 			if (at->at_form == DW_FORM_block1)
3259dd9d0cfSchristos 				bs = 1;
3269dd9d0cfSchristos 			else if (at->at_form == DW_FORM_block2)
3279dd9d0cfSchristos 				bs = 2;
3289dd9d0cfSchristos 			else
3299dd9d0cfSchristos 				bs = 4;
3309dd9d0cfSchristos 			ret = WRITE_VALUE(at->u[0].u64, bs);
3319dd9d0cfSchristos 			if (ret != DW_DLE_NONE)
3329dd9d0cfSchristos 				break;
3339dd9d0cfSchristos 		}
3349dd9d0cfSchristos 
3359dd9d0cfSchristos 		/* Keep block data offset for later use. */
3369dd9d0cfSchristos 		offset = ds->ds_size;
3379dd9d0cfSchristos 
3389dd9d0cfSchristos 		/* Write block data. */
3399dd9d0cfSchristos 		ret = WRITE_BLOCK(at->u[1].u8p, at->u[0].u64);
3409dd9d0cfSchristos 		if (ret != DW_DLE_NONE)
3419dd9d0cfSchristos 			break;
3429dd9d0cfSchristos 		if (at->at_expr == NULL)
3439dd9d0cfSchristos 			break;
3449dd9d0cfSchristos 
3459dd9d0cfSchristos 		/* Generate relocation entry for DW_OP_addr expressions. */
3469dd9d0cfSchristos 		STAILQ_FOREACH(ee, &at->at_expr->pe_eelist, ee_next) {
3479dd9d0cfSchristos 			if (ee->ee_loc.lr_atom != DW_OP_addr || ee->ee_sym == 0)
3489dd9d0cfSchristos 				continue;
3499dd9d0cfSchristos 			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
3509dd9d0cfSchristos 			    dwarf_drt_data_reloc, dbg->dbg_pointer_size,
3519dd9d0cfSchristos 			    offset + ee->ee_loc.lr_offset + 1, ee->ee_sym,
3529dd9d0cfSchristos 			    ee->ee_loc.lr_number, NULL, error);
3539dd9d0cfSchristos 			if (ret != DW_DLE_NONE)
3549dd9d0cfSchristos 				break;
3559dd9d0cfSchristos 		}
3569dd9d0cfSchristos 		break;
3579dd9d0cfSchristos 	case DW_FORM_data1:
3589dd9d0cfSchristos 	case DW_FORM_flag:
3599dd9d0cfSchristos 	case DW_FORM_ref1:
3609dd9d0cfSchristos 		ret = WRITE_VALUE(at->u[0].u64, 1);
3619dd9d0cfSchristos 		break;
3629dd9d0cfSchristos 	case DW_FORM_data2:
3639dd9d0cfSchristos 	case DW_FORM_ref2:
3649dd9d0cfSchristos 		ret = WRITE_VALUE(at->u[0].u64, 2);
3659dd9d0cfSchristos 		break;
3669dd9d0cfSchristos 	case DW_FORM_data4:
3679dd9d0cfSchristos 		if (at->at_relsym || at->at_relsec != NULL)
3689dd9d0cfSchristos 			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
3699dd9d0cfSchristos 			    dwarf_drt_data_reloc, 4, ds->ds_size, at->at_relsym,
3709dd9d0cfSchristos 			    at->u[0].u64, at->at_relsec, error);
3719dd9d0cfSchristos 		else
3729dd9d0cfSchristos 			ret = WRITE_VALUE(at->u[0].u64, 4);
3739dd9d0cfSchristos 		break;
3749dd9d0cfSchristos 	case DW_FORM_data8:
3759dd9d0cfSchristos 		if (at->at_relsym || at->at_relsec != NULL)
3769dd9d0cfSchristos 			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
3779dd9d0cfSchristos 			    dwarf_drt_data_reloc, 8, ds->ds_size, at->at_relsym,
3789dd9d0cfSchristos 			    at->u[0].u64, at->at_relsec, error);
3799dd9d0cfSchristos 		else
3809dd9d0cfSchristos 			ret = WRITE_VALUE(at->u[0].u64, 8);
3819dd9d0cfSchristos 		break;
3829dd9d0cfSchristos 	case DW_FORM_ref4:
3839dd9d0cfSchristos 	case DW_FORM_ref8:
3849dd9d0cfSchristos 		/*
3859dd9d0cfSchristos 		 * The value of ref4 and ref8 could be a reference to another
3869dd9d0cfSchristos 		 * DIE within the CU. And if we don't know the ref DIE's
3879dd9d0cfSchristos 		 * offset at the moement, then we remember at_offset and fill
3889dd9d0cfSchristos 		 * it in the second pass.
3899dd9d0cfSchristos 		 */
3909dd9d0cfSchristos 		if (at->at_refdie) {
3919dd9d0cfSchristos 			value = at->at_refdie->die_offset;
3929dd9d0cfSchristos 			if (value == 0) {
3939dd9d0cfSchristos 				cu->cu_pass2 = 1;
3949dd9d0cfSchristos 				at->at_offset = ds->ds_size;
3959dd9d0cfSchristos 			}
3969dd9d0cfSchristos 		} else
3979dd9d0cfSchristos 			value = at->u[0].u64;
3989dd9d0cfSchristos 		ret = WRITE_VALUE(value, at->at_form == DW_FORM_ref4 ? 4 : 8);
3999dd9d0cfSchristos 		break;
4009dd9d0cfSchristos 	case DW_FORM_indirect:
4019dd9d0cfSchristos 		/* TODO. */
4029dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
4039dd9d0cfSchristos 		ret = DW_DLE_ATTR_FORM_BAD;
4049dd9d0cfSchristos 		break;
4059dd9d0cfSchristos 	case DW_FORM_ref_addr:
4069dd9d0cfSchristos 		/* DWARF2 format. */
4079dd9d0cfSchristos 		if (at->at_relsym)
4089dd9d0cfSchristos 			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
4099dd9d0cfSchristos 			    dwarf_drt_data_reloc, cu->cu_pointer_size,
4109dd9d0cfSchristos 			    ds->ds_size, at->at_relsym, at->u[0].u64, NULL,
4119dd9d0cfSchristos 			    error);
4129dd9d0cfSchristos 		else
4139dd9d0cfSchristos 			ret = WRITE_VALUE(at->u[0].u64, cu->cu_pointer_size);
4149dd9d0cfSchristos 		break;
4159dd9d0cfSchristos 	case DW_FORM_ref_udata:
4169dd9d0cfSchristos 	case DW_FORM_udata:
4179dd9d0cfSchristos 		ret = WRITE_ULEB128(at->u[0].u64);
4189dd9d0cfSchristos 		break;
4199dd9d0cfSchristos 	case DW_FORM_sdata:
4209dd9d0cfSchristos 		ret = WRITE_SLEB128(at->u[0].s64);
4219dd9d0cfSchristos 		break;
4229dd9d0cfSchristos 	case DW_FORM_string:
4239dd9d0cfSchristos 		assert(at->u[0].s != NULL);
4249dd9d0cfSchristos 		ret = WRITE_STRING(at->u[0].s);
4259dd9d0cfSchristos 		break;
4269dd9d0cfSchristos 	case DW_FORM_strp:
4279dd9d0cfSchristos 		ret = _dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc,
4289dd9d0cfSchristos 		    4, ds->ds_size, 0, at->u[0].u64, ".debug_str", error);
4299dd9d0cfSchristos 		break;
4309dd9d0cfSchristos 	default:
4319dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
4329dd9d0cfSchristos 		ret = DW_DLE_ATTR_FORM_BAD;
4339dd9d0cfSchristos 		break;
4349dd9d0cfSchristos 	}
4359dd9d0cfSchristos 
4369dd9d0cfSchristos 	return (ret);
4379dd9d0cfSchristos }
4389dd9d0cfSchristos 
4399dd9d0cfSchristos 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)4409dd9d0cfSchristos _dwarf_add_AT_dataref(Dwarf_P_Debug dbg, Dwarf_P_Die die, Dwarf_Half attr,
4419dd9d0cfSchristos     Dwarf_Unsigned pc_value, Dwarf_Unsigned sym_index, const char *secname,
4429dd9d0cfSchristos     Dwarf_P_Attribute *atp, Dwarf_Error *error)
4439dd9d0cfSchristos {
4449dd9d0cfSchristos 	Dwarf_Attribute at;
4459dd9d0cfSchristos 	int ret;
4469dd9d0cfSchristos 
4479dd9d0cfSchristos 	assert(dbg != NULL && die != NULL);
4489dd9d0cfSchristos 
4499dd9d0cfSchristos 	if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
4509dd9d0cfSchristos 		return (ret);
4519dd9d0cfSchristos 
4529dd9d0cfSchristos 	at->at_die = die;
4539dd9d0cfSchristos 	at->at_attrib = attr;
4549dd9d0cfSchristos 	if (dbg->dbg_pointer_size == 4)
4559dd9d0cfSchristos 		at->at_form = DW_FORM_data4;
4569dd9d0cfSchristos 	else
4579dd9d0cfSchristos 		at->at_form = DW_FORM_data8;
4589dd9d0cfSchristos 	at->at_relsym = sym_index;
4599dd9d0cfSchristos 	at->at_relsec = secname;
4609dd9d0cfSchristos 	at->u[0].u64 = pc_value;
4619dd9d0cfSchristos 
4629dd9d0cfSchristos 	STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
4639dd9d0cfSchristos 
4649dd9d0cfSchristos 	if (atp)
4659dd9d0cfSchristos 		*atp = at;
4669dd9d0cfSchristos 
4679dd9d0cfSchristos 	return (DW_DLE_NONE);
4689dd9d0cfSchristos }
4699dd9d0cfSchristos 
4709dd9d0cfSchristos int
_dwarf_add_string_attr(Dwarf_P_Die die,Dwarf_P_Attribute * atp,Dwarf_Half attr,char * string,Dwarf_Error * error)4719dd9d0cfSchristos _dwarf_add_string_attr(Dwarf_P_Die die, Dwarf_P_Attribute *atp, Dwarf_Half attr,
4729dd9d0cfSchristos     char *string, Dwarf_Error *error)
4739dd9d0cfSchristos {
4749dd9d0cfSchristos 	Dwarf_Attribute at;
4759dd9d0cfSchristos 	Dwarf_Debug dbg;
4769dd9d0cfSchristos 	int ret;
4779dd9d0cfSchristos 
4789dd9d0cfSchristos 	dbg = die != NULL ? die->die_dbg : NULL;
4799dd9d0cfSchristos 
4809dd9d0cfSchristos 	assert(atp != NULL);
4819dd9d0cfSchristos 
4829dd9d0cfSchristos 	if (die == NULL || string == NULL) {
4839dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
4849dd9d0cfSchristos 		return (DW_DLE_ARGUMENT);
4859dd9d0cfSchristos 	}
4869dd9d0cfSchristos 
4879dd9d0cfSchristos 	if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
4889dd9d0cfSchristos 		return (ret);
4899dd9d0cfSchristos 
4909dd9d0cfSchristos 	at->at_die = die;
4919dd9d0cfSchristos 	at->at_attrib = attr;
4929dd9d0cfSchristos 	at->at_form = DW_FORM_strp;
4939dd9d0cfSchristos 	if ((ret = _dwarf_strtab_add(dbg, string, &at->u[0].u64,
4949dd9d0cfSchristos 	    error)) != DW_DLE_NONE) {
4959dd9d0cfSchristos 		free(at);
4969dd9d0cfSchristos 		return (ret);
4979dd9d0cfSchristos 	}
4989dd9d0cfSchristos 	at->u[1].s = _dwarf_strtab_get_table(dbg) + at->u[0].u64;
4999dd9d0cfSchristos 
5009dd9d0cfSchristos 	*atp = at;
5019dd9d0cfSchristos 
5029dd9d0cfSchristos 	STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
5039dd9d0cfSchristos 
5049dd9d0cfSchristos 	return (DW_DLE_NONE);
5059dd9d0cfSchristos }
5069dd9d0cfSchristos 
5079dd9d0cfSchristos 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)5089dd9d0cfSchristos _dwarf_attr_gen(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_Rel_Section drs,
5099dd9d0cfSchristos     Dwarf_CU cu, Dwarf_Die die, int pass2, Dwarf_Error *error)
5109dd9d0cfSchristos {
5119dd9d0cfSchristos 	Dwarf_Attribute at;
5129dd9d0cfSchristos 	int ret;
5139dd9d0cfSchristos 
5149dd9d0cfSchristos 	assert(dbg != NULL && ds != NULL && cu != NULL && die != NULL);
5159dd9d0cfSchristos 
5169dd9d0cfSchristos 	STAILQ_FOREACH(at, &die->die_attr, at_next) {
5179dd9d0cfSchristos 		ret = _dwarf_attr_write(dbg, ds, drs, cu, at, pass2, error);
5189dd9d0cfSchristos 		if (ret != DW_DLE_NONE)
5199dd9d0cfSchristos 			return (ret);
5209dd9d0cfSchristos 	}
5219dd9d0cfSchristos 
5229dd9d0cfSchristos 	return (DW_DLE_NONE);
5239dd9d0cfSchristos }
524