xref: /freebsd/contrib/elftoolchain/libdwarf/libdwarf_attr.c (revision d003e0d7fe0d3a9b4b2c5835bb3f0f6faf3ab538)
12de3b87aSKai Wang /*-
22de3b87aSKai Wang  * Copyright (c) 2007 John Birrell (jb@freebsd.org)
32de3b87aSKai Wang  * Copyright (c) 2009-2011 Kai Wang
42de3b87aSKai Wang  * All rights reserved.
52de3b87aSKai Wang  *
62de3b87aSKai Wang  * Redistribution and use in source and binary forms, with or without
72de3b87aSKai Wang  * modification, are permitted provided that the following conditions
82de3b87aSKai Wang  * are met:
92de3b87aSKai Wang  * 1. Redistributions of source code must retain the above copyright
102de3b87aSKai Wang  *    notice, this list of conditions and the following disclaimer.
112de3b87aSKai Wang  * 2. Redistributions in binary form must reproduce the above copyright
122de3b87aSKai Wang  *    notice, this list of conditions and the following disclaimer in the
132de3b87aSKai Wang  *    documentation and/or other materials provided with the distribution.
142de3b87aSKai Wang  *
152de3b87aSKai Wang  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
162de3b87aSKai Wang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
172de3b87aSKai Wang  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
182de3b87aSKai Wang  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
192de3b87aSKai Wang  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
202de3b87aSKai Wang  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
212de3b87aSKai Wang  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
222de3b87aSKai Wang  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
232de3b87aSKai Wang  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
242de3b87aSKai Wang  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
252de3b87aSKai Wang  * SUCH DAMAGE.
262de3b87aSKai Wang  */
272de3b87aSKai Wang 
282de3b87aSKai Wang #include "_libdwarf.h"
292de3b87aSKai Wang 
30*d003e0d7SEd Maste ELFTC_VCSID("$Id: libdwarf_attr.c 3748 2019-06-28 01:11:13Z emaste $");
312de3b87aSKai Wang 
322de3b87aSKai Wang int
_dwarf_attr_alloc(Dwarf_Die die,Dwarf_Attribute * atp,Dwarf_Error * error)332de3b87aSKai Wang _dwarf_attr_alloc(Dwarf_Die die, Dwarf_Attribute *atp, Dwarf_Error *error)
342de3b87aSKai Wang {
352de3b87aSKai Wang 	Dwarf_Attribute at;
362de3b87aSKai Wang 
372de3b87aSKai Wang 	assert(die != NULL);
382de3b87aSKai Wang 	assert(atp != NULL);
392de3b87aSKai Wang 
402de3b87aSKai Wang 	if ((at = calloc(1, sizeof(struct _Dwarf_Attribute))) == NULL) {
412de3b87aSKai Wang 		DWARF_SET_ERROR(die->die_dbg, error, DW_DLE_MEMORY);
422de3b87aSKai Wang 		return (DW_DLE_MEMORY);
432de3b87aSKai Wang 	}
442de3b87aSKai Wang 
452de3b87aSKai Wang 	*atp = at;
462de3b87aSKai Wang 
472de3b87aSKai Wang 	return (DW_DLE_NONE);
482de3b87aSKai Wang }
492de3b87aSKai Wang 
502de3b87aSKai Wang static int
_dwarf_attr_add(Dwarf_Die die,Dwarf_Attribute atref,Dwarf_Attribute * atp,Dwarf_Error * error)512de3b87aSKai Wang _dwarf_attr_add(Dwarf_Die die, Dwarf_Attribute atref, Dwarf_Attribute *atp,
522de3b87aSKai Wang     Dwarf_Error *error)
532de3b87aSKai Wang {
542de3b87aSKai Wang 	Dwarf_Attribute at;
552de3b87aSKai Wang 	int ret;
562de3b87aSKai Wang 
572de3b87aSKai Wang 	if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
582de3b87aSKai Wang 		return (ret);
592de3b87aSKai Wang 
602de3b87aSKai Wang 	memcpy(at, atref, sizeof(struct _Dwarf_Attribute));
612de3b87aSKai Wang 
622de3b87aSKai Wang 	STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
632de3b87aSKai Wang 
642de3b87aSKai Wang 	/* Save a pointer to the attribute name if this is one. */
652de3b87aSKai Wang 	if (at->at_attrib == DW_AT_name) {
662de3b87aSKai Wang 		switch (at->at_form) {
672de3b87aSKai Wang 		case DW_FORM_strp:
682de3b87aSKai Wang 			die->die_name = at->u[1].s;
692de3b87aSKai Wang 			break;
702de3b87aSKai Wang 		case DW_FORM_string:
712de3b87aSKai Wang 			die->die_name = at->u[0].s;
722de3b87aSKai Wang 			break;
732de3b87aSKai Wang 		default:
742de3b87aSKai Wang 			break;
752de3b87aSKai Wang 		}
762de3b87aSKai Wang 	}
772de3b87aSKai Wang 
782de3b87aSKai Wang 	if (atp != NULL)
792de3b87aSKai Wang 		*atp = at;
802de3b87aSKai Wang 
812de3b87aSKai Wang 	return (DW_DLE_NONE);
822de3b87aSKai Wang }
832de3b87aSKai Wang 
842de3b87aSKai Wang Dwarf_Attribute
_dwarf_attr_find(Dwarf_Die die,Dwarf_Half attr)852de3b87aSKai Wang _dwarf_attr_find(Dwarf_Die die, Dwarf_Half attr)
862de3b87aSKai Wang {
872de3b87aSKai Wang 	Dwarf_Attribute at;
882de3b87aSKai Wang 
892de3b87aSKai Wang 	STAILQ_FOREACH(at, &die->die_attr, at_next) {
902de3b87aSKai Wang 		if (at->at_attrib == attr)
912de3b87aSKai Wang 			break;
922de3b87aSKai Wang 	}
932de3b87aSKai Wang 
942de3b87aSKai Wang 	return (at);
952de3b87aSKai Wang }
962de3b87aSKai Wang 
972de3b87aSKai Wang 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)982de3b87aSKai Wang _dwarf_attr_init(Dwarf_Debug dbg, Dwarf_Section *ds, uint64_t *offsetp,
992de3b87aSKai Wang     int dwarf_size, Dwarf_CU cu, Dwarf_Die die, Dwarf_AttrDef ad,
1002de3b87aSKai Wang     uint64_t form, int indirect, Dwarf_Error *error)
1012de3b87aSKai Wang {
1022de3b87aSKai Wang 	struct _Dwarf_Attribute atref;
1032de3b87aSKai Wang 	int ret;
1042de3b87aSKai Wang 
1052de3b87aSKai Wang 	ret = DW_DLE_NONE;
1062de3b87aSKai Wang 	memset(&atref, 0, sizeof(atref));
1072de3b87aSKai Wang 	atref.at_die = die;
108cf781b2eSEd Maste 	atref.at_offset = *offsetp;
1092de3b87aSKai Wang 	atref.at_attrib = ad->ad_attrib;
1102de3b87aSKai Wang 	atref.at_form = indirect ? form : ad->ad_form;
1112de3b87aSKai Wang 	atref.at_indirect = indirect;
1122de3b87aSKai Wang 	atref.at_ld = NULL;
1132de3b87aSKai Wang 
1142de3b87aSKai Wang 	switch (form) {
1152de3b87aSKai Wang 	case DW_FORM_addr:
1162de3b87aSKai Wang 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
1172de3b87aSKai Wang 		    cu->cu_pointer_size);
1182de3b87aSKai Wang 		break;
1192de3b87aSKai Wang 	case DW_FORM_block:
1202de3b87aSKai Wang 	case DW_FORM_exprloc:
1212de3b87aSKai Wang 		atref.u[0].u64 = _dwarf_read_uleb128(ds->ds_data, offsetp);
1222de3b87aSKai Wang 		atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
1232de3b87aSKai Wang 		    atref.u[0].u64);
1242de3b87aSKai Wang 		break;
1252de3b87aSKai Wang 	case DW_FORM_block1:
1262de3b87aSKai Wang 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 1);
1272de3b87aSKai Wang 		atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
1282de3b87aSKai Wang 		    atref.u[0].u64);
1292de3b87aSKai Wang 		break;
1302de3b87aSKai Wang 	case DW_FORM_block2:
1312de3b87aSKai Wang 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 2);
1322de3b87aSKai Wang 		atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
1332de3b87aSKai Wang 		    atref.u[0].u64);
1342de3b87aSKai Wang 		break;
1352de3b87aSKai Wang 	case DW_FORM_block4:
1362de3b87aSKai Wang 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 4);
1372de3b87aSKai Wang 		atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
1382de3b87aSKai Wang 		    atref.u[0].u64);
1392de3b87aSKai Wang 		break;
1402de3b87aSKai Wang 	case DW_FORM_data1:
1412de3b87aSKai Wang 	case DW_FORM_flag:
1422de3b87aSKai Wang 	case DW_FORM_ref1:
1432de3b87aSKai Wang 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 1);
1442de3b87aSKai Wang 		break;
1452de3b87aSKai Wang 	case DW_FORM_data2:
1462de3b87aSKai Wang 	case DW_FORM_ref2:
1472de3b87aSKai Wang 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 2);
1482de3b87aSKai Wang 		break;
1492de3b87aSKai Wang 	case DW_FORM_data4:
1502de3b87aSKai Wang 	case DW_FORM_ref4:
1512de3b87aSKai Wang 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 4);
1522de3b87aSKai Wang 		break;
1532de3b87aSKai Wang 	case DW_FORM_data8:
1542de3b87aSKai Wang 	case DW_FORM_ref8:
1552de3b87aSKai Wang 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 8);
1562de3b87aSKai Wang 		break;
1572de3b87aSKai Wang 	case DW_FORM_indirect:
1582de3b87aSKai Wang 		form = _dwarf_read_uleb128(ds->ds_data, offsetp);
1592de3b87aSKai Wang 		return (_dwarf_attr_init(dbg, ds, offsetp, dwarf_size, cu, die,
1602de3b87aSKai Wang 		    ad, form, 1, error));
1612de3b87aSKai Wang 	case DW_FORM_ref_addr:
1622de3b87aSKai Wang 		if (cu->cu_version == 2)
1632de3b87aSKai Wang 			atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
1642de3b87aSKai Wang 			    cu->cu_pointer_size);
165cf781b2eSEd Maste 		else
1662de3b87aSKai Wang 			atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
1672de3b87aSKai Wang 			    dwarf_size);
1682de3b87aSKai Wang 		break;
1692de3b87aSKai Wang 	case DW_FORM_ref_udata:
1702de3b87aSKai Wang 	case DW_FORM_udata:
1712de3b87aSKai Wang 		atref.u[0].u64 = _dwarf_read_uleb128(ds->ds_data, offsetp);
1722de3b87aSKai Wang 		break;
1732de3b87aSKai Wang 	case DW_FORM_sdata:
1742de3b87aSKai Wang 		atref.u[0].s64 = _dwarf_read_sleb128(ds->ds_data, offsetp);
1752de3b87aSKai Wang 		break;
1762de3b87aSKai Wang 	case DW_FORM_sec_offset:
1772de3b87aSKai Wang 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size);
1782de3b87aSKai Wang 		break;
1792de3b87aSKai Wang 	case DW_FORM_string:
1802de3b87aSKai Wang 		atref.u[0].s = _dwarf_read_string(ds->ds_data, ds->ds_size,
1812de3b87aSKai Wang 		    offsetp);
1822de3b87aSKai Wang 		break;
1832de3b87aSKai Wang 	case DW_FORM_strp:
1842de3b87aSKai Wang 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size);
185ab69795fSMark Johnston 		atref.u[1].s = _dwarf_strtab_get_table(dbg) + atref.u[0].u64;
1862de3b87aSKai Wang 		break;
1872de3b87aSKai Wang 	case DW_FORM_ref_sig8:
1882de3b87aSKai Wang 		atref.u[0].u64 = 8;
1892de3b87aSKai Wang 		atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
1902de3b87aSKai Wang 		    atref.u[0].u64);
1912de3b87aSKai Wang 		break;
1922de3b87aSKai Wang 	case DW_FORM_flag_present:
1932de3b87aSKai Wang 		/* This form has no value encoded in the DIE. */
1942de3b87aSKai Wang 		atref.u[0].u64 = 1;
1952de3b87aSKai Wang 		break;
1962de3b87aSKai Wang 	default:
1972de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
1982de3b87aSKai Wang 		ret = DW_DLE_ATTR_FORM_BAD;
1992de3b87aSKai Wang 		break;
2002de3b87aSKai Wang 	}
2012de3b87aSKai Wang 
2022de3b87aSKai Wang 	if (ret == DW_DLE_NONE) {
2032de3b87aSKai Wang 		if (form == DW_FORM_block || form == DW_FORM_block1 ||
2042de3b87aSKai Wang 		    form == DW_FORM_block2 || form == DW_FORM_block4) {
2052de3b87aSKai Wang 			atref.at_block.bl_len = atref.u[0].u64;
2062de3b87aSKai Wang 			atref.at_block.bl_data = atref.u[1].u8p;
2072de3b87aSKai Wang 		}
2082de3b87aSKai Wang 		ret = _dwarf_attr_add(die, &atref, NULL, error);
2092de3b87aSKai Wang 	}
2102de3b87aSKai Wang 
2112de3b87aSKai Wang 	return (ret);
2122de3b87aSKai Wang }
2132de3b87aSKai Wang 
2142de3b87aSKai Wang 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)2152de3b87aSKai Wang _dwarf_attr_write(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_Rel_Section drs,
2162de3b87aSKai Wang     Dwarf_CU cu, Dwarf_Attribute at, int pass2, Dwarf_Error *error)
2172de3b87aSKai Wang {
2182de3b87aSKai Wang 	struct _Dwarf_P_Expr_Entry *ee;
2192de3b87aSKai Wang 	uint64_t value, offset, bs;
2202de3b87aSKai Wang 	int ret;
2212de3b87aSKai Wang 
2222de3b87aSKai Wang 	assert(dbg != NULL && ds != NULL && cu != NULL && at != NULL);
2232de3b87aSKai Wang 
2242de3b87aSKai Wang 	/* Fill in reference to other DIE in the second pass. */
2252de3b87aSKai Wang 	if (pass2) {
2262de3b87aSKai Wang 		if (at->at_form != DW_FORM_ref4 && at->at_form != DW_FORM_ref8)
2272de3b87aSKai Wang 			return (DW_DLE_NONE);
2282de3b87aSKai Wang 		if (at->at_refdie == NULL || at->at_offset == 0)
2292de3b87aSKai Wang 			return (DW_DLE_NONE);
2302de3b87aSKai Wang 		offset = at->at_offset;
2312de3b87aSKai Wang 		dbg->write(ds->ds_data, &offset, at->at_refdie->die_offset,
2322de3b87aSKai Wang 		    at->at_form == DW_FORM_ref4 ? 4 : 8);
2332de3b87aSKai Wang 		return (DW_DLE_NONE);
2342de3b87aSKai Wang 	}
2352de3b87aSKai Wang 
2362de3b87aSKai Wang 	switch (at->at_form) {
2372de3b87aSKai Wang 	case DW_FORM_addr:
2382de3b87aSKai Wang 		if (at->at_relsym)
2392de3b87aSKai Wang 			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
2402de3b87aSKai Wang 			    dwarf_drt_data_reloc, cu->cu_pointer_size,
2412de3b87aSKai Wang 			    ds->ds_size, at->at_relsym, at->u[0].u64, NULL,
2422de3b87aSKai Wang 			    error);
2432de3b87aSKai Wang 		else
2442de3b87aSKai Wang 			ret = WRITE_VALUE(at->u[0].u64, cu->cu_pointer_size);
2452de3b87aSKai Wang 		break;
2462de3b87aSKai Wang 	case DW_FORM_block:
2472de3b87aSKai Wang 	case DW_FORM_block1:
2482de3b87aSKai Wang 	case DW_FORM_block2:
2492de3b87aSKai Wang 	case DW_FORM_block4:
2502de3b87aSKai Wang 		/* Write block size. */
2512de3b87aSKai Wang 		if (at->at_form == DW_FORM_block) {
2522de3b87aSKai Wang 			ret = _dwarf_write_uleb128_alloc(&ds->ds_data,
2532de3b87aSKai Wang 			    &ds->ds_cap, &ds->ds_size, at->u[0].u64, error);
2542de3b87aSKai Wang 			if (ret != DW_DLE_NONE)
2552de3b87aSKai Wang 				break;
2562de3b87aSKai Wang 		} else {
2572de3b87aSKai Wang 			if (at->at_form == DW_FORM_block1)
2582de3b87aSKai Wang 				bs = 1;
2592de3b87aSKai Wang 			else if (at->at_form == DW_FORM_block2)
2602de3b87aSKai Wang 				bs = 2;
2612de3b87aSKai Wang 			else
2622de3b87aSKai Wang 				bs = 4;
2632de3b87aSKai Wang 			ret = WRITE_VALUE(at->u[0].u64, bs);
2642de3b87aSKai Wang 			if (ret != DW_DLE_NONE)
2652de3b87aSKai Wang 				break;
2662de3b87aSKai Wang 		}
2672de3b87aSKai Wang 
2682de3b87aSKai Wang 		/* Keep block data offset for later use. */
2692de3b87aSKai Wang 		offset = ds->ds_size;
2702de3b87aSKai Wang 
2712de3b87aSKai Wang 		/* Write block data. */
2722de3b87aSKai Wang 		ret = WRITE_BLOCK(at->u[1].u8p, at->u[0].u64);
2732de3b87aSKai Wang 		if (ret != DW_DLE_NONE)
2742de3b87aSKai Wang 			break;
2752de3b87aSKai Wang 		if (at->at_expr == NULL)
2762de3b87aSKai Wang 			break;
2772de3b87aSKai Wang 
2782de3b87aSKai Wang 		/* Generate relocation entry for DW_OP_addr expressions. */
2792de3b87aSKai Wang 		STAILQ_FOREACH(ee, &at->at_expr->pe_eelist, ee_next) {
2802de3b87aSKai Wang 			if (ee->ee_loc.lr_atom != DW_OP_addr || ee->ee_sym == 0)
2812de3b87aSKai Wang 				continue;
2822de3b87aSKai Wang 			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
2832de3b87aSKai Wang 			    dwarf_drt_data_reloc, dbg->dbg_pointer_size,
2842de3b87aSKai Wang 			    offset + ee->ee_loc.lr_offset + 1, ee->ee_sym,
2852de3b87aSKai Wang 			    ee->ee_loc.lr_number, NULL, error);
2862de3b87aSKai Wang 			if (ret != DW_DLE_NONE)
2872de3b87aSKai Wang 				break;
2882de3b87aSKai Wang 		}
2892de3b87aSKai Wang 		break;
2902de3b87aSKai Wang 	case DW_FORM_data1:
2912de3b87aSKai Wang 	case DW_FORM_flag:
2922de3b87aSKai Wang 	case DW_FORM_ref1:
2932de3b87aSKai Wang 		ret = WRITE_VALUE(at->u[0].u64, 1);
2942de3b87aSKai Wang 		break;
2952de3b87aSKai Wang 	case DW_FORM_data2:
2962de3b87aSKai Wang 	case DW_FORM_ref2:
2972de3b87aSKai Wang 		ret = WRITE_VALUE(at->u[0].u64, 2);
2982de3b87aSKai Wang 		break;
2992de3b87aSKai Wang 	case DW_FORM_data4:
3002de3b87aSKai Wang 		if (at->at_relsym || at->at_relsec != NULL)
3012de3b87aSKai Wang 			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
3022de3b87aSKai Wang 			    dwarf_drt_data_reloc, 4, ds->ds_size, at->at_relsym,
3032de3b87aSKai Wang 			    at->u[0].u64, at->at_relsec, error);
3042de3b87aSKai Wang 		else
3052de3b87aSKai Wang 			ret = WRITE_VALUE(at->u[0].u64, 4);
3062de3b87aSKai Wang 		break;
3072de3b87aSKai Wang 	case DW_FORM_data8:
3082de3b87aSKai Wang 		if (at->at_relsym || at->at_relsec != NULL)
3092de3b87aSKai Wang 			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
3102de3b87aSKai Wang 			    dwarf_drt_data_reloc, 8, ds->ds_size, at->at_relsym,
3112de3b87aSKai Wang 			    at->u[0].u64, at->at_relsec, error);
3122de3b87aSKai Wang 		else
3132de3b87aSKai Wang 			ret = WRITE_VALUE(at->u[0].u64, 8);
3142de3b87aSKai Wang 		break;
3152de3b87aSKai Wang 	case DW_FORM_ref4:
3162de3b87aSKai Wang 	case DW_FORM_ref8:
3172de3b87aSKai Wang 		/*
3182de3b87aSKai Wang 		 * The value of ref4 and ref8 could be a reference to another
3192de3b87aSKai Wang 		 * DIE within the CU. And if we don't know the ref DIE's
3202de3b87aSKai Wang 		 * offset at the moement, then we remember at_offset and fill
3212de3b87aSKai Wang 		 * it in the second pass.
3222de3b87aSKai Wang 		 */
3232de3b87aSKai Wang 		if (at->at_refdie) {
3242de3b87aSKai Wang 			value = at->at_refdie->die_offset;
3252de3b87aSKai Wang 			if (value == 0) {
3262de3b87aSKai Wang 				cu->cu_pass2 = 1;
3272de3b87aSKai Wang 				at->at_offset = ds->ds_size;
3282de3b87aSKai Wang 			}
3292de3b87aSKai Wang 		} else
3302de3b87aSKai Wang 			value = at->u[0].u64;
3312de3b87aSKai Wang 		ret = WRITE_VALUE(value, at->at_form == DW_FORM_ref4 ? 4 : 8);
3322de3b87aSKai Wang 		break;
3332de3b87aSKai Wang 	case DW_FORM_indirect:
3342de3b87aSKai Wang 		/* TODO. */
3352de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
3362de3b87aSKai Wang 		ret = DW_DLE_ATTR_FORM_BAD;
3372de3b87aSKai Wang 		break;
3382de3b87aSKai Wang 	case DW_FORM_ref_addr:
3392de3b87aSKai Wang 		/* DWARF2 format. */
3402de3b87aSKai Wang 		if (at->at_relsym)
3412de3b87aSKai Wang 			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
3422de3b87aSKai Wang 			    dwarf_drt_data_reloc, cu->cu_pointer_size,
3432de3b87aSKai Wang 			    ds->ds_size, at->at_relsym, at->u[0].u64, NULL,
3442de3b87aSKai Wang 			    error);
3452de3b87aSKai Wang 		else
3462de3b87aSKai Wang 			ret = WRITE_VALUE(at->u[0].u64, cu->cu_pointer_size);
3472de3b87aSKai Wang 		break;
3482de3b87aSKai Wang 	case DW_FORM_ref_udata:
3492de3b87aSKai Wang 	case DW_FORM_udata:
3502de3b87aSKai Wang 		ret = WRITE_ULEB128(at->u[0].u64);
3512de3b87aSKai Wang 		break;
3522de3b87aSKai Wang 	case DW_FORM_sdata:
3532de3b87aSKai Wang 		ret = WRITE_SLEB128(at->u[0].s64);
3542de3b87aSKai Wang 		break;
3552de3b87aSKai Wang 	case DW_FORM_string:
3562de3b87aSKai Wang 		assert(at->u[0].s != NULL);
3572de3b87aSKai Wang 		ret = WRITE_STRING(at->u[0].s);
3582de3b87aSKai Wang 		break;
3592de3b87aSKai Wang 	case DW_FORM_strp:
3602de3b87aSKai Wang 		ret = _dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc,
3612de3b87aSKai Wang 		    4, ds->ds_size, 0, at->u[0].u64, ".debug_str", error);
3622de3b87aSKai Wang 		break;
3632de3b87aSKai Wang 	default:
3642de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
3652de3b87aSKai Wang 		ret = DW_DLE_ATTR_FORM_BAD;
3662de3b87aSKai Wang 		break;
3672de3b87aSKai Wang 	}
3682de3b87aSKai Wang 
3692de3b87aSKai Wang 	return (ret);
3702de3b87aSKai Wang }
3712de3b87aSKai Wang 
3722de3b87aSKai Wang 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)3732de3b87aSKai Wang _dwarf_add_AT_dataref(Dwarf_P_Debug dbg, Dwarf_P_Die die, Dwarf_Half attr,
3742de3b87aSKai Wang     Dwarf_Unsigned pc_value, Dwarf_Unsigned sym_index, const char *secname,
3752de3b87aSKai Wang     Dwarf_P_Attribute *atp, Dwarf_Error *error)
3762de3b87aSKai Wang {
3772de3b87aSKai Wang 	Dwarf_Attribute at;
3782de3b87aSKai Wang 	int ret;
3792de3b87aSKai Wang 
3802de3b87aSKai Wang 	assert(dbg != NULL && die != NULL);
3812de3b87aSKai Wang 
3822de3b87aSKai Wang 	if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
3832de3b87aSKai Wang 		return (ret);
3842de3b87aSKai Wang 
3852de3b87aSKai Wang 	at->at_die = die;
3862de3b87aSKai Wang 	at->at_attrib = attr;
3872de3b87aSKai Wang 	if (dbg->dbg_pointer_size == 4)
3882de3b87aSKai Wang 		at->at_form = DW_FORM_data4;
3892de3b87aSKai Wang 	else
3902de3b87aSKai Wang 		at->at_form = DW_FORM_data8;
3912de3b87aSKai Wang 	at->at_relsym = sym_index;
3922de3b87aSKai Wang 	at->at_relsec = secname;
3932de3b87aSKai Wang 	at->u[0].u64 = pc_value;
3942de3b87aSKai Wang 
3952de3b87aSKai Wang 	STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
3962de3b87aSKai Wang 
3972de3b87aSKai Wang 	if (atp)
3982de3b87aSKai Wang 		*atp = at;
3992de3b87aSKai Wang 
4002de3b87aSKai Wang 	return (DW_DLE_NONE);
4012de3b87aSKai Wang }
4022de3b87aSKai Wang 
4032de3b87aSKai Wang int
_dwarf_add_string_attr(Dwarf_P_Die die,Dwarf_P_Attribute * atp,Dwarf_Half attr,char * string,Dwarf_Error * error)4042de3b87aSKai Wang _dwarf_add_string_attr(Dwarf_P_Die die, Dwarf_P_Attribute *atp, Dwarf_Half attr,
4052de3b87aSKai Wang     char *string, Dwarf_Error *error)
4062de3b87aSKai Wang {
4072de3b87aSKai Wang 	Dwarf_Attribute at;
4082de3b87aSKai Wang 	Dwarf_Debug dbg;
4092de3b87aSKai Wang 	int ret;
4102de3b87aSKai Wang 
4112de3b87aSKai Wang 	dbg = die != NULL ? die->die_dbg : NULL;
4122de3b87aSKai Wang 
4132de3b87aSKai Wang 	assert(atp != NULL);
4142de3b87aSKai Wang 
4152de3b87aSKai Wang 	if (die == NULL || string == NULL) {
4162de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
4172de3b87aSKai Wang 		return (DW_DLE_ARGUMENT);
4182de3b87aSKai Wang 	}
4192de3b87aSKai Wang 
4202de3b87aSKai Wang 	if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
4212de3b87aSKai Wang 		return (ret);
4222de3b87aSKai Wang 
4232de3b87aSKai Wang 	at->at_die = die;
4242de3b87aSKai Wang 	at->at_attrib = attr;
4252de3b87aSKai Wang 	at->at_form = DW_FORM_strp;
4262de3b87aSKai Wang 	if ((ret = _dwarf_strtab_add(dbg, string, &at->u[0].u64,
4272de3b87aSKai Wang 	    error)) != DW_DLE_NONE) {
4282de3b87aSKai Wang 		free(at);
4292de3b87aSKai Wang 		return (ret);
4302de3b87aSKai Wang 	}
4312de3b87aSKai Wang 	at->u[1].s = _dwarf_strtab_get_table(dbg) + at->u[0].u64;
4322de3b87aSKai Wang 
4332de3b87aSKai Wang 	*atp = at;
4342de3b87aSKai Wang 
4352de3b87aSKai Wang 	STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
4362de3b87aSKai Wang 
4372de3b87aSKai Wang 	return (DW_DLE_NONE);
4382de3b87aSKai Wang }
4392de3b87aSKai Wang 
4402de3b87aSKai Wang 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)4412de3b87aSKai Wang _dwarf_attr_gen(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_Rel_Section drs,
4422de3b87aSKai Wang     Dwarf_CU cu, Dwarf_Die die, int pass2, Dwarf_Error *error)
4432de3b87aSKai Wang {
4442de3b87aSKai Wang 	Dwarf_Attribute at;
4452de3b87aSKai Wang 	int ret;
4462de3b87aSKai Wang 
4472de3b87aSKai Wang 	assert(dbg != NULL && ds != NULL && cu != NULL && die != NULL);
4482de3b87aSKai Wang 
4492de3b87aSKai Wang 	STAILQ_FOREACH(at, &die->die_attr, at_next) {
4502de3b87aSKai Wang 		ret = _dwarf_attr_write(dbg, ds, drs, cu, at, pass2, error);
4512de3b87aSKai Wang 		if (ret != DW_DLE_NONE)
4522de3b87aSKai Wang 			return (ret);
4532de3b87aSKai Wang 	}
4542de3b87aSKai Wang 
4552de3b87aSKai Wang 	return (DW_DLE_NONE);
4562de3b87aSKai Wang }
457