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