libdwarf_info.c revision 276398
1260684Skaiw/*- 2260684Skaiw * Copyright (c) 2007 John Birrell (jb@freebsd.org) 3276371Semaste * Copyright (c) 2010,2011,2014 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 30276398SemasteELFTC_VCSID("$Id: libdwarf_info.c 3136 2014-12-24 16:04:38Z kaiwang27 $"); 31260684Skaiw 32260684Skaiwint 33260684Skaiw_dwarf_info_first_cu(Dwarf_Debug dbg, Dwarf_Error *error) 34260684Skaiw{ 35260684Skaiw Dwarf_CU cu; 36260684Skaiw int ret; 37260684Skaiw 38260684Skaiw assert(dbg->dbg_cu_current == NULL); 39260684Skaiw cu = STAILQ_FIRST(&dbg->dbg_cu); 40260684Skaiw if (cu != NULL) { 41260684Skaiw dbg->dbg_cu_current = cu; 42260684Skaiw return (DW_DLE_NONE); 43260684Skaiw } 44260684Skaiw 45260684Skaiw if (dbg->dbg_info_loaded) 46260684Skaiw return (DW_DLE_NO_ENTRY); 47260684Skaiw 48260684Skaiw dbg->dbg_info_off = 0; 49276371Semaste ret = _dwarf_info_load(dbg, 0, 1, error); 50260684Skaiw if (ret != DW_DLE_NONE) 51260684Skaiw return (ret); 52260684Skaiw 53260684Skaiw dbg->dbg_cu_current = STAILQ_FIRST(&dbg->dbg_cu); 54260684Skaiw 55260684Skaiw return (DW_DLE_NONE); 56260684Skaiw} 57260684Skaiw 58260684Skaiwint 59276371Semaste_dwarf_info_first_tu(Dwarf_Debug dbg, Dwarf_Error *error) 60276371Semaste{ 61276371Semaste Dwarf_CU tu; 62276371Semaste int ret; 63276371Semaste 64276371Semaste assert(dbg->dbg_tu_current == NULL); 65276371Semaste tu = STAILQ_FIRST(&dbg->dbg_tu); 66276371Semaste if (tu != NULL) { 67276371Semaste dbg->dbg_tu_current = tu; 68276371Semaste return (DW_DLE_NONE); 69276371Semaste } 70276371Semaste 71276371Semaste if (dbg->dbg_types_loaded) 72276371Semaste return (DW_DLE_NO_ENTRY); 73276371Semaste 74276371Semaste dbg->dbg_types_off = 0; 75276371Semaste ret = _dwarf_info_load(dbg, 0, 0, error); 76276371Semaste if (ret != DW_DLE_NONE) 77276371Semaste return (ret); 78276371Semaste 79276371Semaste dbg->dbg_tu_current = STAILQ_FIRST(&dbg->dbg_tu); 80276371Semaste 81276371Semaste return (DW_DLE_NONE); 82276371Semaste} 83276371Semaste 84276371Semasteint 85260684Skaiw_dwarf_info_next_cu(Dwarf_Debug dbg, Dwarf_Error *error) 86260684Skaiw{ 87260684Skaiw Dwarf_CU cu; 88260684Skaiw int ret; 89260684Skaiw 90260684Skaiw assert(dbg->dbg_cu_current != NULL); 91260684Skaiw cu = STAILQ_NEXT(dbg->dbg_cu_current, cu_next); 92260684Skaiw if (cu != NULL) { 93260684Skaiw dbg->dbg_cu_current = cu; 94260684Skaiw return (DW_DLE_NONE); 95260684Skaiw } 96260684Skaiw 97260684Skaiw if (dbg->dbg_info_loaded) { 98260684Skaiw dbg->dbg_cu_current = NULL; 99260684Skaiw return (DW_DLE_NO_ENTRY); 100260684Skaiw } 101260684Skaiw 102276371Semaste ret = _dwarf_info_load(dbg, 0, 1, error); 103260684Skaiw if (ret != DW_DLE_NONE) 104260684Skaiw return (ret); 105260684Skaiw 106260684Skaiw dbg->dbg_cu_current = STAILQ_NEXT(dbg->dbg_cu_current, cu_next); 107260684Skaiw 108260684Skaiw return (DW_DLE_NONE); 109260684Skaiw} 110260684Skaiw 111260684Skaiwint 112276371Semaste_dwarf_info_next_tu(Dwarf_Debug dbg, Dwarf_Error *error) 113260684Skaiw{ 114260684Skaiw Dwarf_CU cu; 115276371Semaste int ret; 116276371Semaste 117276371Semaste assert(dbg->dbg_tu_current != NULL); 118276371Semaste cu = STAILQ_NEXT(dbg->dbg_tu_current, cu_next); 119276371Semaste if (cu != NULL) { 120276371Semaste dbg->dbg_tu_current = cu; 121276371Semaste return (DW_DLE_NONE); 122276371Semaste } 123276371Semaste 124276371Semaste if (dbg->dbg_types_loaded) { 125276371Semaste dbg->dbg_tu_current = NULL; 126276371Semaste return (DW_DLE_NO_ENTRY); 127276371Semaste } 128276371Semaste 129276371Semaste ret = _dwarf_info_load(dbg, 0, 0, error); 130276371Semaste if (ret != DW_DLE_NONE) 131276371Semaste return (ret); 132276371Semaste 133276371Semaste dbg->dbg_tu_current = STAILQ_NEXT(dbg->dbg_tu_current, cu_next); 134276371Semaste 135276371Semaste return (DW_DLE_NONE); 136276371Semaste} 137276371Semaste 138276371Semasteint 139276371Semaste_dwarf_info_load(Dwarf_Debug dbg, Dwarf_Bool load_all, Dwarf_Bool is_info, 140276371Semaste Dwarf_Error *error) 141276371Semaste{ 142276371Semaste Dwarf_CU cu; 143260684Skaiw Dwarf_Section *ds; 144260684Skaiw int dwarf_size, ret; 145260684Skaiw uint64_t length; 146260684Skaiw uint64_t next_offset; 147260684Skaiw uint64_t offset; 148260684Skaiw 149260684Skaiw ret = DW_DLE_NONE; 150260684Skaiw 151276371Semaste if (is_info) { 152276371Semaste if (dbg->dbg_info_loaded) 153276371Semaste return (ret); 154276371Semaste offset = dbg->dbg_info_off; 155276371Semaste ds = dbg->dbg_info_sec; 156276398Semaste if (ds == NULL) 157276398Semaste return (DW_DLE_NO_ENTRY); 158276371Semaste } else { 159276371Semaste if (dbg->dbg_types_loaded) 160276371Semaste return (ret); 161276371Semaste offset = dbg->dbg_types_off; 162276371Semaste ds = dbg->dbg_types_sec; 163276371Semaste if (ds == NULL) 164276371Semaste return (DW_DLE_NO_ENTRY); 165276371Semaste } 166276371Semaste 167260684Skaiw while (offset < ds->ds_size) { 168260684Skaiw if ((cu = calloc(1, sizeof(struct _Dwarf_CU))) == NULL) { 169260684Skaiw DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 170260684Skaiw return (DW_DLE_MEMORY); 171260684Skaiw } 172260684Skaiw 173260684Skaiw cu->cu_dbg = dbg; 174276371Semaste cu->cu_is_info = is_info; 175260684Skaiw cu->cu_offset = offset; 176260684Skaiw 177260684Skaiw length = dbg->read(ds->ds_data, &offset, 4); 178260684Skaiw if (length == 0xffffffff) { 179260684Skaiw length = dbg->read(ds->ds_data, &offset, 8); 180260684Skaiw dwarf_size = 8; 181260684Skaiw } else 182260684Skaiw dwarf_size = 4; 183260684Skaiw cu->cu_dwarf_size = dwarf_size; 184260684Skaiw 185260684Skaiw /* 186260684Skaiw * Check if there is enough ELF data for this CU. This assumes 187260684Skaiw * that libelf gives us the entire section in one Elf_Data 188260684Skaiw * object. 189260684Skaiw */ 190260684Skaiw if (length > ds->ds_size - offset) { 191260684Skaiw free(cu); 192260684Skaiw DWARF_SET_ERROR(dbg, error, DW_DLE_CU_LENGTH_ERROR); 193260684Skaiw return (DW_DLE_CU_LENGTH_ERROR); 194260684Skaiw } 195260684Skaiw 196260684Skaiw /* Compute the offset to the next compilation unit: */ 197260684Skaiw next_offset = offset + length; 198276371Semaste if (is_info) 199276371Semaste dbg->dbg_info_off = next_offset; 200276371Semaste else 201276371Semaste dbg->dbg_types_off = next_offset; 202260684Skaiw 203260684Skaiw /* Initialise the compilation unit. */ 204260684Skaiw cu->cu_length = length; 205260684Skaiw cu->cu_length_size = (dwarf_size == 4 ? 4 : 12); 206260684Skaiw cu->cu_version = dbg->read(ds->ds_data, &offset, 2); 207260684Skaiw cu->cu_abbrev_offset = dbg->read(ds->ds_data, &offset, 208260684Skaiw dwarf_size); 209260684Skaiw cu->cu_abbrev_offset_cur = cu->cu_abbrev_offset; 210260684Skaiw cu->cu_pointer_size = dbg->read(ds->ds_data, &offset, 1); 211260684Skaiw cu->cu_next_offset = next_offset; 212260684Skaiw 213276371Semaste /* .debug_types extra fields. */ 214276371Semaste if (!is_info) { 215276371Semaste memcpy(cu->cu_type_sig.signature, 216276371Semaste (char *) ds->ds_data + offset, 8); 217276371Semaste offset += 8; 218276371Semaste cu->cu_type_offset = dbg->read(ds->ds_data, &offset, 219276371Semaste dwarf_size); 220276371Semaste } 221276371Semaste 222260684Skaiw /* Add the compilation unit to the list. */ 223276371Semaste if (is_info) 224276371Semaste STAILQ_INSERT_TAIL(&dbg->dbg_cu, cu, cu_next); 225276371Semaste else 226276371Semaste STAILQ_INSERT_TAIL(&dbg->dbg_tu, cu, cu_next); 227260684Skaiw 228260684Skaiw if (cu->cu_version < 2 || cu->cu_version > 4) { 229260684Skaiw DWARF_SET_ERROR(dbg, error, DW_DLE_VERSION_STAMP_ERROR); 230260684Skaiw ret = DW_DLE_VERSION_STAMP_ERROR; 231260684Skaiw break; 232260684Skaiw } 233260684Skaiw 234260684Skaiw cu->cu_1st_offset = offset; 235260684Skaiw 236260684Skaiw offset = next_offset; 237260684Skaiw 238260684Skaiw if (!load_all) 239260684Skaiw break; 240260684Skaiw } 241260684Skaiw 242276371Semaste if (is_info) { 243276371Semaste if ((Dwarf_Unsigned) dbg->dbg_info_off >= ds->ds_size) 244276371Semaste dbg->dbg_info_loaded = 1; 245276371Semaste } else { 246276371Semaste if ((Dwarf_Unsigned) dbg->dbg_types_off >= ds->ds_size) 247276371Semaste dbg->dbg_types_loaded = 1; 248276371Semaste } 249260684Skaiw 250260684Skaiw return (ret); 251260684Skaiw} 252260684Skaiw 253260684Skaiwvoid 254260684Skaiw_dwarf_info_cleanup(Dwarf_Debug dbg) 255260684Skaiw{ 256260684Skaiw Dwarf_CU cu, tcu; 257260684Skaiw 258260684Skaiw assert(dbg != NULL && dbg->dbg_mode == DW_DLC_READ); 259260684Skaiw 260260684Skaiw STAILQ_FOREACH_SAFE(cu, &dbg->dbg_cu, cu_next, tcu) { 261260684Skaiw STAILQ_REMOVE(&dbg->dbg_cu, cu, _Dwarf_CU, cu_next); 262260684Skaiw _dwarf_abbrev_cleanup(cu); 263260684Skaiw if (cu->cu_lineinfo != NULL) { 264260684Skaiw _dwarf_lineno_cleanup(cu->cu_lineinfo); 265260684Skaiw cu->cu_lineinfo = NULL; 266260684Skaiw } 267260684Skaiw free(cu); 268260684Skaiw } 269276371Semaste 270276371Semaste _dwarf_type_unit_cleanup(dbg); 271260684Skaiw} 272260684Skaiw 273276371Semastevoid 274276371Semaste_dwarf_type_unit_cleanup(Dwarf_Debug dbg) 275276371Semaste{ 276276371Semaste Dwarf_CU cu, tcu; 277276371Semaste 278276371Semaste assert(dbg != NULL && dbg->dbg_mode == DW_DLC_READ); 279276371Semaste 280276371Semaste STAILQ_FOREACH_SAFE(cu, &dbg->dbg_tu, cu_next, tcu) { 281276371Semaste STAILQ_REMOVE(&dbg->dbg_tu, cu, _Dwarf_CU, cu_next); 282276371Semaste _dwarf_abbrev_cleanup(cu); 283276371Semaste free(cu); 284276371Semaste } 285276371Semaste} 286276371Semaste 287260684Skaiwint 288260684Skaiw_dwarf_info_gen(Dwarf_P_Debug dbg, Dwarf_Error *error) 289260684Skaiw{ 290260684Skaiw Dwarf_P_Section ds; 291260684Skaiw Dwarf_Rel_Section drs; 292260684Skaiw Dwarf_Unsigned offset; 293260684Skaiw Dwarf_CU cu; 294260684Skaiw int ret; 295260684Skaiw 296260684Skaiw assert(dbg != NULL && dbg->write_alloc != NULL); 297260684Skaiw 298260684Skaiw if (dbg->dbgp_root_die == NULL) 299260684Skaiw return (DW_DLE_NONE); 300260684Skaiw 301260684Skaiw /* Create the single CU for this debugging object. */ 302260684Skaiw if ((cu = calloc(1, sizeof(struct _Dwarf_CU))) == NULL) { 303260684Skaiw DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 304260684Skaiw return (DW_DLE_MEMORY); 305260684Skaiw } 306260684Skaiw cu->cu_dbg = dbg; 307260684Skaiw cu->cu_version = 2; /* DWARF2 */ 308260684Skaiw cu->cu_pointer_size = dbg->dbg_pointer_size; 309260684Skaiw STAILQ_INSERT_TAIL(&dbg->dbg_cu, cu, cu_next); 310260684Skaiw 311260684Skaiw /* Create .debug_info section. */ 312260684Skaiw if ((ret = _dwarf_section_init(dbg, &dbg->dbgp_info, ".debug_info", 0, 313260684Skaiw error)) != DW_DLE_NONE) 314260684Skaiw goto gen_fail1; 315260684Skaiw ds = dbg->dbgp_info; 316260684Skaiw 317260684Skaiw /* Create relocation section for .debug_init */ 318260684Skaiw if ((ret = _dwarf_reloc_section_init(dbg, &drs, ds, error)) != 319260684Skaiw DW_DLE_NONE) 320260684Skaiw goto gen_fail0; 321260684Skaiw 322260684Skaiw /* Length placeholder. (We only use 32-bit DWARF format) */ 323260684Skaiw RCHECK(WRITE_VALUE(cu->cu_length, 4)); 324260684Skaiw 325260684Skaiw /* Write CU version */ 326260684Skaiw RCHECK(WRITE_VALUE(cu->cu_version, 2)); 327260684Skaiw 328260684Skaiw /* 329260684Skaiw * Write abbrev offset. (always 0, we only support single CU) 330260684Skaiw * Also generate a relocation entry for this offset. 331260684Skaiw */ 332260684Skaiw RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc, 4, 333260684Skaiw ds->ds_size, 0, cu->cu_abbrev_offset, ".debug_abbrev", error)); 334260684Skaiw 335260684Skaiw /* Pointer size. */ 336260684Skaiw RCHECK(WRITE_VALUE(cu->cu_pointer_size, 1)); 337260684Skaiw 338260684Skaiw /* Transform the DIE(s) of this CU. */ 339260684Skaiw RCHECK(_dwarf_die_gen(dbg, cu, drs, error)); 340260684Skaiw 341260684Skaiw /* Now we can fill in the length of this CU. */ 342260684Skaiw cu->cu_length = ds->ds_size - 4; 343260684Skaiw offset = 0; 344260684Skaiw dbg->write(ds->ds_data, &offset, cu->cu_length, 4); 345260684Skaiw 346260684Skaiw /* Inform application the creation of .debug_info ELF section. */ 347260684Skaiw RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error)); 348260684Skaiw 349260684Skaiw /* 350260684Skaiw * Inform application the creation of relocation section for 351260684Skaiw * .debug_info. 352260684Skaiw */ 353260684Skaiw RCHECK(_dwarf_reloc_section_finalize(dbg, drs, error)); 354260684Skaiw 355260684Skaiw return (DW_DLE_NONE); 356260684Skaiw 357260684Skaiwgen_fail: 358260684Skaiw _dwarf_reloc_section_free(dbg, &drs); 359260684Skaiw 360260684Skaiwgen_fail0: 361260684Skaiw _dwarf_section_free(dbg, &dbg->dbgp_info); 362260684Skaiw 363260684Skaiwgen_fail1: 364260684Skaiw STAILQ_REMOVE(&dbg->dbg_cu, cu, _Dwarf_CU, cu_next); 365260684Skaiw free(cu); 366260684Skaiw 367260684Skaiw return (ret); 368260684Skaiw} 369260684Skaiw 370260684Skaiwvoid 371260684Skaiw_dwarf_info_pro_cleanup(Dwarf_P_Debug dbg) 372260684Skaiw{ 373260684Skaiw Dwarf_CU cu; 374260684Skaiw 375260684Skaiw assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE); 376260684Skaiw 377260684Skaiw cu = STAILQ_FIRST(&dbg->dbg_cu); 378260684Skaiw if (cu != NULL) { 379260684Skaiw STAILQ_REMOVE(&dbg->dbg_cu, cu, _Dwarf_CU, cu_next); 380260684Skaiw _dwarf_abbrev_cleanup(cu); 381260684Skaiw free(cu); 382260684Skaiw } 383260684Skaiw} 384