Home | History | Annotate | Download | only in dwarf2
      1 /*
      2  * DWARF2 debugging format - line information
      3  *
      4  *  Copyright (C) 2006-2007  Peter Johnson
      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  * 3. Neither the name of the author nor the names of other contributors
     15  *    may be used to endorse or promote products derived from this
     16  *    software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
     19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
     22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     28  * POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 #include <util.h>
     31 
     32 #include <libyasm.h>
     33 
     34 #include "dwarf2-dbgfmt.h"
     35 
     36 /* DWARF line number opcodes */
     37 typedef enum {
     38     DW_LNS_extended_op = 0,
     39     DW_LNS_copy,
     40     DW_LNS_advance_pc,
     41     DW_LNS_advance_line,
     42     DW_LNS_set_file,
     43     DW_LNS_set_column,
     44     DW_LNS_negate_stmt,
     45     DW_LNS_set_basic_block,
     46     DW_LNS_const_add_pc,
     47     DW_LNS_fixed_advance_pc,
     48 #ifdef WITH_DWARF3
     49     /* DWARF 3 extensions */
     50     DW_LNS_set_prologue_end,
     51     DW_LNS_set_epilogue_begin,
     52     DW_LNS_set_isa,
     53 #endif
     54     DWARF2_LINE_OPCODE_BASE
     55 } dwarf_line_number_op;
     56 
     57 /* # of LEB128 operands needed for each of the above opcodes */
     58 static unsigned char line_opcode_num_operands[DWARF2_LINE_OPCODE_BASE-1] = {
     59     0,  /* DW_LNS_copy */
     60     1,  /* DW_LNS_advance_pc */
     61     1,  /* DW_LNS_advance_line */
     62     1,  /* DW_LNS_set_file */
     63     1,  /* DW_LNS_set_column */
     64     0,  /* DW_LNS_negate_stmt */
     65     0,  /* DW_LNS_set_basic_block */
     66     0,  /* DW_LNS_const_add_pc */
     67     1,  /* DW_LNS_fixed_advance_pc */
     68 #ifdef WITH_DWARF3
     69     0,  /* DW_LNS_set_prologue_end */
     70     0,  /* DW_LNS_set_epilogue_begin */
     71     1   /* DW_LNS_set_isa */
     72 #endif
     73 };
     74 
     75 /* Line number extended opcodes */
     76 typedef enum {
     77     DW_LNE_end_sequence = 1,
     78     DW_LNE_set_address,
     79     DW_LNE_define_file,
     80     DW_LNE_set_discriminator
     81 } dwarf_line_number_ext_op;
     82 
     83 /* Base and range for line offsets in special opcodes */
     84 #define DWARF2_LINE_BASE                -5
     85 #define DWARF2_LINE_RANGE               14
     86 
     87 #define DWARF2_MAX_SPECIAL_ADDR_DELTA   \
     88     (((255-DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE)*\
     89      dbgfmt_dwarf2->min_insn_len)
     90 
     91 /* Initial value of is_stmt register */
     92 #define DWARF2_LINE_DEFAULT_IS_STMT     1
     93 
     94 /* Line number state machine register state */
     95 typedef struct dwarf2_line_state {
     96     /* static configuration */
     97     yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2;
     98 
     99     /* DWARF2 state machine registers */
    100     unsigned long address;
    101     unsigned long file;
    102     unsigned long line;
    103     unsigned long column;
    104     unsigned long isa;
    105     int is_stmt;
    106 
    107     /* other state information */
    108     /*@null@*/ yasm_bytecode *precbc;
    109 } dwarf2_line_state;
    110 
    111 typedef struct dwarf2_spp {
    112     yasm_bytecode *line_start_prevbc;
    113     yasm_bytecode *line_end_prevbc;
    114 } dwarf2_spp;
    115 
    116 typedef struct dwarf2_line_op {
    117     dwarf_line_number_op opcode;
    118     /*@owned@*/ /*@null@*/ yasm_intnum *operand;
    119 
    120     /* extended opcode */
    121     dwarf_line_number_ext_op ext_opcode;
    122     /*@null@*/ /*@dependent@*/ yasm_symrec *ext_operand;  /* unsigned */
    123     /*@null@*/ /*@dependent@*/ yasm_intnum *ext_operand_int; /* unsigned */
    124     unsigned long ext_operandsize;
    125 } dwarf2_line_op;
    126 
    127 /* Bytecode callback function prototypes */
    128 static void dwarf2_spp_bc_destroy(void *contents);
    129 static void dwarf2_spp_bc_print(const void *contents, FILE *f,
    130                                 int indent_level);
    131 static int dwarf2_spp_bc_calc_len
    132     (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
    133 static int dwarf2_spp_bc_tobytes
    134     (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
    135      yasm_output_value_func output_value,
    136      /*@null@*/ yasm_output_reloc_func output_reloc);
    137 
    138 static void dwarf2_line_op_bc_destroy(void *contents);
    139 static void dwarf2_line_op_bc_print(const void *contents, FILE *f,
    140                                     int indent_level);
    141 static int dwarf2_line_op_bc_calc_len
    142     (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
    143 static int dwarf2_line_op_bc_tobytes
    144     (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
    145      yasm_output_value_func output_value,
    146      /*@null@*/ yasm_output_reloc_func output_reloc);
    147 
    148 /* Bytecode callback structures */
    149 static const yasm_bytecode_callback dwarf2_spp_bc_callback = {
    150     dwarf2_spp_bc_destroy,
    151     dwarf2_spp_bc_print,
    152     yasm_bc_finalize_common,
    153     NULL,
    154     dwarf2_spp_bc_calc_len,
    155     yasm_bc_expand_common,
    156     dwarf2_spp_bc_tobytes,
    157     0
    158 };
    159 
    160 static const yasm_bytecode_callback dwarf2_line_op_bc_callback = {
    161     dwarf2_line_op_bc_destroy,
    162     dwarf2_line_op_bc_print,
    163     yasm_bc_finalize_common,
    164     NULL,
    165     dwarf2_line_op_bc_calc_len,
    166     yasm_bc_expand_common,
    167     dwarf2_line_op_bc_tobytes,
    168     0
    169 };
    170 
    171 
    172 static size_t
    173 dwarf2_dbgfmt_add_file(yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2, unsigned long filenum,
    174                        const char *pathname)
    175 {
    176     size_t dirlen;
    177     const char *filename;
    178     unsigned long i, dir;
    179 
    180     /* Put the directory into the directory table */
    181     dir = 0;
    182     dirlen = yasm__splitpath(pathname, &filename);
    183     if (dirlen > 0) {
    184         /* Look to see if we already have that dir in the table */
    185         for (dir=1; dir<dbgfmt_dwarf2->dirs_size+1; dir++) {
    186             if (strncmp(dbgfmt_dwarf2->dirs[dir-1], pathname, dirlen) == 0
    187                 && dbgfmt_dwarf2->dirs[dir-1][dirlen] == '\0')
    188                 break;
    189         }
    190         if (dir >= dbgfmt_dwarf2->dirs_size+1) {
    191             /* Not found in table, add to end, reallocing if necessary */
    192             if (dir >= dbgfmt_dwarf2->dirs_allocated+1) {
    193                 dbgfmt_dwarf2->dirs_allocated = dir+32;
    194                 dbgfmt_dwarf2->dirs = yasm_xrealloc(dbgfmt_dwarf2->dirs,
    195                     sizeof(char *)*dbgfmt_dwarf2->dirs_allocated);
    196             }
    197             dbgfmt_dwarf2->dirs[dir-1] = yasm__xstrndup(pathname, dirlen);
    198             dbgfmt_dwarf2->dirs_size = dir;
    199         }
    200     }
    201 
    202     /* Put the filename into the filename table */
    203     if (filenum == 0) {
    204         /* Look to see if we already have that filename in the table */
    205         for (; filenum<dbgfmt_dwarf2->filenames_size; filenum++) {
    206             if (!dbgfmt_dwarf2->filenames[filenum].filename ||
    207                 (dbgfmt_dwarf2->filenames[filenum].dir == dir
    208                  && strcmp(dbgfmt_dwarf2->filenames[filenum].filename,
    209                            filename) == 0))
    210                 break;
    211         }
    212     } else
    213         filenum--;      /* array index is 0-based */
    214 
    215     /* Realloc table if necessary */
    216     if (filenum >= dbgfmt_dwarf2->filenames_allocated) {
    217         unsigned long old_allocated = dbgfmt_dwarf2->filenames_allocated;
    218         dbgfmt_dwarf2->filenames_allocated = filenum+32;
    219         dbgfmt_dwarf2->filenames = yasm_xrealloc(dbgfmt_dwarf2->filenames,
    220             sizeof(dwarf2_filename)*dbgfmt_dwarf2->filenames_allocated);
    221         for (i=old_allocated; i<dbgfmt_dwarf2->filenames_allocated; i++) {
    222             dbgfmt_dwarf2->filenames[i].pathname = NULL;
    223             dbgfmt_dwarf2->filenames[i].filename = NULL;
    224             dbgfmt_dwarf2->filenames[i].dir = 0;
    225         }
    226     }
    227 
    228     /* Actually save in table */
    229     if (dbgfmt_dwarf2->filenames[filenum].pathname)
    230         yasm_xfree(dbgfmt_dwarf2->filenames[filenum].pathname);
    231     if (dbgfmt_dwarf2->filenames[filenum].filename)
    232         yasm_xfree(dbgfmt_dwarf2->filenames[filenum].filename);
    233     dbgfmt_dwarf2->filenames[filenum].pathname = yasm__xstrdup(pathname);
    234     dbgfmt_dwarf2->filenames[filenum].filename = yasm__xstrdup(filename);
    235     dbgfmt_dwarf2->filenames[filenum].dir = dir;
    236 
    237     /* Update table size */
    238     if (filenum >= dbgfmt_dwarf2->filenames_size)
    239         dbgfmt_dwarf2->filenames_size = filenum + 1;
    240 
    241     return filenum;
    242 }
    243 
    244 /* Create and add a new line opcode to a section, updating offset on insertion;
    245  * no optimization necessary.
    246  */
    247 static yasm_bytecode *
    248 dwarf2_dbgfmt_append_line_op(yasm_section *sect, dwarf_line_number_op opcode,
    249                              /*@only@*/ /*@null@*/ yasm_intnum *operand)
    250 {
    251     dwarf2_line_op *line_op = yasm_xmalloc(sizeof(dwarf2_line_op));
    252     yasm_bytecode *bc;
    253 
    254     line_op->opcode = opcode;
    255     line_op->operand = operand;
    256     line_op->ext_opcode = 0;
    257     line_op->ext_operand = NULL;
    258     line_op->ext_operand_int = NULL;
    259     line_op->ext_operandsize = 0;
    260 
    261     bc = yasm_bc_create_common(&dwarf2_line_op_bc_callback, line_op, 0);
    262     bc->len = 1;
    263     if (operand)
    264         bc->len += yasm_intnum_size_leb128(operand,
    265                                            opcode == DW_LNS_advance_line);
    266 
    267     yasm_dwarf2__append_bc(sect, bc);
    268     return bc;
    269 }
    270 
    271 /* Create and add a new extended line opcode to a section, updating offset on
    272  * insertion; no optimization necessary.
    273  */
    274 static yasm_bytecode *
    275 dwarf2_dbgfmt_append_line_ext_op(yasm_section *sect,
    276                                  dwarf_line_number_ext_op ext_opcode,
    277                                  unsigned long ext_operandsize,
    278                                  /*@null@*/ yasm_symrec *ext_operand)
    279 {
    280     dwarf2_line_op *line_op = yasm_xmalloc(sizeof(dwarf2_line_op));
    281     yasm_bytecode *bc;
    282 
    283     line_op->opcode = DW_LNS_extended_op;
    284     line_op->operand = yasm_intnum_create_uint(ext_operandsize+1);
    285     line_op->ext_opcode = ext_opcode;
    286     line_op->ext_operand = ext_operand;
    287     line_op->ext_operand_int = NULL;
    288     line_op->ext_operandsize = ext_operandsize;
    289 
    290     bc = yasm_bc_create_common(&dwarf2_line_op_bc_callback, line_op, 0);
    291     bc->len = 2 + yasm_intnum_size_leb128(line_op->operand, 0) +
    292         ext_operandsize;
    293 
    294     yasm_dwarf2__append_bc(sect, bc);
    295     return bc;
    296 }
    297 
    298 static yasm_bytecode *
    299 dwarf2_dbgfmt_append_line_ext_op_int(yasm_section *sect,
    300                                      dwarf_line_number_ext_op ext_opcode,
    301                                      /*@only@*/ yasm_intnum *ext_operand)
    302 {
    303     dwarf2_line_op *line_op = yasm_xmalloc(sizeof(dwarf2_line_op));
    304     unsigned long ext_operandsize = yasm_intnum_size_leb128(ext_operand, 0);
    305     yasm_bytecode *bc;
    306 
    307     line_op->opcode = DW_LNS_extended_op;
    308     line_op->operand = yasm_intnum_create_uint(ext_operandsize+1);
    309     line_op->ext_opcode = ext_opcode;
    310     line_op->ext_operand = NULL;
    311     line_op->ext_operand_int = ext_operand;
    312     line_op->ext_operandsize = ext_operandsize;
    313 
    314     bc = yasm_bc_create_common(&dwarf2_line_op_bc_callback, line_op, 0);
    315     bc->len = 2 + yasm_intnum_size_leb128(line_op->operand, 0) +
    316         ext_operandsize;
    317 
    318     yasm_dwarf2__append_bc(sect, bc);
    319     return bc;
    320 }
    321 
    322 static void
    323 dwarf2_dbgfmt_finalize_locs(yasm_section *sect, dwarf2_section_data *dsd)
    324 {
    325     /*@dependent@*/ yasm_symrec *lastsym = NULL;
    326     /*@null@*/ yasm_bytecode *bc;
    327     /*@null@*/ dwarf2_loc *loc;
    328 
    329     bc = yasm_section_bcs_first(sect);
    330     STAILQ_FOREACH(loc, &dsd->locs, link) {
    331         /* Find the first bytecode following this loc by looking at
    332          * the virtual line numbers.  XXX: this assumes the source file
    333          * order will be the same as the actual section order.  If we ever
    334          * implement subsegs this will NOT necessarily be true and this logic
    335          * will need to be fixed to handle it!
    336          *
    337          * Keep track of last symbol seen prior to the loc.
    338          */
    339         while (bc && bc->line <= loc->vline) {
    340             if (bc->symrecs) {
    341                 int i = 0;
    342                 while (bc->symrecs[i]) {
    343                     lastsym = bc->symrecs[i];
    344                     i++;
    345                 }
    346             }
    347             bc = yasm_bc__next(bc);
    348         }
    349         loc->sym = lastsym;
    350         loc->bc = bc;
    351     }
    352 }
    353 
    354 static int
    355 dwarf2_dbgfmt_gen_line_op(yasm_section *debug_line, dwarf2_line_state *state,
    356                           const dwarf2_loc *loc,
    357                           /*@null@*/ const dwarf2_loc *nextloc)
    358 {
    359     unsigned long addr_delta;
    360     long line_delta;
    361     int opcode1, opcode2;
    362     yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = state->dbgfmt_dwarf2;
    363 
    364     if (state->file != loc->file) {
    365         state->file = loc->file;
    366         dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_set_file,
    367                                      yasm_intnum_create_uint(state->file));
    368     }
    369     if (state->column != loc->column) {
    370         state->column = loc->column;
    371         dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_set_column,
    372                                      yasm_intnum_create_uint(state->column));
    373     }
    374     if (loc->discriminator != 0) {
    375         dwarf2_dbgfmt_append_line_ext_op_int(debug_line,
    376             DW_LNE_set_discriminator,
    377             yasm_intnum_create_uint(loc->discriminator));
    378     }
    379 #ifdef WITH_DWARF3
    380     if (loc->isa_change) {
    381         state->isa = loc->isa;
    382         dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_set_isa,
    383                                      yasm_intnum_create_uint(state->isa));
    384     }
    385 #endif
    386     if (state->is_stmt == 0 && loc->is_stmt == IS_STMT_SET) {
    387         state->is_stmt = 1;
    388         dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_negate_stmt, NULL);
    389     } else if (state->is_stmt == 1 && loc->is_stmt == IS_STMT_CLEAR) {
    390         state->is_stmt = 0;
    391         dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_negate_stmt, NULL);
    392     }
    393     if (loc->basic_block) {
    394         dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_set_basic_block, NULL);
    395     }
    396 #ifdef WITH_DWARF3
    397     if (loc->prologue_end) {
    398         dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_set_prologue_end, NULL);
    399     }
    400     if (loc->epilogue_begin) {
    401         dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_set_epilogue_begin,
    402                                      NULL);
    403     }
    404 #endif
    405 
    406     /* If multiple loc for the same location, use last */
    407     if (nextloc && nextloc->bc->offset == loc->bc->offset)
    408         return 0;
    409 
    410     if (!state->precbc) {
    411         /* Set the starting address for the section */
    412         if (!loc->sym) {
    413             /* shouldn't happen! */
    414             yasm_error_set(YASM_ERROR_GENERAL,
    415                            N_("could not find label prior to loc"));
    416             return 1;
    417         }
    418         dwarf2_dbgfmt_append_line_ext_op(debug_line, DW_LNE_set_address,
    419             dbgfmt_dwarf2->sizeof_address, loc->sym);
    420         addr_delta = 0;
    421     } else if (loc->bc) {
    422         if (state->precbc->offset > loc->bc->offset)
    423             yasm_internal_error(N_("dwarf2 address went backwards?"));
    424         addr_delta = loc->bc->offset - state->precbc->offset;
    425     } else
    426         return 0;       /* ran out of bytecodes!  XXX: do something? */
    427 
    428     /* Generate appropriate opcode(s).  Address can only increment,
    429      * whereas line number can go backwards.
    430      */
    431     line_delta = loc->line - state->line;
    432     state->line = loc->line;
    433 
    434     /* First handle the line delta */
    435     if (line_delta < DWARF2_LINE_BASE
    436         || line_delta >= DWARF2_LINE_BASE+DWARF2_LINE_RANGE) {
    437         /* Won't fit in special opcode, use (signed) line advance */
    438         dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_advance_line,
    439                                      yasm_intnum_create_int(line_delta));
    440         line_delta = 0;
    441     }
    442 
    443     /* Next handle the address delta */
    444     opcode1 = DWARF2_LINE_OPCODE_BASE + line_delta - DWARF2_LINE_BASE +
    445         DWARF2_LINE_RANGE * (addr_delta / dbgfmt_dwarf2->min_insn_len);
    446     opcode2 = DWARF2_LINE_OPCODE_BASE + line_delta - DWARF2_LINE_BASE +
    447         DWARF2_LINE_RANGE * ((addr_delta - DWARF2_MAX_SPECIAL_ADDR_DELTA) /
    448                              dbgfmt_dwarf2->min_insn_len);
    449     if (line_delta == 0 && addr_delta == 0) {
    450         /* Both line and addr deltas are 0: do DW_LNS_copy */
    451         dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_copy, NULL);
    452     } else if (addr_delta <= DWARF2_MAX_SPECIAL_ADDR_DELTA && opcode1 <= 255) {
    453         /* Addr delta in range of special opcode */
    454         dwarf2_dbgfmt_append_line_op(debug_line, opcode1, NULL);
    455     } else if (addr_delta <= 2*DWARF2_MAX_SPECIAL_ADDR_DELTA
    456                && opcode2 <= 255) {
    457         /* Addr delta in range of const_add_pc + special */
    458         dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_const_add_pc, NULL);
    459         dwarf2_dbgfmt_append_line_op(debug_line, opcode2, NULL);
    460     } else {
    461         /* Need advance_pc */
    462         dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_advance_pc,
    463                                      yasm_intnum_create_uint(addr_delta));
    464         /* Take care of any remaining line_delta and add entry to matrix */
    465         if (line_delta == 0)
    466             dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_copy, NULL);
    467         else {
    468             unsigned int opcode;
    469             opcode = DWARF2_LINE_OPCODE_BASE + line_delta - DWARF2_LINE_BASE;
    470             dwarf2_dbgfmt_append_line_op(debug_line, opcode, NULL);
    471         }
    472     }
    473     state->precbc = loc->bc;
    474     return 0;
    475 }
    476 
    477 typedef struct dwarf2_line_bc_info {
    478     yasm_section *debug_line;
    479     yasm_object *object;
    480     yasm_linemap *linemap;
    481     yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2;
    482     dwarf2_line_state *state;
    483     dwarf2_loc loc;
    484     unsigned long lastfile;
    485 } dwarf2_line_bc_info;
    486 
    487 static int
    488 dwarf2_filename_equals(const dwarf2_filename *fn,
    489                        char **dirs,
    490                        const char *pathname,
    491                        unsigned long dirlen,
    492                        const char *filename)
    493 {
    494     /* check directory */
    495     if (fn->dir == 0) {
    496         if (dirlen != 0)
    497             return 0;
    498     } else {
    499         if (strncmp(dirs[fn->dir-1], pathname, dirlen) != 0 ||
    500             dirs[fn->dir-1][dirlen] != '\0')
    501             return 0;
    502     }
    503 
    504     /* check filename */
    505     return strcmp(fn->filename, filename) == 0;
    506 }
    507 
    508 static int
    509 dwarf2_generate_line_bc(yasm_bytecode *bc, /*@null@*/ void *d)
    510 {
    511     dwarf2_line_bc_info *info = (dwarf2_line_bc_info *)d;
    512     yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = info->dbgfmt_dwarf2;
    513     unsigned long i;
    514     size_t dirlen;
    515     const char *pathname, *filename;
    516     /*@null@*/ yasm_bytecode *nextbc = yasm_bc__next(bc);
    517 
    518     if (nextbc && bc->offset == nextbc->offset)
    519         return 0;
    520 
    521     info->loc.vline = bc->line;
    522     info->loc.bc = bc;
    523 
    524     /* Keep track of last symbol seen */
    525     if (bc->symrecs) {
    526         i = 0;
    527         while (bc->symrecs[i]) {
    528             info->loc.sym = bc->symrecs[i];
    529             i++;
    530         }
    531     }
    532 
    533     yasm_linemap_lookup(info->linemap, bc->line, &pathname, &info->loc.line);
    534     dirlen = yasm__splitpath(pathname, &filename);
    535 
    536     /* Find file index; just linear search it unless it was the last used */
    537     if (info->lastfile > 0
    538         && dwarf2_filename_equals(&dbgfmt_dwarf2->filenames[info->lastfile-1],
    539                                   dbgfmt_dwarf2->dirs, pathname, dirlen,
    540                                   filename))
    541         info->loc.file = info->lastfile;
    542     else {
    543         for (i=0; i<dbgfmt_dwarf2->filenames_size; i++) {
    544             if (dwarf2_filename_equals(&dbgfmt_dwarf2->filenames[i],
    545                                        dbgfmt_dwarf2->dirs, pathname, dirlen,
    546                                        filename))
    547                 break;
    548         }
    549         if (i >= dbgfmt_dwarf2->filenames_size)
    550             yasm_internal_error(N_("could not find filename in table"));
    551         info->loc.file = i+1;
    552         info->lastfile = i+1;
    553     }
    554     if (dwarf2_dbgfmt_gen_line_op(info->debug_line, info->state, &info->loc,
    555                                   NULL))
    556         return 1;
    557     return 0;
    558 }
    559 
    560 typedef struct dwarf2_line_info {
    561     yasm_section *debug_line;   /* section to which line number info goes */
    562     yasm_object *object;
    563     yasm_linemap *linemap;
    564     yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2;
    565     yasm_errwarns *errwarns;
    566 
    567     /* Generate based on bytecodes (1) or locs (0)?  Use bytecodes if we're
    568      * generating line numbers for the actual assembly source file.
    569      */
    570     int asm_source;
    571 
    572     /* number of sections line number info generated for */
    573     size_t num_sections;
    574     /* last section line number info generated for */
    575     /*@null@*/ yasm_section *last_code;
    576 } dwarf2_line_info;
    577 
    578 static int
    579 dwarf2_generate_line_section(yasm_section *sect, /*@null@*/ void *d)
    580 {
    581     dwarf2_line_info *info = (dwarf2_line_info *)d;
    582     yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = info->dbgfmt_dwarf2;
    583     /*@null@*/ dwarf2_section_data *dsd;
    584     /*@null@*/ yasm_bytecode *bc;
    585     dwarf2_line_state state;
    586     unsigned long addr_delta;
    587 
    588     dsd = yasm_section_get_data(sect, &yasm_dwarf2__section_data_cb);
    589     if (!dsd) {
    590         if (info->asm_source && yasm_section_is_code(sect)) {
    591             /* Create line data for asm code sections */
    592             dsd = yasm_xmalloc(sizeof(dwarf2_section_data));
    593             STAILQ_INIT(&dsd->locs);
    594             yasm_section_add_data(sect, &yasm_dwarf2__section_data_cb, dsd);
    595         } else
    596             return 0;   /* no line data for this section */
    597     }
    598 
    599     info->num_sections++;
    600     info->last_code = sect;
    601 
    602     /* initialize state machine registers for each sequence */
    603     state.dbgfmt_dwarf2 = dbgfmt_dwarf2;
    604     state.address = 0;
    605     state.file = 1;
    606     state.line = 1;
    607     state.column = 0;
    608     state.isa = 0;
    609     state.is_stmt = DWARF2_LINE_DEFAULT_IS_STMT;
    610     state.precbc = NULL;
    611 
    612     if (info->asm_source) {
    613         dwarf2_line_bc_info bcinfo;
    614 
    615         bcinfo.debug_line = info->debug_line;
    616         bcinfo.object = info->object;
    617         bcinfo.linemap = info->linemap;
    618         bcinfo.dbgfmt_dwarf2 = dbgfmt_dwarf2;
    619         bcinfo.state = &state;
    620         bcinfo.lastfile = 0;
    621         bcinfo.loc.isa_change = 0;
    622         bcinfo.loc.column = 0;
    623         bcinfo.loc.discriminator = 0;
    624         bcinfo.loc.is_stmt = IS_STMT_NOCHANGE;
    625         bcinfo.loc.basic_block = 0;
    626         bcinfo.loc.prologue_end = 0;
    627         bcinfo.loc.epilogue_begin = 0;
    628         bcinfo.loc.sym = NULL;
    629 
    630         /* bcs_traverse() skips first "dummy" bytecode, so look at it
    631          * separately to determine the initial symrec.
    632          */
    633         bc = yasm_section_bcs_first(sect);
    634         if (bc->symrecs) {
    635             size_t i = 0;
    636             while (bc->symrecs[i]) {
    637                 bcinfo.loc.sym = bc->symrecs[i];
    638                 i++;
    639             }
    640         }
    641 
    642         yasm_section_bcs_traverse(sect, info->errwarns, &bcinfo,
    643                                   dwarf2_generate_line_bc);
    644     } else {
    645         /*@null@*/ dwarf2_loc *loc;
    646 
    647         dwarf2_dbgfmt_finalize_locs(sect, dsd);
    648 
    649         STAILQ_FOREACH(loc, &dsd->locs, link) {
    650             if (dwarf2_dbgfmt_gen_line_op(info->debug_line, &state, loc,
    651                                           STAILQ_NEXT(loc, link)))
    652                 return 1;
    653         }
    654     }
    655 
    656     /* End sequence: bring address to end of section, then output end
    657      * sequence opcode.  Don't use a special opcode to do this as we don't
    658      * want an extra entry in the line matrix.
    659      */
    660     if (!state.precbc)
    661         state.precbc = yasm_section_bcs_first(sect);
    662     bc = yasm_section_bcs_last(sect);
    663     addr_delta = yasm_bc_next_offset(bc) - state.precbc->offset;
    664     if (addr_delta == DWARF2_MAX_SPECIAL_ADDR_DELTA)
    665         dwarf2_dbgfmt_append_line_op(info->debug_line, DW_LNS_const_add_pc,
    666                                      NULL);
    667     else if (addr_delta > 0)
    668         dwarf2_dbgfmt_append_line_op(info->debug_line, DW_LNS_advance_pc,
    669                                      yasm_intnum_create_uint(addr_delta));
    670     dwarf2_dbgfmt_append_line_ext_op(info->debug_line, DW_LNE_end_sequence, 0,
    671                                      NULL);
    672 
    673     return 0;
    674 }
    675 
    676 static int
    677 dwarf2_generate_filename(const char *filename, void *d)
    678 {
    679     yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = (yasm_dbgfmt_dwarf2 *)d;
    680     dwarf2_dbgfmt_add_file(dbgfmt_dwarf2, 0, filename);
    681     return 0;
    682 }
    683 
    684 yasm_section *
    685 yasm_dwarf2__generate_line(yasm_object *object, yasm_linemap *linemap,
    686                            yasm_errwarns *errwarns, int asm_source,
    687                            /*@out@*/ yasm_section **main_code,
    688                            /*@out@*/ size_t *num_line_sections)
    689 {
    690     yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = (yasm_dbgfmt_dwarf2 *)object->dbgfmt;
    691     dwarf2_line_info info;
    692     int new;
    693     size_t i;
    694     yasm_bytecode *last, *sppbc;
    695     dwarf2_spp *spp;
    696     dwarf2_head *head;
    697 
    698     if (asm_source) {
    699         /* Generate dirs and filenames based on linemap */
    700         yasm_linemap_traverse_filenames(linemap, dbgfmt_dwarf2,
    701                                         dwarf2_generate_filename);
    702     }
    703 
    704     info.num_sections = 0;
    705     info.last_code = NULL;
    706     info.asm_source = asm_source;
    707     info.object = object;
    708     info.linemap = linemap;
    709     info.dbgfmt_dwarf2 = dbgfmt_dwarf2;
    710     info.debug_line = yasm_object_get_general(object, ".debug_line", 1, 0, 0,
    711                                               &new, 0);
    712     last = yasm_section_bcs_last(info.debug_line);
    713 
    714     /* header */
    715     head = yasm_dwarf2__add_head(dbgfmt_dwarf2, info.debug_line, NULL, 0, 0);
    716 
    717     /* statement program prologue */
    718     spp = yasm_xmalloc(sizeof(dwarf2_spp));
    719     sppbc = yasm_bc_create_common(&dwarf2_spp_bc_callback, spp, 0);
    720     sppbc->len = dbgfmt_dwarf2->sizeof_offset + 5 +
    721         NELEMS(line_opcode_num_operands);
    722 
    723     /* directory list */
    724     for (i=0; i<dbgfmt_dwarf2->dirs_size; i++)
    725         sppbc->len += (unsigned long)strlen(dbgfmt_dwarf2->dirs[i])+1;
    726     sppbc->len++;
    727 
    728     /* filename list */
    729     for (i=0; i<dbgfmt_dwarf2->filenames_size; i++) {
    730         if (!dbgfmt_dwarf2->filenames[i].filename) {
    731             yasm_error_set(YASM_ERROR_GENERAL,
    732                            N_("dwarf2 file number %d unassigned"), i+1);
    733             yasm_errwarn_propagate(errwarns, 0);
    734             continue;
    735         }
    736         sppbc->len +=
    737             (unsigned long)strlen(dbgfmt_dwarf2->filenames[i].filename) + 1 +
    738             yasm_size_uleb128(dbgfmt_dwarf2->filenames[i].dir) + 2;
    739     }
    740     sppbc->len++;
    741     yasm_dwarf2__append_bc(info.debug_line, sppbc);
    742 
    743     /* statement program */
    744     yasm_object_sections_traverse(object, (void *)&info,
    745                                   dwarf2_generate_line_section);
    746 
    747     /* mark end of line information */
    748     yasm_dwarf2__set_head_end(head, yasm_section_bcs_last(info.debug_line));
    749 
    750     *num_line_sections = info.num_sections;
    751     if (info.num_sections == 1)
    752         *main_code = info.last_code;
    753     else
    754         *main_code = NULL;
    755     return info.debug_line;
    756 }
    757 
    758 static void
    759 dwarf2_spp_bc_destroy(void *contents)
    760 {
    761     yasm_xfree(contents);
    762 }
    763 
    764 static void
    765 dwarf2_spp_bc_print(const void *contents, FILE *f, int indent_level)
    766 {
    767     /* TODO */
    768 }
    769 
    770 static int
    771 dwarf2_spp_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
    772                        void *add_span_data)
    773 {
    774     yasm_internal_error(N_("tried to calc_len a dwarf2 spp bytecode"));
    775     /*@notreached@*/
    776     return 0;
    777 }
    778 
    779 static int
    780 dwarf2_spp_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
    781                       unsigned char *bufstart, void *d,
    782                       yasm_output_value_func output_value,
    783                       yasm_output_reloc_func output_reloc)
    784 {
    785     yasm_object *object = yasm_section_get_object(bc->section);
    786     yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = (yasm_dbgfmt_dwarf2 *)object->dbgfmt;
    787     unsigned char *buf = *bufp;
    788     yasm_intnum *cval;
    789     size_t i, len;
    790 
    791     /* Prologue length (following this field) */
    792     cval = yasm_intnum_create_uint(bc->len - (unsigned long)(buf-*bufp) -
    793                                    dbgfmt_dwarf2->sizeof_offset);
    794     yasm_arch_intnum_tobytes(object->arch, cval, buf,
    795                              dbgfmt_dwarf2->sizeof_offset,
    796                              dbgfmt_dwarf2->sizeof_offset*8, 0, bc, 0);
    797     buf += dbgfmt_dwarf2->sizeof_offset;
    798 
    799     YASM_WRITE_8(buf, dbgfmt_dwarf2->min_insn_len);     /* minimum_instr_len */
    800     YASM_WRITE_8(buf, DWARF2_LINE_DEFAULT_IS_STMT);     /* default_is_stmt */
    801     YASM_WRITE_8(buf, DWARF2_LINE_BASE);                /* line_base */
    802     YASM_WRITE_8(buf, DWARF2_LINE_RANGE);               /* line_range */
    803     YASM_WRITE_8(buf, DWARF2_LINE_OPCODE_BASE);         /* opcode_base */
    804 
    805     /* Standard opcode # operands array */
    806     for (i=0; i<NELEMS(line_opcode_num_operands); i++)
    807         YASM_WRITE_8(buf, line_opcode_num_operands[i]);
    808 
    809     /* directory list */
    810     for (i=0; i<dbgfmt_dwarf2->dirs_size; i++) {
    811         len = strlen(dbgfmt_dwarf2->dirs[i])+1;
    812         memcpy(buf, dbgfmt_dwarf2->dirs[i], len);
    813         buf += len;
    814     }
    815     /* finish with single 0 byte */
    816     YASM_WRITE_8(buf, 0);
    817 
    818     /* filename list */
    819     for (i=0; i<dbgfmt_dwarf2->filenames_size; i++) {
    820         len = strlen(dbgfmt_dwarf2->filenames[i].filename)+1;
    821         memcpy(buf, dbgfmt_dwarf2->filenames[i].filename, len);
    822         buf += len;
    823 
    824         /* dir */
    825         buf += yasm_get_uleb128(dbgfmt_dwarf2->filenames[i].dir, buf);
    826         YASM_WRITE_8(buf, 0);   /* time */
    827         YASM_WRITE_8(buf, 0);   /* length */
    828     }
    829     /* finish with single 0 byte */
    830     YASM_WRITE_8(buf, 0);
    831 
    832     *bufp = buf;
    833 
    834     yasm_intnum_destroy(cval);
    835     return 0;
    836 }
    837 
    838 static void
    839 dwarf2_line_op_bc_destroy(void *contents)
    840 {
    841     dwarf2_line_op *line_op = (dwarf2_line_op *)contents;
    842     if (line_op->operand)
    843         yasm_intnum_destroy(line_op->operand);
    844     if (line_op->ext_operand_int)
    845         yasm_intnum_destroy(line_op->ext_operand_int);
    846     yasm_xfree(contents);
    847 }
    848 
    849 static void
    850 dwarf2_line_op_bc_print(const void *contents, FILE *f, int indent_level)
    851 {
    852     /* TODO */
    853 }
    854 
    855 static int
    856 dwarf2_line_op_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
    857                            void *add_span_data)
    858 {
    859     yasm_internal_error(N_("tried to calc_len a dwarf2 line_op bytecode"));
    860     /*@notreached@*/
    861     return 0;
    862 }
    863 
    864 static int
    865 dwarf2_line_op_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
    866                           unsigned char *bufstart, void *d,
    867                           yasm_output_value_func output_value,
    868                           yasm_output_reloc_func output_reloc)
    869 {
    870     dwarf2_line_op *line_op = (dwarf2_line_op *)bc->contents;
    871     unsigned char *buf = *bufp;
    872 
    873     YASM_WRITE_8(buf, line_op->opcode);
    874     if (line_op->operand)
    875         buf += yasm_intnum_get_leb128(line_op->operand, buf,
    876                                       line_op->opcode == DW_LNS_advance_line);
    877     if (line_op->ext_opcode > 0) {
    878         YASM_WRITE_8(buf, line_op->ext_opcode);
    879         if (line_op->ext_operand) {
    880             yasm_value value;
    881             yasm_value_init_sym(&value, line_op->ext_operand,
    882                                 line_op->ext_operandsize*8);
    883             output_value(&value, buf, line_op->ext_operandsize,
    884                          (unsigned long)(buf-bufstart), bc, 0, d);
    885             buf += line_op->ext_operandsize;
    886         }
    887         if (line_op->ext_operand_int) {
    888             buf += yasm_intnum_get_leb128(line_op->ext_operand_int, buf, 0);
    889         }
    890     }
    891 
    892     *bufp = buf;
    893     return 0;
    894 }
    895 
    896 void
    897 yasm_dwarf2__dir_loc(yasm_object *object, yasm_valparamhead *valparams,
    898                      yasm_valparamhead *objext_valparams, unsigned long line)
    899 {
    900     yasm_valparam *vp;
    901     int in_is_stmt = 0, in_isa = 0, in_discriminator = 0;
    902 
    903     /*@dependent@*/ /*@null@*/ const yasm_intnum *intn;
    904     dwarf2_section_data *dsd;
    905     dwarf2_loc *loc = yasm_xmalloc(sizeof(dwarf2_loc));
    906 
    907     /* File number (required) */
    908     if (!valparams || !(vp = yasm_vps_first(valparams)) ||
    909         vp->val || vp->type != YASM_PARAM_EXPR) {
    910         yasm_error_set(YASM_ERROR_SYNTAX, N_("file number required"));
    911         yasm_xfree(loc);
    912         return;
    913     }
    914     intn = yasm_expr_get_intnum(&vp->param.e, 0);
    915     if (!intn) {
    916         yasm_error_set(YASM_ERROR_NOT_CONSTANT,
    917                        N_("file number is not a constant"));
    918         yasm_xfree(loc);
    919         return;
    920     }
    921     if (yasm_intnum_sign(intn) != 1) {
    922         yasm_error_set(YASM_ERROR_VALUE, N_("file number less than one"));
    923         yasm_xfree(loc);
    924         return;
    925     }
    926     loc->file = yasm_intnum_get_uint(intn);
    927 
    928     /* Line number (required) */
    929     vp = yasm_vps_next(vp);
    930     if (!vp || vp->val || vp->type != YASM_PARAM_EXPR) {
    931         yasm_error_set(YASM_ERROR_SYNTAX, N_("line number required"));
    932         yasm_xfree(loc);
    933         return;
    934     }
    935     intn = yasm_expr_get_intnum(&vp->param.e, 0);
    936     if (!intn) {
    937         yasm_error_set(YASM_ERROR_NOT_CONSTANT,
    938                        N_("line number is not a constant"));
    939         yasm_xfree(loc);
    940         return;
    941     }
    942     loc->line = yasm_intnum_get_uint(intn);
    943 
    944     /* Generate new section data if it doesn't already exist */
    945     if (!object->cur_section) {
    946         yasm_error_set(YASM_ERROR_SYNTAX,
    947                        N_("[%s] can only be used inside of a section"), "loc");
    948         yasm_xfree(loc);
    949         return;
    950     }
    951     dsd = yasm_section_get_data(object->cur_section,
    952                                 &yasm_dwarf2__section_data_cb);
    953     if (!dsd) {
    954         dsd = yasm_xmalloc(sizeof(dwarf2_section_data));
    955         STAILQ_INIT(&dsd->locs);
    956         yasm_section_add_data(object->cur_section,
    957                               &yasm_dwarf2__section_data_cb, dsd);
    958     }
    959 
    960     /* Defaults for optional settings */
    961     loc->column = 0;
    962     loc->discriminator = 0;
    963     loc->isa_change = 0;
    964     loc->isa = 0;
    965     loc->is_stmt = IS_STMT_NOCHANGE;
    966     loc->basic_block = 0;
    967     loc->prologue_end = 0;
    968     loc->epilogue_begin = 0;
    969 
    970     /* Optional column number */
    971     vp = yasm_vps_next(vp);
    972     if (vp && !vp->val && vp->type == YASM_PARAM_EXPR) {
    973         intn = yasm_expr_get_intnum(&vp->param.e, 0);
    974         if (!intn) {
    975             yasm_error_set(YASM_ERROR_NOT_CONSTANT,
    976                            N_("column number is not a constant"));
    977             yasm_xfree(loc);
    978             return;
    979         }
    980         loc->column = yasm_intnum_get_uint(intn);
    981         vp = yasm_vps_next(vp);
    982     }
    983 
    984     /* Other options; note for GAS compatibility we need to support both:
    985      * is_stmt=1 (NASM) and
    986      * is_stmt 1 (GAS)
    987      */
    988     while (vp) {
    989         /*@null@*/ /*@dependent@*/ const char *s;
    990         /*@null@*/ /*@only@*/ yasm_expr *e;
    991 
    992 restart:
    993         if (in_is_stmt) {
    994             in_is_stmt = 0;
    995             if (!(e = yasm_vp_expr(vp, object->symtab, line)) ||
    996                 !(intn = yasm_expr_get_intnum(&e, 0))) {
    997                 yasm_error_set(YASM_ERROR_NOT_CONSTANT,
    998                                N_("is_stmt value is not a constant"));
    999                 yasm_xfree(loc);
   1000                 if (e)
   1001                     yasm_expr_destroy(e);
   1002                 return;
   1003             }
   1004             if (yasm_intnum_is_zero(intn))
   1005                 loc->is_stmt = IS_STMT_SET;
   1006             else if (yasm_intnum_is_pos1(intn))
   1007                 loc->is_stmt = IS_STMT_CLEAR;
   1008             else {
   1009                 yasm_error_set(YASM_ERROR_VALUE,
   1010                                N_("is_stmt value not 0 or 1"));
   1011                 yasm_xfree(loc);
   1012                 yasm_expr_destroy(e);
   1013                 return;
   1014             }
   1015             yasm_expr_destroy(e);
   1016         } else if (in_isa) {
   1017             in_isa = 0;
   1018             if (!(e = yasm_vp_expr(vp, object->symtab, line)) ||
   1019                 !(intn = yasm_expr_get_intnum(&e, 0))) {
   1020                 yasm_error_set(YASM_ERROR_NOT_CONSTANT,
   1021                                N_("isa value is not a constant"));
   1022                 yasm_xfree(loc);
   1023                 if (e)
   1024                     yasm_expr_destroy(e);
   1025                 return;
   1026             }
   1027             if (yasm_intnum_sign(intn) < 0) {
   1028                 yasm_error_set(YASM_ERROR_VALUE,
   1029                                N_("isa value less than zero"));
   1030                 yasm_xfree(loc);
   1031                 yasm_expr_destroy(e);
   1032                 return;
   1033             }
   1034             loc->isa_change = 1;
   1035             loc->isa = yasm_intnum_get_uint(intn);
   1036             yasm_expr_destroy(e);
   1037         } else if (in_discriminator) {
   1038             in_discriminator = 0;
   1039             if (!(e = yasm_vp_expr(vp, object->symtab, line)) ||
   1040                 !(intn = yasm_expr_get_intnum(&e, 0))) {
   1041                 yasm_error_set(YASM_ERROR_NOT_CONSTANT,
   1042                                N_("discriminator value is not a constant"));
   1043                 yasm_xfree(loc);
   1044                 if (e)
   1045                     yasm_expr_destroy(e);
   1046                 return;
   1047             }
   1048             if (yasm_intnum_sign(intn) < 0) {
   1049                 yasm_error_set(YASM_ERROR_VALUE,
   1050                                N_("discriminator value less than zero"));
   1051                 yasm_xfree(loc);
   1052                 yasm_expr_destroy(e);
   1053                 return;
   1054             }
   1055             loc->discriminator = yasm_intnum_get_uint(intn);
   1056             yasm_expr_destroy(e);
   1057         } else if (!vp->val && (s = yasm_vp_id(vp))) {
   1058             if (yasm__strcasecmp(s, "is_stmt") == 0)
   1059                 in_is_stmt = 1;
   1060             else if (yasm__strcasecmp(s, "isa") == 0)
   1061                 in_isa = 1;
   1062             else if (yasm__strcasecmp(s, "discriminator") == 0)
   1063                 in_discriminator = 1;
   1064             else if (yasm__strcasecmp(s, "basic_block") == 0)
   1065                 loc->basic_block = 1;
   1066             else if (yasm__strcasecmp(s, "prologue_end") == 0)
   1067                 loc->prologue_end = 1;
   1068             else if (yasm__strcasecmp(s, "epilogue_begin") == 0)
   1069                 loc->epilogue_begin = 1;
   1070             else
   1071                 yasm_warn_set(YASM_WARN_GENERAL,
   1072                               N_("unrecognized loc option `%s'"), s);
   1073         } else if (!vp->val) {
   1074             yasm_warn_set(YASM_WARN_GENERAL,
   1075                           N_("unrecognized numeric qualifier"));
   1076         } else if (yasm__strcasecmp(vp->val, "is_stmt") == 0) {
   1077             in_is_stmt = 1;
   1078             goto restart; /* don't go to the next valparam */
   1079         } else if (yasm__strcasecmp(vp->val, "isa") == 0) {
   1080             in_isa = 1;
   1081             goto restart; /* don't go to the next valparam */
   1082         } else if (yasm__strcasecmp(vp->val, "discriminator") == 0) {
   1083             in_discriminator = 1;
   1084             goto restart; /* don't go to the next valparam */
   1085         } else
   1086             yasm_warn_set(YASM_WARN_GENERAL,
   1087                           N_("unrecognized loc option `%s'"), vp->val);
   1088         vp = yasm_vps_next(vp);
   1089     }
   1090 
   1091     if (in_is_stmt || in_isa || in_discriminator) {
   1092         yasm_error_set(YASM_ERROR_SYNTAX, N_("%s requires value"),
   1093                        in_is_stmt ? "is_stmt" :
   1094                        (in_isa ? "isa" : "discriminator"));
   1095         yasm_xfree(loc);
   1096         return;
   1097     }
   1098 
   1099     /* Append new location */
   1100     loc->vline = line;
   1101     loc->bc = NULL;
   1102     loc->sym = NULL;
   1103     STAILQ_INSERT_TAIL(&dsd->locs, loc, link);
   1104 }
   1105 
   1106 void
   1107 yasm_dwarf2__dir_file(yasm_object *object, yasm_valparamhead *valparams,
   1108                       yasm_valparamhead *objext_valparams, unsigned long line)
   1109 {
   1110     yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = (yasm_dbgfmt_dwarf2 *)object->dbgfmt;
   1111     yasm_valparam *vp;
   1112     /*@dependent@*/ /*@null@*/ const yasm_intnum *file_intn;
   1113     unsigned long filenum;
   1114 
   1115     if (!valparams) {
   1116         yasm_error_set(YASM_ERROR_SYNTAX, N_("[%s] requires an argument"),
   1117                        "FILE");
   1118         return;
   1119     }
   1120 
   1121     vp = yasm_vps_first(valparams);
   1122     if (yasm_vp_string(vp)) {
   1123         /* Just a bare filename */
   1124         yasm_object_set_source_fn(object, yasm_vp_string(vp));
   1125         return;
   1126     }
   1127 
   1128     /* Otherwise.. first vp is the file number */
   1129     if (vp->type != YASM_PARAM_EXPR ||
   1130         !(file_intn = yasm_expr_get_intnum(&vp->param.e, 0))) {
   1131         yasm_error_set(YASM_ERROR_NOT_CONSTANT,
   1132                        N_("file number is not a constant"));
   1133         return;
   1134     }
   1135     filenum = yasm_intnum_get_uint(file_intn);
   1136 
   1137     vp = yasm_vps_next(vp);
   1138     if (!yasm_vp_string(vp)) {
   1139         yasm_error_set(YASM_ERROR_SYNTAX,
   1140                        N_("file number given but no filename"));
   1141         return;
   1142     }
   1143 
   1144     dwarf2_dbgfmt_add_file(dbgfmt_dwarf2, filenum, yasm_vp_string(vp));
   1145 }
   1146