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