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