1 /* $NetBSD: dwarf_attrval.c,v 1.12 2024/03/03 17:37:30 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2007 John Birrell (jb@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 4015 2023-10-15 02:46:33Z 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 72 dbg = die != NULL ? die->die_dbg : NULL; 73 74 if (die == NULL || strp == NULL) { 75 DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT); 76 return (DW_DLV_ERROR); 77 } 78 79 *strp = NULL; 80 81 if ((at = _dwarf_attr_find(die, attr)) == NULL) { 82 DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY); 83 return (DW_DLV_NO_ENTRY); 84 } 85 86 switch (at->at_form) { 87 case DW_FORM_strp: 88 *strp = at->u[1].s; 89 break; 90 case DW_FORM_string: 91 *strp = at->u[0].s; 92 break; 93 default: 94 DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD); 95 return (DW_DLV_ERROR); 96 } 97 98 return (DW_DLV_OK); 99 } 100 101 int 102 dwarf_attrval_signed(Dwarf_Die die, Dwarf_Half attr, Dwarf_Signed *valp, Dwarf_Error *err) 103 { 104 Dwarf_Attribute at; 105 Dwarf_Debug dbg; 106 107 dbg = die != NULL ? die->die_dbg : NULL; 108 109 if (die == NULL || valp == NULL) { 110 DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT); 111 return (DW_DLV_ERROR); 112 } 113 114 *valp = 0; 115 116 if ((at = _dwarf_attr_find(die, attr)) == NULL) { 117 DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY); 118 return (DW_DLV_NO_ENTRY); 119 } 120 121 switch (at->at_form) { 122 case DW_FORM_data1: 123 *valp = (int8_t) at->u[0].s64; 124 break; 125 case DW_FORM_data2: 126 *valp = (int16_t) at->u[0].s64; 127 break; 128 case DW_FORM_data4: 129 *valp = (int32_t) at->u[0].s64; 130 break; 131 case DW_FORM_data8: 132 case DW_FORM_sdata: 133 *valp = at->u[0].s64; 134 break; 135 default: 136 DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD); 137 return (DW_DLV_ERROR); 138 } 139 140 return (DW_DLV_OK); 141 } 142 143 int 144 dwarf_attrval_unsigned(Dwarf_Die die, Dwarf_Half attr, Dwarf_Unsigned *valp, Dwarf_Error *err) 145 { 146 Dwarf_Attribute at; 147 Dwarf_Die die1; 148 Dwarf_Unsigned val; 149 Dwarf_Debug dbg; 150 int first; 151 152 dbg = die != NULL ? die->die_dbg : NULL; 153 154 if (die == NULL || valp == NULL) { 155 DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT); 156 return (DW_DLV_ERROR); 157 } 158 159 *valp = 0; 160 161 die1 = NULL; 162 for (;;) { 163 if ((at = _dwarf_attr_find(die, attr)) != NULL || 164 attr != DW_AT_type) 165 break; 166 if ((at = _dwarf_attr_find(die, DW_AT_abstract_origin)) == 167 NULL && 168 (at = _dwarf_attr_find(die, DW_AT_specification)) == NULL) 169 break; 170 171 switch (at->at_form) { 172 case DW_FORM_ref1: 173 case DW_FORM_ref2: 174 case DW_FORM_ref4: 175 case DW_FORM_ref8: 176 case DW_FORM_ref_udata: 177 val = at->u[0].u64; 178 first = (die1 == NULL); 179 die1 = _dwarf_die_find(die, val); 180 if (!first) 181 dwarf_dealloc(dbg, die, DW_DLA_DIE); 182 if (die1 == NULL) { 183 DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY); 184 return (DW_DLV_NO_ENTRY); 185 } 186 die = die1; 187 break; 188 default: 189 DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD); 190 return (DW_DLV_ERROR); 191 } 192 } 193 194 if (at == NULL) { 195 DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY); 196 return (DW_DLV_NO_ENTRY); 197 } 198 199 switch (at->at_form) { 200 case DW_FORM_addr: 201 case DW_FORM_data1: 202 case DW_FORM_data2: 203 case DW_FORM_data4: 204 case DW_FORM_data8: 205 case DW_FORM_udata: 206 case DW_FORM_ref1: 207 case DW_FORM_ref2: 208 case DW_FORM_ref4: 209 case DW_FORM_ref8: 210 case DW_FORM_ref_udata: 211 case DW_FORM_sec_offset: 212 *valp = at->u[0].u64; 213 break; 214 default: 215 if (die1 != NULL) 216 dwarf_dealloc(dbg, die1, DW_DLA_DIE); 217 DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD); 218 return (DW_DLV_ERROR); 219 } 220 221 if (die1 != NULL) 222 dwarf_dealloc(dbg, die1, DW_DLA_DIE); 223 224 return (DW_DLV_OK); 225 } 226