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 30300311SemasteELFTC_VCSID("$Id: libdwarf_abbrev.c 3420 2016-02-27 02:14:05Z emaste $"); 31260684Skaiw 32260684Skaiwint 33260684Skaiw_dwarf_abbrev_add(Dwarf_CU cu, uint64_t entry, uint64_t tag, uint8_t children, 34260684Skaiw uint64_t aboff, Dwarf_Abbrev *abp, Dwarf_Error *error) 35260684Skaiw{ 36260684Skaiw Dwarf_Abbrev ab; 37260684Skaiw Dwarf_Debug dbg; 38260684Skaiw 39260684Skaiw dbg = cu != NULL ? cu->cu_dbg : NULL; 40260684Skaiw 41260684Skaiw if ((ab = malloc(sizeof(struct _Dwarf_Abbrev))) == NULL) { 42260684Skaiw DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 43260684Skaiw return (DW_DLE_MEMORY); 44260684Skaiw } 45260684Skaiw 46260684Skaiw /* Initialise the abbrev structure. */ 47260684Skaiw ab->ab_entry = entry; 48260684Skaiw ab->ab_tag = tag; 49260684Skaiw ab->ab_children = children; 50260684Skaiw ab->ab_offset = aboff; 51260684Skaiw ab->ab_length = 0; /* fill in later. */ 52260684Skaiw ab->ab_atnum = 0; /* fill in later. */ 53260684Skaiw 54260684Skaiw /* Initialise the list of attribute definitions. */ 55260684Skaiw STAILQ_INIT(&ab->ab_attrdef); 56260684Skaiw 57260684Skaiw /* Add the abbrev to the hash table of the compilation unit. */ 58260684Skaiw if (cu != NULL) 59260684Skaiw HASH_ADD(ab_hh, cu->cu_abbrev_hash, ab_entry, 60260684Skaiw sizeof(ab->ab_entry), ab); 61260684Skaiw 62367466Sdim *abp = ab; 63260684Skaiw return (DW_DLE_NONE); 64260684Skaiw} 65260684Skaiw 66260684Skaiwint 67260684Skaiw_dwarf_attrdef_add(Dwarf_Debug dbg, Dwarf_Abbrev ab, uint64_t attr, 68260684Skaiw uint64_t form, uint64_t adoff, Dwarf_AttrDef *adp, Dwarf_Error *error) 69260684Skaiw{ 70260684Skaiw Dwarf_AttrDef ad; 71260684Skaiw 72260684Skaiw if (ab == NULL) { 73260684Skaiw DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 74260684Skaiw return (DW_DLE_ARGUMENT); 75260684Skaiw } 76260684Skaiw 77260684Skaiw if ((ad = malloc(sizeof(struct _Dwarf_AttrDef))) == NULL) { 78260684Skaiw DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 79260684Skaiw return (DW_DLE_MEMORY); 80260684Skaiw } 81260684Skaiw 82260684Skaiw /* Initialise the attribute definition structure. */ 83260684Skaiw ad->ad_attrib = attr; 84260684Skaiw ad->ad_form = form; 85260684Skaiw ad->ad_offset = adoff; 86260684Skaiw 87260684Skaiw /* Add the attribute definition to the list in the abbrev. */ 88260684Skaiw STAILQ_INSERT_TAIL(&ab->ab_attrdef, ad, ad_next); 89260684Skaiw 90260684Skaiw /* Increase number of attribute counter. */ 91260684Skaiw ab->ab_atnum++; 92260684Skaiw 93260684Skaiw if (adp != NULL) 94260684Skaiw *adp = ad; 95260684Skaiw 96260684Skaiw return (DW_DLE_NONE); 97260684Skaiw} 98260684Skaiw 99260684Skaiwint 100260684Skaiw_dwarf_abbrev_parse(Dwarf_Debug dbg, Dwarf_CU cu, Dwarf_Unsigned *offset, 101260684Skaiw Dwarf_Abbrev *abp, Dwarf_Error *error) 102260684Skaiw{ 103260684Skaiw Dwarf_Section *ds; 104260684Skaiw uint64_t attr; 105260684Skaiw uint64_t entry; 106260684Skaiw uint64_t form; 107260684Skaiw uint64_t aboff; 108260684Skaiw uint64_t adoff; 109260684Skaiw uint64_t tag; 110260684Skaiw uint8_t children; 111260684Skaiw int ret; 112260684Skaiw 113260684Skaiw assert(abp != NULL); 114260684Skaiw 115260684Skaiw ds = _dwarf_find_section(dbg, ".debug_abbrev"); 116300311Semaste if (ds == NULL || *offset >= ds->ds_size) 117260684Skaiw return (DW_DLE_NO_ENTRY); 118260684Skaiw 119260684Skaiw aboff = *offset; 120260684Skaiw 121260684Skaiw entry = _dwarf_read_uleb128(ds->ds_data, offset); 122260684Skaiw if (entry == 0) { 123260684Skaiw /* Last entry. */ 124260684Skaiw ret = _dwarf_abbrev_add(cu, entry, 0, 0, aboff, abp, 125260684Skaiw error); 126260684Skaiw if (ret == DW_DLE_NONE) { 127260684Skaiw (*abp)->ab_length = 1; 128260684Skaiw return (ret); 129260684Skaiw } else 130260684Skaiw return (ret); 131260684Skaiw } 132260684Skaiw tag = _dwarf_read_uleb128(ds->ds_data, offset); 133260684Skaiw children = dbg->read(ds->ds_data, offset, 1); 134260684Skaiw if ((ret = _dwarf_abbrev_add(cu, entry, tag, children, aboff, 135260684Skaiw abp, error)) != DW_DLE_NONE) 136260684Skaiw return (ret); 137260684Skaiw 138260684Skaiw /* Parse attribute definitions. */ 139260684Skaiw do { 140260684Skaiw adoff = *offset; 141260684Skaiw attr = _dwarf_read_uleb128(ds->ds_data, offset); 142260684Skaiw form = _dwarf_read_uleb128(ds->ds_data, offset); 143260684Skaiw if (attr != 0) 144260684Skaiw if ((ret = _dwarf_attrdef_add(dbg, *abp, attr, 145260684Skaiw form, adoff, NULL, error)) != DW_DLE_NONE) 146260684Skaiw return (ret); 147260684Skaiw } while (attr != 0); 148260684Skaiw 149260684Skaiw (*abp)->ab_length = *offset - aboff; 150260684Skaiw 151260684Skaiw return (ret); 152260684Skaiw} 153260684Skaiw 154260684Skaiwint 155260684Skaiw_dwarf_abbrev_find(Dwarf_CU cu, uint64_t entry, Dwarf_Abbrev *abp, 156260684Skaiw Dwarf_Error *error) 157260684Skaiw{ 158260684Skaiw Dwarf_Abbrev ab; 159260684Skaiw Dwarf_Section *ds; 160260684Skaiw Dwarf_Unsigned offset; 161260684Skaiw int ret; 162260684Skaiw 163260684Skaiw if (entry == 0) 164260684Skaiw return (DW_DLE_NO_ENTRY); 165260684Skaiw 166260684Skaiw /* Check if the desired abbrev entry is already in the hash table. */ 167260684Skaiw HASH_FIND(ab_hh, cu->cu_abbrev_hash, &entry, sizeof(entry), ab); 168260684Skaiw if (ab != NULL) { 169260684Skaiw *abp = ab; 170260684Skaiw return (DW_DLE_NONE); 171260684Skaiw } 172260684Skaiw 173260684Skaiw if (cu->cu_abbrev_loaded) { 174260684Skaiw return (DW_DLE_NO_ENTRY); 175260684Skaiw } 176260684Skaiw 177260684Skaiw /* Load and search the abbrev table. */ 178260684Skaiw ds = _dwarf_find_section(cu->cu_dbg, ".debug_abbrev"); 179276398Semaste if (ds == NULL) 180276398Semaste return (DW_DLE_NO_ENTRY); 181276398Semaste 182260684Skaiw offset = cu->cu_abbrev_offset_cur; 183260684Skaiw while (offset < ds->ds_size) { 184260684Skaiw ret = _dwarf_abbrev_parse(cu->cu_dbg, cu, &offset, &ab, error); 185260684Skaiw if (ret != DW_DLE_NONE) 186260684Skaiw return (ret); 187260684Skaiw if (ab->ab_entry == entry) { 188260684Skaiw cu->cu_abbrev_offset_cur = offset; 189260684Skaiw *abp = ab; 190260684Skaiw return (DW_DLE_NONE); 191260684Skaiw } 192260684Skaiw if (ab->ab_entry == 0) { 193260684Skaiw cu->cu_abbrev_offset_cur = offset; 194260684Skaiw cu->cu_abbrev_loaded = 1; 195260684Skaiw break; 196260684Skaiw } 197260684Skaiw } 198260684Skaiw 199260684Skaiw return (DW_DLE_NO_ENTRY); 200260684Skaiw} 201260684Skaiw 202260684Skaiwvoid 203260684Skaiw_dwarf_abbrev_cleanup(Dwarf_CU cu) 204260684Skaiw{ 205260684Skaiw Dwarf_Abbrev ab, tab; 206260684Skaiw Dwarf_AttrDef ad, tad; 207260684Skaiw 208260684Skaiw assert(cu != NULL); 209260684Skaiw 210260684Skaiw HASH_ITER(ab_hh, cu->cu_abbrev_hash, ab, tab) { 211260684Skaiw HASH_DELETE(ab_hh, cu->cu_abbrev_hash, ab); 212260684Skaiw STAILQ_FOREACH_SAFE(ad, &ab->ab_attrdef, ad_next, tad) { 213260684Skaiw STAILQ_REMOVE(&ab->ab_attrdef, ad, _Dwarf_AttrDef, 214260684Skaiw ad_next); 215260684Skaiw free(ad); 216260684Skaiw } 217260684Skaiw free(ab); 218260684Skaiw } 219260684Skaiw} 220260684Skaiw 221260684Skaiwint 222260684Skaiw_dwarf_abbrev_gen(Dwarf_P_Debug dbg, Dwarf_Error *error) 223260684Skaiw{ 224260684Skaiw Dwarf_CU cu; 225260684Skaiw Dwarf_Abbrev ab; 226260684Skaiw Dwarf_AttrDef ad; 227260684Skaiw Dwarf_P_Section ds; 228260684Skaiw int ret; 229260684Skaiw 230260684Skaiw cu = STAILQ_FIRST(&dbg->dbg_cu); 231260684Skaiw if (cu == NULL) 232260684Skaiw return (DW_DLE_NONE); 233260684Skaiw 234260684Skaiw /* Create .debug_abbrev section. */ 235260684Skaiw if ((ret = _dwarf_section_init(dbg, &ds, ".debug_abbrev", 0, error)) != 236260684Skaiw DW_DLE_NONE) 237260684Skaiw return (ret); 238260684Skaiw 239260684Skaiw for (ab = cu->cu_abbrev_hash; ab != NULL; ab = ab->ab_hh.next) { 240260684Skaiw RCHECK(WRITE_ULEB128(ab->ab_entry)); 241260684Skaiw RCHECK(WRITE_ULEB128(ab->ab_tag)); 242260684Skaiw RCHECK(WRITE_VALUE(ab->ab_children, 1)); 243260684Skaiw STAILQ_FOREACH(ad, &ab->ab_attrdef, ad_next) { 244260684Skaiw RCHECK(WRITE_ULEB128(ad->ad_attrib)); 245260684Skaiw RCHECK(WRITE_ULEB128(ad->ad_form)); 246260684Skaiw } 247260684Skaiw /* Signal end of attribute spec list. */ 248260684Skaiw RCHECK(WRITE_ULEB128(0)); 249260684Skaiw RCHECK(WRITE_ULEB128(0)); 250260684Skaiw } 251260684Skaiw /* End of abbreviation for this CU. */ 252260684Skaiw RCHECK(WRITE_ULEB128(0)); 253260684Skaiw 254260684Skaiw /* Notify the creation of .debug_abbrev ELF section. */ 255260684Skaiw RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error)); 256260684Skaiw 257260684Skaiw return (DW_DLE_NONE); 258260684Skaiw 259260684Skaiwgen_fail: 260260684Skaiw 261260684Skaiw _dwarf_section_free(dbg, &ds); 262260684Skaiw 263260684Skaiw return (ret); 264260684Skaiw} 265