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