summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Johnson <peter@tortall.net>2010-08-16 02:28:36 +0000
committerPeter Johnson <peter@tortall.net>2010-08-16 02:28:36 +0000
commit985038f102fc23c63e9012134dd35cfedf82e071 (patch)
treeffbea82624f5022d98b3fa40c36a5a6303204d30
parent2678cb3c3a42b3870a209ed8de38c1a16449695a (diff)
downloadyasm-985038f102fc23c63e9012134dd35cfedf82e071.tar.gz
dwarf2: Add support for .loc "discriminator" option.
svn path=/trunk/yasm/; revision=2359
-rw-r--r--modules/dbgfmts/dwarf2/dwarf2-dbgfmt.h1
-rw-r--r--modules/dbgfmts/dwarf2/dwarf2-line.c73
2 files changed, 70 insertions, 4 deletions
diff --git a/modules/dbgfmts/dwarf2/dwarf2-dbgfmt.h b/modules/dbgfmts/dwarf2/dwarf2-dbgfmt.h
index 7331bf36..d939c1d4 100644
--- a/modules/dbgfmts/dwarf2/dwarf2-dbgfmt.h
+++ b/modules/dbgfmts/dwarf2/dwarf2-dbgfmt.h
@@ -66,6 +66,7 @@ typedef struct dwarf2_loc {
unsigned long file; /* index into table of filenames */
unsigned long line; /* source line number */
unsigned long column; /* source column */
+ unsigned long discriminator;
int isa_change;
unsigned long isa;
enum {
diff --git a/modules/dbgfmts/dwarf2/dwarf2-line.c b/modules/dbgfmts/dwarf2/dwarf2-line.c
index 3f7b96ed..b5d3ad35 100644
--- a/modules/dbgfmts/dwarf2/dwarf2-line.c
+++ b/modules/dbgfmts/dwarf2/dwarf2-line.c
@@ -77,7 +77,8 @@ static unsigned char line_opcode_num_operands[DWARF2_LINE_OPCODE_BASE-1] = {
typedef enum {
DW_LNE_end_sequence = 1,
DW_LNE_set_address,
- DW_LNE_define_file
+ DW_LNE_define_file,
+ DW_LNE_set_discriminator
} dwarf_line_number_ext_op;
/* Base and range for line offsets in special opcodes */
@@ -120,6 +121,7 @@ typedef struct dwarf2_line_op {
/* extended opcode */
dwarf_line_number_ext_op ext_opcode;
/*@null@*/ /*@dependent@*/ yasm_symrec *ext_operand; /* unsigned */
+ /*@null@*/ /*@dependent@*/ yasm_intnum *ext_operand_int; /* unsigned */
unsigned long ext_operandsize;
} dwarf2_line_op;
@@ -254,6 +256,7 @@ dwarf2_dbgfmt_append_line_op(yasm_section *sect, dwarf_line_number_op opcode,
line_op->operand = operand;
line_op->ext_opcode = 0;
line_op->ext_operand = NULL;
+ line_op->ext_operand_int = NULL;
line_op->ext_operandsize = 0;
bc = yasm_bc_create_common(&dwarf2_line_op_bc_callback, line_op, 0);
@@ -282,6 +285,31 @@ dwarf2_dbgfmt_append_line_ext_op(yasm_section *sect,
line_op->operand = yasm_intnum_create_uint(ext_operandsize+1);
line_op->ext_opcode = ext_opcode;
line_op->ext_operand = ext_operand;
+ line_op->ext_operand_int = NULL;
+ line_op->ext_operandsize = ext_operandsize;
+
+ bc = yasm_bc_create_common(&dwarf2_line_op_bc_callback, line_op, 0);
+ bc->len = 2 + yasm_intnum_size_leb128(line_op->operand, 0) +
+ ext_operandsize;
+
+ yasm_dwarf2__append_bc(sect, bc);
+ return bc;
+}
+
+static yasm_bytecode *
+dwarf2_dbgfmt_append_line_ext_op_int(yasm_section *sect,
+ dwarf_line_number_ext_op ext_opcode,
+ /*@only@*/ yasm_intnum *ext_operand)
+{
+ dwarf2_line_op *line_op = yasm_xmalloc(sizeof(dwarf2_line_op));
+ unsigned long ext_operandsize = yasm_intnum_size_leb128(ext_operand, 0);
+ yasm_bytecode *bc;
+
+ line_op->opcode = DW_LNS_extended_op;
+ line_op->operand = yasm_intnum_create_uint(ext_operandsize+1);
+ line_op->ext_opcode = ext_opcode;
+ line_op->ext_operand = NULL;
+ line_op->ext_operand_int = ext_operand;
line_op->ext_operandsize = ext_operandsize;
bc = yasm_bc_create_common(&dwarf2_line_op_bc_callback, line_op, 0);
@@ -344,6 +372,11 @@ dwarf2_dbgfmt_gen_line_op(yasm_section *debug_line, dwarf2_line_state *state,
dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_set_column,
yasm_intnum_create_uint(state->column));
}
+ if (loc->discriminator != 0) {
+ dwarf2_dbgfmt_append_line_ext_op_int(debug_line,
+ DW_LNE_set_discriminator,
+ yasm_intnum_create_uint(loc->discriminator));
+ }
#ifdef WITH_DWARF3
if (loc->isa_change) {
state->isa = loc->isa;
@@ -780,6 +813,8 @@ dwarf2_line_op_bc_destroy(void *contents)
dwarf2_line_op *line_op = (dwarf2_line_op *)contents;
if (line_op->operand)
yasm_intnum_destroy(line_op->operand);
+ if (line_op->ext_operand_int)
+ yasm_intnum_destroy(line_op->ext_operand_int);
yasm_xfree(contents);
}
@@ -820,6 +855,9 @@ dwarf2_line_op_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
(unsigned long)(buf-*bufp), bc, 0, d);
buf += line_op->ext_operandsize;
}
+ if (line_op->ext_operand_int) {
+ buf += yasm_intnum_get_leb128(line_op->ext_operand_int, buf, 0);
+ }
}
*bufp = buf;
@@ -831,7 +869,7 @@ yasm_dwarf2__dir_loc(yasm_object *object, yasm_valparamhead *valparams,
yasm_valparamhead *objext_valparams, unsigned long line)
{
yasm_valparam *vp;
- int in_is_stmt = 0, in_isa = 0;
+ int in_is_stmt = 0, in_isa = 0, in_discriminator = 0;
/*@dependent@*/ /*@null@*/ const yasm_intnum *intn;
dwarf2_section_data *dsd;
@@ -892,6 +930,7 @@ yasm_dwarf2__dir_loc(yasm_object *object, yasm_valparamhead *valparams,
/* Defaults for optional settings */
loc->column = 0;
+ loc->discriminator = 0;
loc->isa_change = 0;
loc->isa = 0;
loc->is_stmt = IS_STMT_NOCHANGE;
@@ -966,11 +1005,33 @@ restart:
loc->isa_change = 1;
loc->isa = yasm_intnum_get_uint(intn);
yasm_expr_destroy(e);
+ } else if (in_discriminator) {
+ in_discriminator = 0;
+ if (!(e = yasm_vp_expr(vp, object->symtab, line)) ||
+ !(intn = yasm_expr_get_intnum(&e, 0))) {
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("discriminator value is not a constant"));
+ yasm_xfree(loc);
+ if (e)
+ yasm_expr_destroy(e);
+ return;
+ }
+ if (yasm_intnum_sign(intn) < 0) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("discriminator value less than zero"));
+ yasm_xfree(loc);
+ yasm_expr_destroy(e);
+ return;
+ }
+ loc->discriminator = yasm_intnum_get_uint(intn);
+ yasm_expr_destroy(e);
} else if (!vp->val && (s = yasm_vp_id(vp))) {
if (yasm__strcasecmp(s, "is_stmt") == 0)
in_is_stmt = 1;
else if (yasm__strcasecmp(s, "isa") == 0)
in_isa = 1;
+ else if (yasm__strcasecmp(s, "discriminator") == 0)
+ in_discriminator = 1;
else if (yasm__strcasecmp(s, "basic_block") == 0)
loc->basic_block = 1;
else if (yasm__strcasecmp(s, "prologue_end") == 0)
@@ -989,15 +1050,19 @@ restart:
} else if (yasm__strcasecmp(vp->val, "isa") == 0) {
in_isa = 1;
goto restart; /* don't go to the next valparam */
+ } else if (yasm__strcasecmp(vp->val, "discriminator") == 0) {
+ in_discriminator = 1;
+ goto restart; /* don't go to the next valparam */
} else
yasm_warn_set(YASM_WARN_GENERAL,
N_("unrecognized loc option `%s'"), vp->val);
vp = yasm_vps_next(vp);
}
- if (in_is_stmt || in_isa) {
+ if (in_is_stmt || in_isa || in_discriminator) {
yasm_error_set(YASM_ERROR_SYNTAX, N_("%s requires value"),
- in_is_stmt ? "is_stmt" : "isa");
+ in_is_stmt ? "is_stmt" :
+ (in_isa ? "isa" : "discriminator"));
yasm_xfree(loc);
return;
}