xref: /netbsd-src/external/bsd/elftoolchain/dist/libdwarf/dwarf_form.c (revision 5ac3bc719ce6e70593039505b491894133237d12)
1*5ac3bc71Schristos /*	$NetBSD: dwarf_form.c,v 1.5 2024/03/03 17:37:30 christos Exp $	*/
2e81373b4Schristos 
39dd9d0cfSchristos /*-
49dd9d0cfSchristos  * Copyright (c) 2007 John Birrell (jb@freebsd.org)
5*5ac3bc71Schristos  * Copyright (c) 2009,2010,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: dwarf_form.c,v 1.5 2024/03/03 17:37:30 christos Exp $");
33*5ac3bc71Schristos ELFTC_VCSID("Id: dwarf_form.c 4016 2023-10-15 05:39:46Z kaiwang27");
349dd9d0cfSchristos 
359dd9d0cfSchristos int
dwarf_hasform(Dwarf_Attribute at,Dwarf_Half form,Dwarf_Bool * return_hasform,Dwarf_Error * error)369dd9d0cfSchristos dwarf_hasform(Dwarf_Attribute at, Dwarf_Half form, Dwarf_Bool *return_hasform,
379dd9d0cfSchristos     Dwarf_Error *error)
389dd9d0cfSchristos {
399dd9d0cfSchristos 	Dwarf_Debug dbg;
409dd9d0cfSchristos 
419dd9d0cfSchristos 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
429dd9d0cfSchristos 
439dd9d0cfSchristos 	if (at == NULL || return_hasform == NULL) {
449dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
459dd9d0cfSchristos 		return (DW_DLV_ERROR);
469dd9d0cfSchristos 	}
479dd9d0cfSchristos 
489dd9d0cfSchristos 	*return_hasform = (at->at_form == form);
499dd9d0cfSchristos 
509dd9d0cfSchristos 	return (DW_DLV_OK);
519dd9d0cfSchristos }
529dd9d0cfSchristos 
539dd9d0cfSchristos int
dwarf_whatform(Dwarf_Attribute at,Dwarf_Half * return_form,Dwarf_Error * error)549dd9d0cfSchristos dwarf_whatform(Dwarf_Attribute at, Dwarf_Half *return_form, Dwarf_Error *error)
559dd9d0cfSchristos {
569dd9d0cfSchristos 	Dwarf_Debug dbg;
579dd9d0cfSchristos 
589dd9d0cfSchristos 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
599dd9d0cfSchristos 
609dd9d0cfSchristos 	if (at == NULL || return_form == NULL) {
619dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
629dd9d0cfSchristos 		return (DW_DLV_ERROR);
639dd9d0cfSchristos 	}
649dd9d0cfSchristos 
659dd9d0cfSchristos 	*return_form = at->at_form;
669dd9d0cfSchristos 
679dd9d0cfSchristos 	return (DW_DLV_OK);
689dd9d0cfSchristos }
699dd9d0cfSchristos 
709dd9d0cfSchristos int
dwarf_whatform_direct(Dwarf_Attribute at,Dwarf_Half * return_form,Dwarf_Error * error)719dd9d0cfSchristos dwarf_whatform_direct(Dwarf_Attribute at, Dwarf_Half *return_form,
729dd9d0cfSchristos     Dwarf_Error *error)
739dd9d0cfSchristos {
749dd9d0cfSchristos 	Dwarf_Debug dbg;
759dd9d0cfSchristos 
769dd9d0cfSchristos 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
779dd9d0cfSchristos 
789dd9d0cfSchristos 	if (at == NULL || return_form == NULL) {
799dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
809dd9d0cfSchristos 		return (DW_DLV_ERROR);
819dd9d0cfSchristos 	}
829dd9d0cfSchristos 
839dd9d0cfSchristos 	if (at->at_indirect)
849dd9d0cfSchristos 		*return_form = DW_FORM_indirect;
859dd9d0cfSchristos 	else
869dd9d0cfSchristos 		*return_form = (Dwarf_Half) at->at_form;
879dd9d0cfSchristos 
889dd9d0cfSchristos 	return (DW_DLV_OK);
899dd9d0cfSchristos }
909dd9d0cfSchristos 
919dd9d0cfSchristos int
dwarf_whatattr(Dwarf_Attribute at,Dwarf_Half * return_attr,Dwarf_Error * error)929dd9d0cfSchristos dwarf_whatattr(Dwarf_Attribute at, Dwarf_Half *return_attr, Dwarf_Error *error)
939dd9d0cfSchristos {
949dd9d0cfSchristos 	Dwarf_Debug dbg;
959dd9d0cfSchristos 
969dd9d0cfSchristos 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
979dd9d0cfSchristos 
989dd9d0cfSchristos 	if (at == NULL || return_attr == NULL) {
999dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
1009dd9d0cfSchristos 		return (DW_DLV_ERROR);
1019dd9d0cfSchristos 	}
1029dd9d0cfSchristos 
1039dd9d0cfSchristos 	*return_attr = (Dwarf_Half) at->at_attrib;
1049dd9d0cfSchristos 
1059dd9d0cfSchristos 	return (DW_DLV_OK);
1069dd9d0cfSchristos }
1079dd9d0cfSchristos 
1089dd9d0cfSchristos int
dwarf_formref(Dwarf_Attribute at,Dwarf_Off * return_offset,Dwarf_Error * error)1099dd9d0cfSchristos dwarf_formref(Dwarf_Attribute at, Dwarf_Off *return_offset, Dwarf_Error *error)
1109dd9d0cfSchristos {
1119dd9d0cfSchristos 	int ret;
1129dd9d0cfSchristos 	Dwarf_Debug dbg;
1139dd9d0cfSchristos 
1149dd9d0cfSchristos 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
1159dd9d0cfSchristos 
1169dd9d0cfSchristos 	if (at == NULL || return_offset == NULL) {
1179dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
1189dd9d0cfSchristos 		return (DW_DLV_ERROR);
1199dd9d0cfSchristos 	}
1209dd9d0cfSchristos 
1219dd9d0cfSchristos 	switch (at->at_form) {
1229dd9d0cfSchristos 	case DW_FORM_ref1:
1239dd9d0cfSchristos 	case DW_FORM_ref2:
1249dd9d0cfSchristos 	case DW_FORM_ref4:
1259dd9d0cfSchristos 	case DW_FORM_ref8:
1269dd9d0cfSchristos 	case DW_FORM_ref_udata:
1279dd9d0cfSchristos 		*return_offset = (Dwarf_Off) at->u[0].u64;
1289dd9d0cfSchristos 		ret = DW_DLV_OK;
1299dd9d0cfSchristos 		break;
1309dd9d0cfSchristos 	default:
1319dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
1329dd9d0cfSchristos 		ret = DW_DLV_ERROR;
1339dd9d0cfSchristos 	}
1349dd9d0cfSchristos 
1359dd9d0cfSchristos 	return (ret);
1369dd9d0cfSchristos }
1379dd9d0cfSchristos 
1389dd9d0cfSchristos int
dwarf_global_formref(Dwarf_Attribute at,Dwarf_Off * return_offset,Dwarf_Error * error)1399dd9d0cfSchristos dwarf_global_formref(Dwarf_Attribute at, Dwarf_Off *return_offset,
1409dd9d0cfSchristos     Dwarf_Error *error)
1419dd9d0cfSchristos {
1429dd9d0cfSchristos 	int ret;
1439dd9d0cfSchristos 	Dwarf_Debug dbg;
1449dd9d0cfSchristos 
1459dd9d0cfSchristos 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
1469dd9d0cfSchristos 
1479dd9d0cfSchristos 	if (at == NULL || return_offset == NULL) {
1489dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
1499dd9d0cfSchristos 		return (DW_DLV_ERROR);
1509dd9d0cfSchristos 	}
1519dd9d0cfSchristos 
1529dd9d0cfSchristos 	switch (at->at_form) {
1539dd9d0cfSchristos 	case DW_FORM_ref_addr:
1549dd9d0cfSchristos 	case DW_FORM_sec_offset:
1559dd9d0cfSchristos 		*return_offset = (Dwarf_Off) at->u[0].u64;
1569dd9d0cfSchristos 		ret = DW_DLV_OK;
1579dd9d0cfSchristos 		break;
1589dd9d0cfSchristos 	case DW_FORM_ref1:
1599dd9d0cfSchristos 	case DW_FORM_ref2:
1609dd9d0cfSchristos 	case DW_FORM_ref4:
1619dd9d0cfSchristos 	case DW_FORM_ref8:
1629dd9d0cfSchristos 	case DW_FORM_ref_udata:
1639dd9d0cfSchristos 		*return_offset = (Dwarf_Off) at->u[0].u64 +
1649dd9d0cfSchristos 			at->at_die->die_cu->cu_offset;
1659dd9d0cfSchristos 		ret = DW_DLV_OK;
1669dd9d0cfSchristos 		break;
1679dd9d0cfSchristos 	default:
1689dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
1699dd9d0cfSchristos 		ret = DW_DLV_ERROR;
1709dd9d0cfSchristos 	}
1719dd9d0cfSchristos 
1729dd9d0cfSchristos 	return (ret);
1739dd9d0cfSchristos }
1749dd9d0cfSchristos 
1759dd9d0cfSchristos int
dwarf_formaddr(Dwarf_Attribute at,Dwarf_Addr * return_addr,Dwarf_Error * error)1769dd9d0cfSchristos dwarf_formaddr(Dwarf_Attribute at, Dwarf_Addr *return_addr, Dwarf_Error *error)
1779dd9d0cfSchristos {
1789dd9d0cfSchristos 	int ret;
1799dd9d0cfSchristos 	Dwarf_Debug dbg;
1809dd9d0cfSchristos 
1819dd9d0cfSchristos 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
1829dd9d0cfSchristos 
1839dd9d0cfSchristos 	if (at == NULL || return_addr == NULL) {
1849dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
1859dd9d0cfSchristos 		return (DW_DLV_ERROR);
1869dd9d0cfSchristos 	}
1879dd9d0cfSchristos 
1889dd9d0cfSchristos 	if (at->at_form == DW_FORM_addr) {
1899dd9d0cfSchristos 		*return_addr = at->u[0].u64;
1909dd9d0cfSchristos 		ret = DW_DLV_OK;
1919dd9d0cfSchristos 	} else {
1929dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
1939dd9d0cfSchristos 		ret = DW_DLV_ERROR;
1949dd9d0cfSchristos 	}
1959dd9d0cfSchristos 
1969dd9d0cfSchristos 	return (ret);
1979dd9d0cfSchristos }
1989dd9d0cfSchristos 
1999dd9d0cfSchristos int
dwarf_formflag(Dwarf_Attribute at,Dwarf_Bool * return_bool,Dwarf_Error * error)2009dd9d0cfSchristos dwarf_formflag(Dwarf_Attribute at, Dwarf_Bool *return_bool, Dwarf_Error *error)
2019dd9d0cfSchristos {
2029dd9d0cfSchristos 	int ret;
2039dd9d0cfSchristos 	Dwarf_Debug dbg;
2049dd9d0cfSchristos 
2059dd9d0cfSchristos 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
2069dd9d0cfSchristos 
2079dd9d0cfSchristos 	if (at == NULL || return_bool == NULL) {
2089dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
2099dd9d0cfSchristos 		return (DW_DLV_ERROR);
2109dd9d0cfSchristos 	}
2119dd9d0cfSchristos 
2129dd9d0cfSchristos 	if (at->at_form == DW_FORM_flag ||
2139dd9d0cfSchristos 	    at->at_form == DW_FORM_flag_present) {
2149dd9d0cfSchristos 		*return_bool = (Dwarf_Bool) (!!at->u[0].u64);
2159dd9d0cfSchristos 		ret = DW_DLV_OK;
2169dd9d0cfSchristos 	} else {
2179dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
2189dd9d0cfSchristos 		ret = DW_DLV_ERROR;
2199dd9d0cfSchristos 	}
2209dd9d0cfSchristos 
2219dd9d0cfSchristos 	return (ret);
2229dd9d0cfSchristos }
2239dd9d0cfSchristos 
2249dd9d0cfSchristos int
dwarf_formudata(Dwarf_Attribute at,Dwarf_Unsigned * return_uvalue,Dwarf_Error * error)2259dd9d0cfSchristos dwarf_formudata(Dwarf_Attribute at, Dwarf_Unsigned *return_uvalue,
2269dd9d0cfSchristos     Dwarf_Error *error)
2279dd9d0cfSchristos {
2289dd9d0cfSchristos 	int ret;
2299dd9d0cfSchristos 	Dwarf_Debug dbg;
2309dd9d0cfSchristos 
2319dd9d0cfSchristos 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
2329dd9d0cfSchristos 
2339dd9d0cfSchristos 	if (at == NULL || return_uvalue == NULL) {
2349dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
2359dd9d0cfSchristos 		return (DW_DLV_ERROR);
2369dd9d0cfSchristos 	}
2379dd9d0cfSchristos 
2389dd9d0cfSchristos 	switch (at->at_form) {
2399dd9d0cfSchristos 	case DW_FORM_data1:
2409dd9d0cfSchristos 	case DW_FORM_data2:
2419dd9d0cfSchristos 	case DW_FORM_data4:
2429dd9d0cfSchristos 	case DW_FORM_data8:
2439dd9d0cfSchristos 	case DW_FORM_udata:
2449dd9d0cfSchristos 		*return_uvalue = at->u[0].u64;
2459dd9d0cfSchristos 		ret = DW_DLV_OK;
2469dd9d0cfSchristos 		break;
2479dd9d0cfSchristos 	default:
2489dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
2499dd9d0cfSchristos 		ret = DW_DLV_ERROR;
2509dd9d0cfSchristos 	}
2519dd9d0cfSchristos 
2529dd9d0cfSchristos 	return (ret);
2539dd9d0cfSchristos }
2549dd9d0cfSchristos 
2559dd9d0cfSchristos int
dwarf_formsdata(Dwarf_Attribute at,Dwarf_Signed * return_svalue,Dwarf_Error * error)2569dd9d0cfSchristos dwarf_formsdata(Dwarf_Attribute at, Dwarf_Signed *return_svalue,
2579dd9d0cfSchristos     Dwarf_Error *error)
2589dd9d0cfSchristos {
2599dd9d0cfSchristos 	int ret;
2609dd9d0cfSchristos 	Dwarf_Debug dbg;
2619dd9d0cfSchristos 
2629dd9d0cfSchristos 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
2639dd9d0cfSchristos 
2649dd9d0cfSchristos 	if (at == NULL || return_svalue == NULL) {
2659dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
2669dd9d0cfSchristos 		return (DW_DLV_ERROR);
2679dd9d0cfSchristos 	}
2689dd9d0cfSchristos 
2699dd9d0cfSchristos 	switch (at->at_form) {
2709dd9d0cfSchristos 	case DW_FORM_data1:
2719dd9d0cfSchristos 		*return_svalue = (int8_t) at->u[0].s64;
2729dd9d0cfSchristos 		ret = DW_DLV_OK;
2739dd9d0cfSchristos 		break;
2749dd9d0cfSchristos 	case DW_FORM_data2:
2759dd9d0cfSchristos 		*return_svalue = (int16_t) at->u[0].s64;
2769dd9d0cfSchristos 		ret = DW_DLV_OK;
2779dd9d0cfSchristos 		break;
2789dd9d0cfSchristos 	case DW_FORM_data4:
2799dd9d0cfSchristos 		*return_svalue = (int32_t) at->u[0].s64;
2809dd9d0cfSchristos 		ret = DW_DLV_OK;
2819dd9d0cfSchristos 		break;
2829dd9d0cfSchristos 	case DW_FORM_data8:
2839dd9d0cfSchristos 	case DW_FORM_sdata:
2849dd9d0cfSchristos 		*return_svalue = at->u[0].s64;
2859dd9d0cfSchristos 		ret = DW_DLV_OK;
2869dd9d0cfSchristos 		break;
2879dd9d0cfSchristos 	default:
2889dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
2899dd9d0cfSchristos 		ret = DW_DLV_ERROR;
2909dd9d0cfSchristos 	}
2919dd9d0cfSchristos 
2929dd9d0cfSchristos 	return (ret);
2939dd9d0cfSchristos }
2949dd9d0cfSchristos 
2959dd9d0cfSchristos int
dwarf_formblock(Dwarf_Attribute at,Dwarf_Block ** return_block,Dwarf_Error * error)2969dd9d0cfSchristos dwarf_formblock(Dwarf_Attribute at, Dwarf_Block **return_block,
2979dd9d0cfSchristos     Dwarf_Error *error)
2989dd9d0cfSchristos {
2999dd9d0cfSchristos 	int ret;
3009dd9d0cfSchristos 	Dwarf_Debug dbg;
3019dd9d0cfSchristos 
3029dd9d0cfSchristos 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
3039dd9d0cfSchristos 
3049dd9d0cfSchristos 	if (at == NULL || return_block == NULL) {
3059dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
3069dd9d0cfSchristos 		return (DW_DLV_ERROR);
3079dd9d0cfSchristos 	}
3089dd9d0cfSchristos 
3099dd9d0cfSchristos 	switch (at->at_form) {
3109dd9d0cfSchristos 	case DW_FORM_block:
3119dd9d0cfSchristos 	case DW_FORM_block1:
3129dd9d0cfSchristos 	case DW_FORM_block2:
3139dd9d0cfSchristos 	case DW_FORM_block4:
3149dd9d0cfSchristos 		*return_block = &at->at_block;
3159dd9d0cfSchristos 		ret = DW_DLV_OK;
3169dd9d0cfSchristos 		break;
3179dd9d0cfSchristos 	default:
3189dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
3199dd9d0cfSchristos 		ret = DW_DLV_ERROR;
3209dd9d0cfSchristos 	}
3219dd9d0cfSchristos 
3229dd9d0cfSchristos 	return (ret);
3239dd9d0cfSchristos }
3249dd9d0cfSchristos 
3259dd9d0cfSchristos int
dwarf_formsig8(Dwarf_Attribute at,Dwarf_Sig8 * return_sig8,Dwarf_Error * error)3269dd9d0cfSchristos dwarf_formsig8(Dwarf_Attribute at, Dwarf_Sig8 *return_sig8, Dwarf_Error *error)
3279dd9d0cfSchristos {
3289dd9d0cfSchristos 	Dwarf_Debug dbg;
3299dd9d0cfSchristos 
3309dd9d0cfSchristos 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
3319dd9d0cfSchristos 
3329dd9d0cfSchristos 	if (at == NULL || return_sig8 == NULL) {
3339dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
3349dd9d0cfSchristos 		return (DW_DLV_ERROR);
3359dd9d0cfSchristos 	}
3369dd9d0cfSchristos 
3379dd9d0cfSchristos 	if (at->at_form != DW_FORM_ref_sig8) {
3389dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
3399dd9d0cfSchristos 		return (DW_DLV_ERROR);
3409dd9d0cfSchristos 	}
3419dd9d0cfSchristos 
3429dd9d0cfSchristos 	assert(at->u[0].u64 == 8);
3439dd9d0cfSchristos 	memcpy(return_sig8->signature, at->u[1].u8p, at->u[0].u64);
3449dd9d0cfSchristos 
3459dd9d0cfSchristos 	return (DW_DLV_OK);
3469dd9d0cfSchristos }
3479dd9d0cfSchristos 
3489dd9d0cfSchristos int
dwarf_formexprloc(Dwarf_Attribute at,Dwarf_Unsigned * return_exprlen,Dwarf_Ptr * return_expr,Dwarf_Error * error)3499dd9d0cfSchristos dwarf_formexprloc(Dwarf_Attribute at, Dwarf_Unsigned *return_exprlen,
3509dd9d0cfSchristos     Dwarf_Ptr *return_expr, Dwarf_Error *error)
3519dd9d0cfSchristos {
3529dd9d0cfSchristos 
3539dd9d0cfSchristos 	Dwarf_Debug dbg;
3549dd9d0cfSchristos 
3559dd9d0cfSchristos 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
3569dd9d0cfSchristos 
3579dd9d0cfSchristos 	if (at == NULL || return_exprlen == NULL || return_expr == NULL) {
3589dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
3599dd9d0cfSchristos 		return (DW_DLV_ERROR);
3609dd9d0cfSchristos 	}
3619dd9d0cfSchristos 
3629dd9d0cfSchristos 	if (at->at_form != DW_FORM_exprloc) {
3639dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
3649dd9d0cfSchristos 		return (DW_DLV_ERROR);
3659dd9d0cfSchristos 	}
3669dd9d0cfSchristos 
3679dd9d0cfSchristos 	*return_exprlen = at->u[0].u64;
3689dd9d0cfSchristos 	*return_expr = (void *) at->u[1].u8p;
3699dd9d0cfSchristos 
3709dd9d0cfSchristos 	return (DW_DLV_OK);
3719dd9d0cfSchristos }
3729dd9d0cfSchristos 
3739dd9d0cfSchristos int
dwarf_formstring(Dwarf_Attribute at,char ** return_string,Dwarf_Error * error)3749dd9d0cfSchristos dwarf_formstring(Dwarf_Attribute at, char **return_string,
3759dd9d0cfSchristos     Dwarf_Error *error)
3769dd9d0cfSchristos {
3779dd9d0cfSchristos 	int ret;
3789dd9d0cfSchristos 	Dwarf_Debug dbg;
3799dd9d0cfSchristos 
3809dd9d0cfSchristos 	dbg = at != NULL ? at->at_die->die_dbg : NULL;
3819dd9d0cfSchristos 
3829dd9d0cfSchristos 	if (at == NULL || return_string == NULL) {
3839dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
3849dd9d0cfSchristos 		return (DW_DLV_ERROR);
3859dd9d0cfSchristos 	}
3869dd9d0cfSchristos 
3879dd9d0cfSchristos 	switch (at->at_form) {
3889dd9d0cfSchristos 	case DW_FORM_string:
3899dd9d0cfSchristos 		*return_string = (char *) at->u[0].s;
3909dd9d0cfSchristos 		ret = DW_DLV_OK;
3919dd9d0cfSchristos 		break;
3929dd9d0cfSchristos 	case DW_FORM_strp:
393*5ac3bc71Schristos 	case DW_FORM_line_strp:
3949dd9d0cfSchristos 		*return_string = (char *) at->u[1].s;
3959dd9d0cfSchristos 		ret = DW_DLV_OK;
3969dd9d0cfSchristos 		break;
3979dd9d0cfSchristos 	default:
3989dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
3999dd9d0cfSchristos 		ret = DW_DLV_ERROR;
4009dd9d0cfSchristos 	}
4019dd9d0cfSchristos 
4029dd9d0cfSchristos 	return (ret);
4039dd9d0cfSchristos }
4049dd9d0cfSchristos 
4059dd9d0cfSchristos enum Dwarf_Form_Class
dwarf_get_form_class(Dwarf_Half dwversion,Dwarf_Half attr,Dwarf_Half offset_size,Dwarf_Half form)4069dd9d0cfSchristos dwarf_get_form_class(Dwarf_Half dwversion, Dwarf_Half attr,
4079dd9d0cfSchristos     Dwarf_Half offset_size, Dwarf_Half form)
4089dd9d0cfSchristos {
4099dd9d0cfSchristos 
4109dd9d0cfSchristos 	switch (form) {
4119dd9d0cfSchristos 	case DW_FORM_addr:
4129dd9d0cfSchristos 		return (DW_FORM_CLASS_ADDRESS);
4139dd9d0cfSchristos 	case DW_FORM_block:
4149dd9d0cfSchristos 	case DW_FORM_block1:
4159dd9d0cfSchristos 	case DW_FORM_block2:
4169dd9d0cfSchristos 	case DW_FORM_block4:
4179dd9d0cfSchristos 		return (DW_FORM_CLASS_BLOCK);
4189dd9d0cfSchristos 	case DW_FORM_string:
4199dd9d0cfSchristos 	case DW_FORM_strp:
4209dd9d0cfSchristos 		return (DW_FORM_CLASS_STRING);
4219dd9d0cfSchristos 	case DW_FORM_flag:
4229dd9d0cfSchristos 	case DW_FORM_flag_present:
4239dd9d0cfSchristos 		return (DW_FORM_CLASS_FLAG);
4249dd9d0cfSchristos 	case DW_FORM_ref_addr:
4259dd9d0cfSchristos 	case DW_FORM_ref_sig8:
4269dd9d0cfSchristos 	case DW_FORM_ref_udata:
4279dd9d0cfSchristos 	case DW_FORM_ref1:
4289dd9d0cfSchristos 	case DW_FORM_ref2:
4299dd9d0cfSchristos 	case DW_FORM_ref4:
4309dd9d0cfSchristos 	case DW_FORM_ref8:
4319dd9d0cfSchristos 		return (DW_FORM_CLASS_REFERENCE);
4329dd9d0cfSchristos 	case DW_FORM_exprloc:
4339dd9d0cfSchristos 		return (DW_FORM_CLASS_EXPRLOC);
4349dd9d0cfSchristos 	case DW_FORM_data1:
4359dd9d0cfSchristos 	case DW_FORM_data2:
4369dd9d0cfSchristos 	case DW_FORM_sdata:
4379dd9d0cfSchristos 	case DW_FORM_udata:
4389dd9d0cfSchristos 		return (DW_FORM_CLASS_CONSTANT);
4399dd9d0cfSchristos 	case DW_FORM_data4:
4409dd9d0cfSchristos 	case DW_FORM_data8:
4419dd9d0cfSchristos 		if (dwversion > 3)
4429dd9d0cfSchristos 			return (DW_FORM_CLASS_CONSTANT);
4439dd9d0cfSchristos 		if (form == DW_FORM_data4 && offset_size != 4)
4449dd9d0cfSchristos 			return (DW_FORM_CLASS_CONSTANT);
4459dd9d0cfSchristos 		if (form == DW_FORM_data8 && offset_size != 8)
4469dd9d0cfSchristos 			return (DW_FORM_CLASS_CONSTANT);
4479dd9d0cfSchristos 		/* FALLTHROUGH */
4489dd9d0cfSchristos 	case DW_FORM_sec_offset:
4499dd9d0cfSchristos 		/*
4509dd9d0cfSchristos 		 * DW_FORM_data4 and DW_FORM_data8 can be used as
4519dd9d0cfSchristos 		 * offset/pointer before DWARF4. Newly added
4529dd9d0cfSchristos 		 * DWARF4 form DW_FORM_sec_offset intents to replace
4539dd9d0cfSchristos 		 * DW_FORM_data{4,8} for this purpose. Anyway, to
4549dd9d0cfSchristos 		 * determine the actual class for these forms, we need
4559dd9d0cfSchristos 		 * to also look at the attribute number.
4569dd9d0cfSchristos 		 */
4579dd9d0cfSchristos 		switch (attr) {
4589dd9d0cfSchristos 		case DW_AT_location:
4599dd9d0cfSchristos 		case DW_AT_string_length:
4609dd9d0cfSchristos 		case DW_AT_return_addr:
4619dd9d0cfSchristos 		case DW_AT_data_member_location:
4629dd9d0cfSchristos 		case DW_AT_frame_base:
4639dd9d0cfSchristos 		case DW_AT_segment:
4649dd9d0cfSchristos 		case DW_AT_static_link:
4659dd9d0cfSchristos 		case DW_AT_use_location:
4669dd9d0cfSchristos 		case DW_AT_vtable_elem_location:
4679dd9d0cfSchristos 			return (DW_FORM_CLASS_LOCLISTPTR);
4689dd9d0cfSchristos 		case DW_AT_stmt_list:
4699dd9d0cfSchristos 			return (DW_FORM_CLASS_LINEPTR);
4709dd9d0cfSchristos 		case DW_AT_start_scope:
4719dd9d0cfSchristos 		case DW_AT_ranges:
4729dd9d0cfSchristos 			return (DW_FORM_CLASS_RANGELISTPTR);
4739dd9d0cfSchristos 		case DW_AT_macro_info:
4749dd9d0cfSchristos 			return (DW_FORM_CLASS_MACPTR);
4759dd9d0cfSchristos 		default:
4769dd9d0cfSchristos 			if (form == DW_FORM_data4 || form == DW_FORM_data8)
4779dd9d0cfSchristos 				return (DW_FORM_CLASS_CONSTANT);
4789dd9d0cfSchristos 			else
4799dd9d0cfSchristos 				return (DW_FORM_CLASS_UNKNOWN);
4809dd9d0cfSchristos 		}
4819dd9d0cfSchristos 	default:
4829dd9d0cfSchristos 		return (DW_FORM_CLASS_UNKNOWN);
4839dd9d0cfSchristos 	}
4849dd9d0cfSchristos }
485