Home | History | Annotate | Line # | Download | only in libdwarf
      1 /*	$NetBSD: dwarf_attrval.c,v 1.13 2026/05/17 21:40:47 jkoshy Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2007 John Birrell (jb (at) freebsd.org)
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include "_libdwarf.h"
     30 
     31 ELFTC_VCSID("Id: dwarf_attrval.c 4039 2024-03-15 04:07:32Z kaiwang27");
     32 
     33 int
     34 dwarf_attrval_flag(Dwarf_Die die, Dwarf_Half attr, Dwarf_Bool *valp, Dwarf_Error *err)
     35 {
     36 	Dwarf_Attribute at;
     37 	Dwarf_Debug dbg;
     38 
     39 	dbg = die != NULL ? die->die_dbg : NULL;
     40 
     41 	if (die == NULL || valp == NULL) {
     42 		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
     43 		return (DW_DLV_ERROR);
     44 	}
     45 
     46 	*valp = 0;
     47 
     48 	if ((at = _dwarf_attr_find(die, attr)) == NULL) {
     49 		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
     50 		return (DW_DLV_NO_ENTRY);
     51 	}
     52 
     53 	switch (at->at_form) {
     54 	case DW_FORM_flag:
     55 	case DW_FORM_flag_present:
     56 		*valp = (Dwarf_Bool) (!!at->u[0].u64);
     57 		break;
     58 	default:
     59 		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
     60 		return (DW_DLV_ERROR);
     61 	}
     62 
     63 	return (DW_DLV_OK);
     64 }
     65 
     66 int
     67 dwarf_attrval_string(Dwarf_Die die, Dwarf_Half attr, const char **strp, Dwarf_Error *err)
     68 {
     69 	Dwarf_Attribute at;
     70 	Dwarf_Debug dbg;
     71 	Dwarf_CU cu;
     72 	char *str;
     73 
     74 	dbg = die != NULL ? die->die_dbg : NULL;
     75 
     76 	if (die == NULL || strp == NULL) {
     77 		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
     78 		return (DW_DLV_ERROR);
     79 	}
     80 
     81 	cu = die->die_cu;
     82 	assert(cu != NULL);
     83 
     84 	*strp = NULL;
     85 
     86 	if ((at = _dwarf_attr_find(die, attr)) == NULL) {
     87 		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
     88 		return (DW_DLV_NO_ENTRY);
     89 	}
     90 
     91 	switch (at->at_form) {
     92 	case DW_FORM_strp:
     93 		*strp = at->u[1].s;
     94 		break;
     95 	case DW_FORM_string:
     96 		*strp = at->u[0].s;
     97 		break;
     98 	case DW_FORM_strx:
     99 	case DW_FORM_strx1:
    100 	case DW_FORM_strx2:
    101 	case DW_FORM_strx3:
    102 	case DW_FORM_strx4:
    103 		if (_dwarf_read_indexed_str(dbg, cu, at->u[0].u64, &str, err) !=
    104 		    DW_DLE_NONE)
    105 			return (DW_DLV_ERROR);
    106 		*strp = str;
    107 		break;
    108 	default:
    109 		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
    110 		return (DW_DLV_ERROR);
    111 	}
    112 
    113 	return (DW_DLV_OK);
    114 }
    115 
    116 int
    117 dwarf_attrval_signed(Dwarf_Die die, Dwarf_Half attr, Dwarf_Signed *valp, Dwarf_Error *err)
    118 {
    119 	Dwarf_Attribute at;
    120 	Dwarf_Debug dbg;
    121 
    122 	dbg = die != NULL ? die->die_dbg : NULL;
    123 
    124 	if (die == NULL || valp == NULL) {
    125 		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
    126 		return (DW_DLV_ERROR);
    127 	}
    128 
    129 	*valp = 0;
    130 
    131 	if ((at = _dwarf_attr_find(die, attr)) == NULL) {
    132 		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
    133 		return (DW_DLV_NO_ENTRY);
    134 	}
    135 
    136 	switch (at->at_form) {
    137 	case DW_FORM_data1:
    138 		*valp = (int8_t) at->u[0].s64;
    139 		break;
    140 	case DW_FORM_data2:
    141 		*valp = (int16_t) at->u[0].s64;
    142 		break;
    143 	case DW_FORM_data4:
    144 		*valp = (int32_t) at->u[0].s64;
    145 		break;
    146 	case DW_FORM_data8:
    147 	case DW_FORM_sdata:
    148 		*valp = at->u[0].s64;
    149 		break;
    150 	default:
    151 		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
    152 		return (DW_DLV_ERROR);
    153 	}
    154 
    155 	return (DW_DLV_OK);
    156 }
    157 
    158 int
    159 dwarf_attrval_unsigned(Dwarf_Die die, Dwarf_Half attr, Dwarf_Unsigned *valp, Dwarf_Error *err)
    160 {
    161 	Dwarf_Attribute at;
    162 	Dwarf_Die die1;
    163 	Dwarf_Unsigned val;
    164 	Dwarf_Debug dbg;
    165 	int first;
    166 
    167 	dbg = die != NULL ? die->die_dbg : NULL;
    168 
    169 	if (die == NULL || valp == NULL) {
    170 		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
    171 		return (DW_DLV_ERROR);
    172 	}
    173 
    174 	*valp = 0;
    175 
    176 	die1 = NULL;
    177 	for (;;) {
    178 		if ((at = _dwarf_attr_find(die, attr)) != NULL ||
    179 		    attr != DW_AT_type)
    180 			break;
    181 		if ((at = _dwarf_attr_find(die, DW_AT_abstract_origin)) ==
    182 		    NULL &&
    183 		    (at = _dwarf_attr_find(die, DW_AT_specification)) == NULL)
    184 			break;
    185 
    186 		switch (at->at_form) {
    187 		case DW_FORM_ref1:
    188 		case DW_FORM_ref2:
    189 		case DW_FORM_ref4:
    190 		case DW_FORM_ref8:
    191 		case DW_FORM_ref_udata:
    192 			val = at->u[0].u64;
    193 			first = (die1 == NULL);
    194 			die1 = _dwarf_die_find(die, val);
    195 			if (!first)
    196 				dwarf_dealloc(dbg, die, DW_DLA_DIE);
    197 			if (die1 == NULL) {
    198 				DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
    199 				return (DW_DLV_NO_ENTRY);
    200 			}
    201 			die = die1;
    202 			break;
    203 		default:
    204 			DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
    205 			return (DW_DLV_ERROR);
    206 		}
    207 	}
    208 
    209 	if (at == NULL) {
    210 		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
    211 		return (DW_DLV_NO_ENTRY);
    212 	}
    213 
    214 	switch (at->at_form) {
    215 	case DW_FORM_addr:
    216 	case DW_FORM_data1:
    217 	case DW_FORM_data2:
    218 	case DW_FORM_data4:
    219 	case DW_FORM_data8:
    220 	case DW_FORM_udata:
    221 	case DW_FORM_ref1:
    222 	case DW_FORM_ref2:
    223 	case DW_FORM_ref4:
    224 	case DW_FORM_ref8:
    225 	case DW_FORM_ref_udata:
    226 	case DW_FORM_sec_offset:
    227 		*valp = at->u[0].u64;
    228 		break;
    229 	default:
    230 		if (die1 != NULL)
    231 			dwarf_dealloc(dbg, die1, DW_DLA_DIE);
    232 		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
    233 		return (DW_DLV_ERROR);
    234 	}
    235 
    236 	if (die1 != NULL)
    237 		dwarf_dealloc(dbg, die1, DW_DLA_DIE);
    238 
    239 	return (DW_DLV_OK);
    240 }
    241