From 42be36b328ae784ae6981da7c7cab95b67ed7737 Mon Sep 17 00:00:00 2001 From: Caroline Tice Date: Fri, 18 May 2007 19:42:42 +0000 Subject: [PATCH] Add ability to report when a variable's value is uninitialized, based on information provided by the compiler. Also add new DWARF OP, DW_OP_GNU_uninit, for this purpose. --- gdb/ChangeLog | 23 +++++++++++++++++++++++ gdb/c-valprint.c | 3 +++ gdb/dwarf2expr.c | 13 ++++++++++++- gdb/dwarf2expr.h | 4 ++++ gdb/dwarf2loc.c | 2 ++ gdb/dwarf2read.c | 5 +++++ gdb/value.c | 20 ++++++++++++++++++++ include/elf/dwarf2.h | 1 + 8 files changed, 70 insertions(+), 1 deletion(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 1f6a1e048a..4852d1f09d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,26 @@ +2007-05-18 Caroline Tice + + * c-valprint.c (c_value_print): If the initialized field of the + value struct is 0, print out "[uninitialized]" before the value. + * dwarf2expr.c (execute_stack_op): Initialize ctx->initialized field; + allow DW_OP_GNU_uninit as legal op following a DW_OP_reg op or a + DW_OP_regx op; add case for DW_OP_GNU_uninit and update + ctx->initialized appropriately. Verify no location op follows + DW_OP_GNU_uninit. + * dwarf2expr.h (struct dwarf_expr_context): New field, initialized. + * dwarf2loc.c (dwarf2_evaluate_loc_desc): Add call to + set_value_initialized. + * dwarf2read.c (dwarf_stack_op_name): Add case for DW_OP_GNU_uninit. + (decode_locdesc): Add case for DW_OP_GNU_uninit. + * value.c (struct value): New field, initialized. + (allocate_value): Initialize new field. + (set_value_initialized): New function. + (value_initialized): New function. + * value.h (value_initialized): New extern declaration. + (set_value_initialized): Likewise. + * include/elf/dwarf2.h: (enum dwarf_location_atom): Add new DW_OP, + DW_OP_GNU_uninit. + 2007-05-18 Caroline Tice * MAINTAINERS (Write After Approval): Add self. diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c index 2ec90585b8..ad5e4d16ed 100644 --- a/gdb/c-valprint.c +++ b/gdb/c-valprint.c @@ -556,6 +556,9 @@ c_value_print (struct value *val, struct ui_file *stream, int format, } } + if (!value_initialized (val)) + fprintf_filtered (stream, " [uninitialized] "); + if (objectprint && (TYPE_CODE (type) == TYPE_CODE_CLASS)) { /* Attempt to determine real type of object */ diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c index ad259f4a40..92d9e16e35 100644 --- a/gdb/dwarf2expr.c +++ b/gdb/dwarf2expr.c @@ -284,6 +284,7 @@ execute_stack_op (struct dwarf_expr_context *ctx, gdb_byte *op_ptr, gdb_byte *op_end) { ctx->in_reg = 0; + ctx->initialized = 1; /* Default is initialized. */ while (op_ptr < op_end) { @@ -410,7 +411,9 @@ execute_stack_op (struct dwarf_expr_context *ctx, case DW_OP_reg29: case DW_OP_reg30: case DW_OP_reg31: - if (op_ptr != op_end && *op_ptr != DW_OP_piece) + if (op_ptr != op_end + && *op_ptr != DW_OP_piece + && *op_ptr != DW_OP_GNU_uninit) error (_("DWARF-2 expression error: DW_OP_reg operations must be " "used either alone or in conjuction with DW_OP_piece.")); @@ -731,6 +734,14 @@ execute_stack_op (struct dwarf_expr_context *ctx, } goto no_push; + case DW_OP_GNU_uninit: + if (op_ptr != op_end) + error (_("DWARF-2 expression error: DW_OP_GNU_unint must always " + "be the very last op.")); + + ctx->initialized = 0; + goto no_push; + default: error (_("Unhandled dwarf expression opcode 0x%x"), op); } diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h index ef85275e3c..c1adf9ad68 100644 --- a/gdb/dwarf2expr.h +++ b/gdb/dwarf2expr.h @@ -76,6 +76,10 @@ struct dwarf_expr_context will be on the expression stack. */ int in_reg; + /* Initialization status of variable: Non-zero if variable has been + initialized; zero otherwise. */ + int initialized; + /* An array of pieces. PIECES points to its first element; NUM_PIECES is its length. diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index a179566cfa..1e6ff67b5b 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -256,6 +256,8 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame, VALUE_ADDRESS (retval) = address; } + set_value_initialized (retval, ctx->initialized); + free_dwarf_expr_context (ctx); return retval; diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 3b3f263ffd..2cb455e03d 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -8656,6 +8656,8 @@ dwarf_stack_op_name (unsigned op) return "DW_OP_bit_piece"; case DW_OP_GNU_push_tls_address: return "DW_OP_GNU_push_tls_address"; + case DW_OP_GNU_uninit: + return "DW_OP_GNU_uninit"; /* HP extensions. */ case DW_OP_HP_is_value: return "DW_OP_HP_is_value"; @@ -9231,6 +9233,9 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu) dwarf2_complex_location_expr_complaint (); break; + case DW_OP_GNU_uninit: + break; + default: complaint (&symfile_complaints, _("unsupported stack op: '%s'"), dwarf_stack_op_name (op)); diff --git a/gdb/value.c b/gdb/value.c index d31a5f4556..26ba2a4489 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -157,6 +157,9 @@ struct value actually exist in the program. */ char optimized_out; + /* If value is a variable, is it initialized or not. */ + int initialized; + /* Actual contents of the value. For use of this value; setting it uses the stuff above. Not valid if lazy is nonzero. Target byte-order. We force it to be aligned properly for any possible @@ -232,6 +235,7 @@ allocate_value (struct type *type) val->embedded_offset = 0; val->pointed_to_offset = 0; val->modifiable = 1; + val->initialized = 1; /* Default to initialized. */ return val; } @@ -1699,6 +1703,22 @@ using_struct_return (struct type *value_type, int gcc_p) != RETURN_VALUE_REGISTER_CONVENTION); } +/* Set the initialized field in a value struct. */ + +void +set_value_initialized (struct value *val, int status) +{ + val->initialized = status; +} + +/* Return the initialized field in a value struct. */ + +int +value_initialized (struct value *val) +{ + return val->initialized; +} + void _initialize_values (void) { diff --git a/include/elf/dwarf2.h b/include/elf/dwarf2.h index 264952af13..2683f5131c 100644 --- a/include/elf/dwarf2.h +++ b/include/elf/dwarf2.h @@ -540,6 +540,7 @@ enum dwarf_location_atom DW_OP_bit_piece = 0x9d, /* GNU extensions. */ DW_OP_GNU_push_tls_address = 0xe0, + DW_OP_GNU_uninit = 0xf0, /* HP extensions. */ DW_OP_HP_unknown = 0xe0, /* Ouch, the same as GNU_push_tls_address. */ DW_OP_HP_is_value = 0xe1,