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 3136 2014-12-24 16:04:38Z kaiwang27 $"); 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 assert(ds != NULL); 119 120 if (*offset >= ds->ds_size) 121 return (DW_DLE_NO_ENTRY); 122 123 aboff = *offset; 124 125 entry = _dwarf_read_uleb128(ds->ds_data, offset); 126 if (entry == 0) { 127 /* Last entry. */ 128 ret = _dwarf_abbrev_add(cu, entry, 0, 0, aboff, abp, 129 error); 130 if (ret == DW_DLE_NONE) { 131 (*abp)->ab_length = 1; 132 return (ret); 133 } else 134 return (ret); 135 } 136 tag = _dwarf_read_uleb128(ds->ds_data, offset); 137 children = dbg->read(ds->ds_data, offset, 1); 138 if ((ret = _dwarf_abbrev_add(cu, entry, tag, children, aboff, 139 abp, error)) != DW_DLE_NONE) 140 return (ret); 141 142 /* Parse attribute definitions. */ 143 do { 144 adoff = *offset; 145 attr = _dwarf_read_uleb128(ds->ds_data, offset); 146 form = _dwarf_read_uleb128(ds->ds_data, offset); 147 if (attr != 0) 148 if ((ret = _dwarf_attrdef_add(dbg, *abp, attr, 149 form, adoff, NULL, error)) != DW_DLE_NONE) 150 return (ret); 151 } while (attr != 0); 152 153 (*abp)->ab_length = *offset - aboff; 154 155 return (ret); 156 } 157 158 int 159 _dwarf_abbrev_find(Dwarf_CU cu, uint64_t entry, Dwarf_Abbrev *abp, 160 Dwarf_Error *error) 161 { 162 Dwarf_Abbrev ab; 163 Dwarf_Section *ds; 164 Dwarf_Unsigned offset; 165 int ret; 166 167 if (entry == 0) 168 return (DW_DLE_NO_ENTRY); 169 170 /* Check if the desired abbrev entry is already in the hash table. */ 171 HASH_FIND(ab_hh, cu->cu_abbrev_hash, &entry, sizeof(entry), ab); 172 if (ab != NULL) { 173 *abp = ab; 174 return (DW_DLE_NONE); 175 } 176 177 if (cu->cu_abbrev_loaded) { 178 return (DW_DLE_NO_ENTRY); 179 } 180 181 /* Load and search the abbrev table. */ 182 ds = _dwarf_find_section(cu->cu_dbg, ".debug_abbrev"); 183 if (ds == NULL) 184 return (DW_DLE_NO_ENTRY); 185 186 offset = cu->cu_abbrev_offset_cur; 187 while (offset < ds->ds_size) { 188 ret = _dwarf_abbrev_parse(cu->cu_dbg, cu, &offset, &ab, error); 189 if (ret != DW_DLE_NONE) 190 return (ret); 191 if (ab->ab_entry == entry) { 192 cu->cu_abbrev_offset_cur = offset; 193 *abp = ab; 194 return (DW_DLE_NONE); 195 } 196 if (ab->ab_entry == 0) { 197 cu->cu_abbrev_offset_cur = offset; 198 cu->cu_abbrev_loaded = 1; 199 break; 200 } 201 } 202 203 return (DW_DLE_NO_ENTRY); 204 } 205 206 void 207 _dwarf_abbrev_cleanup(Dwarf_CU cu) 208 { 209 Dwarf_Abbrev ab, tab; 210 Dwarf_AttrDef ad, tad; 211 212 assert(cu != NULL); 213 214 HASH_ITER(ab_hh, cu->cu_abbrev_hash, ab, tab) { 215 HASH_DELETE(ab_hh, cu->cu_abbrev_hash, ab); 216 STAILQ_FOREACH_SAFE(ad, &ab->ab_attrdef, ad_next, tad) { 217 STAILQ_REMOVE(&ab->ab_attrdef, ad, _Dwarf_AttrDef, 218 ad_next); 219 free(ad); 220 } 221 free(ab); 222 } 223 } 224 225 int 226 _dwarf_abbrev_gen(Dwarf_P_Debug dbg, Dwarf_Error *error) 227 { 228 Dwarf_CU cu; 229 Dwarf_Abbrev ab; 230 Dwarf_AttrDef ad; 231 Dwarf_P_Section ds; 232 int ret; 233 234 cu = STAILQ_FIRST(&dbg->dbg_cu); 235 if (cu == NULL) 236 return (DW_DLE_NONE); 237 238 /* Create .debug_abbrev section. */ 239 if ((ret = _dwarf_section_init(dbg, &ds, ".debug_abbrev", 0, error)) != 240 DW_DLE_NONE) 241 return (ret); 242 243 for (ab = cu->cu_abbrev_hash; ab != NULL; ab = ab->ab_hh.next) { 244 RCHECK(WRITE_ULEB128(ab->ab_entry)); 245 RCHECK(WRITE_ULEB128(ab->ab_tag)); 246 RCHECK(WRITE_VALUE(ab->ab_children, 1)); 247 STAILQ_FOREACH(ad, &ab->ab_attrdef, ad_next) { 248 RCHECK(WRITE_ULEB128(ad->ad_attrib)); 249 RCHECK(WRITE_ULEB128(ad->ad_form)); 250 } 251 /* Signal end of attribute spec list. */ 252 RCHECK(WRITE_ULEB128(0)); 253 RCHECK(WRITE_ULEB128(0)); 254 } 255 /* End of abbreviation for this CU. */ 256 RCHECK(WRITE_ULEB128(0)); 257 258 /* Notify the creation of .debug_abbrev ELF section. */ 259 RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error)); 260 261 return (DW_DLE_NONE); 262 263 gen_fail: 264 265 _dwarf_section_free(dbg, &ds); 266 267 return (ret); 268 } 269