1 /* $NetBSD: dwarf_form.c,v 1.2 2014/03/09 16:58:03 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2007 John Birrell (jb@freebsd.org) 5 * Copyright (c) 2009,2010 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_form.c,v 1.2 2014/03/09 16:58:03 christos Exp $"); 33 ELFTC_VCSID("Id: dwarf_form.c 2073 2011-10-27 03:30:47Z jkoshy "); 34 35 int 36 dwarf_hasform(Dwarf_Attribute at, Dwarf_Half form, Dwarf_Bool *return_hasform, 37 Dwarf_Error *error) 38 { 39 Dwarf_Debug dbg; 40 41 dbg = at != NULL ? at->at_die->die_dbg : NULL; 42 43 if (at == NULL || return_hasform == NULL) { 44 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 45 return (DW_DLV_ERROR); 46 } 47 48 *return_hasform = (at->at_form == form); 49 50 return (DW_DLV_OK); 51 } 52 53 int 54 dwarf_whatform(Dwarf_Attribute at, Dwarf_Half *return_form, Dwarf_Error *error) 55 { 56 Dwarf_Debug dbg; 57 58 dbg = at != NULL ? at->at_die->die_dbg : NULL; 59 60 if (at == NULL || return_form == NULL) { 61 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 62 return (DW_DLV_ERROR); 63 } 64 65 *return_form = at->at_form; 66 67 return (DW_DLV_OK); 68 } 69 70 int 71 dwarf_whatform_direct(Dwarf_Attribute at, Dwarf_Half *return_form, 72 Dwarf_Error *error) 73 { 74 Dwarf_Debug dbg; 75 76 dbg = at != NULL ? at->at_die->die_dbg : NULL; 77 78 if (at == NULL || return_form == NULL) { 79 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 80 return (DW_DLV_ERROR); 81 } 82 83 if (at->at_indirect) 84 *return_form = DW_FORM_indirect; 85 else 86 *return_form = (Dwarf_Half) at->at_form; 87 88 return (DW_DLV_OK); 89 } 90 91 int 92 dwarf_whatattr(Dwarf_Attribute at, Dwarf_Half *return_attr, Dwarf_Error *error) 93 { 94 Dwarf_Debug dbg; 95 96 dbg = at != NULL ? at->at_die->die_dbg : NULL; 97 98 if (at == NULL || return_attr == NULL) { 99 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 100 return (DW_DLV_ERROR); 101 } 102 103 *return_attr = (Dwarf_Half) at->at_attrib; 104 105 return (DW_DLV_OK); 106 } 107 108 int 109 dwarf_formref(Dwarf_Attribute at, Dwarf_Off *return_offset, Dwarf_Error *error) 110 { 111 int ret; 112 Dwarf_Debug dbg; 113 114 dbg = at != NULL ? at->at_die->die_dbg : NULL; 115 116 if (at == NULL || return_offset == NULL) { 117 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 118 return (DW_DLV_ERROR); 119 } 120 121 switch (at->at_form) { 122 case DW_FORM_ref1: 123 case DW_FORM_ref2: 124 case DW_FORM_ref4: 125 case DW_FORM_ref8: 126 case DW_FORM_ref_udata: 127 *return_offset = (Dwarf_Off) at->u[0].u64; 128 ret = DW_DLV_OK; 129 break; 130 default: 131 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD); 132 ret = DW_DLV_ERROR; 133 } 134 135 return (ret); 136 } 137 138 int 139 dwarf_global_formref(Dwarf_Attribute at, Dwarf_Off *return_offset, 140 Dwarf_Error *error) 141 { 142 int ret; 143 Dwarf_Debug dbg; 144 145 dbg = at != NULL ? at->at_die->die_dbg : NULL; 146 147 if (at == NULL || return_offset == NULL) { 148 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 149 return (DW_DLV_ERROR); 150 } 151 152 switch (at->at_form) { 153 case DW_FORM_ref_addr: 154 case DW_FORM_sec_offset: 155 *return_offset = (Dwarf_Off) at->u[0].u64; 156 ret = DW_DLV_OK; 157 break; 158 case DW_FORM_ref1: 159 case DW_FORM_ref2: 160 case DW_FORM_ref4: 161 case DW_FORM_ref8: 162 case DW_FORM_ref_udata: 163 *return_offset = (Dwarf_Off) at->u[0].u64 + 164 at->at_die->die_cu->cu_offset; 165 ret = DW_DLV_OK; 166 break; 167 default: 168 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD); 169 ret = DW_DLV_ERROR; 170 } 171 172 return (ret); 173 } 174 175 int 176 dwarf_formaddr(Dwarf_Attribute at, Dwarf_Addr *return_addr, Dwarf_Error *error) 177 { 178 int ret; 179 Dwarf_Debug dbg; 180 181 dbg = at != NULL ? at->at_die->die_dbg : NULL; 182 183 if (at == NULL || return_addr == NULL) { 184 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 185 return (DW_DLV_ERROR); 186 } 187 188 if (at->at_form == DW_FORM_addr) { 189 *return_addr = at->u[0].u64; 190 ret = DW_DLV_OK; 191 } else { 192 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD); 193 ret = DW_DLV_ERROR; 194 } 195 196 return (ret); 197 } 198 199 int 200 dwarf_formflag(Dwarf_Attribute at, Dwarf_Bool *return_bool, Dwarf_Error *error) 201 { 202 int ret; 203 Dwarf_Debug dbg; 204 205 dbg = at != NULL ? at->at_die->die_dbg : NULL; 206 207 if (at == NULL || return_bool == NULL) { 208 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 209 return (DW_DLV_ERROR); 210 } 211 212 if (at->at_form == DW_FORM_flag || 213 at->at_form == DW_FORM_flag_present) { 214 *return_bool = (Dwarf_Bool) (!!at->u[0].u64); 215 ret = DW_DLV_OK; 216 } else { 217 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD); 218 ret = DW_DLV_ERROR; 219 } 220 221 return (ret); 222 } 223 224 int 225 dwarf_formudata(Dwarf_Attribute at, Dwarf_Unsigned *return_uvalue, 226 Dwarf_Error *error) 227 { 228 int ret; 229 Dwarf_Debug dbg; 230 231 dbg = at != NULL ? at->at_die->die_dbg : NULL; 232 233 if (at == NULL || return_uvalue == NULL) { 234 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 235 return (DW_DLV_ERROR); 236 } 237 238 switch (at->at_form) { 239 case DW_FORM_data1: 240 case DW_FORM_data2: 241 case DW_FORM_data4: 242 case DW_FORM_data8: 243 case DW_FORM_udata: 244 *return_uvalue = at->u[0].u64; 245 ret = DW_DLV_OK; 246 break; 247 default: 248 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD); 249 ret = DW_DLV_ERROR; 250 } 251 252 return (ret); 253 } 254 255 int 256 dwarf_formsdata(Dwarf_Attribute at, Dwarf_Signed *return_svalue, 257 Dwarf_Error *error) 258 { 259 int ret; 260 Dwarf_Debug dbg; 261 262 dbg = at != NULL ? at->at_die->die_dbg : NULL; 263 264 if (at == NULL || return_svalue == NULL) { 265 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 266 return (DW_DLV_ERROR); 267 } 268 269 switch (at->at_form) { 270 case DW_FORM_data1: 271 *return_svalue = (int8_t) at->u[0].s64; 272 ret = DW_DLV_OK; 273 break; 274 case DW_FORM_data2: 275 *return_svalue = (int16_t) at->u[0].s64; 276 ret = DW_DLV_OK; 277 break; 278 case DW_FORM_data4: 279 *return_svalue = (int32_t) at->u[0].s64; 280 ret = DW_DLV_OK; 281 break; 282 case DW_FORM_data8: 283 case DW_FORM_sdata: 284 *return_svalue = at->u[0].s64; 285 ret = DW_DLV_OK; 286 break; 287 default: 288 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD); 289 ret = DW_DLV_ERROR; 290 } 291 292 return (ret); 293 } 294 295 int 296 dwarf_formblock(Dwarf_Attribute at, Dwarf_Block **return_block, 297 Dwarf_Error *error) 298 { 299 int ret; 300 Dwarf_Debug dbg; 301 302 dbg = at != NULL ? at->at_die->die_dbg : NULL; 303 304 if (at == NULL || return_block == NULL) { 305 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 306 return (DW_DLV_ERROR); 307 } 308 309 switch (at->at_form) { 310 case DW_FORM_block: 311 case DW_FORM_block1: 312 case DW_FORM_block2: 313 case DW_FORM_block4: 314 *return_block = &at->at_block; 315 ret = DW_DLV_OK; 316 break; 317 default: 318 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD); 319 ret = DW_DLV_ERROR; 320 } 321 322 return (ret); 323 } 324 325 int 326 dwarf_formsig8(Dwarf_Attribute at, Dwarf_Sig8 *return_sig8, Dwarf_Error *error) 327 { 328 Dwarf_Debug dbg; 329 330 dbg = at != NULL ? at->at_die->die_dbg : NULL; 331 332 if (at == NULL || return_sig8 == NULL) { 333 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 334 return (DW_DLV_ERROR); 335 } 336 337 if (at->at_form != DW_FORM_ref_sig8) { 338 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD); 339 return (DW_DLV_ERROR); 340 } 341 342 assert(at->u[0].u64 == 8); 343 memcpy(return_sig8->signature, at->u[1].u8p, at->u[0].u64); 344 345 return (DW_DLV_OK); 346 } 347 348 int 349 dwarf_formexprloc(Dwarf_Attribute at, Dwarf_Unsigned *return_exprlen, 350 Dwarf_Ptr *return_expr, Dwarf_Error *error) 351 { 352 353 Dwarf_Debug dbg; 354 355 dbg = at != NULL ? at->at_die->die_dbg : NULL; 356 357 if (at == NULL || return_exprlen == NULL || return_expr == NULL) { 358 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 359 return (DW_DLV_ERROR); 360 } 361 362 if (at->at_form != DW_FORM_exprloc) { 363 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD); 364 return (DW_DLV_ERROR); 365 } 366 367 *return_exprlen = at->u[0].u64; 368 *return_expr = (void *) at->u[1].u8p; 369 370 return (DW_DLV_OK); 371 } 372 373 int 374 dwarf_formstring(Dwarf_Attribute at, char **return_string, 375 Dwarf_Error *error) 376 { 377 int ret; 378 Dwarf_Debug dbg; 379 380 dbg = at != NULL ? at->at_die->die_dbg : NULL; 381 382 if (at == NULL || return_string == NULL) { 383 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 384 return (DW_DLV_ERROR); 385 } 386 387 switch (at->at_form) { 388 case DW_FORM_string: 389 *return_string = (char *) at->u[0].s; 390 ret = DW_DLV_OK; 391 break; 392 case DW_FORM_strp: 393 *return_string = (char *) at->u[1].s; 394 ret = DW_DLV_OK; 395 break; 396 default: 397 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD); 398 ret = DW_DLV_ERROR; 399 } 400 401 return (ret); 402 } 403 404 enum Dwarf_Form_Class 405 dwarf_get_form_class(Dwarf_Half dwversion, Dwarf_Half attr, 406 Dwarf_Half offset_size, Dwarf_Half form) 407 { 408 409 switch (form) { 410 case DW_FORM_addr: 411 return (DW_FORM_CLASS_ADDRESS); 412 case DW_FORM_block: 413 case DW_FORM_block1: 414 case DW_FORM_block2: 415 case DW_FORM_block4: 416 return (DW_FORM_CLASS_BLOCK); 417 case DW_FORM_string: 418 case DW_FORM_strp: 419 return (DW_FORM_CLASS_STRING); 420 case DW_FORM_flag: 421 case DW_FORM_flag_present: 422 return (DW_FORM_CLASS_FLAG); 423 case DW_FORM_ref_addr: 424 case DW_FORM_ref_sig8: 425 case DW_FORM_ref_udata: 426 case DW_FORM_ref1: 427 case DW_FORM_ref2: 428 case DW_FORM_ref4: 429 case DW_FORM_ref8: 430 return (DW_FORM_CLASS_REFERENCE); 431 case DW_FORM_exprloc: 432 return (DW_FORM_CLASS_EXPRLOC); 433 case DW_FORM_data1: 434 case DW_FORM_data2: 435 case DW_FORM_sdata: 436 case DW_FORM_udata: 437 return (DW_FORM_CLASS_CONSTANT); 438 case DW_FORM_data4: 439 case DW_FORM_data8: 440 if (dwversion > 3) 441 return (DW_FORM_CLASS_CONSTANT); 442 if (form == DW_FORM_data4 && offset_size != 4) 443 return (DW_FORM_CLASS_CONSTANT); 444 if (form == DW_FORM_data8 && offset_size != 8) 445 return (DW_FORM_CLASS_CONSTANT); 446 /* FALLTHROUGH */ 447 case DW_FORM_sec_offset: 448 /* 449 * DW_FORM_data4 and DW_FORM_data8 can be used as 450 * offset/pointer before DWARF4. Newly added 451 * DWARF4 form DW_FORM_sec_offset intents to replace 452 * DW_FORM_data{4,8} for this purpose. Anyway, to 453 * determine the actual class for these forms, we need 454 * to also look at the attribute number. 455 */ 456 switch (attr) { 457 case DW_AT_location: 458 case DW_AT_string_length: 459 case DW_AT_return_addr: 460 case DW_AT_data_member_location: 461 case DW_AT_frame_base: 462 case DW_AT_segment: 463 case DW_AT_static_link: 464 case DW_AT_use_location: 465 case DW_AT_vtable_elem_location: 466 return (DW_FORM_CLASS_LOCLISTPTR); 467 case DW_AT_stmt_list: 468 return (DW_FORM_CLASS_LINEPTR); 469 case DW_AT_start_scope: 470 case DW_AT_ranges: 471 return (DW_FORM_CLASS_RANGELISTPTR); 472 case DW_AT_macro_info: 473 return (DW_FORM_CLASS_MACPTR); 474 default: 475 if (form == DW_FORM_data4 || form == DW_FORM_data8) 476 return (DW_FORM_CLASS_CONSTANT); 477 else 478 return (DW_FORM_CLASS_UNKNOWN); 479 } 480 default: 481 return (DW_FORM_CLASS_UNKNOWN); 482 } 483 } 484