1 1.5 christos /* $NetBSD: libdwarf_lineno.c,v 1.5 2024/03/03 17:37:32 christos Exp $ */ 2 1.2 christos 3 1.1 christos /*- 4 1.5 christos * Copyright (c) 2009,2010,2023 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_lineno.c,v 1.5 2024/03/03 17:37:32 christos Exp $"); 32 1.5 christos ELFTC_VCSID("Id: libdwarf_lineno.c 4019 2023-10-22 03:06:17Z kaiwang27"); 33 1.5 christos 34 1.5 christos static int 35 1.5 christos _dwarf_lineno_make_fullpath(Dwarf_Debug dbg, Dwarf_LineInfo li, 36 1.5 christos Dwarf_LineFile lf, const char *compdir, Dwarf_Error *error) 37 1.5 christos { 38 1.5 christos const char *dirname; 39 1.5 christos int slen; 40 1.5 christos 41 1.5 christos /* Make full pathname if need. */ 42 1.5 christos if (*lf->lf_fname != '/') { 43 1.5 christos dirname = compdir; 44 1.5 christos if (lf->lf_dirndx > 0) 45 1.5 christos dirname = li->li_incdirs[lf->lf_dirndx - 1]; 46 1.5 christos if (dirname != NULL) { 47 1.5 christos slen = strlen(dirname) + strlen(lf->lf_fname) + 2; 48 1.5 christos if ((lf->lf_fullpath = malloc(slen)) == NULL) { 49 1.5 christos DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 50 1.5 christos return (DW_DLE_MEMORY); 51 1.5 christos } 52 1.5 christos snprintf(lf->lf_fullpath, slen, "%s/%s", dirname, 53 1.5 christos lf->lf_fname); 54 1.5 christos } 55 1.5 christos } 56 1.5 christos 57 1.5 christos return (DW_DLE_NONE); 58 1.5 christos } 59 1.1 christos 60 1.1 christos static int 61 1.1 christos _dwarf_lineno_add_file(Dwarf_LineInfo li, uint8_t **p, const char *compdir, 62 1.1 christos Dwarf_Error *error, Dwarf_Debug dbg) 63 1.1 christos { 64 1.1 christos Dwarf_LineFile lf; 65 1.1 christos uint8_t *src; 66 1.5 christos int ret; 67 1.1 christos 68 1.1 christos src = *p; 69 1.1 christos 70 1.1 christos if ((lf = malloc(sizeof(struct _Dwarf_LineFile))) == NULL) { 71 1.1 christos DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 72 1.1 christos return (DW_DLE_MEMORY); 73 1.1 christos } 74 1.1 christos 75 1.1 christos lf->lf_fullpath = NULL; 76 1.1 christos lf->lf_fname = (char *) src; 77 1.1 christos src += strlen(lf->lf_fname) + 1; 78 1.1 christos lf->lf_dirndx = _dwarf_decode_uleb128(&src); 79 1.1 christos if (lf->lf_dirndx > li->li_inclen) { 80 1.1 christos free(lf); 81 1.1 christos DWARF_SET_ERROR(dbg, error, DW_DLE_DIR_INDEX_BAD); 82 1.1 christos return (DW_DLE_DIR_INDEX_BAD); 83 1.1 christos } 84 1.1 christos 85 1.5 christos ret = _dwarf_lineno_make_fullpath(dbg, li, lf, compdir, error); 86 1.5 christos if (ret != DW_DLE_NONE) { 87 1.5 christos free(lf); 88 1.5 christos return (ret); 89 1.1 christos } 90 1.1 christos 91 1.1 christos lf->lf_mtime = _dwarf_decode_uleb128(&src); 92 1.1 christos lf->lf_size = _dwarf_decode_uleb128(&src); 93 1.1 christos STAILQ_INSERT_TAIL(&li->li_lflist, lf, lf_next); 94 1.1 christos li->li_lflen++; 95 1.1 christos 96 1.1 christos *p = src; 97 1.1 christos 98 1.1 christos return (DW_DLE_NONE); 99 1.1 christos } 100 1.1 christos 101 1.1 christos static int 102 1.1 christos _dwarf_lineno_run_program(Dwarf_CU cu, Dwarf_LineInfo li, uint8_t *p, 103 1.1 christos uint8_t *pe, const char *compdir, Dwarf_Error *error) 104 1.1 christos { 105 1.1 christos Dwarf_Debug dbg; 106 1.1 christos Dwarf_Line ln, tln; 107 1.3 christos uint64_t address, file, line, column, opsize; 108 1.1 christos int is_stmt, basic_block, end_sequence; 109 1.1 christos int ret; 110 1.1 christos 111 1.1 christos #define RESET_REGISTERS \ 112 1.1 christos do { \ 113 1.1 christos address = 0; \ 114 1.1 christos file = 1; \ 115 1.1 christos line = 1; \ 116 1.1 christos column = 0; \ 117 1.1 christos is_stmt = li->li_defstmt; \ 118 1.1 christos basic_block = 0; \ 119 1.1 christos end_sequence = 0; \ 120 1.1 christos } while(0) 121 1.1 christos 122 1.1 christos #define APPEND_ROW \ 123 1.1 christos do { \ 124 1.1 christos ln = malloc(sizeof(struct _Dwarf_Line)); \ 125 1.1 christos if (ln == NULL) { \ 126 1.1 christos ret = DW_DLE_MEMORY; \ 127 1.1 christos DWARF_SET_ERROR(dbg, error, ret); \ 128 1.1 christos goto prog_fail; \ 129 1.1 christos } \ 130 1.1 christos ln->ln_li = li; \ 131 1.1 christos ln->ln_addr = address; \ 132 1.1 christos ln->ln_symndx = 0; \ 133 1.1 christos ln->ln_fileno = file; \ 134 1.1 christos ln->ln_lineno = line; \ 135 1.1 christos ln->ln_column = column; \ 136 1.1 christos ln->ln_bblock = basic_block; \ 137 1.1 christos ln->ln_stmt = is_stmt; \ 138 1.1 christos ln->ln_endseq = end_sequence; \ 139 1.1 christos STAILQ_INSERT_TAIL(&li->li_lnlist, ln, ln_next);\ 140 1.1 christos li->li_lnlen++; \ 141 1.1 christos } while(0) 142 1.1 christos 143 1.1 christos #define LINE(x) (li->li_lbase + (((x) - li->li_opbase) % li->li_lrange)) 144 1.1 christos #define ADDRESS(x) ((((x) - li->li_opbase) / li->li_lrange) * li->li_minlen) 145 1.1 christos 146 1.1 christos dbg = cu->cu_dbg; 147 1.1 christos 148 1.1 christos /* 149 1.1 christos * Set registers to their default values. 150 1.1 christos */ 151 1.1 christos RESET_REGISTERS; 152 1.1 christos 153 1.1 christos /* 154 1.1 christos * Start line number program. 155 1.1 christos */ 156 1.1 christos while (p < pe) { 157 1.1 christos if (*p == 0) { 158 1.1 christos 159 1.1 christos /* 160 1.1 christos * Extended Opcodes. 161 1.1 christos */ 162 1.1 christos 163 1.1 christos p++; 164 1.1 christos opsize = _dwarf_decode_uleb128(&p); 165 1.1 christos switch (*p) { 166 1.1 christos case DW_LNE_end_sequence: 167 1.1 christos p++; 168 1.1 christos end_sequence = 1; 169 1.1 christos APPEND_ROW; 170 1.1 christos RESET_REGISTERS; 171 1.1 christos break; 172 1.1 christos case DW_LNE_set_address: 173 1.1 christos p++; 174 1.1 christos address = dbg->decode(&p, cu->cu_pointer_size); 175 1.1 christos break; 176 1.1 christos case DW_LNE_define_file: 177 1.1 christos p++; 178 1.1 christos ret = _dwarf_lineno_add_file(li, &p, compdir, 179 1.1 christos error, dbg); 180 1.1 christos if (ret != DW_DLE_NONE) 181 1.1 christos goto prog_fail; 182 1.1 christos break; 183 1.1 christos default: 184 1.1 christos /* Unrecognized extened opcodes. */ 185 1.1 christos p += opsize; 186 1.1 christos } 187 1.1 christos 188 1.1 christos } else if (*p > 0 && *p < li->li_opbase) { 189 1.1 christos 190 1.1 christos /* 191 1.1 christos * Standard Opcodes. 192 1.1 christos */ 193 1.1 christos 194 1.1 christos switch (*p++) { 195 1.1 christos case DW_LNS_copy: 196 1.1 christos APPEND_ROW; 197 1.1 christos basic_block = 0; 198 1.1 christos break; 199 1.1 christos case DW_LNS_advance_pc: 200 1.1 christos address += _dwarf_decode_uleb128(&p) * 201 1.1 christos li->li_minlen; 202 1.1 christos break; 203 1.1 christos case DW_LNS_advance_line: 204 1.1 christos line += _dwarf_decode_sleb128(&p); 205 1.1 christos break; 206 1.1 christos case DW_LNS_set_file: 207 1.1 christos file = _dwarf_decode_uleb128(&p); 208 1.1 christos break; 209 1.1 christos case DW_LNS_set_column: 210 1.1 christos column = _dwarf_decode_uleb128(&p); 211 1.1 christos break; 212 1.1 christos case DW_LNS_negate_stmt: 213 1.1 christos is_stmt = !is_stmt; 214 1.1 christos break; 215 1.1 christos case DW_LNS_set_basic_block: 216 1.1 christos basic_block = 1; 217 1.1 christos break; 218 1.1 christos case DW_LNS_const_add_pc: 219 1.1 christos address += ADDRESS(255); 220 1.1 christos break; 221 1.1 christos case DW_LNS_fixed_advance_pc: 222 1.1 christos address += dbg->decode(&p, 2); 223 1.1 christos break; 224 1.1 christos case DW_LNS_set_prologue_end: 225 1.1 christos break; 226 1.1 christos case DW_LNS_set_epilogue_begin: 227 1.1 christos break; 228 1.1 christos case DW_LNS_set_isa: 229 1.3 christos (void) _dwarf_decode_uleb128(&p); 230 1.1 christos break; 231 1.1 christos default: 232 1.1 christos /* Unrecognized extened opcodes. What to do? */ 233 1.1 christos break; 234 1.1 christos } 235 1.1 christos 236 1.1 christos } else { 237 1.1 christos 238 1.1 christos /* 239 1.1 christos * Special Opcodes. 240 1.1 christos */ 241 1.1 christos 242 1.1 christos line += LINE(*p); 243 1.1 christos address += ADDRESS(*p); 244 1.1 christos APPEND_ROW; 245 1.1 christos basic_block = 0; 246 1.1 christos p++; 247 1.1 christos } 248 1.1 christos } 249 1.1 christos 250 1.1 christos return (DW_DLE_NONE); 251 1.1 christos 252 1.1 christos prog_fail: 253 1.1 christos 254 1.1 christos STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) { 255 1.1 christos STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line, ln_next); 256 1.1 christos free(ln); 257 1.1 christos } 258 1.1 christos 259 1.1 christos return (ret); 260 1.1 christos 261 1.1 christos #undef RESET_REGISTERS 262 1.1 christos #undef APPEND_ROW 263 1.1 christos #undef LINE 264 1.1 christos #undef ADDRESS 265 1.1 christos } 266 1.1 christos 267 1.5 christos struct lnct { 268 1.5 christos unsigned type; 269 1.5 christos unsigned form; 270 1.5 christos }; 271 1.5 christos 272 1.5 christos 273 1.5 christos static int 274 1.5 christos _dwarf_lineno_parse_lnct_desc(Dwarf_Debug dbg, int fmt, struct lnct **lnct, 275 1.5 christos uint8_t *data, uint64_t *offsetp, Dwarf_Error *error) 276 1.5 christos { 277 1.5 christos int i; 278 1.5 christos 279 1.5 christos if (fmt == 0) { 280 1.5 christos *lnct = NULL; 281 1.5 christos return (DW_DLE_NONE); 282 1.5 christos } 283 1.5 christos 284 1.5 christos if ((*lnct = calloc(fmt, sizeof(struct lnct))) == NULL) { 285 1.5 christos DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 286 1.5 christos return (DW_DLE_MEMORY); 287 1.5 christos } 288 1.5 christos for (i = 0; i < fmt; i++) { 289 1.5 christos (*lnct)[i].type = _dwarf_read_uleb128(data, offsetp); 290 1.5 christos (*lnct)[i].form = _dwarf_read_uleb128(data, offsetp); 291 1.5 christos } 292 1.5 christos 293 1.5 christos return (DW_DLE_NONE); 294 1.5 christos } 295 1.5 christos 296 1.5 christos static int 297 1.5 christos _dwarf_lineno_lnct_path(Dwarf_Debug dbg, char **fname, unsigned form, 298 1.5 christos uint8_t *data, uint64_t size, uint64_t *offsetp, int dwarf_size, 299 1.5 christos Dwarf_Error *error) 300 1.5 christos { 301 1.5 christos Dwarf_Unsigned sp; 302 1.5 christos int ret; 303 1.5 christos 304 1.5 christos ret = DW_DLE_NONE; 305 1.5 christos 306 1.5 christos switch (form) { 307 1.5 christos case DW_FORM_string: 308 1.5 christos *fname = _dwarf_read_string(data, size, offsetp); 309 1.5 christos break; 310 1.5 christos case DW_FORM_strp: 311 1.5 christos sp = dbg->read(data, offsetp, dwarf_size); 312 1.5 christos *fname = _dwarf_strtab_get_table(dbg) + sp; 313 1.5 christos break; 314 1.5 christos case DW_FORM_line_strp: 315 1.5 christos sp = dbg->read(data, offsetp, dwarf_size); 316 1.5 christos *fname = _dwarf_strtab_get_line_table(dbg) + sp; 317 1.5 christos break; 318 1.5 christos case DW_FORM_strp_sup: 319 1.5 christos sp = dbg->read(data, offsetp, dwarf_size); 320 1.5 christos *fname = NULL; /* TODO: support sup string table. */ 321 1.5 christos break; 322 1.5 christos default: 323 1.5 christos ret = DW_DLE_LNCT_DESC_BAD; 324 1.5 christos DWARF_SET_ERROR(dbg, error, ret); 325 1.5 christos break; 326 1.5 christos } 327 1.5 christos 328 1.5 christos return (ret); 329 1.5 christos } 330 1.5 christos 331 1.5 christos static int 332 1.5 christos _dwarf_lineno_lnct_dirndx(Dwarf_Debug dbg, Dwarf_Unsigned *dirndx, 333 1.5 christos unsigned form, uint8_t *data, uint64_t *offsetp, Dwarf_Error *error) 334 1.5 christos { 335 1.5 christos int ret; 336 1.5 christos 337 1.5 christos ret = DW_DLE_NONE; 338 1.5 christos 339 1.5 christos switch (form) { 340 1.5 christos case DW_FORM_data1: 341 1.5 christos *dirndx = dbg->read(data, offsetp, 1); 342 1.5 christos break; 343 1.5 christos case DW_FORM_data2: 344 1.5 christos *dirndx = dbg->read(data, offsetp, 2); 345 1.5 christos break; 346 1.5 christos case DW_FORM_udata: 347 1.5 christos *dirndx = _dwarf_read_uleb128(data, offsetp); 348 1.5 christos break; 349 1.5 christos default: 350 1.5 christos ret = DW_DLE_LNCT_DESC_BAD; 351 1.5 christos DWARF_SET_ERROR(dbg, error, ret); 352 1.5 christos break; 353 1.5 christos } 354 1.5 christos 355 1.5 christos return (ret); 356 1.5 christos } 357 1.5 christos 358 1.5 christos static int 359 1.5 christos _dwarf_lineno_lnct_timestamp(Dwarf_Debug dbg, Dwarf_Unsigned *ts, 360 1.5 christos unsigned form, uint8_t *data, uint64_t *offsetp, Dwarf_Error *error) 361 1.5 christos { 362 1.5 christos int ret; 363 1.5 christos 364 1.5 christos ret = DW_DLE_NONE; 365 1.5 christos 366 1.5 christos switch (form) { 367 1.5 christos case DW_FORM_udata: 368 1.5 christos *ts = _dwarf_read_uleb128(data, offsetp); 369 1.5 christos break; 370 1.5 christos case DW_FORM_data4: 371 1.5 christos *ts = dbg->read(data, offsetp, 4); 372 1.5 christos break; 373 1.5 christos case DW_FORM_data8: 374 1.5 christos *ts = dbg->read(data, offsetp, 8); 375 1.5 christos break; 376 1.5 christos case DW_FORM_block: 377 1.5 christos /* TODO: Not supported. */ 378 1.5 christos default: 379 1.5 christos ret = DW_DLE_LNCT_DESC_BAD; 380 1.5 christos DWARF_SET_ERROR(dbg, error, ret); 381 1.5 christos break; 382 1.5 christos } 383 1.5 christos 384 1.5 christos return (ret); 385 1.5 christos } 386 1.5 christos 387 1.5 christos static int 388 1.5 christos _dwarf_lineno_lnct_size(Dwarf_Debug dbg, Dwarf_Unsigned *sz, unsigned form, 389 1.5 christos uint8_t *data, uint64_t *offsetp, Dwarf_Error *error) 390 1.5 christos { 391 1.5 christos int ret; 392 1.5 christos 393 1.5 christos ret = DW_DLE_NONE; 394 1.5 christos 395 1.5 christos switch (form) { 396 1.5 christos case DW_FORM_udata: 397 1.5 christos *sz = _dwarf_read_uleb128(data, offsetp); 398 1.5 christos break; 399 1.5 christos case DW_FORM_data1: 400 1.5 christos *sz = dbg->read(data, offsetp, 1); 401 1.5 christos break; 402 1.5 christos case DW_FORM_data2: 403 1.5 christos *sz = dbg->read(data, offsetp, 2); 404 1.5 christos break; 405 1.5 christos case DW_FORM_data4: 406 1.5 christos *sz = dbg->read(data, offsetp, 4); 407 1.5 christos break; 408 1.5 christos case DW_FORM_data8: 409 1.5 christos *sz = dbg->read(data, offsetp, 8); 410 1.5 christos break; 411 1.5 christos default: 412 1.5 christos ret = DW_DLE_LNCT_DESC_BAD; 413 1.5 christos DWARF_SET_ERROR(dbg, error, ret); 414 1.5 christos break; 415 1.5 christos } 416 1.5 christos 417 1.5 christos return (ret); 418 1.5 christos } 419 1.5 christos 420 1.5 christos static int 421 1.5 christos _dwarf_lineno_lnct_md5(Dwarf_Debug dbg, Dwarf_Form_Data16 *md5, 422 1.5 christos unsigned form, uint8_t *data, uint64_t *offsetp, Dwarf_Error *error) 423 1.5 christos { 424 1.5 christos 425 1.5 christos if (form != DW_FORM_data16) { 426 1.5 christos DWARF_SET_ERROR(dbg, error, DW_DLE_LNCT_DESC_BAD); 427 1.5 christos return (DW_DLE_LNCT_DESC_BAD); 428 1.5 christos } 429 1.5 christos 430 1.5 christos memcpy(md5->fd_data, data + *offsetp, 16); 431 1.5 christos offsetp += 16; 432 1.5 christos 433 1.5 christos return (DW_DLE_NONE); 434 1.5 christos } 435 1.5 christos 436 1.1 christos int 437 1.1 christos _dwarf_lineno_init(Dwarf_Die die, uint64_t offset, Dwarf_Error *error) 438 1.1 christos { 439 1.1 christos Dwarf_Debug dbg; 440 1.1 christos Dwarf_Section *ds; 441 1.1 christos Dwarf_CU cu; 442 1.1 christos Dwarf_Attribute at; 443 1.1 christos Dwarf_LineInfo li; 444 1.1 christos Dwarf_LineFile lf, tlf; 445 1.5 christos struct lnct *lnct; 446 1.1 christos const char *compdir; 447 1.1 christos uint64_t length, hdroff, endoff; 448 1.1 christos uint8_t *p; 449 1.5 christos int dwarf_size, fmt, i, j, ret; 450 1.1 christos 451 1.1 christos cu = die->die_cu; 452 1.1 christos assert(cu != NULL); 453 1.1 christos 454 1.1 christos dbg = cu->cu_dbg; 455 1.1 christos assert(dbg != NULL); 456 1.1 christos 457 1.1 christos if ((ds = _dwarf_find_section(dbg, ".debug_line")) == NULL) 458 1.1 christos return (DW_DLE_NONE); 459 1.1 christos 460 1.1 christos /* 461 1.1 christos * Try to find out the dir where the CU was compiled. Later we 462 1.1 christos * will use the dir to create full pathnames, if need. 463 1.1 christos */ 464 1.1 christos compdir = NULL; 465 1.1 christos at = _dwarf_attr_find(die, DW_AT_comp_dir); 466 1.1 christos if (at != NULL) { 467 1.1 christos switch (at->at_form) { 468 1.1 christos case DW_FORM_strp: 469 1.5 christos case DW_FORM_strp_sup: 470 1.5 christos case DW_FORM_line_strp: 471 1.1 christos compdir = at->u[1].s; 472 1.1 christos break; 473 1.1 christos case DW_FORM_string: 474 1.1 christos compdir = at->u[0].s; 475 1.1 christos break; 476 1.1 christos default: 477 1.1 christos break; 478 1.1 christos } 479 1.1 christos } 480 1.1 christos 481 1.1 christos length = dbg->read(ds->ds_data, &offset, 4); 482 1.1 christos if (length == 0xffffffff) { 483 1.1 christos dwarf_size = 8; 484 1.1 christos length = dbg->read(ds->ds_data, &offset, 8); 485 1.1 christos } else 486 1.1 christos dwarf_size = 4; 487 1.1 christos 488 1.1 christos if (length > ds->ds_size - offset) { 489 1.1 christos DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_LINE_LENGTH_BAD); 490 1.1 christos return (DW_DLE_DEBUG_LINE_LENGTH_BAD); 491 1.1 christos } 492 1.1 christos 493 1.1 christos if ((li = calloc(1, sizeof(struct _Dwarf_LineInfo))) == NULL) { 494 1.1 christos DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 495 1.1 christos return (DW_DLE_MEMORY); 496 1.1 christos } 497 1.1 christos 498 1.1 christos /* 499 1.1 christos * Read in line number program header. 500 1.1 christos */ 501 1.1 christos li->li_length = length; 502 1.1 christos endoff = offset + length; 503 1.5 christos li->li_version = dbg->read(ds->ds_data, &offset, 2); 504 1.5 christos if (li->li_version == 5) { 505 1.5 christos (void) dbg->read(ds->ds_data, &offset, 1); /* TODO */ 506 1.5 christos (void) dbg->read(ds->ds_data, &offset, 1); /* TODO */ 507 1.5 christos } 508 1.1 christos li->li_hdrlen = dbg->read(ds->ds_data, &offset, dwarf_size); 509 1.1 christos hdroff = offset; 510 1.1 christos li->li_minlen = dbg->read(ds->ds_data, &offset, 1); 511 1.5 christos if (li->li_version >= 4) 512 1.3 christos li->li_maxop = dbg->read(ds->ds_data, &offset, 1); 513 1.1 christos li->li_defstmt = dbg->read(ds->ds_data, &offset, 1); 514 1.1 christos li->li_lbase = dbg->read(ds->ds_data, &offset, 1); 515 1.1 christos li->li_lrange = dbg->read(ds->ds_data, &offset, 1); 516 1.1 christos li->li_opbase = dbg->read(ds->ds_data, &offset, 1); 517 1.1 christos STAILQ_INIT(&li->li_lflist); 518 1.1 christos STAILQ_INIT(&li->li_lnlist); 519 1.1 christos 520 1.1 christos if ((int)li->li_hdrlen - 5 < li->li_opbase - 1) { 521 1.1 christos ret = DW_DLE_DEBUG_LINE_LENGTH_BAD; 522 1.1 christos DWARF_SET_ERROR(dbg, error, ret); 523 1.1 christos goto fail_cleanup; 524 1.1 christos } 525 1.1 christos 526 1.1 christos if ((li->li_oplen = malloc(li->li_opbase)) == NULL) { 527 1.1 christos ret = DW_DLE_MEMORY; 528 1.1 christos DWARF_SET_ERROR(dbg, error, ret); 529 1.1 christos goto fail_cleanup; 530 1.1 christos } 531 1.1 christos 532 1.1 christos /* 533 1.1 christos * Read in std opcode arg length list. Note that the first 534 1.1 christos * element is not used. 535 1.1 christos */ 536 1.1 christos for (i = 1; i < li->li_opbase; i++) 537 1.1 christos li->li_oplen[i] = dbg->read(ds->ds_data, &offset, 1); 538 1.1 christos 539 1.1 christos /* 540 1.5 christos * Directory and filename parser for DWARF4 and below. 541 1.1 christos */ 542 1.5 christos if (li->li_version <= 4) { 543 1.5 christos 544 1.5 christos /* 545 1.5 christos * Check how many strings in the include dir string array. 546 1.5 christos */ 547 1.5 christos length = 0; 548 1.5 christos p = ds->ds_data + offset; 549 1.5 christos while (*p != '\0') { 550 1.5 christos while (*p++ != '\0') 551 1.5 christos ; 552 1.5 christos length++; 553 1.5 christos } 554 1.5 christos li->li_inclen = length; 555 1.5 christos 556 1.5 christos /* Sanity check. */ 557 1.5 christos if (p - ds->ds_data > (int) ds->ds_size) { 558 1.5 christos ret = DW_DLE_DEBUG_LINE_LENGTH_BAD; 559 1.5 christos DWARF_SET_ERROR(dbg, error, ret); 560 1.5 christos goto fail_cleanup; 561 1.5 christos } 562 1.5 christos 563 1.5 christos if (length != 0) { 564 1.5 christos if ((li->li_incdirs = malloc(length * sizeof(char *))) == 565 1.5 christos NULL) { 566 1.5 christos ret = DW_DLE_MEMORY; 567 1.5 christos DWARF_SET_ERROR(dbg, error, ret); 568 1.5 christos goto fail_cleanup; 569 1.5 christos } 570 1.5 christos } 571 1.5 christos 572 1.5 christos /* Fill in include dir array. */ 573 1.5 christos i = 0; 574 1.5 christos p = ds->ds_data + offset; 575 1.5 christos while (*p != '\0') { 576 1.5 christos li->li_incdirs[i++] = (char *) p; 577 1.5 christos while (*p++ != '\0') 578 1.5 christos ; 579 1.5 christos } 580 1.5 christos 581 1.5 christos p++; 582 1.5 christos 583 1.5 christos /* 584 1.5 christos * Process file list. 585 1.5 christos */ 586 1.5 christos while (*p != '\0') { 587 1.5 christos ret = _dwarf_lineno_add_file(li, &p, compdir, error, dbg); 588 1.5 christos if (ret != DW_DLE_NONE) 589 1.5 christos goto fail_cleanup; 590 1.5 christos if (p - ds->ds_data > (int) ds->ds_size) { 591 1.5 christos ret = DW_DLE_DEBUG_LINE_LENGTH_BAD; 592 1.5 christos DWARF_SET_ERROR(dbg, error, ret); 593 1.5 christos goto fail_cleanup; 594 1.5 christos } 595 1.5 christos } 596 1.5 christos 597 1.5 christos p++; 598 1.5 christos 599 1.5 christos /* Sanity check. */ 600 1.5 christos if (p - ds->ds_data - hdroff != li->li_hdrlen) { 601 1.5 christos ret = DW_DLE_DEBUG_LINE_LENGTH_BAD; 602 1.5 christos DWARF_SET_ERROR(dbg, error, ret); 603 1.5 christos goto fail_cleanup; 604 1.5 christos } 605 1.5 christos 606 1.5 christos goto lnprog; 607 1.1 christos } 608 1.1 christos 609 1.5 christos /* 610 1.5 christos * DWARF5 has completely overhauled the dir/source file information 611 1.5 christos * fields, which are incompatible with DWARF4 or lower. 612 1.5 christos */ 613 1.5 christos 614 1.5 christos lnct = NULL; 615 1.5 christos fmt = dbg->read(ds->ds_data, &offset, 1); 616 1.5 christos if ((ret = _dwarf_lineno_parse_lnct_desc(dbg, fmt, &lnct, ds->ds_data, 617 1.5 christos &offset, error)) != DW_DLE_NONE) 618 1.1 christos goto fail_cleanup; 619 1.1 christos 620 1.5 christos li->li_inclen = dbg->read(ds->ds_data, &offset, 1); 621 1.5 christos if (li->li_inclen == 0) { 622 1.5 christos if (fmt > 0) { 623 1.5 christos free(lnct); 624 1.5 christos ret = DW_DLE_DIR_COUNT_BAD; 625 1.1 christos DWARF_SET_ERROR(dbg, error, ret); 626 1.1 christos goto fail_cleanup; 627 1.1 christos } 628 1.5 christos 629 1.5 christos goto file_entries; 630 1.1 christos } 631 1.1 christos 632 1.5 christos if (fmt == 0) { 633 1.5 christos ret = DW_DLE_DIR_COUNT_BAD; 634 1.5 christos DWARF_SET_ERROR(dbg, error, ret); 635 1.5 christos goto fail_cleanup; 636 1.5 christos } 637 1.5 christos if ((li->li_incdirs = malloc(length * sizeof(char *))) == NULL) { 638 1.5 christos free(lnct); 639 1.5 christos ret = DW_DLE_MEMORY; 640 1.5 christos DWARF_SET_ERROR(dbg, error, ret); 641 1.5 christos goto fail_cleanup; 642 1.5 christos } 643 1.5 christos for (i = 0; i < li->li_inclen; i++) { 644 1.5 christos for (j = 0; j < fmt; j++) { 645 1.5 christos if (lnct[j].type != DW_LNCT_path) { 646 1.5 christos free(lnct); 647 1.5 christos ret = DW_DLE_LNCT_DESC_BAD; 648 1.5 christos DWARF_SET_ERROR(dbg, error, ret); 649 1.5 christos goto fail_cleanup; 650 1.5 christos } 651 1.5 christos 652 1.5 christos ret = _dwarf_lineno_lnct_path(dbg, &li->li_incdirs[i], 653 1.5 christos lnct[j].form, ds->ds_data, ds->ds_size, &offset, 654 1.5 christos dwarf_size, error); 655 1.5 christos if (ret != DW_DLE_NONE) { 656 1.5 christos free(lnct); 657 1.5 christos goto fail_cleanup; 658 1.5 christos } 659 1.5 christos } 660 1.1 christos } 661 1.5 christos if (lnct) 662 1.5 christos free(lnct); 663 1.5 christos 664 1.5 christos file_entries: 665 1.1 christos 666 1.5 christos lnct = NULL; 667 1.5 christos fmt = dbg->read(ds->ds_data, &offset, 1); 668 1.5 christos if ((ret = _dwarf_lineno_parse_lnct_desc(dbg, fmt, &lnct, ds->ds_data, 669 1.5 christos &offset, error)) != DW_DLE_NONE) 670 1.5 christos goto fail_cleanup; 671 1.1 christos 672 1.5 christos li->li_lflen = dbg->read(ds->ds_data, &offset, 1); 673 1.5 christos if (li->li_lflen == 0) { 674 1.5 christos if (fmt > 0) { 675 1.5 christos free(lnct); 676 1.5 christos ret = DW_DLE_FILE_COUNT_BAD; 677 1.5 christos DWARF_SET_ERROR(dbg, error, ret); 678 1.1 christos goto fail_cleanup; 679 1.5 christos } 680 1.5 christos 681 1.5 christos p = ds->ds_data + offset; 682 1.5 christos goto lnprog; 683 1.5 christos } 684 1.5 christos 685 1.5 christos for (i = 0; i < li->li_lflen; i++) { 686 1.5 christos if ((lf = malloc(sizeof(struct _Dwarf_LineFile))) == NULL) { 687 1.5 christos free(lnct); 688 1.5 christos ret = DW_DLE_MEMORY; 689 1.1 christos DWARF_SET_ERROR(dbg, error, ret); 690 1.1 christos goto fail_cleanup; 691 1.1 christos } 692 1.5 christos for (j = 0; j < fmt; j++) { 693 1.5 christos switch (lnct[j].type) { 694 1.5 christos case DW_LNCT_path: 695 1.5 christos ret = _dwarf_lineno_lnct_path(dbg, 696 1.5 christos &lf->lf_fname, lnct[j].form, ds->ds_data, 697 1.5 christos ds->ds_size, &offset, dwarf_size, error); 698 1.5 christos break; 699 1.5 christos case DW_LNCT_directory_index: 700 1.5 christos ret = _dwarf_lineno_lnct_dirndx(dbg, 701 1.5 christos &lf->lf_dirndx, lnct[j].form, ds->ds_data, 702 1.5 christos &offset, error); 703 1.5 christos break; 704 1.5 christos case DW_LNCT_timestamp: 705 1.5 christos ret = _dwarf_lineno_lnct_timestamp(dbg, 706 1.5 christos &lf->lf_mtime, lnct[j].form, ds->ds_data, 707 1.5 christos &offset, error); 708 1.5 christos break; 709 1.5 christos case DW_LNCT_size: 710 1.5 christos ret = _dwarf_lineno_lnct_size(dbg, 711 1.5 christos &lf->lf_size, lnct[j].form, ds->ds_data, 712 1.5 christos &offset, error); 713 1.5 christos break; 714 1.5 christos case DW_LNCT_MD5: 715 1.5 christos ret = _dwarf_lineno_lnct_md5(dbg, 716 1.5 christos &lf->lf_md5, lnct[j].form, ds->ds_data, 717 1.5 christos &offset, error); 718 1.5 christos break; 719 1.5 christos default: 720 1.5 christos ret = DW_DLE_LNCT_DESC_BAD; 721 1.5 christos DWARF_SET_ERROR(dbg, error, ret); 722 1.5 christos break; 723 1.5 christos } 724 1.5 christos if (ret != DW_DLE_NONE) { 725 1.5 christos free(lf); 726 1.5 christos free(lnct); 727 1.5 christos goto fail_cleanup; 728 1.5 christos } 729 1.5 christos } 730 1.5 christos ret = _dwarf_lineno_make_fullpath(dbg, li, lf, compdir, error); 731 1.5 christos if (ret != DW_DLE_NONE) { 732 1.5 christos free(lf); 733 1.5 christos free(lnct); 734 1.5 christos goto fail_cleanup; 735 1.5 christos } 736 1.5 christos STAILQ_INSERT_TAIL(&li->li_lflist, lf, lf_next); 737 1.1 christos } 738 1.5 christos if (lnct) 739 1.5 christos free(lnct); 740 1.1 christos 741 1.5 christos p = ds->ds_data + offset; 742 1.1 christos 743 1.5 christos lnprog: 744 1.1 christos /* 745 1.1 christos * Process line number program. 746 1.1 christos */ 747 1.1 christos ret = _dwarf_lineno_run_program(cu, li, p, ds->ds_data + endoff, compdir, 748 1.1 christos error); 749 1.1 christos if (ret != DW_DLE_NONE) 750 1.1 christos goto fail_cleanup; 751 1.1 christos 752 1.1 christos cu->cu_lineinfo = li; 753 1.1 christos 754 1.1 christos return (DW_DLE_NONE); 755 1.1 christos 756 1.1 christos fail_cleanup: 757 1.1 christos 758 1.1 christos STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) { 759 1.1 christos STAILQ_REMOVE(&li->li_lflist, lf, _Dwarf_LineFile, lf_next); 760 1.1 christos if (lf->lf_fullpath) 761 1.1 christos free(lf->lf_fullpath); 762 1.1 christos free(lf); 763 1.1 christos } 764 1.1 christos 765 1.1 christos if (li->li_oplen) 766 1.1 christos free(li->li_oplen); 767 1.1 christos if (li->li_incdirs) 768 1.1 christos free(li->li_incdirs); 769 1.1 christos free(li); 770 1.1 christos 771 1.1 christos return (ret); 772 1.1 christos } 773 1.1 christos 774 1.1 christos void 775 1.1 christos _dwarf_lineno_cleanup(Dwarf_LineInfo li) 776 1.1 christos { 777 1.1 christos Dwarf_LineFile lf, tlf; 778 1.1 christos Dwarf_Line ln, tln; 779 1.1 christos 780 1.1 christos if (li == NULL) 781 1.1 christos return; 782 1.1 christos STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) { 783 1.1 christos STAILQ_REMOVE(&li->li_lflist, lf, 784 1.1 christos _Dwarf_LineFile, lf_next); 785 1.1 christos if (lf->lf_fullpath) 786 1.1 christos free(lf->lf_fullpath); 787 1.1 christos free(lf); 788 1.1 christos } 789 1.1 christos STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) { 790 1.1 christos STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line, 791 1.1 christos ln_next); 792 1.1 christos free(ln); 793 1.1 christos } 794 1.1 christos if (li->li_oplen) 795 1.1 christos free(li->li_oplen); 796 1.1 christos if (li->li_incdirs) 797 1.1 christos free(li->li_incdirs); 798 1.1 christos if (li->li_lnarray) 799 1.1 christos free(li->li_lnarray); 800 1.1 christos if (li->li_lfnarray) 801 1.1 christos free(li->li_lfnarray); 802 1.1 christos free(li); 803 1.1 christos } 804 1.1 christos 805 1.1 christos static int 806 1.1 christos _dwarf_lineno_gen_program(Dwarf_P_Debug dbg, Dwarf_P_Section ds, 807 1.1 christos Dwarf_Rel_Section drs, Dwarf_Error * error) 808 1.1 christos { 809 1.1 christos Dwarf_LineInfo li; 810 1.1 christos Dwarf_Line ln; 811 1.1 christos Dwarf_Unsigned address, file, line, spc; 812 1.1 christos Dwarf_Unsigned addr0, maddr; 813 1.1 christos Dwarf_Signed line0, column; 814 1.3 christos int is_stmt, basic_block; 815 1.1 christos int need_copy; 816 1.1 christos int ret; 817 1.1 christos 818 1.1 christos #define RESET_REGISTERS \ 819 1.1 christos do { \ 820 1.1 christos address = 0; \ 821 1.1 christos file = 1; \ 822 1.1 christos line = 1; \ 823 1.1 christos column = 0; \ 824 1.1 christos is_stmt = li->li_defstmt; \ 825 1.1 christos basic_block = 0; \ 826 1.1 christos } while(0) 827 1.1 christos 828 1.1 christos li = dbg->dbgp_lineinfo; 829 1.1 christos maddr = (255 - li->li_opbase) / li->li_lrange; 830 1.1 christos 831 1.1 christos RESET_REGISTERS; 832 1.1 christos 833 1.1 christos STAILQ_FOREACH(ln, &li->li_lnlist, ln_next) { 834 1.1 christos if (ln->ln_symndx > 0) { 835 1.1 christos /* 836 1.1 christos * Generate DW_LNE_set_address extended op. 837 1.1 christos */ 838 1.1 christos RCHECK(WRITE_VALUE(0, 1)); 839 1.1 christos RCHECK(WRITE_ULEB128(dbg->dbg_pointer_size + 1)); 840 1.1 christos RCHECK(WRITE_VALUE(DW_LNE_set_address, 1)); 841 1.1 christos RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds, 842 1.1 christos dwarf_drt_data_reloc, dbg->dbg_pointer_size, 843 1.1 christos ds->ds_size, ln->ln_symndx, ln->ln_addr, 844 1.1 christos NULL, error)); 845 1.1 christos address = ln->ln_addr; 846 1.1 christos continue; 847 1.1 christos } else if (ln->ln_endseq) { 848 1.1 christos addr0 = (ln->ln_addr - address) / li->li_minlen; 849 1.1 christos if (addr0 != 0) { 850 1.1 christos RCHECK(WRITE_VALUE(DW_LNS_advance_pc, 1)); 851 1.1 christos RCHECK(WRITE_ULEB128(addr0)); 852 1.1 christos } 853 1.1 christos 854 1.1 christos /* 855 1.1 christos * Generate DW_LNE_end_sequence. 856 1.1 christos */ 857 1.1 christos RCHECK(WRITE_VALUE(0, 1)); 858 1.1 christos RCHECK(WRITE_ULEB128(1)); 859 1.1 christos RCHECK(WRITE_VALUE(DW_LNE_end_sequence, 1)); 860 1.1 christos RESET_REGISTERS; 861 1.1 christos continue; 862 1.1 christos } 863 1.1 christos 864 1.1 christos /* 865 1.1 christos * Generate standard opcodes for file, column, is_stmt or 866 1.1 christos * basic_block changes. 867 1.1 christos */ 868 1.1 christos if (ln->ln_fileno != file) { 869 1.1 christos RCHECK(WRITE_VALUE(DW_LNS_set_file, 1)); 870 1.1 christos RCHECK(WRITE_ULEB128(ln->ln_fileno)); 871 1.1 christos file = ln->ln_fileno; 872 1.1 christos } 873 1.1 christos if (ln->ln_column != column) { 874 1.1 christos RCHECK(WRITE_VALUE(DW_LNS_set_column, 1)); 875 1.1 christos RCHECK(WRITE_ULEB128(ln->ln_column)); 876 1.1 christos column = ln->ln_column; 877 1.1 christos } 878 1.1 christos if (ln->ln_stmt != is_stmt) { 879 1.1 christos RCHECK(WRITE_VALUE(DW_LNS_negate_stmt, 1)); 880 1.1 christos is_stmt = ln->ln_stmt; 881 1.1 christos } 882 1.1 christos if (ln->ln_bblock && !basic_block) { 883 1.1 christos RCHECK(WRITE_VALUE(DW_LNS_set_basic_block, 1)); 884 1.1 christos basic_block = 1; 885 1.1 christos } 886 1.1 christos 887 1.1 christos /* 888 1.1 christos * Calculate address and line number change. 889 1.1 christos */ 890 1.1 christos addr0 = (ln->ln_addr - address) / li->li_minlen; 891 1.1 christos line0 = ln->ln_lineno - line; 892 1.1 christos 893 1.1 christos if (addr0 == 0 && line0 == 0) 894 1.1 christos continue; 895 1.1 christos 896 1.1 christos /* 897 1.1 christos * Check if line delta is with the range and if the special 898 1.1 christos * opcode can be used. 899 1.1 christos */ 900 1.1 christos assert(li->li_lbase <= 0); 901 1.1 christos if (line0 >= li->li_lbase && 902 1.1 christos line0 <= li->li_lbase + li->li_lrange - 1) { 903 1.1 christos spc = (line0 - li->li_lbase) + 904 1.1 christos (li->li_lrange * addr0) + li->li_opbase; 905 1.1 christos if (spc <= 255) { 906 1.1 christos RCHECK(WRITE_VALUE(spc, 1)); 907 1.1 christos basic_block = 0; 908 1.1 christos goto next_line; 909 1.1 christos } 910 1.1 christos } 911 1.1 christos 912 1.1 christos /* Generate DW_LNS_advance_line for line number change. */ 913 1.1 christos if (line0 != 0) { 914 1.1 christos RCHECK(WRITE_VALUE(DW_LNS_advance_line, 1)); 915 1.1 christos RCHECK(WRITE_SLEB128(line0)); 916 1.1 christos line0 = 0; 917 1.1 christos need_copy = 1; 918 1.1 christos } else 919 1.1 christos need_copy = basic_block; 920 1.1 christos 921 1.1 christos if (addr0 != 0) { 922 1.1 christos /* See if it can be handled by DW_LNS_const_add_pc. */ 923 1.1 christos spc = (line0 - li->li_lbase) + 924 1.1 christos (li->li_lrange * (addr0 - maddr)) + li->li_opbase; 925 1.1 christos if (addr0 >= maddr && spc <= 255) { 926 1.1 christos RCHECK(WRITE_VALUE(DW_LNS_const_add_pc, 1)); 927 1.1 christos RCHECK(WRITE_VALUE(spc, 1)); 928 1.1 christos } else { 929 1.1 christos /* Otherwise we use DW_LNS_advance_pc. */ 930 1.1 christos RCHECK(WRITE_VALUE(DW_LNS_advance_pc, 1)); 931 1.1 christos RCHECK(WRITE_ULEB128(addr0)); 932 1.1 christos } 933 1.1 christos } 934 1.1 christos 935 1.1 christos if (need_copy) { 936 1.1 christos RCHECK(WRITE_VALUE(DW_LNS_copy, 1)); 937 1.1 christos basic_block = 0; 938 1.1 christos } 939 1.1 christos 940 1.1 christos next_line: 941 1.1 christos address = ln->ln_addr; 942 1.1 christos line = ln->ln_lineno; 943 1.1 christos } 944 1.1 christos 945 1.1 christos return (DW_DLE_NONE); 946 1.1 christos 947 1.1 christos gen_fail: 948 1.1 christos return (ret); 949 1.1 christos 950 1.1 christos #undef RESET_REGISTERS 951 1.1 christos } 952 1.1 christos 953 1.1 christos static uint8_t 954 1.1 christos _dwarf_get_minlen(Dwarf_P_Debug dbg) 955 1.1 christos { 956 1.1 christos 957 1.1 christos assert(dbg != NULL); 958 1.1 christos 959 1.1 christos switch (dbg->dbgp_isa) { 960 1.1 christos case DW_ISA_ARM: 961 1.1 christos return (2); 962 1.1 christos case DW_ISA_X86: 963 1.1 christos case DW_ISA_X86_64: 964 1.1 christos return (1); 965 1.1 christos default: 966 1.1 christos return (4); 967 1.1 christos } 968 1.1 christos } 969 1.1 christos 970 1.1 christos static uint8_t oplen[] = {0, 1, 1, 1, 1, 0, 0, 0, 1}; 971 1.1 christos 972 1.1 christos int 973 1.1 christos _dwarf_lineno_gen(Dwarf_P_Debug dbg, Dwarf_Error *error) 974 1.1 christos { 975 1.1 christos Dwarf_LineInfo li; 976 1.1 christos Dwarf_LineFile lf; 977 1.1 christos Dwarf_P_Section ds; 978 1.1 christos Dwarf_Rel_Section drs; 979 1.1 christos Dwarf_Unsigned offset; 980 1.1 christos int i, ret; 981 1.1 christos 982 1.1 christos assert(dbg != NULL && dbg->dbgp_lineinfo != NULL); 983 1.1 christos 984 1.1 christos li = dbg->dbgp_lineinfo; 985 1.1 christos if (STAILQ_EMPTY(&li->li_lnlist)) 986 1.1 christos return (DW_DLE_NONE); 987 1.1 christos 988 1.1 christos li->li_length = 0; 989 1.1 christos li->li_version = 2; 990 1.1 christos li->li_hdrlen = 0; 991 1.1 christos li->li_minlen = _dwarf_get_minlen(dbg); 992 1.1 christos li->li_defstmt = 1; 993 1.1 christos li->li_lbase = -5; 994 1.1 christos li->li_lrange = 14; 995 1.1 christos li->li_opbase = 10; 996 1.1 christos 997 1.1 christos /* Create .debug_line section. */ 998 1.1 christos if ((ret = _dwarf_section_init(dbg, &ds, ".debug_line", 0, error)) != 999 1.1 christos DW_DLE_NONE) 1000 1.1 christos return (ret); 1001 1.1 christos 1002 1.1 christos /* Create relocation section for .debug_line */ 1003 1.1 christos if ((ret = _dwarf_reloc_section_init(dbg, &drs, ds, error)) != 1004 1.1 christos DW_DLE_NONE) 1005 1.1 christos goto gen_fail1; 1006 1.1 christos 1007 1.1 christos /* Length placeholder. (We only use 32-bit DWARF format) */ 1008 1.1 christos RCHECK(WRITE_VALUE(0, 4)); 1009 1.1 christos 1010 1.1 christos /* Write line number dwarf version. (DWARF2) */ 1011 1.1 christos RCHECK(WRITE_VALUE(li->li_version, 2)); 1012 1.1 christos 1013 1.1 christos /* Header length placeholder. */ 1014 1.1 christos offset = ds->ds_size; 1015 1.1 christos RCHECK(WRITE_VALUE(li->li_hdrlen, 4)); 1016 1.1 christos 1017 1.1 christos /* Write minimum instruction length. */ 1018 1.1 christos RCHECK(WRITE_VALUE(li->li_minlen, 1)); 1019 1.1 christos 1020 1.1 christos /* 1021 1.1 christos * Write initial value for is_stmt. XXX Which default value we 1022 1.1 christos * should use? 1023 1.1 christos */ 1024 1.1 christos RCHECK(WRITE_VALUE(li->li_defstmt, 1)); 1025 1.1 christos 1026 1.1 christos /* 1027 1.1 christos * Write line_base and line_range. FIXME These value needs to be 1028 1.1 christos * fine tuned. 1029 1.1 christos */ 1030 1.1 christos RCHECK(WRITE_VALUE(li->li_lbase, 1)); 1031 1.1 christos RCHECK(WRITE_VALUE(li->li_lrange, 1)); 1032 1.1 christos 1033 1.1 christos /* Write opcode_base. (DWARF2) */ 1034 1.1 christos RCHECK(WRITE_VALUE(li->li_opbase, 1)); 1035 1.1 christos 1036 1.1 christos /* Write standard op length array. */ 1037 1.1 christos RCHECK(WRITE_BLOCK(oplen, sizeof(oplen) / sizeof(oplen[0]))); 1038 1.1 christos 1039 1.1 christos /* Write the list of include directories. */ 1040 1.1 christos for (i = 0; (Dwarf_Unsigned) i < li->li_inclen; i++) 1041 1.1 christos RCHECK(WRITE_STRING(li->li_incdirs[i])); 1042 1.1 christos RCHECK(WRITE_VALUE(0, 1)); 1043 1.1 christos 1044 1.1 christos /* Write the list of filenames. */ 1045 1.1 christos STAILQ_FOREACH(lf, &li->li_lflist, lf_next) { 1046 1.1 christos RCHECK(WRITE_STRING(lf->lf_fname)); 1047 1.1 christos RCHECK(WRITE_ULEB128(lf->lf_dirndx)); 1048 1.1 christos RCHECK(WRITE_ULEB128(lf->lf_mtime)); 1049 1.1 christos RCHECK(WRITE_ULEB128(lf->lf_size)); 1050 1.1 christos } 1051 1.1 christos RCHECK(WRITE_VALUE(0, 1)); 1052 1.1 christos 1053 1.1 christos /* Fill in the header length. */ 1054 1.1 christos li->li_hdrlen = ds->ds_size - offset - 4; 1055 1.1 christos dbg->write(ds->ds_data, &offset, li->li_hdrlen, 4); 1056 1.1 christos 1057 1.1 christos /* Generate the line number program. */ 1058 1.1 christos RCHECK(_dwarf_lineno_gen_program(dbg, ds, drs, error)); 1059 1.1 christos 1060 1.1 christos /* Fill in the length of this line info. */ 1061 1.1 christos li->li_length = ds->ds_size - 4; 1062 1.1 christos offset = 0; 1063 1.1 christos dbg->write(ds->ds_data, &offset, li->li_length, 4); 1064 1.1 christos 1065 1.1 christos /* Notify the creation of .debug_line ELF section. */ 1066 1.1 christos RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error)); 1067 1.1 christos 1068 1.1 christos /* Finalize relocation section for .debug_line. */ 1069 1.1 christos RCHECK(_dwarf_reloc_section_finalize(dbg, drs, error)); 1070 1.1 christos 1071 1.1 christos return (DW_DLE_NONE); 1072 1.1 christos 1073 1.1 christos gen_fail: 1074 1.1 christos _dwarf_reloc_section_free(dbg, &drs); 1075 1.1 christos 1076 1.1 christos gen_fail1: 1077 1.1 christos _dwarf_section_free(dbg, &ds); 1078 1.1 christos 1079 1.1 christos return (ret); 1080 1.1 christos } 1081 1.1 christos 1082 1.1 christos void 1083 1.1 christos _dwarf_lineno_pro_cleanup(Dwarf_P_Debug dbg) 1084 1.1 christos { 1085 1.1 christos Dwarf_LineInfo li; 1086 1.1 christos Dwarf_LineFile lf, tlf; 1087 1.1 christos Dwarf_Line ln, tln; 1088 1.1 christos int i; 1089 1.1 christos 1090 1.1 christos assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE); 1091 1.1 christos if (dbg->dbgp_lineinfo == NULL) 1092 1.1 christos return; 1093 1.1 christos 1094 1.1 christos li = dbg->dbgp_lineinfo; 1095 1.1 christos STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) { 1096 1.1 christos STAILQ_REMOVE(&li->li_lflist, lf, _Dwarf_LineFile, 1097 1.1 christos lf_next); 1098 1.1 christos if (lf->lf_fname) 1099 1.1 christos free(lf->lf_fname); 1100 1.1 christos free(lf); 1101 1.1 christos } 1102 1.1 christos STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) { 1103 1.1 christos STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line, ln_next); 1104 1.1 christos free(ln); 1105 1.1 christos } 1106 1.1 christos if (li->li_incdirs) { 1107 1.1 christos for (i = 0; (Dwarf_Unsigned) i < li->li_inclen; i++) 1108 1.1 christos free(li->li_incdirs[i]); 1109 1.1 christos free(li->li_incdirs); 1110 1.1 christos } 1111 1.1 christos free(li); 1112 1.1 christos dbg->dbgp_lineinfo = NULL; 1113 1.1 christos } 1114