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