1 /*- 2 * Copyright (c) 2009-2011 Kai Wang 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include "_libdwarf.h" 28 29 ELFTC_VCSID("$Id: libdwarf_macinfo.c 2974 2013-12-23 06:46:22Z kaiwang27 $"); 30 31 #define _FILEINDEX_STACK_SIZE 16384 32 33 static int 34 _dwarf_macinfo_parse(Dwarf_Debug dbg, Dwarf_Section *ds, uint64_t *off, 35 Dwarf_Macro_Details *dmd, Dwarf_Unsigned *cnt, Dwarf_Error *error) 36 { 37 Dwarf_Unsigned lineno; 38 Dwarf_Signed fileindex[_FILEINDEX_STACK_SIZE]; 39 char *p; 40 int i, type, sp; 41 42 i = 0; 43 sp = 0; 44 fileindex[sp] = -1; 45 while (*off < ds->ds_size) { 46 47 if (dmd != NULL) 48 dmd[i].dmd_offset = *off; 49 50 type = dbg->read(ds->ds_data, off, 1); 51 52 if (dmd != NULL) { 53 dmd[i].dmd_type = type; 54 dmd[i].dmd_fileindex = fileindex[sp]; 55 } 56 57 switch (type) { 58 case 0: 59 break; 60 case DW_MACINFO_define: 61 case DW_MACINFO_undef: 62 case DW_MACINFO_vendor_ext: 63 lineno = _dwarf_read_uleb128(ds->ds_data, off); 64 p = (char *) ds->ds_data; 65 if (dmd != NULL) { 66 dmd[i].dmd_lineno = lineno; 67 dmd[i].dmd_macro = p + *off; 68 69 } 70 while (p[(*off)++] != '\0') 71 ; 72 break; 73 case DW_MACINFO_start_file: 74 lineno = _dwarf_read_uleb128(ds->ds_data, off); 75 if (sp >= _FILEINDEX_STACK_SIZE - 1) { 76 assert(0); 77 } 78 fileindex[++sp] = _dwarf_read_uleb128(ds->ds_data, off); 79 if (dmd != NULL) { 80 dmd[i].dmd_lineno = lineno; 81 dmd[i].dmd_fileindex = fileindex[sp]; 82 } 83 break; 84 case DW_MACINFO_end_file: 85 if (sp > 0) { 86 sp--; 87 break; 88 } 89 /* FALLTHROUGH */ 90 default: 91 DWARF_SET_ERROR(dbg, error, 92 DW_DLE_DEBUG_MACRO_INCONSISTENT); 93 return (DW_DLE_DEBUG_MACRO_INCONSISTENT); 94 } 95 96 i++; 97 98 if (type == 0) 99 break; 100 } 101 102 if (cnt != NULL) 103 *cnt = i; 104 105 return (DW_DLE_NONE); 106 } 107 108 void 109 _dwarf_macinfo_cleanup(Dwarf_Debug dbg) 110 { 111 Dwarf_MacroSet ms, tms; 112 113 if (STAILQ_EMPTY(&dbg->dbg_mslist)) 114 return; 115 116 STAILQ_FOREACH_SAFE(ms, &dbg->dbg_mslist, ms_next, tms) { 117 STAILQ_REMOVE(&dbg->dbg_mslist, ms, _Dwarf_MacroSet, ms_next); 118 if (ms->ms_mdlist) 119 free(ms->ms_mdlist); 120 free(ms); 121 } 122 } 123 124 int 125 _dwarf_macinfo_init(Dwarf_Debug dbg, Dwarf_Error *error) 126 { 127 Dwarf_MacroSet ms; 128 Dwarf_Unsigned cnt; 129 Dwarf_Section *ds; 130 uint64_t offset, entry_off; 131 int ret; 132 133 if ((ds = _dwarf_find_section(dbg, ".debug_macinfo")) == NULL) 134 return (DW_DLE_NONE); 135 136 offset = 0; 137 while (offset < ds->ds_size) { 138 139 entry_off = offset; 140 141 ret = _dwarf_macinfo_parse(dbg, ds, &offset, NULL, &cnt, error); 142 if (ret != DW_DLE_NONE) 143 return (ret); 144 145 if (cnt == 0) 146 break; 147 148 if ((ms = calloc(1, sizeof(struct _Dwarf_MacroSet))) == NULL) { 149 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 150 ret = DW_DLE_MEMORY; 151 goto fail_cleanup; 152 } 153 STAILQ_INSERT_TAIL(&dbg->dbg_mslist, ms, ms_next); 154 155 if ((ms->ms_mdlist = calloc(cnt, sizeof(Dwarf_Macro_Details))) 156 == NULL) { 157 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 158 ret = DW_DLE_MEMORY; 159 goto fail_cleanup; 160 } 161 162 ms->ms_cnt = cnt; 163 164 offset = entry_off; 165 166 ret = _dwarf_macinfo_parse(dbg, ds, &offset, ms->ms_mdlist, 167 NULL, error); 168 169 if (ret != DW_DLE_NONE) { 170 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 171 ret = DW_DLE_MEMORY; 172 goto fail_cleanup; 173 } 174 } 175 176 return (DW_DLE_NONE); 177 178 fail_cleanup: 179 180 _dwarf_macinfo_cleanup(dbg); 181 182 return (ret); 183 } 184 185 int 186 _dwarf_macinfo_gen(Dwarf_P_Debug dbg, Dwarf_Error *error) 187 { 188 Dwarf_P_Section ds; 189 Dwarf_Macro_Details *md; 190 int i, ret; 191 192 if (dbg->dbgp_mdcnt == 0) 193 return (DW_DLE_NONE); 194 195 /* Create .debug_frame section. */ 196 RCHECK(_dwarf_section_init(dbg, &ds, ".debug_macinfo", 0, error)); 197 198 /* Write the list of Dwarf_Macro_Details. */ 199 for (i = 0; (Dwarf_Unsigned) i < dbg->dbgp_mdcnt; i++) { 200 md = &dbg->dbgp_mdlist[i]; 201 md->dmd_offset = ds->ds_size; 202 RCHECK(WRITE_VALUE(md->dmd_type, 1)); 203 switch (md->dmd_type) { 204 case DW_MACINFO_define: 205 case DW_MACINFO_undef: 206 case DW_MACINFO_vendor_ext: 207 RCHECK(WRITE_ULEB128(md->dmd_lineno)); 208 assert(md->dmd_macro != NULL); 209 RCHECK(WRITE_STRING(md->dmd_macro)); 210 break; 211 case DW_MACINFO_start_file: 212 RCHECK(WRITE_ULEB128(md->dmd_lineno)); 213 RCHECK(WRITE_ULEB128(md->dmd_fileindex)); 214 break; 215 case DW_MACINFO_end_file: 216 break; 217 default: 218 assert(0); 219 break; 220 } 221 } 222 RCHECK(WRITE_VALUE(0, 1)); 223 224 /* Inform application the creation of .debug_macinfo ELF section. */ 225 RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error)); 226 227 return (DW_DLE_NONE); 228 229 gen_fail: 230 _dwarf_section_free(dbg, &ds); 231 232 return (ret); 233 } 234 235 void 236 _dwarf_macinfo_pro_cleanup(Dwarf_P_Debug dbg) 237 { 238 Dwarf_Macro_Details *md; 239 int i; 240 241 assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE); 242 if (dbg->dbgp_mdlist == NULL) 243 return; 244 245 assert(dbg->dbgp_mdcnt > 0); 246 for (i = 0; (Dwarf_Unsigned) i < dbg->dbgp_mdcnt; i++) { 247 md = &dbg->dbgp_mdlist[i]; 248 if (md->dmd_macro) 249 free(md->dmd_macro); 250 } 251 free(dbg->dbgp_mdlist); 252 dbg->dbgp_mdlist = NULL; 253 dbg->dbgp_mdcnt = 0; 254 } 255