X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fdwarf2loc.c;h=99a18a95ed68844e160a2e262ed3cbd861e5bea3;hb=9f1b45b0da430a7a7abf9e54acbe6f2ef9d3a763;hp=ab4ecee8244edbb9e0b48bd625d612d9e2cf75d1;hpb=948f8e3d72fa7047c43a952017ad4a7c9d55ab0d;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index ab4ecee824..99a18a95ed 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -1,6 +1,6 @@ /* DWARF 2 location expression support for GDB. - Copyright (C) 2003-2013 Free Software Foundation, Inc. + Copyright (C) 2003-2014 Free Software Foundation, Inc. Contributed by Daniel Jacobowitz, MontaVista Software, Inc. @@ -39,11 +39,9 @@ #include "dwarf2loc.h" #include "dwarf2-frame.h" -#include "gdb_string.h" +#include #include "gdb_assert.h" -DEF_VEC_I(int); - extern int dwarf2_always_disassemble; static void dwarf_expr_frame_base_1 (struct symbol *framefunc, CORE_ADDR pc, @@ -90,6 +88,16 @@ enum debug_loc_kind DEBUG_LOC_INVALID_ENTRY = -2 }; +/* Helper function which throws an error if a synthetic pointer is + invalid. */ + +static void +invalid_synthetic_pointer (void) +{ + error (_("access outside bounds of object " + "referenced via synthetic pointer")); +} + /* Decode the addresses in a non-dwo .debug_loc entry. A pointer to the next byte to examine is returned in *NEW_PTR. The encoded low,high addresses are return in *LOW,*HIGH. @@ -305,7 +313,7 @@ struct dwarf_expr_baton /* Using the frame specified in BATON, return the value of register REGNUM, treated as a pointer. */ static CORE_ADDR -dwarf_expr_read_reg (void *baton, int dwarf_regnum) +dwarf_expr_read_addr_from_reg (void *baton, int dwarf_regnum) { struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton; struct gdbarch *gdbarch = get_frame_arch (debaton->frame); @@ -318,6 +326,18 @@ dwarf_expr_read_reg (void *baton, int dwarf_regnum) return result; } +/* Implement struct dwarf_expr_context_funcs' "get_reg_value" callback. */ + +static struct value * +dwarf_expr_get_reg_value (void *baton, struct type *type, int dwarf_regnum) +{ + struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton; + struct gdbarch *gdbarch = get_frame_arch (debaton->frame); + int regnum = gdbarch_dwarf2_reg_to_regnum (gdbarch, dwarf_regnum); + + return value_from_register (type, regnum, debaton->frame); +} + /* Read memory at ADDR (length LEN) into BUF. */ static void @@ -741,8 +761,9 @@ chain_candidate (struct gdbarch *gdbarch, struct call_site_chain **resultp, * (length - 1)); result->length = length; result->callers = result->callees = length; - memcpy (result->call_site, VEC_address (call_sitep, chain), - sizeof (*result->call_site) * length); + if (!VEC_empty (call_sitep, chain)) + memcpy (result->call_site, VEC_address (call_sitep, chain), + sizeof (*result->call_site) * length); *resultp = result; if (entry_values_debug) @@ -1393,14 +1414,14 @@ allocate_piece_closure (struct dwarf2_per_cu_data *per_cu, int n_pieces, struct dwarf_expr_piece *pieces, int addr_size) { - struct piece_closure *c = XZALLOC (struct piece_closure); + struct piece_closure *c = XCNEW (struct piece_closure); int i; c->refc = 1; c->per_cu = per_cu; c->n_pieces = n_pieces; c->addr_size = addr_size; - c->pieces = XCALLOC (n_pieces, struct dwarf_expr_piece); + c->pieces = XCNEWVEC (struct dwarf_expr_piece, n_pieces); memcpy (c->pieces, pieces, n_pieces * sizeof (struct dwarf_expr_piece)); for (i = 0; i < n_pieces; ++i) @@ -1631,8 +1652,6 @@ read_pieced_value (struct value *v) bits_to_skip -= this_size_bits; continue; } - if (this_size_bits > type_len - offset) - this_size_bits = type_len - offset; if (bits_to_skip > 0) { dest_offset_bits = 0; @@ -1645,6 +1664,8 @@ read_pieced_value (struct value *v) dest_offset_bits = offset; source_offset_bits = 0; } + if (this_size_bits > type_len - offset) + this_size_bits = type_len - offset; this_size = (this_size_bits + source_offset_bits % 8 + 7) / 8; source_offset = source_offset_bits / 8; @@ -1688,7 +1709,7 @@ read_pieced_value (struct value *v) if (optim) set_value_optimized_out (v, 1); if (unavail) - mark_value_bytes_unavailable (v, offset, this_size); + mark_value_bits_unavailable (v, offset, this_size_bits); } } else @@ -1872,9 +1893,10 @@ write_pieced_value (struct value *to, struct value *from) &optim, &unavail)) { if (optim) - error (_("Can't do read-modify-write to " - "update bitfield; containing word has been " - "optimized out")); + throw_error (OPTIMIZED_OUT_ERROR, + _("Can't do read-modify-write to " + "update bitfield; containing word " + "has been optimized out")); if (unavail) throw_error (NOT_AVAILABLE_ERROR, _("Can't do read-modify-write to update " @@ -2077,8 +2099,15 @@ indirect_pieced_value (struct value *value) frame = get_selected_frame (_("No frame selected.")); - /* This is an offset requested by GDB, such as value subcripts. */ + /* This is an offset requested by GDB, such as value subscripts. + However, due to how synthetic pointers are implemented, this is + always presented to us as a pointer type. This means we have to + sign-extend it manually as appropriate. */ byte_offset = value_as_address (value); + if (TYPE_LENGTH (value_type (value)) < sizeof (LONGEST)) + byte_offset = gdb_sign_extend (byte_offset, + 8 * TYPE_LENGTH (value_type (value))); + byte_offset += piece->v.ptr.offset; gdb_assert (piece); baton @@ -2086,9 +2115,37 @@ indirect_pieced_value (struct value *value) get_frame_address_in_block_wrapper, frame); - return dwarf2_evaluate_loc_desc_full (TYPE_TARGET_TYPE (type), frame, - baton.data, baton.size, baton.per_cu, - piece->v.ptr.offset + byte_offset); + if (baton.data != NULL) + return dwarf2_evaluate_loc_desc_full (TYPE_TARGET_TYPE (type), frame, + baton.data, baton.size, baton.per_cu, + byte_offset); + + { + struct obstack temp_obstack; + struct cleanup *cleanup; + const gdb_byte *bytes; + LONGEST len; + struct value *result; + + obstack_init (&temp_obstack); + cleanup = make_cleanup_obstack_free (&temp_obstack); + + bytes = dwarf2_fetch_constant_bytes (piece->v.ptr.die, c->per_cu, + &temp_obstack, &len); + if (bytes == NULL) + result = allocate_optimized_out_value (TYPE_TARGET_TYPE (type)); + else + { + if (byte_offset < 0 + || byte_offset + TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > len) + invalid_synthetic_pointer (); + bytes += byte_offset; + result = value_from_contents (TYPE_TARGET_TYPE (type), bytes); + } + + do_cleanups (cleanup); + return result; + } } static void * @@ -2134,21 +2191,12 @@ static const struct lval_funcs pieced_value_funcs = { free_pieced_value_closure }; -/* Helper function which throws an error if a synthetic pointer is - invalid. */ - -static void -invalid_synthetic_pointer (void) -{ - error (_("access outside bounds of object " - "referenced via synthetic pointer")); -} - /* Virtual method table for dwarf2_evaluate_loc_desc_full below. */ static const struct dwarf_expr_context_funcs dwarf_expr_ctx_funcs = { - dwarf_expr_read_reg, + dwarf_expr_read_addr_from_reg, + dwarf_expr_get_reg_value, dwarf_expr_read_mem, dwarf_expr_frame_base, dwarf_expr_frame_cfa, @@ -2250,17 +2298,28 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, case DWARF_VALUE_REGISTER: { struct gdbarch *arch = get_frame_arch (frame); - ULONGEST dwarf_regnum = value_as_long (dwarf_expr_fetch (ctx, 0)); + int dwarf_regnum + = longest_to_int (value_as_long (dwarf_expr_fetch (ctx, 0))); int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, dwarf_regnum); if (byte_offset != 0) error (_("cannot use offset on synthetic pointer to register")); do_cleanups (value_chain); - if (gdb_regnum != -1) - retval = value_from_register (type, gdb_regnum, frame); - else - error (_("Unable to access DWARF register number %s"), - paddress (arch, dwarf_regnum)); + if (gdb_regnum == -1) + error (_("Unable to access DWARF register number %d"), + dwarf_regnum); + retval = value_from_register (type, gdb_regnum, frame); + if (value_optimized_out (retval)) + { + /* This means the register has undefined value / was + not saved. As we're computing the location of some + variable etc. in the program, not a value for + inspecting a register ($pc, $sp, etc.), return a + generic optimized out value instead, so that we show + instead of . */ + do_cleanups (value_chain); + retval = allocate_optimized_out_value (type); + } } break; @@ -2270,11 +2329,9 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, int in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 0); do_cleanups (value_chain); - retval = allocate_value_lazy (type); - VALUE_LVAL (retval) = lval_memory; + retval = value_at_lazy (type, address + byte_offset); if (in_stack_memory) set_value_stack (retval, 1); - set_value_address (retval, address + byte_offset); } break; @@ -2385,7 +2442,7 @@ struct needs_frame_baton /* Reads from registers do require a frame. */ static CORE_ADDR -needs_frame_read_reg (void *baton, int regnum) +needs_frame_read_addr_from_reg (void *baton, int regnum) { struct needs_frame_baton *nf_baton = baton; @@ -2393,6 +2450,18 @@ needs_frame_read_reg (void *baton, int regnum) return 1; } +/* struct dwarf_expr_context_funcs' "get_reg_value" callback: + Reads from registers do require a frame. */ + +static struct value * +needs_frame_get_reg_value (void *baton, struct type *type, int regnum) +{ + struct needs_frame_baton *nf_baton = baton; + + nf_baton->needs_frame = 1; + return value_zero (type, not_lval); +} + /* Reads from memory do not require a frame. */ static void needs_frame_read_mem (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t len) @@ -2473,7 +2542,8 @@ needs_get_addr_index (void *baton, unsigned int index) static const struct dwarf_expr_context_funcs needs_frame_ctx_funcs = { - needs_frame_read_reg, + needs_frame_read_addr_from_reg, + needs_frame_get_reg_value, needs_frame_read_mem, needs_frame_frame_base, needs_frame_frame_cfa, @@ -3455,7 +3525,7 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream, fprintf_filtered (stream, _("a thread-local variable at offset 0x%s " "in the thread-local storage for `%s'"), - phex_nz (offset, addr_size), objfile->name); + phex_nz (offset, addr_size), objfile_name (objfile)); data += 1 + addr_size + 1; } @@ -3478,7 +3548,7 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream, fprintf_filtered (stream, _("a thread-local variable at offset 0x%s " "in the thread-local storage for `%s'"), - phex_nz (offset, addr_size), objfile->name); + phex_nz (offset, addr_size), objfile_name (objfile)); ++data; }