1*2de3b87aSKai Wang /*- 2*2de3b87aSKai Wang * Copyright (c) 2007 John Birrell (jb@freebsd.org) 3*2de3b87aSKai Wang * Copyright (c) 2009-2011 Kai Wang 4*2de3b87aSKai Wang * All rights reserved. 5*2de3b87aSKai Wang * 6*2de3b87aSKai Wang * Redistribution and use in source and binary forms, with or without 7*2de3b87aSKai Wang * modification, are permitted provided that the following conditions 8*2de3b87aSKai Wang * are met: 9*2de3b87aSKai Wang * 1. Redistributions of source code must retain the above copyright 10*2de3b87aSKai Wang * notice, this list of conditions and the following disclaimer. 11*2de3b87aSKai Wang * 2. Redistributions in binary form must reproduce the above copyright 12*2de3b87aSKai Wang * notice, this list of conditions and the following disclaimer in the 13*2de3b87aSKai Wang * documentation and/or other materials provided with the distribution. 14*2de3b87aSKai Wang * 15*2de3b87aSKai Wang * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16*2de3b87aSKai Wang * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17*2de3b87aSKai Wang * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18*2de3b87aSKai Wang * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19*2de3b87aSKai Wang * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20*2de3b87aSKai Wang * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21*2de3b87aSKai Wang * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22*2de3b87aSKai Wang * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23*2de3b87aSKai Wang * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24*2de3b87aSKai Wang * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25*2de3b87aSKai Wang * SUCH DAMAGE. 26*2de3b87aSKai Wang */ 27*2de3b87aSKai Wang 28*2de3b87aSKai Wang #include "_libdwarf.h" 29*2de3b87aSKai Wang 30*2de3b87aSKai Wang ELFTC_VCSID("$Id: libdwarf_abbrev.c 2070 2011-10-27 03:05:32Z jkoshy $"); 31*2de3b87aSKai Wang 32*2de3b87aSKai Wang int 33*2de3b87aSKai Wang _dwarf_abbrev_add(Dwarf_CU cu, uint64_t entry, uint64_t tag, uint8_t children, 34*2de3b87aSKai Wang uint64_t aboff, Dwarf_Abbrev *abp, Dwarf_Error *error) 35*2de3b87aSKai Wang { 36*2de3b87aSKai Wang Dwarf_Abbrev ab; 37*2de3b87aSKai Wang Dwarf_Debug dbg; 38*2de3b87aSKai Wang 39*2de3b87aSKai Wang dbg = cu != NULL ? cu->cu_dbg : NULL; 40*2de3b87aSKai Wang 41*2de3b87aSKai Wang if ((ab = malloc(sizeof(struct _Dwarf_Abbrev))) == NULL) { 42*2de3b87aSKai Wang DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 43*2de3b87aSKai Wang return (DW_DLE_MEMORY); 44*2de3b87aSKai Wang } 45*2de3b87aSKai Wang 46*2de3b87aSKai Wang /* Initialise the abbrev structure. */ 47*2de3b87aSKai Wang ab->ab_entry = entry; 48*2de3b87aSKai Wang ab->ab_tag = tag; 49*2de3b87aSKai Wang ab->ab_children = children; 50*2de3b87aSKai Wang ab->ab_offset = aboff; 51*2de3b87aSKai Wang ab->ab_length = 0; /* fill in later. */ 52*2de3b87aSKai Wang ab->ab_atnum = 0; /* fill in later. */ 53*2de3b87aSKai Wang 54*2de3b87aSKai Wang /* Initialise the list of attribute definitions. */ 55*2de3b87aSKai Wang STAILQ_INIT(&ab->ab_attrdef); 56*2de3b87aSKai Wang 57*2de3b87aSKai Wang /* Add the abbrev to the hash table of the compilation unit. */ 58*2de3b87aSKai Wang if (cu != NULL) 59*2de3b87aSKai Wang HASH_ADD(ab_hh, cu->cu_abbrev_hash, ab_entry, 60*2de3b87aSKai Wang sizeof(ab->ab_entry), ab); 61*2de3b87aSKai Wang 62*2de3b87aSKai Wang if (abp != NULL) 63*2de3b87aSKai Wang *abp = ab; 64*2de3b87aSKai Wang 65*2de3b87aSKai Wang return (DW_DLE_NONE); 66*2de3b87aSKai Wang } 67*2de3b87aSKai Wang 68*2de3b87aSKai Wang int 69*2de3b87aSKai Wang _dwarf_attrdef_add(Dwarf_Debug dbg, Dwarf_Abbrev ab, uint64_t attr, 70*2de3b87aSKai Wang uint64_t form, uint64_t adoff, Dwarf_AttrDef *adp, Dwarf_Error *error) 71*2de3b87aSKai Wang { 72*2de3b87aSKai Wang Dwarf_AttrDef ad; 73*2de3b87aSKai Wang 74*2de3b87aSKai Wang if (ab == NULL) { 75*2de3b87aSKai Wang DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 76*2de3b87aSKai Wang return (DW_DLE_ARGUMENT); 77*2de3b87aSKai Wang } 78*2de3b87aSKai Wang 79*2de3b87aSKai Wang if ((ad = malloc(sizeof(struct _Dwarf_AttrDef))) == NULL) { 80*2de3b87aSKai Wang DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 81*2de3b87aSKai Wang return (DW_DLE_MEMORY); 82*2de3b87aSKai Wang } 83*2de3b87aSKai Wang 84*2de3b87aSKai Wang /* Initialise the attribute definition structure. */ 85*2de3b87aSKai Wang ad->ad_attrib = attr; 86*2de3b87aSKai Wang ad->ad_form = form; 87*2de3b87aSKai Wang ad->ad_offset = adoff; 88*2de3b87aSKai Wang 89*2de3b87aSKai Wang /* Add the attribute definition to the list in the abbrev. */ 90*2de3b87aSKai Wang STAILQ_INSERT_TAIL(&ab->ab_attrdef, ad, ad_next); 91*2de3b87aSKai Wang 92*2de3b87aSKai Wang /* Increase number of attribute counter. */ 93*2de3b87aSKai Wang ab->ab_atnum++; 94*2de3b87aSKai Wang 95*2de3b87aSKai Wang if (adp != NULL) 96*2de3b87aSKai Wang *adp = ad; 97*2de3b87aSKai Wang 98*2de3b87aSKai Wang return (DW_DLE_NONE); 99*2de3b87aSKai Wang } 100*2de3b87aSKai Wang 101*2de3b87aSKai Wang int 102*2de3b87aSKai Wang _dwarf_abbrev_parse(Dwarf_Debug dbg, Dwarf_CU cu, Dwarf_Unsigned *offset, 103*2de3b87aSKai Wang Dwarf_Abbrev *abp, Dwarf_Error *error) 104*2de3b87aSKai Wang { 105*2de3b87aSKai Wang Dwarf_Section *ds; 106*2de3b87aSKai Wang uint64_t attr; 107*2de3b87aSKai Wang uint64_t entry; 108*2de3b87aSKai Wang uint64_t form; 109*2de3b87aSKai Wang uint64_t aboff; 110*2de3b87aSKai Wang uint64_t adoff; 111*2de3b87aSKai Wang uint64_t tag; 112*2de3b87aSKai Wang uint8_t children; 113*2de3b87aSKai Wang int ret; 114*2de3b87aSKai Wang 115*2de3b87aSKai Wang assert(abp != NULL); 116*2de3b87aSKai Wang 117*2de3b87aSKai Wang ds = _dwarf_find_section(dbg, ".debug_abbrev"); 118*2de3b87aSKai Wang assert(ds != NULL); 119*2de3b87aSKai Wang 120*2de3b87aSKai Wang if (*offset >= ds->ds_size) 121*2de3b87aSKai Wang return (DW_DLE_NO_ENTRY); 122*2de3b87aSKai Wang 123*2de3b87aSKai Wang aboff = *offset; 124*2de3b87aSKai Wang 125*2de3b87aSKai Wang entry = _dwarf_read_uleb128(ds->ds_data, offset); 126*2de3b87aSKai Wang if (entry == 0) { 127*2de3b87aSKai Wang /* Last entry. */ 128*2de3b87aSKai Wang ret = _dwarf_abbrev_add(cu, entry, 0, 0, aboff, abp, 129*2de3b87aSKai Wang error); 130*2de3b87aSKai Wang if (ret == DW_DLE_NONE) { 131*2de3b87aSKai Wang (*abp)->ab_length = 1; 132*2de3b87aSKai Wang return (ret); 133*2de3b87aSKai Wang } else 134*2de3b87aSKai Wang return (ret); 135*2de3b87aSKai Wang } 136*2de3b87aSKai Wang tag = _dwarf_read_uleb128(ds->ds_data, offset); 137*2de3b87aSKai Wang children = dbg->read(ds->ds_data, offset, 1); 138*2de3b87aSKai Wang if ((ret = _dwarf_abbrev_add(cu, entry, tag, children, aboff, 139*2de3b87aSKai Wang abp, error)) != DW_DLE_NONE) 140*2de3b87aSKai Wang return (ret); 141*2de3b87aSKai Wang 142*2de3b87aSKai Wang /* Parse attribute definitions. */ 143*2de3b87aSKai Wang do { 144*2de3b87aSKai Wang adoff = *offset; 145*2de3b87aSKai Wang attr = _dwarf_read_uleb128(ds->ds_data, offset); 146*2de3b87aSKai Wang form = _dwarf_read_uleb128(ds->ds_data, offset); 147*2de3b87aSKai Wang if (attr != 0) 148*2de3b87aSKai Wang if ((ret = _dwarf_attrdef_add(dbg, *abp, attr, 149*2de3b87aSKai Wang form, adoff, NULL, error)) != DW_DLE_NONE) 150*2de3b87aSKai Wang return (ret); 151*2de3b87aSKai Wang } while (attr != 0); 152*2de3b87aSKai Wang 153*2de3b87aSKai Wang (*abp)->ab_length = *offset - aboff; 154*2de3b87aSKai Wang 155*2de3b87aSKai Wang return (ret); 156*2de3b87aSKai Wang } 157*2de3b87aSKai Wang 158*2de3b87aSKai Wang int 159*2de3b87aSKai Wang _dwarf_abbrev_find(Dwarf_CU cu, uint64_t entry, Dwarf_Abbrev *abp, 160*2de3b87aSKai Wang Dwarf_Error *error) 161*2de3b87aSKai Wang { 162*2de3b87aSKai Wang Dwarf_Abbrev ab; 163*2de3b87aSKai Wang Dwarf_Section *ds; 164*2de3b87aSKai Wang Dwarf_Unsigned offset; 165*2de3b87aSKai Wang int ret; 166*2de3b87aSKai Wang 167*2de3b87aSKai Wang if (entry == 0) 168*2de3b87aSKai Wang return (DW_DLE_NO_ENTRY); 169*2de3b87aSKai Wang 170*2de3b87aSKai Wang /* Check if the desired abbrev entry is already in the hash table. */ 171*2de3b87aSKai Wang HASH_FIND(ab_hh, cu->cu_abbrev_hash, &entry, sizeof(entry), ab); 172*2de3b87aSKai Wang if (ab != NULL) { 173*2de3b87aSKai Wang *abp = ab; 174*2de3b87aSKai Wang return (DW_DLE_NONE); 175*2de3b87aSKai Wang } 176*2de3b87aSKai Wang 177*2de3b87aSKai Wang if (cu->cu_abbrev_loaded) { 178*2de3b87aSKai Wang return (DW_DLE_NO_ENTRY); 179*2de3b87aSKai Wang } 180*2de3b87aSKai Wang 181*2de3b87aSKai Wang /* Load and search the abbrev table. */ 182*2de3b87aSKai Wang ds = _dwarf_find_section(cu->cu_dbg, ".debug_abbrev"); 183*2de3b87aSKai Wang assert(ds != NULL); 184*2de3b87aSKai Wang offset = cu->cu_abbrev_offset_cur; 185*2de3b87aSKai Wang while (offset < ds->ds_size) { 186*2de3b87aSKai Wang ret = _dwarf_abbrev_parse(cu->cu_dbg, cu, &offset, &ab, error); 187*2de3b87aSKai Wang if (ret != DW_DLE_NONE) 188*2de3b87aSKai Wang return (ret); 189*2de3b87aSKai Wang if (ab->ab_entry == entry) { 190*2de3b87aSKai Wang cu->cu_abbrev_offset_cur = offset; 191*2de3b87aSKai Wang *abp = ab; 192*2de3b87aSKai Wang return (DW_DLE_NONE); 193*2de3b87aSKai Wang } 194*2de3b87aSKai Wang if (ab->ab_entry == 0) { 195*2de3b87aSKai Wang cu->cu_abbrev_offset_cur = offset; 196*2de3b87aSKai Wang cu->cu_abbrev_loaded = 1; 197*2de3b87aSKai Wang break; 198*2de3b87aSKai Wang } 199*2de3b87aSKai Wang } 200*2de3b87aSKai Wang 201*2de3b87aSKai Wang return (DW_DLE_NO_ENTRY); 202*2de3b87aSKai Wang } 203*2de3b87aSKai Wang 204*2de3b87aSKai Wang void 205*2de3b87aSKai Wang _dwarf_abbrev_cleanup(Dwarf_CU cu) 206*2de3b87aSKai Wang { 207*2de3b87aSKai Wang Dwarf_Abbrev ab, tab; 208*2de3b87aSKai Wang Dwarf_AttrDef ad, tad; 209*2de3b87aSKai Wang 210*2de3b87aSKai Wang assert(cu != NULL); 211*2de3b87aSKai Wang 212*2de3b87aSKai Wang HASH_ITER(ab_hh, cu->cu_abbrev_hash, ab, tab) { 213*2de3b87aSKai Wang HASH_DELETE(ab_hh, cu->cu_abbrev_hash, ab); 214*2de3b87aSKai Wang STAILQ_FOREACH_SAFE(ad, &ab->ab_attrdef, ad_next, tad) { 215*2de3b87aSKai Wang STAILQ_REMOVE(&ab->ab_attrdef, ad, _Dwarf_AttrDef, 216*2de3b87aSKai Wang ad_next); 217*2de3b87aSKai Wang free(ad); 218*2de3b87aSKai Wang } 219*2de3b87aSKai Wang free(ab); 220*2de3b87aSKai Wang } 221*2de3b87aSKai Wang } 222*2de3b87aSKai Wang 223*2de3b87aSKai Wang int 224*2de3b87aSKai Wang _dwarf_abbrev_gen(Dwarf_P_Debug dbg, Dwarf_Error *error) 225*2de3b87aSKai Wang { 226*2de3b87aSKai Wang Dwarf_CU cu; 227*2de3b87aSKai Wang Dwarf_Abbrev ab; 228*2de3b87aSKai Wang Dwarf_AttrDef ad; 229*2de3b87aSKai Wang Dwarf_P_Section ds; 230*2de3b87aSKai Wang int ret; 231*2de3b87aSKai Wang 232*2de3b87aSKai Wang cu = STAILQ_FIRST(&dbg->dbg_cu); 233*2de3b87aSKai Wang if (cu == NULL) 234*2de3b87aSKai Wang return (DW_DLE_NONE); 235*2de3b87aSKai Wang 236*2de3b87aSKai Wang /* Create .debug_abbrev section. */ 237*2de3b87aSKai Wang if ((ret = _dwarf_section_init(dbg, &ds, ".debug_abbrev", 0, error)) != 238*2de3b87aSKai Wang DW_DLE_NONE) 239*2de3b87aSKai Wang return (ret); 240*2de3b87aSKai Wang 241*2de3b87aSKai Wang for (ab = cu->cu_abbrev_hash; ab != NULL; ab = ab->ab_hh.next) { 242*2de3b87aSKai Wang RCHECK(WRITE_ULEB128(ab->ab_entry)); 243*2de3b87aSKai Wang RCHECK(WRITE_ULEB128(ab->ab_tag)); 244*2de3b87aSKai Wang RCHECK(WRITE_VALUE(ab->ab_children, 1)); 245*2de3b87aSKai Wang STAILQ_FOREACH(ad, &ab->ab_attrdef, ad_next) { 246*2de3b87aSKai Wang RCHECK(WRITE_ULEB128(ad->ad_attrib)); 247*2de3b87aSKai Wang RCHECK(WRITE_ULEB128(ad->ad_form)); 248*2de3b87aSKai Wang } 249*2de3b87aSKai Wang /* Signal end of attribute spec list. */ 250*2de3b87aSKai Wang RCHECK(WRITE_ULEB128(0)); 251*2de3b87aSKai Wang RCHECK(WRITE_ULEB128(0)); 252*2de3b87aSKai Wang } 253*2de3b87aSKai Wang /* End of abbreviation for this CU. */ 254*2de3b87aSKai Wang RCHECK(WRITE_ULEB128(0)); 255*2de3b87aSKai Wang 256*2de3b87aSKai Wang /* Notify the creation of .debug_abbrev ELF section. */ 257*2de3b87aSKai Wang RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error)); 258*2de3b87aSKai Wang 259*2de3b87aSKai Wang return (DW_DLE_NONE); 260*2de3b87aSKai Wang 261*2de3b87aSKai Wang gen_fail: 262*2de3b87aSKai Wang 263*2de3b87aSKai Wang _dwarf_section_free(dbg, &ds); 264*2de3b87aSKai Wang 265*2de3b87aSKai Wang return (ret); 266*2de3b87aSKai Wang } 267