1 /* $NetBSD: dwarf_attr.c,v 1.3 2016/02/20 02:43:41 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2007 John Birrell (jb@freebsd.org) 5 * Copyright (c) 2009 Kai Wang 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include "_libdwarf.h" 31 32 __RCSID("$NetBSD: dwarf_attr.c,v 1.3 2016/02/20 02:43:41 christos Exp $"); 33 ELFTC_VCSID("Id: dwarf_attr.c 3064 2014-06-06 19:35:55Z kaiwang27 "); 34 35 int 36 dwarf_attr(Dwarf_Die die, Dwarf_Half attr, Dwarf_Attribute *atp, 37 Dwarf_Error *error) 38 { 39 Dwarf_Debug dbg; 40 Dwarf_Attribute at; 41 42 dbg = die != NULL ? die->die_dbg : NULL; 43 44 if (die == NULL || atp == NULL) { 45 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 46 return (DW_DLV_ERROR); 47 } 48 49 if ((at = _dwarf_attr_find(die, attr)) == NULL) { 50 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); 51 return (DW_DLV_NO_ENTRY); 52 } 53 54 *atp = at; 55 56 return (DW_DLV_OK); 57 } 58 59 int 60 dwarf_attrlist(Dwarf_Die die, Dwarf_Attribute **attrbuf, 61 Dwarf_Signed *attrcount, Dwarf_Error *error) 62 { 63 Dwarf_Attribute at; 64 Dwarf_Debug dbg; 65 int i; 66 67 dbg = die != NULL ? die->die_dbg : NULL; 68 69 if (die == NULL || attrbuf == NULL || attrcount == NULL) { 70 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 71 return (DW_DLV_ERROR); 72 } 73 74 if (die->die_ab->ab_atnum == 0) { 75 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); 76 return (DW_DLV_NO_ENTRY); 77 } 78 79 *attrcount = die->die_ab->ab_atnum; 80 81 if (die->die_attrarray != NULL) { 82 *attrbuf = die->die_attrarray; 83 return (DW_DLV_OK); 84 } 85 86 if ((die->die_attrarray = malloc(*attrcount * sizeof(Dwarf_Attribute))) 87 == NULL) { 88 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 89 return (DW_DLV_ERROR); 90 } 91 92 for (i = 0, at = STAILQ_FIRST(&die->die_attr); 93 i < *attrcount && at != NULL; i++, at = STAILQ_NEXT(at, at_next)) 94 die->die_attrarray[i] = at; 95 96 *attrbuf = die->die_attrarray; 97 98 return (DW_DLV_OK); 99 } 100 101 int 102 dwarf_hasattr(Dwarf_Die die, Dwarf_Half attr, Dwarf_Bool *ret_bool, 103 Dwarf_Error *error) 104 { 105 Dwarf_Debug dbg; 106 107 dbg = die != NULL ? die->die_dbg : NULL; 108 109 if (die == NULL || ret_bool == NULL) { 110 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 111 return (DW_DLV_ERROR); 112 } 113 114 *ret_bool = (_dwarf_attr_find(die, attr) != NULL); 115 116 return (DW_DLV_OK); 117 } 118 119 int 120 dwarf_attroffset(Dwarf_Attribute at, Dwarf_Off *ret_off, Dwarf_Error *error) 121 { 122 Dwarf_Debug dbg; 123 124 dbg = at != NULL ? at->at_die->die_dbg : NULL; 125 126 if (at == NULL || ret_off == NULL) { 127 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 128 return (DW_DLV_ERROR); 129 } 130 131 *ret_off = at->at_offset; 132 133 return (DW_DLV_OK); 134 } 135 136 int 137 dwarf_lowpc(Dwarf_Die die, Dwarf_Addr *ret_lowpc, Dwarf_Error *error) 138 { 139 Dwarf_Attribute at; 140 Dwarf_Debug dbg; 141 142 dbg = die != NULL ? die->die_dbg : NULL; 143 144 if (die == NULL || ret_lowpc == NULL) { 145 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 146 return (DW_DLV_ERROR); 147 } 148 149 if ((at = _dwarf_attr_find(die, DW_AT_low_pc)) == NULL) { 150 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); 151 return (DW_DLV_NO_ENTRY); 152 } 153 154 *ret_lowpc = at->u[0].u64; 155 156 return (DW_DLV_OK); 157 } 158 159 int 160 dwarf_highpc(Dwarf_Die die, Dwarf_Addr *ret_highpc, Dwarf_Error *error) 161 { 162 163 return (dwarf_highpc_b(die, ret_highpc, NULL, NULL, error)); 164 } 165 166 int 167 dwarf_highpc_b(Dwarf_Die die, Dwarf_Addr *ret_highpc, Dwarf_Half *ret_form, 168 enum Dwarf_Form_Class *ret_class, Dwarf_Error *error) 169 { 170 Dwarf_Attribute at; 171 Dwarf_Debug dbg; 172 Dwarf_CU cu; 173 174 dbg = die != NULL ? die->die_dbg : NULL; 175 176 if (die == NULL || ret_highpc == NULL) { 177 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 178 return (DW_DLV_ERROR); 179 } 180 181 if ((at = _dwarf_attr_find(die, DW_AT_high_pc)) == NULL) { 182 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); 183 return (DW_DLV_NO_ENTRY); 184 } 185 186 *ret_highpc = at->u[0].u64; 187 188 if (ret_form != NULL) { 189 *ret_form = at->at_form; 190 } 191 192 if (ret_class != NULL) { 193 cu = die->die_cu; 194 *ret_class = dwarf_get_form_class(cu->cu_version, 195 DW_AT_high_pc, cu->cu_length_size == 4 ? 4 : 8, 196 at->at_form); 197 } 198 199 return (DW_DLV_OK); 200 } 201 202 int 203 dwarf_bytesize(Dwarf_Die die, Dwarf_Unsigned *ret_size, Dwarf_Error *error) 204 { 205 Dwarf_Attribute at; 206 Dwarf_Debug dbg; 207 208 dbg = die != NULL ? die->die_dbg : NULL; 209 210 if (die == NULL || ret_size == NULL) { 211 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 212 return (DW_DLV_ERROR); 213 } 214 215 if ((at = _dwarf_attr_find(die, DW_AT_byte_size)) == NULL) { 216 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); 217 return (DW_DLV_NO_ENTRY); 218 } 219 220 *ret_size = at->u[0].u64; 221 222 return (DW_DLV_OK); 223 } 224 225 int 226 dwarf_bitsize(Dwarf_Die die, Dwarf_Unsigned *ret_size, Dwarf_Error *error) 227 { 228 Dwarf_Attribute at; 229 Dwarf_Debug dbg; 230 231 dbg = die != NULL ? die->die_dbg : NULL; 232 233 if (die == NULL || ret_size == NULL) { 234 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 235 return (DW_DLV_ERROR); 236 } 237 238 if ((at = _dwarf_attr_find(die, DW_AT_bit_size)) == NULL) { 239 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); 240 return (DW_DLV_NO_ENTRY); 241 } 242 243 *ret_size = at->u[0].u64; 244 245 return (DW_DLV_OK); 246 } 247 248 int 249 dwarf_bitoffset(Dwarf_Die die, Dwarf_Unsigned *ret_size, Dwarf_Error *error) 250 { 251 Dwarf_Attribute at; 252 Dwarf_Debug dbg; 253 254 dbg = die != NULL ? die->die_dbg : NULL; 255 256 if (die == NULL || ret_size == NULL) { 257 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 258 return (DW_DLV_ERROR); 259 } 260 261 if ((at = _dwarf_attr_find(die, DW_AT_bit_offset)) == NULL) { 262 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); 263 return (DW_DLV_NO_ENTRY); 264 } 265 266 *ret_size = at->u[0].u64; 267 268 return (DW_DLV_OK); 269 } 270 271 int 272 dwarf_srclang(Dwarf_Die die, Dwarf_Unsigned *ret_lang, Dwarf_Error *error) 273 { 274 Dwarf_Attribute at; 275 Dwarf_Debug dbg; 276 277 dbg = die != NULL ? die->die_dbg : NULL; 278 279 if (die == NULL || ret_lang == NULL) { 280 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 281 return (DW_DLV_ERROR); 282 } 283 284 if ((at = _dwarf_attr_find(die, DW_AT_language)) == NULL) { 285 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); 286 return (DW_DLV_NO_ENTRY); 287 } 288 289 *ret_lang = at->u[0].u64; 290 291 return (DW_DLV_OK); 292 } 293 294 int 295 dwarf_arrayorder(Dwarf_Die die, Dwarf_Unsigned *ret_order, Dwarf_Error *error) 296 { 297 Dwarf_Attribute at; 298 Dwarf_Debug dbg; 299 300 dbg = die != NULL ? die->die_dbg : NULL; 301 302 if (die == NULL || ret_order == NULL) { 303 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 304 return (DW_DLV_ERROR); 305 } 306 307 if ((at = _dwarf_attr_find(die, DW_AT_ordering)) == NULL) { 308 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); 309 return (DW_DLV_NO_ENTRY); 310 } 311 312 *ret_order = at->u[0].u64; 313 314 return (DW_DLV_OK); 315 } 316