1 /* $NetBSD: libdwarf_die.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-2011 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: libdwarf_die.c,v 1.3 2016/02/20 02:43:41 christos Exp $"); 33 ELFTC_VCSID("Id: libdwarf_die.c 3039 2014-05-18 15:10:56Z kaiwang27 "); 34 35 int 36 _dwarf_die_alloc(Dwarf_Debug dbg, Dwarf_Die *ret_die, Dwarf_Error *error) 37 { 38 Dwarf_Die die; 39 40 assert(ret_die != NULL); 41 42 if ((die = calloc(1, sizeof(struct _Dwarf_Die))) == NULL) { 43 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 44 return (DW_DLE_MEMORY); 45 } 46 47 STAILQ_INIT(&die->die_attr); 48 49 *ret_die = die; 50 51 return (DW_DLE_NONE); 52 } 53 54 static int 55 _dwarf_die_add(Dwarf_CU cu, uint64_t offset, uint64_t abnum, Dwarf_Abbrev ab, 56 Dwarf_Die *diep, Dwarf_Error *error) 57 { 58 Dwarf_Debug dbg; 59 Dwarf_Die die; 60 int ret; 61 62 assert(cu != NULL); 63 assert(ab != NULL); 64 65 dbg = cu->cu_dbg; 66 67 if ((ret = _dwarf_die_alloc(dbg, &die, error)) != DW_DLE_NONE) 68 return (ret); 69 70 die->die_offset = offset; 71 die->die_abnum = abnum; 72 die->die_ab = ab; 73 die->die_cu = cu; 74 die->die_dbg = cu->cu_dbg; 75 76 if (diep != NULL) 77 *diep = die; 78 79 return (DW_DLE_NONE); 80 } 81 82 /* Find die at offset 'off' within the same CU. */ 83 Dwarf_Die 84 _dwarf_die_find(Dwarf_Die die, Dwarf_Unsigned off) 85 { 86 Dwarf_Debug dbg; 87 Dwarf_Section *ds; 88 Dwarf_CU cu; 89 Dwarf_Die die1; 90 Dwarf_Error de; 91 int ret; 92 93 cu = die->die_cu; 94 dbg = die->die_dbg; 95 ds = cu->cu_is_info ? dbg->dbg_info_sec : dbg->dbg_types_sec; 96 97 ret = _dwarf_die_parse(dbg, ds, cu, cu->cu_dwarf_size, off, 98 cu->cu_next_offset, &die1, 0, &de); 99 100 if (ret == DW_DLE_NONE) 101 return (die1); 102 else 103 return (NULL); 104 } 105 106 int 107 _dwarf_die_parse(Dwarf_Debug dbg, Dwarf_Section *ds, Dwarf_CU cu, 108 int dwarf_size, uint64_t offset, uint64_t next_offset, Dwarf_Die *ret_die, 109 int search_sibling, Dwarf_Error *error) 110 { 111 Dwarf_Abbrev ab; 112 Dwarf_AttrDef ad; 113 Dwarf_Die die; 114 uint64_t abnum; 115 uint64_t die_offset; 116 int ret, level; 117 118 assert(cu != NULL); 119 120 level = 1; 121 die = NULL; 122 123 while (offset < next_offset && offset < ds->ds_size) { 124 125 die_offset = offset; 126 127 abnum = _dwarf_read_uleb128(ds->ds_data, &offset); 128 129 if (abnum == 0) { 130 if (level == 0 || !search_sibling) 131 return (DW_DLE_NO_ENTRY); 132 133 /* 134 * Return to previous DIE level. 135 */ 136 level--; 137 continue; 138 } 139 140 if ((ret = _dwarf_abbrev_find(cu, abnum, &ab, error)) != 141 DW_DLE_NONE) 142 return (ret); 143 144 if ((ret = _dwarf_die_add(cu, die_offset, abnum, ab, &die, 145 error)) != DW_DLE_NONE) 146 return (ret); 147 148 STAILQ_FOREACH(ad, &ab->ab_attrdef, ad_next) { 149 if ((ret = _dwarf_attr_init(dbg, ds, &offset, 150 dwarf_size, cu, die, ad, ad->ad_form, 0, 151 error)) != DW_DLE_NONE) 152 return (ret); 153 } 154 155 die->die_next_off = offset; 156 if (search_sibling && level > 0) { 157 dwarf_dealloc(dbg, die, DW_DLA_DIE); 158 if (ab->ab_children == DW_CHILDREN_yes) { 159 /* Advance to next DIE level. */ 160 level++; 161 } 162 } else { 163 *ret_die = die; 164 return (DW_DLE_NONE); 165 } 166 } 167 168 return (DW_DLE_NO_ENTRY); 169 } 170 171 void 172 _dwarf_die_link(Dwarf_P_Die die, Dwarf_P_Die parent, Dwarf_P_Die child, 173 Dwarf_P_Die left_sibling, Dwarf_P_Die right_sibling) 174 { 175 Dwarf_P_Die last_child; 176 177 assert(die != NULL); 178 179 if (parent) { 180 181 /* Disconnect from old parent. */ 182 if (die->die_parent) { 183 if (die->die_parent != parent) { 184 if (die->die_parent->die_child == die) 185 die->die_parent->die_child = NULL; 186 die->die_parent = NULL; 187 } 188 } 189 190 /* Find the last child of this parent. */ 191 last_child = parent->die_child; 192 if (last_child) { 193 while (last_child->die_right != NULL) 194 last_child = last_child->die_right; 195 } 196 197 /* Connect to new parent. */ 198 die->die_parent = parent; 199 200 /* 201 * Attach this DIE to the end of sibling list. If new 202 * parent doesn't have any child, set this DIE as the 203 * first child. 204 */ 205 if (last_child) { 206 assert(last_child->die_right == NULL); 207 last_child->die_right = die; 208 die->die_left = last_child; 209 } else 210 parent->die_child = die; 211 } 212 213 if (child) { 214 215 /* Disconnect from old child. */ 216 if (die->die_child) { 217 if (die->die_child != child) { 218 die->die_child->die_parent = NULL; 219 die->die_child = NULL; 220 } 221 } 222 223 /* Connect to new child. */ 224 die->die_child = child; 225 child->die_parent = die; 226 } 227 228 if (left_sibling) { 229 230 /* Disconnect from old left sibling. */ 231 if (die->die_left) { 232 if (die->die_left != left_sibling) { 233 die->die_left->die_right = NULL; 234 die->die_left = NULL; 235 } 236 } 237 238 /* Connect to new right sibling. */ 239 die->die_left = left_sibling; 240 left_sibling->die_right = die; 241 } 242 243 if (right_sibling) { 244 245 /* Disconnect from old right sibling. */ 246 if (die->die_right) { 247 if (die->die_right != right_sibling) { 248 die->die_right->die_left = NULL; 249 die->die_right = NULL; 250 } 251 } 252 253 /* Connect to new right sibling. */ 254 die->die_right = right_sibling; 255 right_sibling->die_left = die; 256 } 257 } 258 259 int 260 _dwarf_die_count_links(Dwarf_P_Die parent, Dwarf_P_Die child, 261 Dwarf_P_Die left_sibling, Dwarf_P_Die right_sibling) 262 { 263 int count; 264 265 count = 0; 266 267 if (parent) 268 count++; 269 if (child) 270 count++; 271 if (left_sibling) 272 count++; 273 if (right_sibling) 274 count++; 275 276 return (count); 277 } 278 279 static int 280 _dwarf_die_gen_recursive(Dwarf_P_Debug dbg, Dwarf_CU cu, Dwarf_Rel_Section drs, 281 Dwarf_P_Die die, int pass2, Dwarf_Error *error) 282 { 283 Dwarf_P_Section ds; 284 Dwarf_Abbrev ab; 285 Dwarf_Attribute at; 286 Dwarf_AttrDef ad; 287 int match, ret; 288 289 ds = dbg->dbgp_info; 290 assert(ds != NULL); 291 292 if (pass2) 293 goto attr_gen; 294 295 /* 296 * Add DW_AT_sibling attribute for DIEs with children, so consumers 297 * can quickly scan chains of siblings, while ignoring the children 298 * of individual siblings. 299 */ 300 if (die->die_child && die->die_right) { 301 if (_dwarf_attr_find(die, DW_AT_sibling) == NULL) 302 (void) dwarf_add_AT_reference(dbg, die, DW_AT_sibling, 303 die->die_right, error); 304 } 305 306 /* 307 * Search abbrev list to find a matching entry. 308 */ 309 die->die_ab = NULL; 310 for (ab = cu->cu_abbrev_hash; ab != NULL; ab = ab->ab_hh.next) { 311 if (die->die_tag != ab->ab_tag) 312 continue; 313 if (ab->ab_children == DW_CHILDREN_no && die->die_child != NULL) 314 continue; 315 if (ab->ab_children == DW_CHILDREN_yes && 316 die->die_child == NULL) 317 continue; 318 at = STAILQ_FIRST(&die->die_attr); 319 ad = STAILQ_FIRST(&ab->ab_attrdef); 320 match = 1; 321 while (at != NULL && ad != NULL) { 322 if (at->at_attrib != ad->ad_attrib || 323 at->at_form != ad->ad_form) { 324 match = 0; 325 break; 326 } 327 at = STAILQ_NEXT(at, at_next); 328 ad = STAILQ_NEXT(ad, ad_next); 329 } 330 if ((at == NULL && ad != NULL) || (at != NULL && ad == NULL)) 331 match = 0; 332 if (match) { 333 die->die_ab = ab; 334 break; 335 } 336 } 337 338 /* 339 * Create a new abbrev entry if we can not reuse any existing one. 340 */ 341 if (die->die_ab == NULL) { 342 ret = _dwarf_abbrev_add(cu, ++cu->cu_abbrev_cnt, die->die_tag, 343 die->die_child != NULL ? DW_CHILDREN_yes : DW_CHILDREN_no, 344 0, &ab, error); 345 if (ret != DW_DLE_NONE) 346 return (ret); 347 STAILQ_FOREACH(at, &die->die_attr, at_next) { 348 ret = _dwarf_attrdef_add(dbg, ab, at->at_attrib, 349 at->at_form, 0, NULL, error); 350 if (ret != DW_DLE_NONE) 351 return (ret); 352 } 353 die->die_ab = ab; 354 } 355 356 die->die_offset = ds->ds_size; 357 358 /* 359 * Transform the DIE to bytes stream. 360 */ 361 ret = _dwarf_write_uleb128_alloc(&ds->ds_data, &ds->ds_cap, 362 &ds->ds_size, die->die_ab->ab_entry, error); 363 if (ret != DW_DLE_NONE) 364 return (ret); 365 366 attr_gen: 367 368 /* Transform the attributes of this DIE. */ 369 ret = _dwarf_attr_gen(dbg, ds, drs, cu, die, pass2, error); 370 if (ret != DW_DLE_NONE) 371 return (ret); 372 373 /* Proceed to child DIE. */ 374 if (die->die_child != NULL) { 375 ret = _dwarf_die_gen_recursive(dbg, cu, drs, die->die_child, 376 pass2, error); 377 if (ret != DW_DLE_NONE) 378 return (ret); 379 } 380 381 /* Proceed to sibling DIE. */ 382 if (die->die_right != NULL) { 383 ret = _dwarf_die_gen_recursive(dbg, cu, drs, die->die_right, 384 pass2, error); 385 if (ret != DW_DLE_NONE) 386 return (ret); 387 } 388 389 /* Write a null DIE indicating the end of current level. */ 390 if (die->die_right == NULL) { 391 ret = _dwarf_write_uleb128_alloc(&ds->ds_data, &ds->ds_cap, 392 &ds->ds_size, 0, error); 393 if (ret != DW_DLE_NONE) 394 return (ret); 395 } 396 397 return (DW_DLE_NONE); 398 } 399 400 int 401 _dwarf_die_gen(Dwarf_P_Debug dbg, Dwarf_CU cu, Dwarf_Rel_Section drs, 402 Dwarf_Error *error) 403 { 404 Dwarf_Abbrev ab, tab; 405 Dwarf_AttrDef ad, tad; 406 Dwarf_Die die; 407 int ret; 408 409 assert(dbg != NULL && cu != NULL); 410 assert(dbg->dbgp_root_die != NULL); 411 412 die = dbg->dbgp_root_die; 413 414 /* 415 * Insert a DW_AT_stmt_list attribute into root DIE, if there are 416 * line number information. 417 */ 418 if (!STAILQ_EMPTY(&dbg->dbgp_lineinfo->li_lnlist)) 419 RCHECK(_dwarf_add_AT_dataref(dbg, die, DW_AT_stmt_list, 0, 0, 420 ".debug_line", NULL, error)); 421 422 RCHECK(_dwarf_die_gen_recursive(dbg, cu, drs, die, 0, error)); 423 424 if (cu->cu_pass2) 425 RCHECK(_dwarf_die_gen_recursive(dbg, cu, drs, die, 1, error)); 426 427 return (DW_DLE_NONE); 428 429 gen_fail: 430 431 HASH_ITER(ab_hh, cu->cu_abbrev_hash, ab, tab) { 432 HASH_DELETE(ab_hh, cu->cu_abbrev_hash, ab); 433 STAILQ_FOREACH_SAFE(ad, &ab->ab_attrdef, ad_next, tad) { 434 STAILQ_REMOVE(&ab->ab_attrdef, ad, _Dwarf_AttrDef, 435 ad_next); 436 free(ad); 437 } 438 free(ab); 439 } 440 441 return (ret); 442 } 443 444 void 445 _dwarf_die_pro_cleanup(Dwarf_P_Debug dbg) 446 { 447 Dwarf_P_Die die, tdie; 448 Dwarf_P_Attribute at, tat; 449 450 assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE); 451 452 STAILQ_FOREACH_SAFE(die, &dbg->dbgp_dielist, die_pro_next, tdie) { 453 STAILQ_FOREACH_SAFE(at, &die->die_attr, at_next, tat) { 454 STAILQ_REMOVE(&die->die_attr, at, _Dwarf_Attribute, 455 at_next); 456 free(at); 457 } 458 free(die); 459 } 460 } 461