1179187Sjb/*- 2179187Sjb * Copyright (c) 2007 John Birrell (jb@freebsd.org) 3179187Sjb * All rights reserved. 4179187Sjb * 5179187Sjb * Redistribution and use in source and binary forms, with or without 6179187Sjb * modification, are permitted provided that the following conditions 7179187Sjb * are met: 8179187Sjb * 1. Redistributions of source code must retain the above copyright 9179187Sjb * notice, this list of conditions and the following disclaimer. 10179187Sjb * 2. Redistributions in binary form must reproduce the above copyright 11179187Sjb * notice, this list of conditions and the following disclaimer in the 12179187Sjb * documentation and/or other materials provided with the distribution. 13179187Sjb * 14179187Sjb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15179187Sjb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16179187Sjb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17179187Sjb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18179187Sjb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19179187Sjb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20179187Sjb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21179187Sjb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22179187Sjb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23179187Sjb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24179187Sjb * SUCH DAMAGE. 25179187Sjb * 26179187Sjb * $FreeBSD$ 27179187Sjb */ 28179187Sjb 29179187Sjb#include <stdlib.h> 30179187Sjb#include <string.h> 31179187Sjb#include <unistd.h> 32179187Sjb#include "_libdwarf.h" 33179187Sjb 34179187SjbDwarf_AttrValue 35179187Sjbdwarf_attrval_find(Dwarf_Die die, Dwarf_Half attr) 36179187Sjb{ 37179187Sjb Dwarf_AttrValue av; 38179187Sjb 39179187Sjb STAILQ_FOREACH(av, &die->die_attrval, av_next) { 40179187Sjb if (av->av_attrib == attr) 41179187Sjb break; 42179187Sjb } 43179187Sjb 44179187Sjb return av; 45179187Sjb} 46179187Sjb 47179187Sjbint 48179187Sjbdwarf_attrval_add(Dwarf_Die die, Dwarf_AttrValue avref, Dwarf_AttrValue *avp, Dwarf_Error *error) 49179187Sjb{ 50179187Sjb Dwarf_AttrValue av; 51179187Sjb int ret = DWARF_E_NONE; 52179187Sjb 53179187Sjb if ((av = malloc(sizeof(struct _Dwarf_AttrValue))) == NULL) { 54179187Sjb DWARF_SET_ERROR(error, DWARF_E_MEMORY); 55179187Sjb return DWARF_E_MEMORY; 56179187Sjb } 57179187Sjb 58179187Sjb memcpy(av, avref, sizeof(struct _Dwarf_AttrValue)); 59179187Sjb 60179187Sjb /* Add the attribute value to the list in the die. */ 61179187Sjb STAILQ_INSERT_TAIL(&die->die_attrval, av, av_next); 62179187Sjb 63179187Sjb /* Save a pointer to the attribute name if this is one. */ 64179187Sjb if (av->av_attrib == DW_AT_name) 65179187Sjb switch (av->av_form) { 66179187Sjb case DW_FORM_strp: 67179187Sjb die->die_name = av->u[1].s; 68179187Sjb break; 69179187Sjb case DW_FORM_string: 70179187Sjb die->die_name = av->u[0].s; 71179187Sjb break; 72179187Sjb default: 73179187Sjb break; 74179187Sjb } 75179187Sjb 76179187Sjb if (avp != NULL) 77179187Sjb *avp = av; 78179187Sjb 79179187Sjb return ret; 80179187Sjb} 81179187Sjb 82179187Sjbint 83179187Sjbdwarf_attrval_flag(Dwarf_Die die, uint64_t attr, Dwarf_Bool *valp, Dwarf_Error *err) 84179187Sjb{ 85179187Sjb Dwarf_AttrValue av; 86179187Sjb int ret = DWARF_E_NONE; 87179187Sjb 88179187Sjb if (err == NULL) 89179187Sjb return DWARF_E_ERROR; 90179187Sjb 91179187Sjb if (die == NULL || valp == NULL) { 92179187Sjb DWARF_SET_ERROR(err, DWARF_E_ARGUMENT); 93179187Sjb return DWARF_E_ARGUMENT; 94179187Sjb } 95179187Sjb 96179187Sjb *valp = 0; 97179187Sjb 98179187Sjb if ((av = dwarf_attrval_find(die, attr)) == NULL) { 99179187Sjb DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY); 100179187Sjb ret = DWARF_E_NO_ENTRY; 101179187Sjb } else { 102179187Sjb switch (av->av_form) { 103179187Sjb case DW_FORM_flag: 104239872Sdim case DW_FORM_flag_present: 105179187Sjb *valp = (Dwarf_Bool) av->u[0].u64; 106179187Sjb break; 107179187Sjb default: 108179187Sjb printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n", 109179187Sjb __func__,__LINE__,get_form_desc(av->av_form), 110179187Sjb (u_long) av->av_form); 111179187Sjb DWARF_SET_ERROR(err, DWARF_E_BAD_FORM); 112179187Sjb ret = DWARF_E_BAD_FORM; 113179187Sjb } 114179187Sjb } 115179187Sjb 116179187Sjb return ret; 117179187Sjb} 118179187Sjb 119179187Sjbint 120179187Sjbdwarf_attrval_string(Dwarf_Die die, uint64_t attr, const char **strp, Dwarf_Error *err) 121179187Sjb{ 122179187Sjb Dwarf_AttrValue av; 123179187Sjb int ret = DWARF_E_NONE; 124179187Sjb 125179187Sjb if (err == NULL) 126179187Sjb return DWARF_E_ERROR; 127179187Sjb 128179187Sjb if (die == NULL || strp == NULL) { 129179187Sjb DWARF_SET_ERROR(err, DWARF_E_ARGUMENT); 130179187Sjb return DWARF_E_ARGUMENT; 131179187Sjb } 132179187Sjb 133179187Sjb *strp = NULL; 134179187Sjb 135179187Sjb if (attr == DW_AT_name) 136179187Sjb *strp = die->die_name; 137179187Sjb else if ((av = dwarf_attrval_find(die, attr)) == NULL) { 138179187Sjb DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY); 139179187Sjb ret = DWARF_E_NO_ENTRY; 140179187Sjb } else { 141179187Sjb switch (av->av_form) { 142179187Sjb case DW_FORM_strp: 143179187Sjb *strp = av->u[1].s; 144179187Sjb break; 145179187Sjb case DW_FORM_string: 146179187Sjb *strp = av->u[0].s; 147179187Sjb break; 148179187Sjb default: 149179187Sjb printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n", 150179187Sjb __func__,__LINE__,get_form_desc(av->av_form), 151179187Sjb (u_long) av->av_form); 152179187Sjb DWARF_SET_ERROR(err, DWARF_E_BAD_FORM); 153179187Sjb ret = DWARF_E_BAD_FORM; 154179187Sjb } 155179187Sjb } 156179187Sjb 157179187Sjb return ret; 158179187Sjb} 159179187Sjb 160179187Sjbint 161179187Sjbdwarf_attrval_signed(Dwarf_Die die, uint64_t attr, Dwarf_Signed *valp, Dwarf_Error *err) 162179187Sjb{ 163179187Sjb Dwarf_AttrValue av; 164179187Sjb int ret = DWARF_E_NONE; 165179187Sjb 166179187Sjb if (err == NULL) 167179187Sjb return DWARF_E_ERROR; 168179187Sjb 169179187Sjb if (die == NULL || valp == NULL) { 170179187Sjb DWARF_SET_ERROR(err, DWARF_E_ARGUMENT); 171179187Sjb return DWARF_E_ARGUMENT; 172179187Sjb } 173179187Sjb 174179187Sjb *valp = 0; 175179187Sjb 176179187Sjb if ((av = dwarf_attrval_find(die, attr)) == NULL) { 177179187Sjb DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY); 178179187Sjb ret = DWARF_E_NO_ENTRY; 179179187Sjb } else { 180179187Sjb switch (av->av_form) { 181179187Sjb case DW_FORM_data1: 182179187Sjb case DW_FORM_sdata: 183179187Sjb *valp = av->u[0].s64; 184179187Sjb break; 185179187Sjb default: 186179187Sjb printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n", 187179187Sjb __func__,__LINE__,get_form_desc(av->av_form), 188179187Sjb (u_long) av->av_form); 189179187Sjb DWARF_SET_ERROR(err, DWARF_E_BAD_FORM); 190179187Sjb ret = DWARF_E_BAD_FORM; 191179187Sjb } 192179187Sjb } 193179187Sjb 194179187Sjb return ret; 195179187Sjb} 196179187Sjb 197179187Sjbint 198179187Sjbdwarf_attrval_unsigned(Dwarf_Die die, uint64_t attr, Dwarf_Unsigned *valp, Dwarf_Error *err) 199179187Sjb{ 200179187Sjb Dwarf_AttrValue av; 201179187Sjb int ret = DWARF_E_NONE; 202179187Sjb 203179187Sjb if (err == NULL) 204179187Sjb return DWARF_E_ERROR; 205179187Sjb 206179187Sjb if (die == NULL || valp == NULL) { 207179187Sjb DWARF_SET_ERROR(err, DWARF_E_ARGUMENT); 208179187Sjb return DWARF_E_ARGUMENT; 209179187Sjb } 210179187Sjb 211179187Sjb *valp = 0; 212179187Sjb 213179187Sjb if ((av = dwarf_attrval_find(die, attr)) == NULL && attr != DW_AT_type) { 214179187Sjb DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY); 215179187Sjb ret = DWARF_E_NO_ENTRY; 216179187Sjb } else if (av == NULL && (av = dwarf_attrval_find(die, 217179187Sjb DW_AT_abstract_origin)) != NULL) { 218179187Sjb Dwarf_Die die1; 219179187Sjb Dwarf_Unsigned val; 220179187Sjb 221179187Sjb switch (av->av_form) { 222179187Sjb case DW_FORM_data1: 223179187Sjb case DW_FORM_data2: 224179187Sjb case DW_FORM_data4: 225179187Sjb case DW_FORM_data8: 226179187Sjb case DW_FORM_ref1: 227179187Sjb case DW_FORM_ref2: 228179187Sjb case DW_FORM_ref4: 229179187Sjb case DW_FORM_ref8: 230179187Sjb case DW_FORM_ref_udata: 231179187Sjb val = av->u[0].u64; 232179187Sjb 233179187Sjb if ((die1 = dwarf_die_find(die, val)) == NULL || 234179187Sjb (av = dwarf_attrval_find(die1, attr)) == NULL) { 235179187Sjb DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY); 236179187Sjb ret = DWARF_E_NO_ENTRY; 237179187Sjb } 238179187Sjb break; 239179187Sjb default: 240179187Sjb printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n", 241179187Sjb __func__,__LINE__,get_form_desc(av->av_form), 242179187Sjb (u_long) av->av_form); 243179187Sjb DWARF_SET_ERROR(err, DWARF_E_BAD_FORM); 244179187Sjb ret = DWARF_E_BAD_FORM; 245179187Sjb } 246179187Sjb } 247179187Sjb 248179187Sjb if (ret == DWARF_E_NONE) { 249179187Sjb switch (av->av_form) { 250179187Sjb case DW_FORM_data1: 251179187Sjb case DW_FORM_data2: 252179187Sjb case DW_FORM_data4: 253179187Sjb case DW_FORM_data8: 254179187Sjb case DW_FORM_ref1: 255179187Sjb case DW_FORM_ref2: 256179187Sjb case DW_FORM_ref4: 257179187Sjb case DW_FORM_ref8: 258179187Sjb case DW_FORM_ref_udata: 259179187Sjb *valp = av->u[0].u64; 260179187Sjb break; 261179187Sjb default: 262179187Sjb printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n", 263179187Sjb __func__,__LINE__,get_form_desc(av->av_form), 264179187Sjb (u_long) av->av_form); 265179187Sjb DWARF_SET_ERROR(err, DWARF_E_BAD_FORM); 266179187Sjb ret = DWARF_E_BAD_FORM; 267179187Sjb } 268179187Sjb } 269179187Sjb 270179187Sjb return ret; 271179187Sjb} 272