1*2de3b87aSKai Wang /*- 2*2de3b87aSKai Wang * Copyright (c) 2007 John Birrell (jb@freebsd.org) 3*2de3b87aSKai Wang * Copyright (c) 2010,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_info.c 2942 2013-05-04 23:03:54Z kaiwang27 $"); 31*2de3b87aSKai Wang 32*2de3b87aSKai Wang int 33*2de3b87aSKai Wang _dwarf_info_first_cu(Dwarf_Debug dbg, Dwarf_Error *error) 34*2de3b87aSKai Wang { 35*2de3b87aSKai Wang Dwarf_CU cu; 36*2de3b87aSKai Wang int ret; 37*2de3b87aSKai Wang 38*2de3b87aSKai Wang assert(dbg->dbg_cu_current == NULL); 39*2de3b87aSKai Wang cu = STAILQ_FIRST(&dbg->dbg_cu); 40*2de3b87aSKai Wang if (cu != NULL) { 41*2de3b87aSKai Wang dbg->dbg_cu_current = cu; 42*2de3b87aSKai Wang return (DW_DLE_NONE); 43*2de3b87aSKai Wang } 44*2de3b87aSKai Wang 45*2de3b87aSKai Wang if (dbg->dbg_info_loaded) 46*2de3b87aSKai Wang return (DW_DLE_NO_ENTRY); 47*2de3b87aSKai Wang 48*2de3b87aSKai Wang dbg->dbg_info_off = 0; 49*2de3b87aSKai Wang ret = _dwarf_info_load(dbg, 0, error); 50*2de3b87aSKai Wang if (ret != DW_DLE_NONE) 51*2de3b87aSKai Wang return (ret); 52*2de3b87aSKai Wang 53*2de3b87aSKai Wang dbg->dbg_cu_current = STAILQ_FIRST(&dbg->dbg_cu); 54*2de3b87aSKai Wang 55*2de3b87aSKai Wang return (DW_DLE_NONE); 56*2de3b87aSKai Wang } 57*2de3b87aSKai Wang 58*2de3b87aSKai Wang int 59*2de3b87aSKai Wang _dwarf_info_next_cu(Dwarf_Debug dbg, Dwarf_Error *error) 60*2de3b87aSKai Wang { 61*2de3b87aSKai Wang Dwarf_CU cu; 62*2de3b87aSKai Wang int ret; 63*2de3b87aSKai Wang 64*2de3b87aSKai Wang assert(dbg->dbg_cu_current != NULL); 65*2de3b87aSKai Wang cu = STAILQ_NEXT(dbg->dbg_cu_current, cu_next); 66*2de3b87aSKai Wang if (cu != NULL) { 67*2de3b87aSKai Wang dbg->dbg_cu_current = cu; 68*2de3b87aSKai Wang return (DW_DLE_NONE); 69*2de3b87aSKai Wang } 70*2de3b87aSKai Wang 71*2de3b87aSKai Wang if (dbg->dbg_info_loaded) { 72*2de3b87aSKai Wang dbg->dbg_cu_current = NULL; 73*2de3b87aSKai Wang return (DW_DLE_NO_ENTRY); 74*2de3b87aSKai Wang } 75*2de3b87aSKai Wang 76*2de3b87aSKai Wang ret = _dwarf_info_load(dbg, 0, error); 77*2de3b87aSKai Wang if (ret != DW_DLE_NONE) 78*2de3b87aSKai Wang return (ret); 79*2de3b87aSKai Wang 80*2de3b87aSKai Wang dbg->dbg_cu_current = STAILQ_NEXT(dbg->dbg_cu_current, cu_next); 81*2de3b87aSKai Wang 82*2de3b87aSKai Wang return (DW_DLE_NONE); 83*2de3b87aSKai Wang } 84*2de3b87aSKai Wang 85*2de3b87aSKai Wang int 86*2de3b87aSKai Wang _dwarf_info_load(Dwarf_Debug dbg, int load_all, Dwarf_Error *error) 87*2de3b87aSKai Wang { 88*2de3b87aSKai Wang Dwarf_CU cu; 89*2de3b87aSKai Wang Dwarf_Section *ds; 90*2de3b87aSKai Wang int dwarf_size, ret; 91*2de3b87aSKai Wang uint64_t length; 92*2de3b87aSKai Wang uint64_t next_offset; 93*2de3b87aSKai Wang uint64_t offset; 94*2de3b87aSKai Wang 95*2de3b87aSKai Wang ret = DW_DLE_NONE; 96*2de3b87aSKai Wang if (dbg->dbg_info_loaded) 97*2de3b87aSKai Wang return (DW_DLE_NONE); 98*2de3b87aSKai Wang 99*2de3b87aSKai Wang offset = dbg->dbg_info_off; 100*2de3b87aSKai Wang ds = dbg->dbg_info_sec; 101*2de3b87aSKai Wang assert(ds != NULL); 102*2de3b87aSKai Wang while (offset < ds->ds_size) { 103*2de3b87aSKai Wang if ((cu = calloc(1, sizeof(struct _Dwarf_CU))) == NULL) { 104*2de3b87aSKai Wang DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 105*2de3b87aSKai Wang return (DW_DLE_MEMORY); 106*2de3b87aSKai Wang } 107*2de3b87aSKai Wang 108*2de3b87aSKai Wang cu->cu_dbg = dbg; 109*2de3b87aSKai Wang cu->cu_offset = offset; 110*2de3b87aSKai Wang 111*2de3b87aSKai Wang length = dbg->read(ds->ds_data, &offset, 4); 112*2de3b87aSKai Wang if (length == 0xffffffff) { 113*2de3b87aSKai Wang length = dbg->read(ds->ds_data, &offset, 8); 114*2de3b87aSKai Wang dwarf_size = 8; 115*2de3b87aSKai Wang } else 116*2de3b87aSKai Wang dwarf_size = 4; 117*2de3b87aSKai Wang cu->cu_dwarf_size = dwarf_size; 118*2de3b87aSKai Wang 119*2de3b87aSKai Wang /* 120*2de3b87aSKai Wang * Check if there is enough ELF data for this CU. This assumes 121*2de3b87aSKai Wang * that libelf gives us the entire section in one Elf_Data 122*2de3b87aSKai Wang * object. 123*2de3b87aSKai Wang */ 124*2de3b87aSKai Wang if (length > ds->ds_size - offset) { 125*2de3b87aSKai Wang free(cu); 126*2de3b87aSKai Wang DWARF_SET_ERROR(dbg, error, DW_DLE_CU_LENGTH_ERROR); 127*2de3b87aSKai Wang return (DW_DLE_CU_LENGTH_ERROR); 128*2de3b87aSKai Wang } 129*2de3b87aSKai Wang 130*2de3b87aSKai Wang /* Compute the offset to the next compilation unit: */ 131*2de3b87aSKai Wang next_offset = offset + length; 132*2de3b87aSKai Wang dbg->dbg_info_off = next_offset; 133*2de3b87aSKai Wang 134*2de3b87aSKai Wang /* Initialise the compilation unit. */ 135*2de3b87aSKai Wang cu->cu_length = length; 136*2de3b87aSKai Wang cu->cu_length_size = (dwarf_size == 4 ? 4 : 12); 137*2de3b87aSKai Wang cu->cu_version = dbg->read(ds->ds_data, &offset, 2); 138*2de3b87aSKai Wang cu->cu_abbrev_offset = dbg->read(ds->ds_data, &offset, 139*2de3b87aSKai Wang dwarf_size); 140*2de3b87aSKai Wang cu->cu_abbrev_offset_cur = cu->cu_abbrev_offset; 141*2de3b87aSKai Wang cu->cu_pointer_size = dbg->read(ds->ds_data, &offset, 1); 142*2de3b87aSKai Wang cu->cu_next_offset = next_offset; 143*2de3b87aSKai Wang 144*2de3b87aSKai Wang /* Add the compilation unit to the list. */ 145*2de3b87aSKai Wang STAILQ_INSERT_TAIL(&dbg->dbg_cu, cu, cu_next); 146*2de3b87aSKai Wang 147*2de3b87aSKai Wang if (cu->cu_version < 2 || cu->cu_version > 4) { 148*2de3b87aSKai Wang DWARF_SET_ERROR(dbg, error, DW_DLE_VERSION_STAMP_ERROR); 149*2de3b87aSKai Wang ret = DW_DLE_VERSION_STAMP_ERROR; 150*2de3b87aSKai Wang break; 151*2de3b87aSKai Wang } 152*2de3b87aSKai Wang 153*2de3b87aSKai Wang cu->cu_1st_offset = offset; 154*2de3b87aSKai Wang 155*2de3b87aSKai Wang offset = next_offset; 156*2de3b87aSKai Wang 157*2de3b87aSKai Wang if (!load_all) 158*2de3b87aSKai Wang break; 159*2de3b87aSKai Wang } 160*2de3b87aSKai Wang 161*2de3b87aSKai Wang if ((Dwarf_Unsigned) dbg->dbg_info_off >= ds->ds_size) 162*2de3b87aSKai Wang dbg->dbg_info_loaded = 1; 163*2de3b87aSKai Wang 164*2de3b87aSKai Wang return (ret); 165*2de3b87aSKai Wang } 166*2de3b87aSKai Wang 167*2de3b87aSKai Wang void 168*2de3b87aSKai Wang _dwarf_info_cleanup(Dwarf_Debug dbg) 169*2de3b87aSKai Wang { 170*2de3b87aSKai Wang Dwarf_CU cu, tcu; 171*2de3b87aSKai Wang 172*2de3b87aSKai Wang assert(dbg != NULL && dbg->dbg_mode == DW_DLC_READ); 173*2de3b87aSKai Wang 174*2de3b87aSKai Wang STAILQ_FOREACH_SAFE(cu, &dbg->dbg_cu, cu_next, tcu) { 175*2de3b87aSKai Wang STAILQ_REMOVE(&dbg->dbg_cu, cu, _Dwarf_CU, cu_next); 176*2de3b87aSKai Wang _dwarf_abbrev_cleanup(cu); 177*2de3b87aSKai Wang if (cu->cu_lineinfo != NULL) { 178*2de3b87aSKai Wang _dwarf_lineno_cleanup(cu->cu_lineinfo); 179*2de3b87aSKai Wang cu->cu_lineinfo = NULL; 180*2de3b87aSKai Wang } 181*2de3b87aSKai Wang free(cu); 182*2de3b87aSKai Wang } 183*2de3b87aSKai Wang } 184*2de3b87aSKai Wang 185*2de3b87aSKai Wang int 186*2de3b87aSKai Wang _dwarf_info_gen(Dwarf_P_Debug dbg, Dwarf_Error *error) 187*2de3b87aSKai Wang { 188*2de3b87aSKai Wang Dwarf_P_Section ds; 189*2de3b87aSKai Wang Dwarf_Rel_Section drs; 190*2de3b87aSKai Wang Dwarf_Unsigned offset; 191*2de3b87aSKai Wang Dwarf_CU cu; 192*2de3b87aSKai Wang int ret; 193*2de3b87aSKai Wang 194*2de3b87aSKai Wang assert(dbg != NULL && dbg->write_alloc != NULL); 195*2de3b87aSKai Wang 196*2de3b87aSKai Wang if (dbg->dbgp_root_die == NULL) 197*2de3b87aSKai Wang return (DW_DLE_NONE); 198*2de3b87aSKai Wang 199*2de3b87aSKai Wang /* Create the single CU for this debugging object. */ 200*2de3b87aSKai Wang if ((cu = calloc(1, sizeof(struct _Dwarf_CU))) == NULL) { 201*2de3b87aSKai Wang DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 202*2de3b87aSKai Wang return (DW_DLE_MEMORY); 203*2de3b87aSKai Wang } 204*2de3b87aSKai Wang cu->cu_dbg = dbg; 205*2de3b87aSKai Wang cu->cu_version = 2; /* DWARF2 */ 206*2de3b87aSKai Wang cu->cu_pointer_size = dbg->dbg_pointer_size; 207*2de3b87aSKai Wang STAILQ_INSERT_TAIL(&dbg->dbg_cu, cu, cu_next); 208*2de3b87aSKai Wang 209*2de3b87aSKai Wang /* Create .debug_info section. */ 210*2de3b87aSKai Wang if ((ret = _dwarf_section_init(dbg, &dbg->dbgp_info, ".debug_info", 0, 211*2de3b87aSKai Wang error)) != DW_DLE_NONE) 212*2de3b87aSKai Wang goto gen_fail1; 213*2de3b87aSKai Wang ds = dbg->dbgp_info; 214*2de3b87aSKai Wang 215*2de3b87aSKai Wang /* Create relocation section for .debug_init */ 216*2de3b87aSKai Wang if ((ret = _dwarf_reloc_section_init(dbg, &drs, ds, error)) != 217*2de3b87aSKai Wang DW_DLE_NONE) 218*2de3b87aSKai Wang goto gen_fail0; 219*2de3b87aSKai Wang 220*2de3b87aSKai Wang /* Length placeholder. (We only use 32-bit DWARF format) */ 221*2de3b87aSKai Wang RCHECK(WRITE_VALUE(cu->cu_length, 4)); 222*2de3b87aSKai Wang 223*2de3b87aSKai Wang /* Write CU version */ 224*2de3b87aSKai Wang RCHECK(WRITE_VALUE(cu->cu_version, 2)); 225*2de3b87aSKai Wang 226*2de3b87aSKai Wang /* 227*2de3b87aSKai Wang * Write abbrev offset. (always 0, we only support single CU) 228*2de3b87aSKai Wang * Also generate a relocation entry for this offset. 229*2de3b87aSKai Wang */ 230*2de3b87aSKai Wang RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc, 4, 231*2de3b87aSKai Wang ds->ds_size, 0, cu->cu_abbrev_offset, ".debug_abbrev", error)); 232*2de3b87aSKai Wang 233*2de3b87aSKai Wang /* Pointer size. */ 234*2de3b87aSKai Wang RCHECK(WRITE_VALUE(cu->cu_pointer_size, 1)); 235*2de3b87aSKai Wang 236*2de3b87aSKai Wang /* Transform the DIE(s) of this CU. */ 237*2de3b87aSKai Wang RCHECK(_dwarf_die_gen(dbg, cu, drs, error)); 238*2de3b87aSKai Wang 239*2de3b87aSKai Wang /* Now we can fill in the length of this CU. */ 240*2de3b87aSKai Wang cu->cu_length = ds->ds_size - 4; 241*2de3b87aSKai Wang offset = 0; 242*2de3b87aSKai Wang dbg->write(ds->ds_data, &offset, cu->cu_length, 4); 243*2de3b87aSKai Wang 244*2de3b87aSKai Wang /* Inform application the creation of .debug_info ELF section. */ 245*2de3b87aSKai Wang RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error)); 246*2de3b87aSKai Wang 247*2de3b87aSKai Wang /* 248*2de3b87aSKai Wang * Inform application the creation of relocation section for 249*2de3b87aSKai Wang * .debug_info. 250*2de3b87aSKai Wang */ 251*2de3b87aSKai Wang RCHECK(_dwarf_reloc_section_finalize(dbg, drs, error)); 252*2de3b87aSKai Wang 253*2de3b87aSKai Wang return (DW_DLE_NONE); 254*2de3b87aSKai Wang 255*2de3b87aSKai Wang gen_fail: 256*2de3b87aSKai Wang _dwarf_reloc_section_free(dbg, &drs); 257*2de3b87aSKai Wang 258*2de3b87aSKai Wang gen_fail0: 259*2de3b87aSKai Wang _dwarf_section_free(dbg, &dbg->dbgp_info); 260*2de3b87aSKai Wang 261*2de3b87aSKai Wang gen_fail1: 262*2de3b87aSKai Wang STAILQ_REMOVE(&dbg->dbg_cu, cu, _Dwarf_CU, cu_next); 263*2de3b87aSKai Wang free(cu); 264*2de3b87aSKai Wang 265*2de3b87aSKai Wang return (ret); 266*2de3b87aSKai Wang } 267*2de3b87aSKai Wang 268*2de3b87aSKai Wang void 269*2de3b87aSKai Wang _dwarf_info_pro_cleanup(Dwarf_P_Debug dbg) 270*2de3b87aSKai Wang { 271*2de3b87aSKai Wang Dwarf_CU cu; 272*2de3b87aSKai Wang 273*2de3b87aSKai Wang assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE); 274*2de3b87aSKai Wang 275*2de3b87aSKai Wang cu = STAILQ_FIRST(&dbg->dbg_cu); 276*2de3b87aSKai Wang if (cu != NULL) { 277*2de3b87aSKai Wang STAILQ_REMOVE(&dbg->dbg_cu, cu, _Dwarf_CU, cu_next); 278*2de3b87aSKai Wang _dwarf_abbrev_cleanup(cu); 279*2de3b87aSKai Wang free(cu); 280*2de3b87aSKai Wang } 281*2de3b87aSKai Wang } 282