1260684Skaiw/*- 2260684Skaiw * Copyright (c) 2007 John Birrell (jb@freebsd.org) 3260684Skaiw * Copyright (c) 2009-2011 Kai Wang 4260684Skaiw * All rights reserved. 5260684Skaiw * 6260684Skaiw * Redistribution and use in source and binary forms, with or without 7260684Skaiw * modification, are permitted provided that the following conditions 8260684Skaiw * are met: 9260684Skaiw * 1. Redistributions of source code must retain the above copyright 10260684Skaiw * notice, this list of conditions and the following disclaimer. 11260684Skaiw * 2. Redistributions in binary form must reproduce the above copyright 12260684Skaiw * notice, this list of conditions and the following disclaimer in the 13260684Skaiw * documentation and/or other materials provided with the distribution. 14260684Skaiw * 15260684Skaiw * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16260684Skaiw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17260684Skaiw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18260684Skaiw * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19260684Skaiw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20260684Skaiw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21260684Skaiw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22260684Skaiw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23260684Skaiw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24260684Skaiw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25260684Skaiw * SUCH DAMAGE. 26260684Skaiw */ 27260684Skaiw 28260684Skaiw#include "_libdwarf.h" 29260684Skaiw 30276371SemasteELFTC_VCSID("$Id: libdwarf_die.c 3039 2014-05-18 15:10:56Z kaiwang27 $"); 31260684Skaiw 32260684Skaiwint 33260684Skaiw_dwarf_die_alloc(Dwarf_Debug dbg, Dwarf_Die *ret_die, Dwarf_Error *error) 34260684Skaiw{ 35260684Skaiw Dwarf_Die die; 36260684Skaiw 37260684Skaiw assert(ret_die != NULL); 38260684Skaiw 39260684Skaiw if ((die = calloc(1, sizeof(struct _Dwarf_Die))) == NULL) { 40260684Skaiw DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 41260684Skaiw return (DW_DLE_MEMORY); 42260684Skaiw } 43260684Skaiw 44260684Skaiw STAILQ_INIT(&die->die_attr); 45260684Skaiw 46260684Skaiw *ret_die = die; 47260684Skaiw 48260684Skaiw return (DW_DLE_NONE); 49260684Skaiw} 50260684Skaiw 51260684Skaiwstatic int 52260684Skaiw_dwarf_die_add(Dwarf_CU cu, uint64_t offset, uint64_t abnum, Dwarf_Abbrev ab, 53260684Skaiw Dwarf_Die *diep, Dwarf_Error *error) 54260684Skaiw{ 55260684Skaiw Dwarf_Debug dbg; 56260684Skaiw Dwarf_Die die; 57260684Skaiw int ret; 58260684Skaiw 59260684Skaiw assert(cu != NULL); 60260684Skaiw assert(ab != NULL); 61260684Skaiw 62260684Skaiw dbg = cu->cu_dbg; 63260684Skaiw 64260684Skaiw if ((ret = _dwarf_die_alloc(dbg, &die, error)) != DW_DLE_NONE) 65260684Skaiw return (ret); 66260684Skaiw 67260684Skaiw die->die_offset = offset; 68260684Skaiw die->die_abnum = abnum; 69260684Skaiw die->die_ab = ab; 70260684Skaiw die->die_cu = cu; 71260684Skaiw die->die_dbg = cu->cu_dbg; 72260684Skaiw 73367466Sdim *diep = die; 74260684Skaiw 75260684Skaiw return (DW_DLE_NONE); 76260684Skaiw} 77260684Skaiw 78260684Skaiw/* Find die at offset 'off' within the same CU. */ 79260684SkaiwDwarf_Die 80260684Skaiw_dwarf_die_find(Dwarf_Die die, Dwarf_Unsigned off) 81260684Skaiw{ 82260684Skaiw Dwarf_Debug dbg; 83276371Semaste Dwarf_Section *ds; 84260684Skaiw Dwarf_CU cu; 85260684Skaiw Dwarf_Die die1; 86260684Skaiw Dwarf_Error de; 87260684Skaiw int ret; 88260684Skaiw 89260684Skaiw cu = die->die_cu; 90260684Skaiw dbg = die->die_dbg; 91276371Semaste ds = cu->cu_is_info ? dbg->dbg_info_sec : dbg->dbg_types_sec; 92260684Skaiw 93276371Semaste ret = _dwarf_die_parse(dbg, ds, cu, cu->cu_dwarf_size, off, 94276371Semaste cu->cu_next_offset, &die1, 0, &de); 95260684Skaiw 96260684Skaiw if (ret == DW_DLE_NONE) 97260684Skaiw return (die1); 98260684Skaiw else 99260684Skaiw return (NULL); 100260684Skaiw} 101260684Skaiw 102260684Skaiwint 103260684Skaiw_dwarf_die_parse(Dwarf_Debug dbg, Dwarf_Section *ds, Dwarf_CU cu, 104260684Skaiw int dwarf_size, uint64_t offset, uint64_t next_offset, Dwarf_Die *ret_die, 105260684Skaiw int search_sibling, Dwarf_Error *error) 106260684Skaiw{ 107260684Skaiw Dwarf_Abbrev ab; 108260684Skaiw Dwarf_AttrDef ad; 109260684Skaiw Dwarf_Die die; 110260684Skaiw uint64_t abnum; 111260684Skaiw uint64_t die_offset; 112260684Skaiw int ret, level; 113260684Skaiw 114260684Skaiw assert(cu != NULL); 115260684Skaiw 116260684Skaiw level = 1; 117260684Skaiw die = NULL; 118260684Skaiw 119260684Skaiw while (offset < next_offset && offset < ds->ds_size) { 120260684Skaiw 121260684Skaiw die_offset = offset; 122260684Skaiw 123260684Skaiw abnum = _dwarf_read_uleb128(ds->ds_data, &offset); 124260684Skaiw 125260684Skaiw if (abnum == 0) { 126260684Skaiw if (level == 0 || !search_sibling) 127260684Skaiw return (DW_DLE_NO_ENTRY); 128260684Skaiw 129260684Skaiw /* 130260684Skaiw * Return to previous DIE level. 131260684Skaiw */ 132260684Skaiw level--; 133260684Skaiw continue; 134260684Skaiw } 135260684Skaiw 136260684Skaiw if ((ret = _dwarf_abbrev_find(cu, abnum, &ab, error)) != 137260684Skaiw DW_DLE_NONE) 138260684Skaiw return (ret); 139260684Skaiw 140260684Skaiw if ((ret = _dwarf_die_add(cu, die_offset, abnum, ab, &die, 141260684Skaiw error)) != DW_DLE_NONE) 142260684Skaiw return (ret); 143260684Skaiw 144260684Skaiw STAILQ_FOREACH(ad, &ab->ab_attrdef, ad_next) { 145260684Skaiw if ((ret = _dwarf_attr_init(dbg, ds, &offset, 146260684Skaiw dwarf_size, cu, die, ad, ad->ad_form, 0, 147260684Skaiw error)) != DW_DLE_NONE) 148260684Skaiw return (ret); 149260684Skaiw } 150260684Skaiw 151260684Skaiw die->die_next_off = offset; 152260684Skaiw if (search_sibling && level > 0) { 153260684Skaiw dwarf_dealloc(dbg, die, DW_DLA_DIE); 154260684Skaiw if (ab->ab_children == DW_CHILDREN_yes) { 155260684Skaiw /* Advance to next DIE level. */ 156260684Skaiw level++; 157260684Skaiw } 158260684Skaiw } else { 159260684Skaiw *ret_die = die; 160260684Skaiw return (DW_DLE_NONE); 161260684Skaiw } 162260684Skaiw } 163260684Skaiw 164260684Skaiw return (DW_DLE_NO_ENTRY); 165260684Skaiw} 166260684Skaiw 167260684Skaiwvoid 168260684Skaiw_dwarf_die_link(Dwarf_P_Die die, Dwarf_P_Die parent, Dwarf_P_Die child, 169260684Skaiw Dwarf_P_Die left_sibling, Dwarf_P_Die right_sibling) 170260684Skaiw{ 171260684Skaiw Dwarf_P_Die last_child; 172260684Skaiw 173260684Skaiw assert(die != NULL); 174260684Skaiw 175260684Skaiw if (parent) { 176260684Skaiw 177260684Skaiw /* Disconnect from old parent. */ 178260684Skaiw if (die->die_parent) { 179260684Skaiw if (die->die_parent != parent) { 180260684Skaiw if (die->die_parent->die_child == die) 181260684Skaiw die->die_parent->die_child = NULL; 182260684Skaiw die->die_parent = NULL; 183260684Skaiw } 184260684Skaiw } 185260684Skaiw 186260684Skaiw /* Find the last child of this parent. */ 187260684Skaiw last_child = parent->die_child; 188260684Skaiw if (last_child) { 189260684Skaiw while (last_child->die_right != NULL) 190260684Skaiw last_child = last_child->die_right; 191260684Skaiw } 192260684Skaiw 193260684Skaiw /* Connect to new parent. */ 194260684Skaiw die->die_parent = parent; 195260684Skaiw 196260684Skaiw /* 197260684Skaiw * Attach this DIE to the end of sibling list. If new 198260684Skaiw * parent doesn't have any child, set this DIE as the 199260684Skaiw * first child. 200260684Skaiw */ 201260684Skaiw if (last_child) { 202260684Skaiw assert(last_child->die_right == NULL); 203260684Skaiw last_child->die_right = die; 204260684Skaiw die->die_left = last_child; 205260684Skaiw } else 206260684Skaiw parent->die_child = die; 207260684Skaiw } 208260684Skaiw 209260684Skaiw if (child) { 210260684Skaiw 211260684Skaiw /* Disconnect from old child. */ 212260684Skaiw if (die->die_child) { 213260684Skaiw if (die->die_child != child) { 214260684Skaiw die->die_child->die_parent = NULL; 215260684Skaiw die->die_child = NULL; 216260684Skaiw } 217260684Skaiw } 218260684Skaiw 219260684Skaiw /* Connect to new child. */ 220260684Skaiw die->die_child = child; 221260684Skaiw child->die_parent = die; 222260684Skaiw } 223260684Skaiw 224260684Skaiw if (left_sibling) { 225260684Skaiw 226260684Skaiw /* Disconnect from old left sibling. */ 227260684Skaiw if (die->die_left) { 228260684Skaiw if (die->die_left != left_sibling) { 229260684Skaiw die->die_left->die_right = NULL; 230260684Skaiw die->die_left = NULL; 231260684Skaiw } 232260684Skaiw } 233260684Skaiw 234260684Skaiw /* Connect to new right sibling. */ 235260684Skaiw die->die_left = left_sibling; 236260684Skaiw left_sibling->die_right = die; 237260684Skaiw } 238260684Skaiw 239260684Skaiw if (right_sibling) { 240260684Skaiw 241260684Skaiw /* Disconnect from old right sibling. */ 242260684Skaiw if (die->die_right) { 243260684Skaiw if (die->die_right != right_sibling) { 244260684Skaiw die->die_right->die_left = NULL; 245260684Skaiw die->die_right = NULL; 246260684Skaiw } 247260684Skaiw } 248260684Skaiw 249260684Skaiw /* Connect to new right sibling. */ 250260684Skaiw die->die_right = right_sibling; 251260684Skaiw right_sibling->die_left = die; 252260684Skaiw } 253260684Skaiw} 254260684Skaiw 255260684Skaiwint 256260684Skaiw_dwarf_die_count_links(Dwarf_P_Die parent, Dwarf_P_Die child, 257260684Skaiw Dwarf_P_Die left_sibling, Dwarf_P_Die right_sibling) 258260684Skaiw{ 259260684Skaiw int count; 260260684Skaiw 261260684Skaiw count = 0; 262260684Skaiw 263260684Skaiw if (parent) 264260684Skaiw count++; 265260684Skaiw if (child) 266260684Skaiw count++; 267260684Skaiw if (left_sibling) 268260684Skaiw count++; 269260684Skaiw if (right_sibling) 270260684Skaiw count++; 271260684Skaiw 272260684Skaiw return (count); 273260684Skaiw} 274260684Skaiw 275260684Skaiwstatic int 276260684Skaiw_dwarf_die_gen_recursive(Dwarf_P_Debug dbg, Dwarf_CU cu, Dwarf_Rel_Section drs, 277260684Skaiw Dwarf_P_Die die, int pass2, Dwarf_Error *error) 278260684Skaiw{ 279260684Skaiw Dwarf_P_Section ds; 280260684Skaiw Dwarf_Abbrev ab; 281260684Skaiw Dwarf_Attribute at; 282260684Skaiw Dwarf_AttrDef ad; 283260684Skaiw int match, ret; 284260684Skaiw 285260684Skaiw ds = dbg->dbgp_info; 286260684Skaiw assert(ds != NULL); 287260684Skaiw 288260684Skaiw if (pass2) 289260684Skaiw goto attr_gen; 290260684Skaiw 291260684Skaiw /* 292260684Skaiw * Add DW_AT_sibling attribute for DIEs with children, so consumers 293260684Skaiw * can quickly scan chains of siblings, while ignoring the children 294260684Skaiw * of individual siblings. 295260684Skaiw */ 296260684Skaiw if (die->die_child && die->die_right) { 297260684Skaiw if (_dwarf_attr_find(die, DW_AT_sibling) == NULL) 298260684Skaiw (void) dwarf_add_AT_reference(dbg, die, DW_AT_sibling, 299260684Skaiw die->die_right, error); 300260684Skaiw } 301260684Skaiw 302260684Skaiw /* 303260684Skaiw * Search abbrev list to find a matching entry. 304260684Skaiw */ 305260684Skaiw die->die_ab = NULL; 306260684Skaiw for (ab = cu->cu_abbrev_hash; ab != NULL; ab = ab->ab_hh.next) { 307260684Skaiw if (die->die_tag != ab->ab_tag) 308260684Skaiw continue; 309260684Skaiw if (ab->ab_children == DW_CHILDREN_no && die->die_child != NULL) 310260684Skaiw continue; 311260684Skaiw if (ab->ab_children == DW_CHILDREN_yes && 312260684Skaiw die->die_child == NULL) 313260684Skaiw continue; 314260684Skaiw at = STAILQ_FIRST(&die->die_attr); 315260684Skaiw ad = STAILQ_FIRST(&ab->ab_attrdef); 316260684Skaiw match = 1; 317260684Skaiw while (at != NULL && ad != NULL) { 318260684Skaiw if (at->at_attrib != ad->ad_attrib || 319260684Skaiw at->at_form != ad->ad_form) { 320260684Skaiw match = 0; 321260684Skaiw break; 322260684Skaiw } 323260684Skaiw at = STAILQ_NEXT(at, at_next); 324260684Skaiw ad = STAILQ_NEXT(ad, ad_next); 325260684Skaiw } 326260684Skaiw if ((at == NULL && ad != NULL) || (at != NULL && ad == NULL)) 327260684Skaiw match = 0; 328260684Skaiw if (match) { 329260684Skaiw die->die_ab = ab; 330260684Skaiw break; 331260684Skaiw } 332260684Skaiw } 333260684Skaiw 334260684Skaiw /* 335260684Skaiw * Create a new abbrev entry if we can not reuse any existing one. 336260684Skaiw */ 337260684Skaiw if (die->die_ab == NULL) { 338260684Skaiw ret = _dwarf_abbrev_add(cu, ++cu->cu_abbrev_cnt, die->die_tag, 339260684Skaiw die->die_child != NULL ? DW_CHILDREN_yes : DW_CHILDREN_no, 340260684Skaiw 0, &ab, error); 341260684Skaiw if (ret != DW_DLE_NONE) 342260684Skaiw return (ret); 343260684Skaiw STAILQ_FOREACH(at, &die->die_attr, at_next) { 344260684Skaiw ret = _dwarf_attrdef_add(dbg, ab, at->at_attrib, 345260684Skaiw at->at_form, 0, NULL, error); 346260684Skaiw if (ret != DW_DLE_NONE) 347260684Skaiw return (ret); 348260684Skaiw } 349260684Skaiw die->die_ab = ab; 350260684Skaiw } 351260684Skaiw 352260684Skaiw die->die_offset = ds->ds_size; 353260684Skaiw 354260684Skaiw /* 355260684Skaiw * Transform the DIE to bytes stream. 356260684Skaiw */ 357260684Skaiw ret = _dwarf_write_uleb128_alloc(&ds->ds_data, &ds->ds_cap, 358260684Skaiw &ds->ds_size, die->die_ab->ab_entry, error); 359260684Skaiw if (ret != DW_DLE_NONE) 360260684Skaiw return (ret); 361260684Skaiw 362260684Skaiwattr_gen: 363260684Skaiw 364260684Skaiw /* Transform the attributes of this DIE. */ 365260684Skaiw ret = _dwarf_attr_gen(dbg, ds, drs, cu, die, pass2, error); 366260684Skaiw if (ret != DW_DLE_NONE) 367260684Skaiw return (ret); 368260684Skaiw 369260684Skaiw /* Proceed to child DIE. */ 370260684Skaiw if (die->die_child != NULL) { 371260684Skaiw ret = _dwarf_die_gen_recursive(dbg, cu, drs, die->die_child, 372260684Skaiw pass2, error); 373260684Skaiw if (ret != DW_DLE_NONE) 374260684Skaiw return (ret); 375260684Skaiw } 376260684Skaiw 377260684Skaiw /* Proceed to sibling DIE. */ 378260684Skaiw if (die->die_right != NULL) { 379260684Skaiw ret = _dwarf_die_gen_recursive(dbg, cu, drs, die->die_right, 380260684Skaiw pass2, error); 381260684Skaiw if (ret != DW_DLE_NONE) 382260684Skaiw return (ret); 383260684Skaiw } 384260684Skaiw 385260684Skaiw /* Write a null DIE indicating the end of current level. */ 386260684Skaiw if (die->die_right == NULL) { 387260684Skaiw ret = _dwarf_write_uleb128_alloc(&ds->ds_data, &ds->ds_cap, 388260684Skaiw &ds->ds_size, 0, error); 389260684Skaiw if (ret != DW_DLE_NONE) 390260684Skaiw return (ret); 391260684Skaiw } 392260684Skaiw 393260684Skaiw return (DW_DLE_NONE); 394260684Skaiw} 395260684Skaiw 396260684Skaiwint 397260684Skaiw_dwarf_die_gen(Dwarf_P_Debug dbg, Dwarf_CU cu, Dwarf_Rel_Section drs, 398260684Skaiw Dwarf_Error *error) 399260684Skaiw{ 400260684Skaiw Dwarf_Abbrev ab, tab; 401260684Skaiw Dwarf_AttrDef ad, tad; 402260684Skaiw Dwarf_Die die; 403260684Skaiw int ret; 404260684Skaiw 405260684Skaiw assert(dbg != NULL && cu != NULL); 406260684Skaiw assert(dbg->dbgp_root_die != NULL); 407260684Skaiw 408260684Skaiw die = dbg->dbgp_root_die; 409260684Skaiw 410260684Skaiw /* 411260684Skaiw * Insert a DW_AT_stmt_list attribute into root DIE, if there are 412260684Skaiw * line number information. 413260684Skaiw */ 414260684Skaiw if (!STAILQ_EMPTY(&dbg->dbgp_lineinfo->li_lnlist)) 415260684Skaiw RCHECK(_dwarf_add_AT_dataref(dbg, die, DW_AT_stmt_list, 0, 0, 416260684Skaiw ".debug_line", NULL, error)); 417260684Skaiw 418260684Skaiw RCHECK(_dwarf_die_gen_recursive(dbg, cu, drs, die, 0, error)); 419260684Skaiw 420260684Skaiw if (cu->cu_pass2) 421260684Skaiw RCHECK(_dwarf_die_gen_recursive(dbg, cu, drs, die, 1, error)); 422260684Skaiw 423260684Skaiw return (DW_DLE_NONE); 424260684Skaiw 425260684Skaiwgen_fail: 426260684Skaiw 427260684Skaiw HASH_ITER(ab_hh, cu->cu_abbrev_hash, ab, tab) { 428260684Skaiw HASH_DELETE(ab_hh, cu->cu_abbrev_hash, ab); 429260684Skaiw STAILQ_FOREACH_SAFE(ad, &ab->ab_attrdef, ad_next, tad) { 430260684Skaiw STAILQ_REMOVE(&ab->ab_attrdef, ad, _Dwarf_AttrDef, 431260684Skaiw ad_next); 432260684Skaiw free(ad); 433260684Skaiw } 434260684Skaiw free(ab); 435260684Skaiw } 436260684Skaiw 437260684Skaiw return (ret); 438260684Skaiw} 439260684Skaiw 440260684Skaiwvoid 441260684Skaiw_dwarf_die_pro_cleanup(Dwarf_P_Debug dbg) 442260684Skaiw{ 443260684Skaiw Dwarf_P_Die die, tdie; 444260684Skaiw Dwarf_P_Attribute at, tat; 445260684Skaiw 446260684Skaiw assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE); 447260684Skaiw 448260684Skaiw STAILQ_FOREACH_SAFE(die, &dbg->dbgp_dielist, die_pro_next, tdie) { 449260684Skaiw STAILQ_FOREACH_SAFE(at, &die->die_attr, at_next, tat) { 450260684Skaiw STAILQ_REMOVE(&die->die_attr, at, _Dwarf_Attribute, 451260684Skaiw at_next); 452260684Skaiw free(at); 453260684Skaiw } 454260684Skaiw free(die); 455260684Skaiw } 456260684Skaiw} 457