From ac56253ddece35aff4402b848f88ba40856102b1 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Wed, 7 Jul 2010 17:26:38 +0000 Subject: [PATCH] * dwarf2read.c (dwarf2_const_value) : Create a LOC_COMPUTED symbol. * dwarf2loc.c (dwarf2_evaluate_loc_desc): Set new field. (dwarf2_loc_desc_needs_frame): Likewise. (compile_dwarf_to_ax) : Use offset. * dwarf2expr.h (struct dwarf_expr_context) : New field. * dwarf2expr.c (execute_stack_op) : Use offset. * dwarf2-frame.c (execute_stack_op): Set 'offset' field. Add 'offset' argument. (struct dwarf2_frame_cache) : New field. (dwarf2_frame_cache): Set new field. (dwarf2_frame_prev_register): Update. (dwarf2_frame_sniffer): Update. (dwarf2_frame_base_sniffer): Update. (dwarf2_frame_find_fde): Add 'out_offset' argument. --- gdb/ChangeLog | 18 ++++++++++++++++++ gdb/dwarf2-frame.c | 30 ++++++++++++++++++++---------- gdb/dwarf2expr.c | 6 ++++++ gdb/dwarf2expr.h | 3 +++ gdb/dwarf2loc.c | 23 +++++++++++++++++++---- gdb/dwarf2read.c | 42 ++++++++++++++++++++++++++++++------------ 6 files changed, 96 insertions(+), 26 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index dd81237482e..64eef43998a 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,21 @@ +2010-07-07 Tom Tromey + + * dwarf2read.c (dwarf2_const_value) : Create a + LOC_COMPUTED symbol. + * dwarf2loc.c (dwarf2_evaluate_loc_desc): Set new field. + (dwarf2_loc_desc_needs_frame): Likewise. + (compile_dwarf_to_ax) : Use offset. + * dwarf2expr.h (struct dwarf_expr_context) : New field. + * dwarf2expr.c (execute_stack_op) : Use offset. + * dwarf2-frame.c (execute_stack_op): Set 'offset' field. Add + 'offset' argument. + (struct dwarf2_frame_cache) : New field. + (dwarf2_frame_cache): Set new field. + (dwarf2_frame_prev_register): Update. + (dwarf2_frame_sniffer): Update. + (dwarf2_frame_base_sniffer): Update. + (dwarf2_frame_find_fde): Add 'out_offset' argument. + 2010-07-07 Sergio Durigan Junior Thiago Jung Bauermann diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c index 9576341ec5a..a027b0206ce 100644 --- a/gdb/dwarf2-frame.c +++ b/gdb/dwarf2-frame.c @@ -150,7 +150,8 @@ struct comp_unit bfd_vma tbase; }; -static struct dwarf2_fde *dwarf2_frame_find_fde (CORE_ADDR *pc); +static struct dwarf2_fde *dwarf2_frame_find_fde (CORE_ADDR *pc, + CORE_ADDR *out_offset); static int dwarf2_frame_adjust_regnum (struct gdbarch *gdbarch, int regnum, int eh_frame_p); @@ -369,8 +370,8 @@ register %s (#%d) at %s"), static CORE_ADDR execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size, - struct frame_info *this_frame, CORE_ADDR initial, - int initial_in_stack_memory) + CORE_ADDR offset, struct frame_info *this_frame, + CORE_ADDR initial, int initial_in_stack_memory) { struct dwarf_expr_context *ctx; CORE_ADDR result; @@ -381,6 +382,7 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size, ctx->gdbarch = get_frame_arch (this_frame); ctx->addr_size = addr_size; + ctx->offset = offset; ctx->baton = this_frame; ctx->read_reg = read_reg; ctx->read_mem = read_mem; @@ -901,6 +903,9 @@ struct dwarf2_frame_cache /* Target address size in bytes. */ int addr_size; + + /* The .text offset. */ + CORE_ADDR text_offset; }; static struct dwarf2_frame_cache * @@ -944,7 +949,7 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache) fs->pc = get_frame_address_in_block (this_frame); /* Find the correct FDE. */ - fde = dwarf2_frame_find_fde (&fs->pc); + fde = dwarf2_frame_find_fde (&fs->pc, &cache->text_offset); gdb_assert (fde != NULL); /* Extract any interesting information from the CIE. */ @@ -981,7 +986,8 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache) case CFA_EXP: cache->cfa = execute_stack_op (fs->regs.cfa_exp, fs->regs.cfa_exp_len, - cache->addr_size, this_frame, 0, 0); + cache->addr_size, cache->text_offset, + this_frame, 0, 0); break; default: @@ -1137,7 +1143,8 @@ dwarf2_frame_prev_register (struct frame_info *this_frame, void **this_cache, case DWARF2_FRAME_REG_SAVED_EXP: addr = execute_stack_op (cache->reg[regnum].loc.exp, cache->reg[regnum].exp_len, - cache->addr_size, this_frame, cache->cfa, 1); + cache->addr_size, cache->text_offset, + this_frame, cache->cfa, 1); return frame_unwind_got_memory (this_frame, regnum, addr); case DWARF2_FRAME_REG_SAVED_VAL_OFFSET: @@ -1147,7 +1154,8 @@ dwarf2_frame_prev_register (struct frame_info *this_frame, void **this_cache, case DWARF2_FRAME_REG_SAVED_VAL_EXP: addr = execute_stack_op (cache->reg[regnum].loc.exp, cache->reg[regnum].exp_len, - cache->addr_size, this_frame, cache->cfa, 1); + cache->addr_size, cache->text_offset, + this_frame, cache->cfa, 1); return frame_unwind_got_constant (this_frame, regnum, addr); case DWARF2_FRAME_REG_UNSPECIFIED: @@ -1197,7 +1205,7 @@ dwarf2_frame_sniffer (const struct frame_unwind *self, extend one byte before its start address or we could potentially select the FDE of the previous function. */ CORE_ADDR block_addr = get_frame_address_in_block (this_frame); - struct dwarf2_fde *fde = dwarf2_frame_find_fde (&block_addr); + struct dwarf2_fde *fde = dwarf2_frame_find_fde (&block_addr, NULL); if (!fde) return 0; @@ -1270,7 +1278,7 @@ dwarf2_frame_base_sniffer (struct frame_info *this_frame) { CORE_ADDR block_addr = get_frame_address_in_block (this_frame); - if (dwarf2_frame_find_fde (&block_addr)) + if (dwarf2_frame_find_fde (&block_addr, NULL)) return &dwarf2_frame_base; return NULL; @@ -1582,7 +1590,7 @@ bsearch_fde_cmp (const void *key, const void *element) inital location associated with it into *PC. */ static struct dwarf2_fde * -dwarf2_frame_find_fde (CORE_ADDR *pc) +dwarf2_frame_find_fde (CORE_ADDR *pc, CORE_ADDR *out_offset) { struct objfile *objfile; @@ -1617,6 +1625,8 @@ dwarf2_frame_find_fde (CORE_ADDR *pc) if (p_fde != NULL) { *pc = (*p_fde)->initial_location + offset; + if (out_offset) + *out_offset = offset; return *p_fde; } } diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c index af9fc0fc587..b9ae108c5ff 100644 --- a/gdb/dwarf2expr.c +++ b/gdb/dwarf2expr.c @@ -403,6 +403,12 @@ execute_stack_op (struct dwarf_expr_context *ctx, result = extract_unsigned_integer (op_ptr, ctx->addr_size, byte_order); op_ptr += ctx->addr_size; + /* Some versions of GCC emit DW_OP_addr before + DW_OP_GNU_push_tls_address. In this case the value is an + index, not an address. We don't support things like + branching between the address and the TLS op. */ + if (op_ptr >= op_end || *op_ptr != DW_OP_GNU_push_tls_address) + result += ctx->offset; break; case DW_OP_const1u: diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h index 31381c09e69..61b8f003303 100644 --- a/gdb/dwarf2expr.h +++ b/gdb/dwarf2expr.h @@ -75,6 +75,9 @@ struct dwarf_expr_context /* Target address size in bytes. */ int addr_size; + /* Offset used to relocate DW_OP_addr argument. */ + CORE_ADDR offset; + /* An opaque argument provided by the caller, which will be passed to all of the callback functions. */ void *baton; diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index f26b46e2bbb..4106b7fd6c0 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -891,6 +891,7 @@ dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame, struct dwarf_expr_baton baton; struct dwarf_expr_context *ctx; struct cleanup *old_chain; + struct objfile *objfile = dwarf2_per_cu_objfile (per_cu); if (size == 0) { @@ -906,8 +907,9 @@ dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame, ctx = new_dwarf_expr_context (); old_chain = make_cleanup_free_dwarf_expr_context (ctx); - ctx->gdbarch = get_objfile_arch (dwarf2_per_cu_objfile (per_cu)); + ctx->gdbarch = get_objfile_arch (objfile); ctx->addr_size = dwarf2_per_cu_addr_size (per_cu); + ctx->offset = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); ctx->baton = &baton; ctx->read_reg = dwarf_expr_read_reg; ctx->read_mem = dwarf_expr_read_mem; @@ -1083,6 +1085,7 @@ dwarf2_loc_desc_needs_frame (const gdb_byte *data, unsigned short size, struct dwarf_expr_context *ctx; int in_reg; struct cleanup *old_chain; + struct objfile *objfile = dwarf2_per_cu_objfile (per_cu); baton.needs_frame = 0; baton.per_cu = per_cu; @@ -1090,8 +1093,9 @@ dwarf2_loc_desc_needs_frame (const gdb_byte *data, unsigned short size, ctx = new_dwarf_expr_context (); old_chain = make_cleanup_free_dwarf_expr_context (ctx); - ctx->gdbarch = get_objfile_arch (dwarf2_per_cu_objfile (per_cu)); + ctx->gdbarch = get_objfile_arch (objfile); ctx->addr_size = dwarf2_per_cu_addr_size (per_cu); + ctx->offset = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); ctx->baton = &baton; ctx->read_reg = needs_frame_read_reg; ctx->read_mem = needs_frame_read_mem; @@ -1293,9 +1297,20 @@ compile_dwarf_to_ax (struct agent_expr *expr, struct axs_value *loc, break; case DW_OP_addr: - ax_const_l (expr, extract_unsigned_integer (op_ptr, - addr_size, byte_order)); + uoffset = extract_unsigned_integer (op_ptr, addr_size, byte_order); op_ptr += addr_size; + /* Some versions of GCC emit DW_OP_addr before + DW_OP_GNU_push_tls_address. In this case the value is an + index, not an address. We don't support things like + branching between the address and the TLS op. */ + if (op_ptr >= op_end || *op_ptr != DW_OP_GNU_push_tls_address) + { + struct objfile *objfile = dwarf2_per_cu_objfile (per_cu); + + uoffset += ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); + } + ax_const_l (expr, uoffset); break; case DW_OP_const1u: diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 858b18e44da..e4ab034e4ac 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -9075,18 +9075,36 @@ dwarf2_const_value (struct attribute *attr, struct symbol *sym, switch (attr->form) { case DW_FORM_addr: - if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != cu_header->addr_size) - dwarf2_const_value_length_mismatch_complaint (SYMBOL_PRINT_NAME (sym), - cu_header->addr_size, - TYPE_LENGTH (SYMBOL_TYPE - (sym))); - SYMBOL_VALUE_BYTES (sym) = - obstack_alloc (&objfile->objfile_obstack, cu_header->addr_size); - /* NOTE: cagney/2003-05-09: In-lined store_address call with - it's body - store_unsigned_integer. */ - store_unsigned_integer (SYMBOL_VALUE_BYTES (sym), cu_header->addr_size, - byte_order, DW_ADDR (attr)); - SYMBOL_CLASS (sym) = LOC_CONST_BYTES; + { + struct dwarf2_locexpr_baton *baton; + gdb_byte *data; + + if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != cu_header->addr_size) + dwarf2_const_value_length_mismatch_complaint (SYMBOL_PRINT_NAME (sym), + cu_header->addr_size, + TYPE_LENGTH (SYMBOL_TYPE + (sym))); + /* Symbols of this form are reasonably rare, so we just + piggyback on the existing location code rather than writing + a new implementation of symbol_computed_ops. */ + baton = obstack_alloc (&objfile->objfile_obstack, + sizeof (struct dwarf2_locexpr_baton)); + baton->per_cu = cu->per_cu; + gdb_assert (baton->per_cu); + + baton->size = 2 + cu_header->addr_size; + data = obstack_alloc (&objfile->objfile_obstack, baton->size); + baton->data = data; + + data[0] = DW_OP_addr; + store_unsigned_integer (&data[1], cu_header->addr_size, + byte_order, DW_ADDR (attr)); + data[cu_header->addr_size + 1] = DW_OP_stack_value; + + SYMBOL_COMPUTED_OPS (sym) = &dwarf2_locexpr_funcs; + SYMBOL_LOCATION_BATON (sym) = baton; + SYMBOL_CLASS (sym) = LOC_COMPUTED; + } break; case DW_FORM_string: case DW_FORM_strp: -- 2.30.2