yasm_symrec *sym; /* last symbol preceding */
} dwarf2_loc;
+/* Line number state machine register state */
+typedef struct dwarf2_line_state {
+ /* static configuration */
+ yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2;
+
+ /* DWARF2 state machine registers */
+ unsigned long address;
+ unsigned long file;
+ unsigned long line;
+ unsigned long column;
+ unsigned long isa;
+ int is_stmt;
+
+ /* other state information */
+ /*@null@*/ yasm_bytecode *precbc;
+} dwarf2_line_state;
+
/* Per-section data */
typedef struct dwarf2_section_data {
/* The locations set by the .loc directives in this section, in assembly
return bc;
}
-static int
-dwarf2_dbgfmt_generate_section(yasm_section *sect, /*@null@*/ void *d)
+static void
+dwarf2_dbgfmt_finalize_locs(yasm_section *sect, dwarf2_section_data *dsd)
{
- dwarf2_info *info = (dwarf2_info *)d;
- yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = info->dbgfmt_dwarf2;
- /*@null@*/ dwarf2_section_data *dsd;
- /*@null@*/ dwarf2_loc *loc;
- /*@null@*/ yasm_bytecode *precbc = NULL, *bc;
/*@dependent@*/ yasm_symrec *lastsym = NULL;
- unsigned long addr_delta;
-
- /* registers for state machine for each sequence */
- unsigned long address = 0;
- unsigned long file = 1;
- unsigned long line = 1;
- unsigned long column = 0;
- unsigned long isa = 0;
- int is_stmt = DWARF2_LINE_DEFAULT_IS_STMT;
-
- dsd = yasm_section_get_data(sect, &dwarf2_section_data_cb);
- if (!dsd)
- return 0; /* no line data for this section */
+ /*@null@*/ yasm_bytecode *bc;
+ /*@null@*/ dwarf2_loc *loc;
bc = yasm_section_bcs_first(sect);
STAILQ_FOREACH(loc, &dsd->locs, link) {
loc->sym = lastsym;
loc->bc = bc;
}
+}
- STAILQ_FOREACH(loc, &dsd->locs, link) {
- long line_delta;
- int opcode1, opcode2;
-
- if (file != loc->file) {
- file = loc->file;
- dwarf2_dbgfmt_append_line_op(info->debug_line, DW_LNS_set_file,
- yasm_intnum_create_uint(file));
- }
- if (column != loc->column) {
- column = loc->column;
- dwarf2_dbgfmt_append_line_op(info->debug_line, DW_LNS_set_column,
- yasm_intnum_create_uint(column));
- }
+static int
+dwarf2_dbgfmt_gen_line_op(yasm_section *debug_line, dwarf2_line_state *state,
+ dwarf2_loc *loc, /*@null@*/ dwarf2_loc *nextloc)
+{
+ unsigned long addr_delta;
+ long line_delta;
+ int opcode1, opcode2;
+ yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = state->dbgfmt_dwarf2;
+
+ if (state->file != loc->file) {
+ state->file = loc->file;
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_set_file,
+ yasm_intnum_create_uint(state->file));
+ }
+ if (state->column != loc->column) {
+ state->column = loc->column;
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_set_column,
+ yasm_intnum_create_uint(state->column));
+ }
#ifdef WITH_DWARF3
- if (loc->isa_change) {
- isa = loc->isa;
- dwarf2_dbgfmt_append_line_op(info->debug_line, DW_LNS_set_isa,
- yasm_intnum_create_uint(isa));
- }
+ if (loc->isa_change) {
+ state->isa = loc->isa;
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_set_isa,
+ yasm_intnum_create_uint(state->isa));
+ }
#endif
- if (is_stmt == 0 && loc->is_stmt == IS_STMT_SET) {
- is_stmt = 1;
- dwarf2_dbgfmt_append_line_op(info->debug_line, DW_LNS_negate_stmt,
- NULL);
- } else if (is_stmt == 1 && loc->is_stmt == IS_STMT_CLEAR) {
- is_stmt = 0;
- dwarf2_dbgfmt_append_line_op(info->debug_line, DW_LNS_negate_stmt,
- NULL);
- }
- if (loc->basic_block) {
- dwarf2_dbgfmt_append_line_op(info->debug_line,
- DW_LNS_set_basic_block, NULL);
- }
+ if (state->is_stmt == 0 && loc->is_stmt == IS_STMT_SET) {
+ state->is_stmt = 1;
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_negate_stmt, NULL);
+ } else if (state->is_stmt == 1 && loc->is_stmt == IS_STMT_CLEAR) {
+ state->is_stmt = 0;
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_negate_stmt, NULL);
+ }
+ if (loc->basic_block) {
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_set_basic_block, NULL);
+ }
#ifdef WITH_DWARF3
- if (loc->prologue_end) {
- dwarf2_dbgfmt_append_line_op(info->debug_line,
- DW_LNS_set_prologue_end, NULL);
- }
- if (loc->epilogue_begin) {
- dwarf2_dbgfmt_append_line_op(info->debug_line,
- DW_LNS_set_epilogue_begin, NULL);
- }
+ if (loc->prologue_end) {
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_set_prologue_end, NULL);
+ }
+ if (loc->epilogue_begin) {
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_set_epilogue_begin,
+ NULL);
+ }
#endif
- /* If multiple loc for the same location, use last */
- bc = loc->bc;
- if (STAILQ_NEXT(loc, link)
- && STAILQ_NEXT(loc, link)->bc->offset == bc->offset)
- continue;
-
- if (!precbc) {
- /* Set the starting address for the section */
- if (!loc->sym) {
- /* shouldn't happen! */
- yasm__error(loc->line, N_("could not find label prior to loc"));
- return 1;
- }
- dwarf2_dbgfmt_append_line_ext_op(info->debug_line,
- DW_LNE_set_address, dbgfmt_dwarf2->sizeof_address,
- yasm_expr_create_ident(yasm_expr_sym(loc->sym), loc->line));
- addr_delta = 0;
- } else if (bc) {
- if (precbc->offset > bc->offset)
- yasm_internal_error(N_("dwarf2 address went backwards?"));
- addr_delta = bc->offset - precbc->offset;
- } else
- break; /* ran out of bytecodes! XXX: do something? */
+ /* If multiple loc for the same location, use last */
+ if (nextloc && nextloc->bc->offset == loc->bc->offset)
+ return 0;
- /* Generate appropriate opcode(s). Address can only increment,
- * whereas line number can go backwards.
- */
- line_delta = loc->line - line;
- line = loc->line;
-
- /* First handle the line delta */
- if (line_delta < DWARF2_LINE_BASE
- || line_delta >= DWARF2_LINE_BASE+DWARF2_LINE_RANGE) {
- /* Won't fit in special opcode, use (signed) line advance */
- dwarf2_dbgfmt_append_line_op(info->debug_line, DW_LNS_advance_line,
- yasm_intnum_create_int(line_delta));
- line_delta = 0;
+ if (!state->precbc) {
+ /* Set the starting address for the section */
+ if (!loc->sym) {
+ /* shouldn't happen! */
+ yasm__error(loc->line, N_("could not find label prior to loc"));
+ return 1;
}
+ dwarf2_dbgfmt_append_line_ext_op(debug_line, DW_LNE_set_address,
+ dbgfmt_dwarf2->sizeof_address,
+ yasm_expr_create_ident(yasm_expr_sym(loc->sym), loc->line));
+ addr_delta = 0;
+ } else if (loc->bc) {
+ if (state->precbc->offset > loc->bc->offset)
+ yasm_internal_error(N_("dwarf2 address went backwards?"));
+ addr_delta = loc->bc->offset - state->precbc->offset;
+ } else
+ return 0; /* ran out of bytecodes! XXX: do something? */
+
+ /* Generate appropriate opcode(s). Address can only increment,
+ * whereas line number can go backwards.
+ */
+ line_delta = loc->line - state->line;
+ state->line = loc->line;
+
+ /* First handle the line delta */
+ if (line_delta < DWARF2_LINE_BASE
+ || line_delta >= DWARF2_LINE_BASE+DWARF2_LINE_RANGE) {
+ /* Won't fit in special opcode, use (signed) line advance */
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_advance_line,
+ yasm_intnum_create_int(line_delta));
+ line_delta = 0;
+ }
- /* Next handle the address delta */
- opcode1 = DWARF2_LINE_OPCODE_BASE + line_delta - DWARF2_LINE_BASE +
- DWARF2_LINE_RANGE * (addr_delta / dbgfmt_dwarf2->min_insn_len);
- opcode2 = DWARF2_LINE_OPCODE_BASE + line_delta - DWARF2_LINE_BASE +
- DWARF2_LINE_RANGE * ((addr_delta - DWARF2_MAX_SPECIAL_ADDR_DELTA) /
- dbgfmt_dwarf2->min_insn_len);
- if (line_delta == 0 && addr_delta == 0) {
- /* Both line and addr deltas are 0: do DW_LNS_copy */
- dwarf2_dbgfmt_append_line_op(info->debug_line, DW_LNS_copy, NULL);
- } else if (addr_delta <= DWARF2_MAX_SPECIAL_ADDR_DELTA
- && opcode1 <= 255) {
- /* Addr delta in range of special opcode */
- dwarf2_dbgfmt_append_line_op(info->debug_line, opcode1, NULL);
- } else if (addr_delta <= 2*DWARF2_MAX_SPECIAL_ADDR_DELTA
- && opcode2 <= 255) {
- /* Addr delta in range of const_add_pc + special */
+ /* Next handle the address delta */
+ opcode1 = DWARF2_LINE_OPCODE_BASE + line_delta - DWARF2_LINE_BASE +
+ DWARF2_LINE_RANGE * (addr_delta / dbgfmt_dwarf2->min_insn_len);
+ opcode2 = DWARF2_LINE_OPCODE_BASE + line_delta - DWARF2_LINE_BASE +
+ DWARF2_LINE_RANGE * ((addr_delta - DWARF2_MAX_SPECIAL_ADDR_DELTA) /
+ dbgfmt_dwarf2->min_insn_len);
+ if (line_delta == 0 && addr_delta == 0) {
+ /* Both line and addr deltas are 0: do DW_LNS_copy */
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_copy, NULL);
+ } else if (addr_delta <= DWARF2_MAX_SPECIAL_ADDR_DELTA && opcode1 <= 255) {
+ /* Addr delta in range of special opcode */
+ dwarf2_dbgfmt_append_line_op(debug_line, opcode1, NULL);
+ } else if (addr_delta <= 2*DWARF2_MAX_SPECIAL_ADDR_DELTA
+ && opcode2 <= 255) {
+ /* Addr delta in range of const_add_pc + special */
+ unsigned int opcode;
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_const_add_pc, NULL);
+ dwarf2_dbgfmt_append_line_op(debug_line, opcode2, NULL);
+ } else {
+ /* Need advance_pc */
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_advance_pc,
+ yasm_intnum_create_uint(addr_delta));
+ /* Take care of any remaining line_delta and add entry to matrix */
+ if (line_delta == 0)
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_copy, NULL);
+ else {
unsigned int opcode;
- dwarf2_dbgfmt_append_line_op(info->debug_line, DW_LNS_const_add_pc,
- NULL);
- dwarf2_dbgfmt_append_line_op(info->debug_line, opcode2, NULL);
- } else {
- /* Need advance_pc */
- dwarf2_dbgfmt_append_line_op(info->debug_line, DW_LNS_advance_pc,
- yasm_intnum_create_uint(addr_delta));
- /* Take care of any remaining line_delta and add entry to matrix */
- if (line_delta == 0)
- dwarf2_dbgfmt_append_line_op(info->debug_line, DW_LNS_copy,
- NULL);
- else {
- unsigned int opcode;
- opcode = DWARF2_LINE_OPCODE_BASE + line_delta -
- DWARF2_LINE_BASE;
- dwarf2_dbgfmt_append_line_op(info->debug_line, opcode, NULL);
- }
+ opcode = DWARF2_LINE_OPCODE_BASE + line_delta - DWARF2_LINE_BASE;
+ dwarf2_dbgfmt_append_line_op(debug_line, opcode, NULL);
}
+ }
+ state->precbc = loc->bc;
+ return 0;
+}
- precbc = bc;
+static int
+dwarf2_dbgfmt_generate_section(yasm_section *sect, /*@null@*/ void *d)
+{
+ dwarf2_info *info = (dwarf2_info *)d;
+ yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = info->dbgfmt_dwarf2;
+ /*@null@*/ dwarf2_section_data *dsd;
+ /*@null@*/ dwarf2_loc *loc;
+ /*@null@*/ yasm_bytecode *bc;
+ dwarf2_line_state state;
+ unsigned long addr_delta;
+
+ dsd = yasm_section_get_data(sect, &dwarf2_section_data_cb);
+ if (!dsd)
+ return 0; /* no line data for this section */
+
+ /* initialize state machine registers for each sequence */
+ state.dbgfmt_dwarf2 = dbgfmt_dwarf2;
+ state.address = 0;
+ state.file = 1;
+ state.line = 1;
+ state.column = 0;
+ state.isa = 0;
+ state.is_stmt = DWARF2_LINE_DEFAULT_IS_STMT;
+ state.precbc = NULL;
+
+ dwarf2_dbgfmt_finalize_locs(sect, dsd);
+
+ STAILQ_FOREACH(loc, &dsd->locs, link) {
+ if (dwarf2_dbgfmt_gen_line_op(info->debug_line, &state, loc,
+ STAILQ_NEXT(loc, link)))
+ return 1;
}
/* End sequence: bring address to end of section, then output end
* want an extra entry in the line matrix.
*/
bc = yasm_section_bcs_last(sect);
- addr_delta = bc->offset + bc->len - precbc->offset;
+ addr_delta = bc->offset + bc->len - state.precbc->offset;
if (addr_delta == DWARF2_MAX_SPECIAL_ADDR_DELTA)
dwarf2_dbgfmt_append_line_op(info->debug_line, DW_LNS_const_add_pc,
NULL);