1*2de3b87aSKai Wang /*- 2*2de3b87aSKai Wang * Copyright (c) 2009,2010 Kai Wang 3*2de3b87aSKai Wang * All rights reserved. 4*2de3b87aSKai Wang * 5*2de3b87aSKai Wang * Redistribution and use in source and binary forms, with or without 6*2de3b87aSKai Wang * modification, are permitted provided that the following conditions 7*2de3b87aSKai Wang * are met: 8*2de3b87aSKai Wang * 1. Redistributions of source code must retain the above copyright 9*2de3b87aSKai Wang * notice, this list of conditions and the following disclaimer. 10*2de3b87aSKai Wang * 2. Redistributions in binary form must reproduce the above copyright 11*2de3b87aSKai Wang * notice, this list of conditions and the following disclaimer in the 12*2de3b87aSKai Wang * documentation and/or other materials provided with the distribution. 13*2de3b87aSKai Wang * 14*2de3b87aSKai Wang * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15*2de3b87aSKai Wang * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*2de3b87aSKai Wang * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*2de3b87aSKai Wang * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18*2de3b87aSKai Wang * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*2de3b87aSKai Wang * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*2de3b87aSKai Wang * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*2de3b87aSKai Wang * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*2de3b87aSKai Wang * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*2de3b87aSKai Wang * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*2de3b87aSKai Wang * SUCH DAMAGE. 25*2de3b87aSKai Wang */ 26*2de3b87aSKai Wang 27*2de3b87aSKai Wang #include "_libdwarf.h" 28*2de3b87aSKai Wang 29*2de3b87aSKai Wang ELFTC_VCSID("$Id: libdwarf_nametbl.c 2070 2011-10-27 03:05:32Z jkoshy $"); 30*2de3b87aSKai Wang 31*2de3b87aSKai Wang void 32*2de3b87aSKai Wang _dwarf_nametbl_cleanup(Dwarf_NameSec *nsp) 33*2de3b87aSKai Wang { 34*2de3b87aSKai Wang Dwarf_NameSec ns; 35*2de3b87aSKai Wang Dwarf_NameTbl nt, tnt; 36*2de3b87aSKai Wang Dwarf_NamePair np, tnp; 37*2de3b87aSKai Wang 38*2de3b87aSKai Wang assert(nsp != NULL); 39*2de3b87aSKai Wang if ((ns = *nsp) == NULL) 40*2de3b87aSKai Wang return; 41*2de3b87aSKai Wang 42*2de3b87aSKai Wang STAILQ_FOREACH_SAFE(nt, &ns->ns_ntlist, nt_next, tnt) { 43*2de3b87aSKai Wang STAILQ_FOREACH_SAFE(np, &nt->nt_nplist, np_next, tnp) { 44*2de3b87aSKai Wang STAILQ_REMOVE(&nt->nt_nplist, np, _Dwarf_NamePair, 45*2de3b87aSKai Wang np_next); 46*2de3b87aSKai Wang free(np); 47*2de3b87aSKai Wang } 48*2de3b87aSKai Wang STAILQ_REMOVE(&ns->ns_ntlist, nt, _Dwarf_NameTbl, nt_next); 49*2de3b87aSKai Wang free(nt); 50*2de3b87aSKai Wang } 51*2de3b87aSKai Wang if (ns->ns_array) 52*2de3b87aSKai Wang free(ns->ns_array); 53*2de3b87aSKai Wang free(ns); 54*2de3b87aSKai Wang *nsp = NULL; 55*2de3b87aSKai Wang } 56*2de3b87aSKai Wang 57*2de3b87aSKai Wang int 58*2de3b87aSKai Wang _dwarf_nametbl_init(Dwarf_Debug dbg, Dwarf_NameSec *namesec, Dwarf_Section *ds, 59*2de3b87aSKai Wang Dwarf_Error *error) 60*2de3b87aSKai Wang { 61*2de3b87aSKai Wang Dwarf_CU cu; 62*2de3b87aSKai Wang Dwarf_NameSec ns; 63*2de3b87aSKai Wang Dwarf_NameTbl nt; 64*2de3b87aSKai Wang Dwarf_NamePair np; 65*2de3b87aSKai Wang uint64_t offset, dwarf_size, length, cuoff; 66*2de3b87aSKai Wang char *p; 67*2de3b87aSKai Wang int i, ret; 68*2de3b87aSKai Wang 69*2de3b87aSKai Wang assert(*namesec == NULL); 70*2de3b87aSKai Wang 71*2de3b87aSKai Wang if ((ns = malloc(sizeof(struct _Dwarf_NameSec))) == NULL) { 72*2de3b87aSKai Wang DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 73*2de3b87aSKai Wang return (DW_DLE_MEMORY); 74*2de3b87aSKai Wang } 75*2de3b87aSKai Wang STAILQ_INIT(&ns->ns_ntlist); 76*2de3b87aSKai Wang ns->ns_array = NULL; 77*2de3b87aSKai Wang ns->ns_len = 0; 78*2de3b87aSKai Wang 79*2de3b87aSKai Wang offset = 0; 80*2de3b87aSKai Wang while (offset < ds->ds_size) { 81*2de3b87aSKai Wang 82*2de3b87aSKai Wang /* Allocate a new name table. */ 83*2de3b87aSKai Wang if ((nt = malloc(sizeof(struct _Dwarf_NameTbl))) == NULL) { 84*2de3b87aSKai Wang ret = DW_DLE_MEMORY; 85*2de3b87aSKai Wang DWARF_SET_ERROR(dbg, error, ret); 86*2de3b87aSKai Wang goto fail_cleanup; 87*2de3b87aSKai Wang } 88*2de3b87aSKai Wang STAILQ_INIT(&nt->nt_nplist); 89*2de3b87aSKai Wang STAILQ_INSERT_TAIL(&ns->ns_ntlist, nt, nt_next); 90*2de3b87aSKai Wang 91*2de3b87aSKai Wang /* Read in the table header. */ 92*2de3b87aSKai Wang length = dbg->read(ds->ds_data, &offset, 4); 93*2de3b87aSKai Wang if (length == 0xffffffff) { 94*2de3b87aSKai Wang dwarf_size = 8; 95*2de3b87aSKai Wang length = dbg->read(ds->ds_data, &offset, 8); 96*2de3b87aSKai Wang } else 97*2de3b87aSKai Wang dwarf_size = 4; 98*2de3b87aSKai Wang 99*2de3b87aSKai Wang nt->nt_length = length; 100*2de3b87aSKai Wang /* FIXME: verify version */ 101*2de3b87aSKai Wang nt->nt_version = dbg->read(ds->ds_data, &offset, 2); 102*2de3b87aSKai Wang nt->nt_cu_offset = dbg->read(ds->ds_data, &offset, dwarf_size); 103*2de3b87aSKai Wang nt->nt_cu_length = dbg->read(ds->ds_data, &offset, dwarf_size); 104*2de3b87aSKai Wang 105*2de3b87aSKai Wang if (!dbg->dbg_info_loaded) { 106*2de3b87aSKai Wang ret = _dwarf_info_load(dbg, 1, error); 107*2de3b87aSKai Wang if (ret != DW_DLE_NONE) 108*2de3b87aSKai Wang goto fail_cleanup; 109*2de3b87aSKai Wang } 110*2de3b87aSKai Wang 111*2de3b87aSKai Wang /* Find the referenced CU. */ 112*2de3b87aSKai Wang STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) { 113*2de3b87aSKai Wang if (cu->cu_offset == nt->nt_cu_offset) 114*2de3b87aSKai Wang break; 115*2de3b87aSKai Wang } 116*2de3b87aSKai Wang nt->nt_cu = cu; /* FIXME: Check if NULL here */ 117*2de3b87aSKai Wang 118*2de3b87aSKai Wang /* Add name pairs. */ 119*2de3b87aSKai Wang while (offset < ds->ds_size) { 120*2de3b87aSKai Wang cuoff = dbg->read(ds->ds_data, &offset, dwarf_size); 121*2de3b87aSKai Wang if (cuoff == 0) 122*2de3b87aSKai Wang break; 123*2de3b87aSKai Wang if ((np = malloc(sizeof(struct _Dwarf_NamePair))) == 124*2de3b87aSKai Wang NULL) { 125*2de3b87aSKai Wang ret = DW_DLE_MEMORY; 126*2de3b87aSKai Wang DWARF_SET_ERROR(dbg, error, ret); 127*2de3b87aSKai Wang goto fail_cleanup; 128*2de3b87aSKai Wang } 129*2de3b87aSKai Wang np->np_nt = nt; 130*2de3b87aSKai Wang np->np_offset = cuoff; 131*2de3b87aSKai Wang p = (char *) ds->ds_data; 132*2de3b87aSKai Wang np->np_name = &p[offset]; 133*2de3b87aSKai Wang while (p[offset++] != '\0') 134*2de3b87aSKai Wang ; 135*2de3b87aSKai Wang STAILQ_INSERT_TAIL(&nt->nt_nplist, np, np_next); 136*2de3b87aSKai Wang ns->ns_len++; 137*2de3b87aSKai Wang } 138*2de3b87aSKai Wang } 139*2de3b87aSKai Wang 140*2de3b87aSKai Wang /* Build array of name pairs from all tables. */ 141*2de3b87aSKai Wang if (ns->ns_len > 0) { 142*2de3b87aSKai Wang if ((ns->ns_array = malloc(sizeof(Dwarf_NamePair) * 143*2de3b87aSKai Wang ns->ns_len)) == NULL) { 144*2de3b87aSKai Wang ret = DW_DLE_MEMORY; 145*2de3b87aSKai Wang DWARF_SET_ERROR(dbg, error, ret); 146*2de3b87aSKai Wang goto fail_cleanup; 147*2de3b87aSKai Wang } 148*2de3b87aSKai Wang 149*2de3b87aSKai Wang i = 0; 150*2de3b87aSKai Wang STAILQ_FOREACH(nt, &ns->ns_ntlist, nt_next) { 151*2de3b87aSKai Wang STAILQ_FOREACH(np, &nt->nt_nplist, np_next) 152*2de3b87aSKai Wang ns->ns_array[i++] = np; 153*2de3b87aSKai Wang } 154*2de3b87aSKai Wang assert((Dwarf_Unsigned)i == ns->ns_len); 155*2de3b87aSKai Wang } 156*2de3b87aSKai Wang 157*2de3b87aSKai Wang *namesec = ns; 158*2de3b87aSKai Wang 159*2de3b87aSKai Wang return (DW_DLE_NONE); 160*2de3b87aSKai Wang 161*2de3b87aSKai Wang fail_cleanup: 162*2de3b87aSKai Wang 163*2de3b87aSKai Wang _dwarf_nametbl_cleanup(&ns); 164*2de3b87aSKai Wang 165*2de3b87aSKai Wang return (ret); 166*2de3b87aSKai Wang } 167*2de3b87aSKai Wang 168*2de3b87aSKai Wang int 169*2de3b87aSKai Wang _dwarf_nametbl_gen(Dwarf_P_Debug dbg, const char *name, Dwarf_NameTbl nt, 170*2de3b87aSKai Wang Dwarf_Error *error) 171*2de3b87aSKai Wang { 172*2de3b87aSKai Wang Dwarf_P_Section ds; 173*2de3b87aSKai Wang Dwarf_Rel_Section drs; 174*2de3b87aSKai Wang Dwarf_NamePair np; 175*2de3b87aSKai Wang uint64_t offset; 176*2de3b87aSKai Wang int ret; 177*2de3b87aSKai Wang 178*2de3b87aSKai Wang assert(dbg != NULL && name != NULL); 179*2de3b87aSKai Wang if (nt == NULL || STAILQ_EMPTY(&nt->nt_nplist)) 180*2de3b87aSKai Wang return (DW_DLE_NONE); 181*2de3b87aSKai Wang 182*2de3b87aSKai Wang nt->nt_length = 0; 183*2de3b87aSKai Wang nt->nt_version = 2; 184*2de3b87aSKai Wang nt->nt_cu = STAILQ_FIRST(&dbg->dbg_cu); 185*2de3b87aSKai Wang assert(nt->nt_cu != NULL); 186*2de3b87aSKai Wang nt->nt_cu_offset = nt->nt_cu->cu_offset; 187*2de3b87aSKai Wang nt->nt_cu_length = nt->nt_cu->cu_length; 188*2de3b87aSKai Wang 189*2de3b87aSKai Wang /* Create name lookup section. */ 190*2de3b87aSKai Wang if ((ret = _dwarf_section_init(dbg, &ds, name, 0, error)) != 191*2de3b87aSKai Wang DW_DLE_NONE) 192*2de3b87aSKai Wang goto gen_fail0; 193*2de3b87aSKai Wang 194*2de3b87aSKai Wang /* Create relocation section for the name lookup section. */ 195*2de3b87aSKai Wang RCHECK(_dwarf_reloc_section_init(dbg, &drs, ds, error)); 196*2de3b87aSKai Wang 197*2de3b87aSKai Wang /* Write table header. */ 198*2de3b87aSKai Wang RCHECK(WRITE_VALUE(nt->nt_length, 4)); 199*2de3b87aSKai Wang RCHECK(WRITE_VALUE(nt->nt_version, 2)); 200*2de3b87aSKai Wang RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc, 4, 201*2de3b87aSKai Wang ds->ds_size, 0, nt->nt_cu_offset, ".debug_info", error)); 202*2de3b87aSKai Wang RCHECK(WRITE_VALUE(nt->nt_cu_length, 4)); 203*2de3b87aSKai Wang 204*2de3b87aSKai Wang /* Write tuples. */ 205*2de3b87aSKai Wang STAILQ_FOREACH(np, &nt->nt_nplist, np_next) { 206*2de3b87aSKai Wang assert(np->np_die != NULL); 207*2de3b87aSKai Wang np->np_offset = np->np_die->die_offset; 208*2de3b87aSKai Wang RCHECK(WRITE_VALUE(np->np_offset, 4)); 209*2de3b87aSKai Wang RCHECK(WRITE_STRING(np->np_name)); 210*2de3b87aSKai Wang } 211*2de3b87aSKai Wang RCHECK(WRITE_VALUE(0, 4)); 212*2de3b87aSKai Wang 213*2de3b87aSKai Wang /* Fill in the length field. */ 214*2de3b87aSKai Wang nt->nt_length = ds->ds_size - 4; 215*2de3b87aSKai Wang offset = 0; 216*2de3b87aSKai Wang dbg->write(ds->ds_data, &offset, nt->nt_length, 4); 217*2de3b87aSKai Wang 218*2de3b87aSKai Wang /* Inform application the creation of name lookup ELF section. */ 219*2de3b87aSKai Wang RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error)); 220*2de3b87aSKai Wang 221*2de3b87aSKai Wang /* Finalize relocation section for the name lookup section. */ 222*2de3b87aSKai Wang RCHECK(_dwarf_reloc_section_finalize(dbg, drs, error)); 223*2de3b87aSKai Wang 224*2de3b87aSKai Wang return (DW_DLE_NONE); 225*2de3b87aSKai Wang 226*2de3b87aSKai Wang gen_fail: 227*2de3b87aSKai Wang _dwarf_reloc_section_free(dbg, &drs); 228*2de3b87aSKai Wang 229*2de3b87aSKai Wang gen_fail0: 230*2de3b87aSKai Wang _dwarf_section_free(dbg, &ds); 231*2de3b87aSKai Wang 232*2de3b87aSKai Wang return (ret); 233*2de3b87aSKai Wang } 234*2de3b87aSKai Wang 235*2de3b87aSKai Wang void 236*2de3b87aSKai Wang _dwarf_nametbl_pro_cleanup(Dwarf_NameTbl *ntp) 237*2de3b87aSKai Wang { 238*2de3b87aSKai Wang Dwarf_NameTbl nt; 239*2de3b87aSKai Wang Dwarf_NamePair np, tnp; 240*2de3b87aSKai Wang 241*2de3b87aSKai Wang assert(ntp != NULL); 242*2de3b87aSKai Wang if ((nt = *ntp) == NULL) 243*2de3b87aSKai Wang return; 244*2de3b87aSKai Wang 245*2de3b87aSKai Wang STAILQ_FOREACH_SAFE(np, &nt->nt_nplist, np_next, tnp) { 246*2de3b87aSKai Wang STAILQ_REMOVE(&nt->nt_nplist, np, _Dwarf_NamePair, np_next); 247*2de3b87aSKai Wang if (np->np_name) 248*2de3b87aSKai Wang free(np->np_name); 249*2de3b87aSKai Wang free(np); 250*2de3b87aSKai Wang } 251*2de3b87aSKai Wang free(nt); 252*2de3b87aSKai Wang *ntp = NULL; 253*2de3b87aSKai Wang } 254