1/*- 2 * Copyright (c) 2007 John Birrell (jb@freebsd.org) 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29#include <stdlib.h> 30#include <string.h> 31#include <unistd.h> 32#include "_libdwarf.h" 33 34Dwarf_AttrValue 35dwarf_attrval_find(Dwarf_Die die, Dwarf_Half attr) 36{ 37 Dwarf_AttrValue av; 38 39 STAILQ_FOREACH(av, &die->die_attrval, av_next) { 40 if (av->av_attrib == attr) 41 break; 42 } 43 44 return av; 45} 46 47int 48dwarf_attrval_add(Dwarf_Die die, Dwarf_AttrValue avref, Dwarf_AttrValue *avp, Dwarf_Error *error) 49{ 50 Dwarf_AttrValue av; 51 int ret = DWARF_E_NONE; 52 53 if ((av = malloc(sizeof(struct _Dwarf_AttrValue))) == NULL) { 54 DWARF_SET_ERROR(error, DWARF_E_MEMORY); 55 return DWARF_E_MEMORY; 56 } 57 58 memcpy(av, avref, sizeof(struct _Dwarf_AttrValue)); 59 60 /* Add the attribute value to the list in the die. */ 61 STAILQ_INSERT_TAIL(&die->die_attrval, av, av_next); 62 63 /* Save a pointer to the attribute name if this is one. */ 64 if (av->av_attrib == DW_AT_name) 65 switch (av->av_form) { 66 case DW_FORM_strp: 67 die->die_name = av->u[1].s; 68 break; 69 case DW_FORM_string: 70 die->die_name = av->u[0].s; 71 break; 72 default: 73 break; 74 } 75 76 if (avp != NULL) 77 *avp = av; 78 79 return ret; 80} 81 82int 83dwarf_attrval_flag(Dwarf_Die die, uint64_t attr, Dwarf_Bool *valp, Dwarf_Error *err) 84{ 85 Dwarf_AttrValue av; 86 int ret = DWARF_E_NONE; 87 88 if (err == NULL) 89 return DWARF_E_ERROR; 90 91 if (die == NULL || valp == NULL) { 92 DWARF_SET_ERROR(err, DWARF_E_ARGUMENT); 93 return DWARF_E_ARGUMENT; 94 } 95 96 *valp = 0; 97 98 if ((av = dwarf_attrval_find(die, attr)) == NULL) { 99 DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY); 100 ret = DWARF_E_NO_ENTRY; 101 } else { 102 switch (av->av_form) { 103 case DW_FORM_flag: 104 case DW_FORM_flag_present: 105 *valp = (Dwarf_Bool) av->u[0].u64; 106 break; 107 default: 108 printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n", 109 __func__,__LINE__,get_form_desc(av->av_form), 110 (u_long) av->av_form); 111 DWARF_SET_ERROR(err, DWARF_E_BAD_FORM); 112 ret = DWARF_E_BAD_FORM; 113 } 114 } 115 116 return ret; 117} 118 119int 120dwarf_attrval_string(Dwarf_Die die, uint64_t attr, const char **strp, Dwarf_Error *err) 121{ 122 Dwarf_AttrValue av; 123 int ret = DWARF_E_NONE; 124 125 if (err == NULL) 126 return DWARF_E_ERROR; 127 128 if (die == NULL || strp == NULL) { 129 DWARF_SET_ERROR(err, DWARF_E_ARGUMENT); 130 return DWARF_E_ARGUMENT; 131 } 132 133 *strp = NULL; 134 135 if (attr == DW_AT_name) 136 *strp = die->die_name; 137 else if ((av = dwarf_attrval_find(die, attr)) == NULL) { 138 DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY); 139 ret = DWARF_E_NO_ENTRY; 140 } else { 141 switch (av->av_form) { 142 case DW_FORM_strp: 143 *strp = av->u[1].s; 144 break; 145 case DW_FORM_string: 146 *strp = av->u[0].s; 147 break; 148 default: 149 printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n", 150 __func__,__LINE__,get_form_desc(av->av_form), 151 (u_long) av->av_form); 152 DWARF_SET_ERROR(err, DWARF_E_BAD_FORM); 153 ret = DWARF_E_BAD_FORM; 154 } 155 } 156 157 return ret; 158} 159 160int 161dwarf_attrval_signed(Dwarf_Die die, uint64_t attr, Dwarf_Signed *valp, Dwarf_Error *err) 162{ 163 Dwarf_AttrValue av; 164 int ret = DWARF_E_NONE; 165 166 if (err == NULL) 167 return DWARF_E_ERROR; 168 169 if (die == NULL || valp == NULL) { 170 DWARF_SET_ERROR(err, DWARF_E_ARGUMENT); 171 return DWARF_E_ARGUMENT; 172 } 173 174 *valp = 0; 175 176 if ((av = dwarf_attrval_find(die, attr)) == NULL) { 177 DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY); 178 ret = DWARF_E_NO_ENTRY; 179 } else { 180 switch (av->av_form) { 181 case DW_FORM_data1: 182 case DW_FORM_sdata: 183 *valp = av->u[0].s64; 184 break; 185 default: 186 printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n", 187 __func__,__LINE__,get_form_desc(av->av_form), 188 (u_long) av->av_form); 189 DWARF_SET_ERROR(err, DWARF_E_BAD_FORM); 190 ret = DWARF_E_BAD_FORM; 191 } 192 } 193 194 return ret; 195} 196 197int 198dwarf_attrval_unsigned(Dwarf_Die die, uint64_t attr, Dwarf_Unsigned *valp, Dwarf_Error *err) 199{ 200 Dwarf_AttrValue av; 201 int ret = DWARF_E_NONE; 202 203 if (err == NULL) 204 return DWARF_E_ERROR; 205 206 if (die == NULL || valp == NULL) { 207 DWARF_SET_ERROR(err, DWARF_E_ARGUMENT); 208 return DWARF_E_ARGUMENT; 209 } 210 211 *valp = 0; 212 213 if ((av = dwarf_attrval_find(die, attr)) == NULL && attr != DW_AT_type) { 214 DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY); 215 ret = DWARF_E_NO_ENTRY; 216 } else if (av == NULL && (av = dwarf_attrval_find(die, 217 DW_AT_abstract_origin)) != NULL) { 218 Dwarf_Die die1; 219 Dwarf_Unsigned val; 220 221 switch (av->av_form) { 222 case DW_FORM_data1: 223 case DW_FORM_data2: 224 case DW_FORM_data4: 225 case DW_FORM_data8: 226 case DW_FORM_ref1: 227 case DW_FORM_ref2: 228 case DW_FORM_ref4: 229 case DW_FORM_ref8: 230 case DW_FORM_ref_udata: 231 val = av->u[0].u64; 232 233 if ((die1 = dwarf_die_find(die, val)) == NULL || 234 (av = dwarf_attrval_find(die1, attr)) == NULL) { 235 DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY); 236 ret = DWARF_E_NO_ENTRY; 237 } 238 break; 239 default: 240 printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n", 241 __func__,__LINE__,get_form_desc(av->av_form), 242 (u_long) av->av_form); 243 DWARF_SET_ERROR(err, DWARF_E_BAD_FORM); 244 ret = DWARF_E_BAD_FORM; 245 } 246 } 247 248 if (ret == DWARF_E_NONE) { 249 switch (av->av_form) { 250 case DW_FORM_data1: 251 case DW_FORM_data2: 252 case DW_FORM_data4: 253 case DW_FORM_data8: 254 case DW_FORM_ref1: 255 case DW_FORM_ref2: 256 case DW_FORM_ref4: 257 case DW_FORM_ref8: 258 case DW_FORM_ref_udata: 259 *valp = av->u[0].u64; 260 break; 261 default: 262 printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n", 263 __func__,__LINE__,get_form_desc(av->av_form), 264 (u_long) av->av_form); 265 DWARF_SET_ERROR(err, DWARF_E_BAD_FORM); 266 ret = DWARF_E_BAD_FORM; 267 } 268 } 269 270 return ret; 271} 272