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