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