xref: /netbsd-src/external/bsd/elftoolchain/dist/libdwarf/dwarf_attrval.c (revision 5ac3bc719ce6e70593039505b491894133237d12)
1*5ac3bc71Schristos /*	$NetBSD: dwarf_attrval.c,v 1.12 2024/03/03 17:37:30 christos Exp $	*/
2e81373b4Schristos 
39dd9d0cfSchristos /*-
49dd9d0cfSchristos  * Copyright (c) 2007 John Birrell (jb@freebsd.org)
59dd9d0cfSchristos  * All rights reserved.
69dd9d0cfSchristos  *
79dd9d0cfSchristos  * Redistribution and use in source and binary forms, with or without
89dd9d0cfSchristos  * modification, are permitted provided that the following conditions
99dd9d0cfSchristos  * are met:
109dd9d0cfSchristos  * 1. Redistributions of source code must retain the above copyright
119dd9d0cfSchristos  *    notice, this list of conditions and the following disclaimer.
129dd9d0cfSchristos  * 2. Redistributions in binary form must reproduce the above copyright
139dd9d0cfSchristos  *    notice, this list of conditions and the following disclaimer in the
149dd9d0cfSchristos  *    documentation and/or other materials provided with the distribution.
159dd9d0cfSchristos  *
169dd9d0cfSchristos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
179dd9d0cfSchristos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
189dd9d0cfSchristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
199dd9d0cfSchristos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
209dd9d0cfSchristos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
219dd9d0cfSchristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
229dd9d0cfSchristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
239dd9d0cfSchristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
249dd9d0cfSchristos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
259dd9d0cfSchristos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
269dd9d0cfSchristos  * SUCH DAMAGE.
279dd9d0cfSchristos  */
289dd9d0cfSchristos 
299dd9d0cfSchristos #include "_libdwarf.h"
309dd9d0cfSchristos 
31*5ac3bc71Schristos ELFTC_VCSID("Id: dwarf_attrval.c 4015 2023-10-15 02:46:33Z kaiwang27");
329dd9d0cfSchristos 
339dd9d0cfSchristos int
dwarf_attrval_flag(Dwarf_Die die,Dwarf_Half attr,Dwarf_Bool * valp,Dwarf_Error * err)349dd9d0cfSchristos dwarf_attrval_flag(Dwarf_Die die, Dwarf_Half attr, Dwarf_Bool *valp, Dwarf_Error *err)
359dd9d0cfSchristos {
369dd9d0cfSchristos 	Dwarf_Attribute at;
379dd9d0cfSchristos 	Dwarf_Debug dbg;
389dd9d0cfSchristos 
399dd9d0cfSchristos 	dbg = die != NULL ? die->die_dbg : NULL;
409dd9d0cfSchristos 
419dd9d0cfSchristos 	if (die == NULL || valp == NULL) {
429dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
439dd9d0cfSchristos 		return (DW_DLV_ERROR);
449dd9d0cfSchristos 	}
459dd9d0cfSchristos 
469dd9d0cfSchristos 	*valp = 0;
479dd9d0cfSchristos 
489dd9d0cfSchristos 	if ((at = _dwarf_attr_find(die, attr)) == NULL) {
499dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
509dd9d0cfSchristos 		return (DW_DLV_NO_ENTRY);
519dd9d0cfSchristos 	}
529dd9d0cfSchristos 
539dd9d0cfSchristos 	switch (at->at_form) {
549dd9d0cfSchristos 	case DW_FORM_flag:
559dd9d0cfSchristos 	case DW_FORM_flag_present:
569dd9d0cfSchristos 		*valp = (Dwarf_Bool) (!!at->u[0].u64);
579dd9d0cfSchristos 		break;
589dd9d0cfSchristos 	default:
599dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
609dd9d0cfSchristos 		return (DW_DLV_ERROR);
619dd9d0cfSchristos 	}
629dd9d0cfSchristos 
639dd9d0cfSchristos 	return (DW_DLV_OK);
649dd9d0cfSchristos }
659dd9d0cfSchristos 
669dd9d0cfSchristos int
dwarf_attrval_string(Dwarf_Die die,Dwarf_Half attr,const char ** strp,Dwarf_Error * err)679dd9d0cfSchristos dwarf_attrval_string(Dwarf_Die die, Dwarf_Half attr, const char **strp, Dwarf_Error *err)
689dd9d0cfSchristos {
699dd9d0cfSchristos 	Dwarf_Attribute at;
709dd9d0cfSchristos 	Dwarf_Debug dbg;
719dd9d0cfSchristos 
729dd9d0cfSchristos 	dbg = die != NULL ? die->die_dbg : NULL;
739dd9d0cfSchristos 
749dd9d0cfSchristos 	if (die == NULL || strp == NULL) {
759dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
769dd9d0cfSchristos 		return (DW_DLV_ERROR);
779dd9d0cfSchristos 	}
789dd9d0cfSchristos 
799dd9d0cfSchristos 	*strp = NULL;
809dd9d0cfSchristos 
819dd9d0cfSchristos 	if ((at = _dwarf_attr_find(die, attr)) == NULL) {
829dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
839dd9d0cfSchristos 		return (DW_DLV_NO_ENTRY);
849dd9d0cfSchristos 	}
859dd9d0cfSchristos 
869dd9d0cfSchristos 	switch (at->at_form) {
879dd9d0cfSchristos 	case DW_FORM_strp:
889dd9d0cfSchristos 		*strp = at->u[1].s;
899dd9d0cfSchristos 		break;
909dd9d0cfSchristos 	case DW_FORM_string:
919dd9d0cfSchristos 		*strp = at->u[0].s;
929dd9d0cfSchristos 		break;
939dd9d0cfSchristos 	default:
949dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
959dd9d0cfSchristos 		return (DW_DLV_ERROR);
969dd9d0cfSchristos 	}
979dd9d0cfSchristos 
989dd9d0cfSchristos 	return (DW_DLV_OK);
999dd9d0cfSchristos }
1009dd9d0cfSchristos 
1019dd9d0cfSchristos int
dwarf_attrval_signed(Dwarf_Die die,Dwarf_Half attr,Dwarf_Signed * valp,Dwarf_Error * err)1029dd9d0cfSchristos dwarf_attrval_signed(Dwarf_Die die, Dwarf_Half attr, Dwarf_Signed *valp, Dwarf_Error *err)
1039dd9d0cfSchristos {
1049dd9d0cfSchristos 	Dwarf_Attribute at;
1059dd9d0cfSchristos 	Dwarf_Debug dbg;
1069dd9d0cfSchristos 
1079dd9d0cfSchristos 	dbg = die != NULL ? die->die_dbg : NULL;
1089dd9d0cfSchristos 
1099dd9d0cfSchristos 	if (die == NULL || valp == NULL) {
1109dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
1119dd9d0cfSchristos 		return (DW_DLV_ERROR);
1129dd9d0cfSchristos 	}
1139dd9d0cfSchristos 
1149dd9d0cfSchristos 	*valp = 0;
1159dd9d0cfSchristos 
1169dd9d0cfSchristos 	if ((at = _dwarf_attr_find(die, attr)) == NULL) {
1179dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
1189dd9d0cfSchristos 		return (DW_DLV_NO_ENTRY);
1199dd9d0cfSchristos 	}
1209dd9d0cfSchristos 
1219dd9d0cfSchristos 	switch (at->at_form) {
1229dd9d0cfSchristos 	case DW_FORM_data1:
1239dd9d0cfSchristos 		*valp = (int8_t) at->u[0].s64;
1249dd9d0cfSchristos 		break;
1259dd9d0cfSchristos 	case DW_FORM_data2:
1269dd9d0cfSchristos 		*valp = (int16_t) at->u[0].s64;
1279dd9d0cfSchristos 		break;
1289dd9d0cfSchristos 	case DW_FORM_data4:
1299dd9d0cfSchristos 		*valp = (int32_t) at->u[0].s64;
130015ca5a9Smartin 		break;
1319dd9d0cfSchristos 	case DW_FORM_data8:
1329dd9d0cfSchristos 	case DW_FORM_sdata:
1339dd9d0cfSchristos 		*valp = at->u[0].s64;
1349dd9d0cfSchristos 		break;
1359dd9d0cfSchristos 	default:
1369dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
1379dd9d0cfSchristos 		return (DW_DLV_ERROR);
1389dd9d0cfSchristos 	}
1399dd9d0cfSchristos 
1409dd9d0cfSchristos 	return (DW_DLV_OK);
1419dd9d0cfSchristos }
1429dd9d0cfSchristos 
1439dd9d0cfSchristos int
dwarf_attrval_unsigned(Dwarf_Die die,Dwarf_Half attr,Dwarf_Unsigned * valp,Dwarf_Error * err)1449dd9d0cfSchristos dwarf_attrval_unsigned(Dwarf_Die die, Dwarf_Half attr, Dwarf_Unsigned *valp, Dwarf_Error *err)
1459dd9d0cfSchristos {
1469dd9d0cfSchristos 	Dwarf_Attribute at;
1474ac26a15Schristos 	Dwarf_Die die1;
148*5ac3bc71Schristos 	Dwarf_Unsigned val;
149*5ac3bc71Schristos 	Dwarf_Debug dbg;
150*5ac3bc71Schristos 	int first;
1519dd9d0cfSchristos 
1529dd9d0cfSchristos 	dbg = die != NULL ? die->die_dbg : NULL;
1539dd9d0cfSchristos 
1549dd9d0cfSchristos 	if (die == NULL || valp == NULL) {
1559dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
1569dd9d0cfSchristos 		return (DW_DLV_ERROR);
1579dd9d0cfSchristos 	}
1589dd9d0cfSchristos 
1599dd9d0cfSchristos 	*valp = 0;
160*5ac3bc71Schristos 
161*5ac3bc71Schristos 	die1 = NULL;
162*5ac3bc71Schristos 	for (;;) {
163*5ac3bc71Schristos 		if ((at = _dwarf_attr_find(die, attr)) != NULL ||
164*5ac3bc71Schristos 		    attr != DW_AT_type)
165*5ac3bc71Schristos 			break;
166*5ac3bc71Schristos 		if ((at = _dwarf_attr_find(die, DW_AT_abstract_origin)) ==
167*5ac3bc71Schristos 		    NULL &&
168*5ac3bc71Schristos 		    (at = _dwarf_attr_find(die, DW_AT_specification)) == NULL)
169*5ac3bc71Schristos 			break;
170*5ac3bc71Schristos 
1719dd9d0cfSchristos 		switch (at->at_form) {
1729dd9d0cfSchristos 		case DW_FORM_ref1:
1739dd9d0cfSchristos 		case DW_FORM_ref2:
1749dd9d0cfSchristos 		case DW_FORM_ref4:
1759dd9d0cfSchristos 		case DW_FORM_ref8:
1769dd9d0cfSchristos 		case DW_FORM_ref_udata:
177*5ac3bc71Schristos 			val = at->u[0].u64;
178*5ac3bc71Schristos 			first = (die1 == NULL);
179*5ac3bc71Schristos 			die1 = _dwarf_die_find(die, val);
180*5ac3bc71Schristos 			if (!first)
181*5ac3bc71Schristos 				dwarf_dealloc(dbg, die, DW_DLA_DIE);
182*5ac3bc71Schristos 			if (die1 == NULL) {
183*5ac3bc71Schristos 				DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
184*5ac3bc71Schristos 				return (DW_DLV_NO_ENTRY);
1854ac26a15Schristos 			}
186*5ac3bc71Schristos 			die = die1;
187*5ac3bc71Schristos 			break;
1889dd9d0cfSchristos 		default:
1899dd9d0cfSchristos 			DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
1909dd9d0cfSchristos 			return (DW_DLV_ERROR);
1919dd9d0cfSchristos 		}
1929dd9d0cfSchristos 	}
1939dd9d0cfSchristos 
1944266f233Schristos 	if (at == NULL) {
1954266f233Schristos 		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
1964266f233Schristos 		return (DW_DLV_NO_ENTRY);
1974266f233Schristos 	}
1984266f233Schristos 
1999dd9d0cfSchristos 	switch (at->at_form) {
2009dd9d0cfSchristos 	case DW_FORM_addr:
2019dd9d0cfSchristos 	case DW_FORM_data1:
2029dd9d0cfSchristos 	case DW_FORM_data2:
2039dd9d0cfSchristos 	case DW_FORM_data4:
2049dd9d0cfSchristos 	case DW_FORM_data8:
2059dd9d0cfSchristos 	case DW_FORM_udata:
2069dd9d0cfSchristos 	case DW_FORM_ref1:
2079dd9d0cfSchristos 	case DW_FORM_ref2:
2089dd9d0cfSchristos 	case DW_FORM_ref4:
2099dd9d0cfSchristos 	case DW_FORM_ref8:
2109dd9d0cfSchristos 	case DW_FORM_ref_udata:
211*5ac3bc71Schristos 	case DW_FORM_sec_offset:
2129dd9d0cfSchristos 		*valp = at->u[0].u64;
2139dd9d0cfSchristos 		break;
2149dd9d0cfSchristos 	default:
215*5ac3bc71Schristos 		if (die1 != NULL)
216*5ac3bc71Schristos 			dwarf_dealloc(dbg, die1, DW_DLA_DIE);
2179dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
2189dd9d0cfSchristos 		return (DW_DLV_ERROR);
2199dd9d0cfSchristos 	}
2209dd9d0cfSchristos 
221*5ac3bc71Schristos 	if (die1 != NULL)
222*5ac3bc71Schristos 		dwarf_dealloc(dbg, die1, DW_DLA_DIE);
223*5ac3bc71Schristos 
2249dd9d0cfSchristos 	return (DW_DLV_OK);
2259dd9d0cfSchristos }
226