* dwarf2-dbgfmt.c (generate_section): Split off large chunks into gen_line_op

and finalize_locs functions, preparing for later asm-source dbg generation.

svn path=/trunk/yasm/; revision=1357
0.5.0rc2
Peter Johnson 19 years ago
parent f7665e25c5
commit 274e1fa43c
  1. 292
      modules/dbgfmts/dwarf2/dwarf2-dbgfmt.c

@ -149,6 +149,23 @@ typedef struct dwarf2_loc {
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
@ -355,28 +372,12 @@ dwarf2_dbgfmt_append_line_ext_op(yasm_section *sect,
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) {
@ -401,128 +402,157 @@ dwarf2_dbgfmt_generate_section(yasm_section *sect, /*@null@*/ void *d)
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
@ -530,7 +560,7 @@ dwarf2_dbgfmt_generate_section(yasm_section *sect, /*@null@*/ void *d)
* 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);

Loading…
Cancel
Save