From ae0d2f24fd27f8510e4b6703293f7e9b4dafa805 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Tue, 18 Mar 2008 19:40:47 +0000 Subject: [PATCH] 2008-03-18 Ulrich Weigand Jim Blandy Daniel Jacobowitz * dwarf2expr.h (struct dwarf_expr_context): Add ADDR_SIZE member. (dwarf2_read_address): Update prototype. * dwarf2expr.c (unsigned_address_type): Add ADDR_SIZE parameter. (signed_address_type): Likewise. (dwarf2_read_address): Replace BYTES_READ parameter with ADDR_SIZE. (execute_stack_op): Update calls to unsigned_address_type, signed_address_type and dwarf2_read_address. Fix implementation of DW_OP_deref_size. * dwarf2loc.h (dwarf2_per_cu_objfile): Add prototype. (dwarf2_per_cu_addr_size): Likewise. (struct dwarf2_locexpr_baton): Replace OBJFILE with PER_CU. (struct dwarf2_loclist_baton): Likewise. * dwarf2loc.c (find_location_expression): Update calls to dwarf2_read_address. Use dwarf2_per_cu_objfile and dwarf2_per_cu_addr_size to retrieve PER_CU parameters. (locexpr_describe_location): Likewise. (dwarf2_evaluate_loc_desc): Replace OBJFILE with PER_CU parameter. Set ctx->addr_size to dwarf2_per_cu_addr_size (per_cu). (dwarf2_loc_desc_needs_frame): Add PER_CU parameter. Set ctx->addr_size to dwarf2_per_cu_addr_size (per_cu). (locexpr_read_variable): Update dwarf2_evaluate_loc_desc call. (loclist_read_variable): Likewise. (locexpr_read_needs_frame): Update dwarf2_loc_desc_needs_frame call. * dwarf2read.c (dwarf2_symbol_mark_computed): Set baton->per_cu instead of baton->objfile. (dwarf2_per_cu_obfile): New function. (dwarf2_per_cu_addr_size): Likewise. * dwarf2-frame.c (struct comp_unit): Move higher. (struct dwarf2_cie): Add UNIT and ADDR_SIZE members. (execute_stack_op): Add ADDR_SIZE parameter; set ctx->addr_size. (execute_cfa_program): Add FDE parameter. Replace EH_FRAME_P parameter by using fde->eh_frame_p. Use read_encoded_value to implement DW_CFA_set_loc. (struct dwarf2_frame_cache): Add ADDR_SIZE member. (dwarf2_frame_cache): Set cache->addr_size. Update calls to execute_stack_op and execute_cfa_program. (dwarf2_frame_prev_register): Update calls to execute_stack_op. (size_of_encoded_value): Remove. (read_encoded_value): Add PTR_LEN and FUNC_BASE parameters. Remove call to size_of_encoded_value. Implement DW_EH_PE_funcrel. (add_cie): Set cie->unit backlink. (decode_frame_entry_1): Set cie->addr_size. Update calls to read_encoded_value. (dwarf2_build_frame_info): Allocate UNIT on objfile obstack. --- gdb/ChangeLog | 54 ++++++++++++ gdb/dwarf2-frame.c | 210 ++++++++++++++++++++++++--------------------- gdb/dwarf2expr.c | 81 +++++++---------- gdb/dwarf2expr.h | 5 +- gdb/dwarf2loc.c | 38 ++++---- gdb/dwarf2loc.h | 22 +++-- gdb/dwarf2read.c | 50 +++++++++-- 7 files changed, 278 insertions(+), 182 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index b28267e086..deefe94e13 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,57 @@ +2008-03-18 Ulrich Weigand + Jim Blandy + Daniel Jacobowitz + + * dwarf2expr.h (struct dwarf_expr_context): Add ADDR_SIZE member. + (dwarf2_read_address): Update prototype. + + * dwarf2expr.c (unsigned_address_type): Add ADDR_SIZE parameter. + (signed_address_type): Likewise. + (dwarf2_read_address): Replace BYTES_READ parameter with ADDR_SIZE. + (execute_stack_op): Update calls to unsigned_address_type, + signed_address_type and dwarf2_read_address. Fix implementation + of DW_OP_deref_size. + + * dwarf2loc.h (dwarf2_per_cu_objfile): Add prototype. + (dwarf2_per_cu_addr_size): Likewise. + (struct dwarf2_locexpr_baton): Replace OBJFILE with PER_CU. + (struct dwarf2_loclist_baton): Likewise. + + * dwarf2loc.c (find_location_expression): Update calls to + dwarf2_read_address. Use dwarf2_per_cu_objfile and + dwarf2_per_cu_addr_size to retrieve PER_CU parameters. + (locexpr_describe_location): Likewise. + (dwarf2_evaluate_loc_desc): Replace OBJFILE with PER_CU parameter. + Set ctx->addr_size to dwarf2_per_cu_addr_size (per_cu). + (dwarf2_loc_desc_needs_frame): Add PER_CU parameter. Set ctx->addr_size + to dwarf2_per_cu_addr_size (per_cu). + (locexpr_read_variable): Update dwarf2_evaluate_loc_desc call. + (loclist_read_variable): Likewise. + (locexpr_read_needs_frame): Update dwarf2_loc_desc_needs_frame call. + + * dwarf2read.c (dwarf2_symbol_mark_computed): Set baton->per_cu + instead of baton->objfile. + (dwarf2_per_cu_obfile): New function. + (dwarf2_per_cu_addr_size): Likewise. + + * dwarf2-frame.c (struct comp_unit): Move higher. + (struct dwarf2_cie): Add UNIT and ADDR_SIZE members. + (execute_stack_op): Add ADDR_SIZE parameter; set ctx->addr_size. + (execute_cfa_program): Add FDE parameter. Replace EH_FRAME_P + parameter by using fde->eh_frame_p. Use read_encoded_value + to implement DW_CFA_set_loc. + (struct dwarf2_frame_cache): Add ADDR_SIZE member. + (dwarf2_frame_cache): Set cache->addr_size. Update calls to + execute_stack_op and execute_cfa_program. + (dwarf2_frame_prev_register): Update calls to execute_stack_op. + (size_of_encoded_value): Remove. + (read_encoded_value): Add PTR_LEN and FUNC_BASE parameters. + Remove call to size_of_encoded_value. Implement DW_EH_PE_funcrel. + (add_cie): Set cie->unit backlink. + (decode_frame_entry_1): Set cie->addr_size. Update calls to + read_encoded_value. + (dwarf2_build_frame_info): Allocate UNIT on objfile obstack. + 2008-03-17 Markus Deuling * i386-tdep.c (i386_print_insn): Remove unnecessary call to diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c index c4cd9f3d3e..e48fad9cd0 100644 --- a/gdb/dwarf2-frame.c +++ b/gdb/dwarf2-frame.c @@ -38,12 +38,17 @@ #include "complaints.h" #include "dwarf2-frame.h" +struct comp_unit; + /* Call Frame Information (CFI). */ /* Common Information Entry (CIE). */ struct dwarf2_cie { + /* Computation Unit for this CIE. */ + struct comp_unit *unit; + /* Offset into the .debug_frame section where this CIE was found. Used to identify this CIE. */ ULONGEST cie_pointer; @@ -68,6 +73,9 @@ struct dwarf2_cie /* Encoding of addresses. */ gdb_byte encoding; + /* Target address size in bytes. */ + int addr_size; + /* True if a 'z' augmentation existed. */ unsigned char saw_z_augmentation; @@ -104,10 +112,44 @@ struct dwarf2_fde struct dwarf2_fde *next; }; +/* A minimal decoding of DWARF2 compilation units. We only decode + what's needed to get to the call frame information. */ + +struct comp_unit +{ + /* Keep the bfd convenient. */ + bfd *abfd; + + struct objfile *objfile; + + /* Linked list of CIEs for this object. */ + struct dwarf2_cie *cie; + + /* Pointer to the .debug_frame section loaded into memory. */ + gdb_byte *dwarf_frame_buffer; + + /* Length of the loaded .debug_frame section. */ + unsigned long dwarf_frame_size; + + /* Pointer to the .debug_frame section. */ + asection *dwarf_frame_section; + + /* Base for DW_EH_PE_datarel encodings. */ + bfd_vma dbase; + + /* Base for DW_EH_PE_textrel encodings. */ + bfd_vma tbase; +}; + static struct dwarf2_fde *dwarf2_frame_find_fde (CORE_ADDR *pc); static int dwarf2_frame_adjust_regnum (struct gdbarch *gdbarch, int regnum, int eh_frame_p); + +static CORE_ADDR read_encoded_value (struct comp_unit *unit, gdb_byte encoding, + int ptr_len, gdb_byte *buf, + unsigned int *bytes_read_ptr, + CORE_ADDR func_base); /* Structure describing a frame state. */ @@ -299,13 +341,14 @@ register %s (#%d) at 0x%s"), } static CORE_ADDR -execute_stack_op (gdb_byte *exp, ULONGEST len, +execute_stack_op (gdb_byte *exp, ULONGEST len, int addr_size, struct frame_info *next_frame, CORE_ADDR initial) { struct dwarf_expr_context *ctx; CORE_ADDR result; ctx = new_dwarf_expr_context (); + ctx->addr_size = addr_size; ctx->baton = next_frame; ctx->read_reg = read_reg; ctx->read_mem = read_mem; @@ -326,10 +369,11 @@ execute_stack_op (gdb_byte *exp, ULONGEST len, static void -execute_cfa_program (gdb_byte *insn_ptr, gdb_byte *insn_end, - struct frame_info *next_frame, - struct dwarf2_frame_state *fs, int eh_frame_p) +execute_cfa_program (struct dwarf2_fde *fde, gdb_byte *insn_ptr, + gdb_byte *insn_end, struct frame_info *next_frame, + struct dwarf2_frame_state *fs) { + int eh_frame_p = fde->eh_frame_p; CORE_ADDR pc = frame_pc_unwind (next_frame); int bytes_read; struct gdbarch *gdbarch = get_frame_arch (next_frame); @@ -362,7 +406,12 @@ execute_cfa_program (gdb_byte *insn_ptr, gdb_byte *insn_end, switch (insn) { case DW_CFA_set_loc: - fs->pc = dwarf2_read_address (insn_ptr, insn_end, &bytes_read); + fs->pc = read_encoded_value (fde->cie->unit, fde->cie->encoding, + fde->cie->addr_size, insn_ptr, + &bytes_read, fde->initial_location); + /* Apply the objfile offset for relocatable objects. */ + fs->pc += ANOFFSET (fde->cie->unit->objfile->section_offsets, + SECT_OFF_TEXT (fde->cie->unit->objfile)); insn_ptr += bytes_read; break; @@ -813,6 +862,9 @@ struct dwarf2_frame_cache /* Return address register. */ struct dwarf2_frame_state_reg retaddr_reg; + + /* Target address size in bytes. */ + int addr_size; }; static struct dwarf2_frame_cache * @@ -863,21 +915,21 @@ dwarf2_frame_cache (struct frame_info *next_frame, void **this_cache) fs->data_align = fde->cie->data_alignment_factor; fs->code_align = fde->cie->code_alignment_factor; fs->retaddr_column = fde->cie->return_address_register; + cache->addr_size = fde->cie->addr_size; /* Check for "quirks" - known bugs in producers. */ dwarf2_frame_find_quirks (fs, fde); /* First decode all the insns in the CIE. */ - execute_cfa_program (fde->cie->initial_instructions, - fde->cie->end, next_frame, fs, fde->eh_frame_p); + execute_cfa_program (fde, fde->cie->initial_instructions, + fde->cie->end, next_frame, fs); /* Save the initialized register set. */ fs->initial = fs->regs; fs->initial.reg = dwarf2_frame_state_copy_regs (&fs->regs); /* Then decode the insns in the FDE up to our target PC. */ - execute_cfa_program (fde->instructions, fde->end, next_frame, fs, - fde->eh_frame_p); + execute_cfa_program (fde, fde->instructions, fde->end, next_frame, fs); /* Caclulate the CFA. */ switch (fs->cfa_how) @@ -892,7 +944,8 @@ dwarf2_frame_cache (struct frame_info *next_frame, void **this_cache) case CFA_EXP: cache->cfa = - execute_stack_op (fs->cfa_exp, fs->cfa_exp_len, next_frame, 0); + execute_stack_op (fs->cfa_exp, fs->cfa_exp_len, + cache->addr_size, next_frame, 0); break; default: @@ -1089,7 +1142,7 @@ dwarf2_frame_prev_register (struct frame_info *next_frame, void **this_cache, *lvalp = lval_memory; *addrp = execute_stack_op (cache->reg[regnum].loc.exp, cache->reg[regnum].exp_len, - next_frame, cache->cfa); + cache->addr_size, next_frame, cache->cfa); *realnump = -1; if (valuep) { @@ -1117,7 +1170,8 @@ dwarf2_frame_prev_register (struct frame_info *next_frame, void **this_cache, store_unsigned_integer (valuep, register_size (gdbarch, regnum), execute_stack_op (cache->reg[regnum].loc.exp, cache->reg[regnum].exp_len, - next_frame, cache->cfa)); + cache->addr_size, next_frame, + cache->cfa)); break; case DWARF2_FRAME_REG_UNSPECIFIED: @@ -1261,35 +1315,6 @@ dwarf2_frame_base_sniffer (struct frame_info *next_frame) return NULL; } -/* A minimal decoding of DWARF2 compilation units. We only decode - what's needed to get to the call frame information. */ - -struct comp_unit -{ - /* Keep the bfd convenient. */ - bfd *abfd; - - struct objfile *objfile; - - /* Linked list of CIEs for this object. */ - struct dwarf2_cie *cie; - - /* Pointer to the .debug_frame section loaded into memory. */ - gdb_byte *dwarf_frame_buffer; - - /* Length of the loaded .debug_frame section. */ - unsigned long dwarf_frame_size; - - /* Pointer to the .debug_frame section. */ - asection *dwarf_frame_section; - - /* Base for DW_EH_PE_datarel encodings. */ - bfd_vma dbase; - - /* Base for DW_EH_PE_textrel encodings. */ - bfd_vma tbase; -}; - const struct objfile_data *dwarf2_frame_objfile_data; static unsigned int @@ -1417,32 +1442,11 @@ encoding_for_size (unsigned int size) } } -static unsigned int -size_of_encoded_value (gdb_byte encoding) -{ - if (encoding == DW_EH_PE_omit) - return 0; - - switch (encoding & 0x07) - { - case DW_EH_PE_absptr: - return TYPE_LENGTH (builtin_type_void_data_ptr); - case DW_EH_PE_udata2: - return 2; - case DW_EH_PE_udata4: - return 4; - case DW_EH_PE_udata8: - return 8; - default: - internal_error (__FILE__, __LINE__, _("Invalid or unsupported encoding")); - } -} - static CORE_ADDR read_encoded_value (struct comp_unit *unit, gdb_byte encoding, - gdb_byte *buf, unsigned int *bytes_read_ptr) + int ptr_len, gdb_byte *buf, unsigned int *bytes_read_ptr, + CORE_ADDR func_base) { - int ptr_len = size_of_encoded_value (DW_EH_PE_absptr); ptrdiff_t offset; CORE_ADDR base; @@ -1470,12 +1474,7 @@ read_encoded_value (struct comp_unit *unit, gdb_byte encoding, base = unit->tbase; break; case DW_EH_PE_funcrel: - /* FIXME: kettenis/20040501: For now just pretend - DW_EH_PE_funcrel is equivalent to DW_EH_PE_absptr. For - reading the initial location of an FDE it should be treated - as such, and currently that's the only place where this code - is used. */ - base = 0; + base = func_base; break; case DW_EH_PE_aligned: base = 0; @@ -1561,6 +1560,7 @@ add_cie (struct comp_unit *unit, struct dwarf2_cie *cie) { cie->next = unit->cie; unit->cie = cie; + cie->unit = unit; } /* Find the FDE for *PC. Return a pointer to the FDE, and store the @@ -1685,6 +1685,13 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p) depends on the target address size. */ cie->encoding = DW_EH_PE_absptr; + /* The target address size. For .eh_frame FDEs this is considered + equal to the size of a target pointer. For .dwarf_frame FDEs, + this is supposed to be the target address size from the associated + CU header. FIXME: We do not have a good way to determine the + latter. Always use the target pointer size for now. */ + cie->addr_size = gdbarch_ptr_bit (current_gdbarch) / TARGET_CHAR_BIT; + /* We'll determine the final value later, but we need to initialize it conservatively. */ cie->signal_frame = 0; @@ -1773,7 +1780,8 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p) { /* Skip. Avoid indirection since we throw away the result. */ gdb_byte encoding = (*buf++) & ~DW_EH_PE_indirect; - read_encoded_value (unit, encoding, buf, &bytes_read); + read_encoded_value (unit, encoding, cie->addr_size, + buf, &bytes_read, 0); buf += bytes_read; augmentation++; } @@ -1837,11 +1845,13 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p) gdb_assert (fde->cie != NULL); fde->initial_location = - read_encoded_value (unit, fde->cie->encoding, buf, &bytes_read); + read_encoded_value (unit, fde->cie->encoding, fde->cie->addr_size, + buf, &bytes_read, 0); buf += bytes_read; fde->address_range = - read_encoded_value (unit, fde->cie->encoding & 0x0f, buf, &bytes_read); + read_encoded_value (unit, fde->cie->encoding & 0x0f, + fde->cie->addr_size, buf, &bytes_read, 0); buf += bytes_read; /* A 'z' augmentation in the CIE implies the presence of an @@ -1975,14 +1985,16 @@ extern gdb_byte *dwarf2_read_section (struct objfile *objfile, asection *sectp); void dwarf2_build_frame_info (struct objfile *objfile) { - struct comp_unit unit; + struct comp_unit *unit; gdb_byte *frame_ptr; /* Build a minimal decoding of the DWARF2 compilation unit. */ - unit.abfd = objfile->obfd; - unit.objfile = objfile; - unit.dbase = 0; - unit.tbase = 0; + unit = (struct comp_unit *) obstack_alloc (&objfile->objfile_obstack, + sizeof (struct comp_unit)); + unit->abfd = objfile->obfd; + unit->objfile = objfile; + unit->dbase = 0; + unit->tbase = 0; /* First add the information from the .eh_frame section. That way, the FDEs from that section are searched last. */ @@ -1990,43 +2002,43 @@ dwarf2_build_frame_info (struct objfile *objfile) { asection *got, *txt; - unit.cie = NULL; - unit.dwarf_frame_buffer = dwarf2_read_section (objfile, - dwarf_eh_frame_section); + unit->cie = NULL; + unit->dwarf_frame_buffer = dwarf2_read_section (objfile, + dwarf_eh_frame_section); - unit.dwarf_frame_size = bfd_get_section_size (dwarf_eh_frame_section); - unit.dwarf_frame_section = dwarf_eh_frame_section; + unit->dwarf_frame_size = bfd_get_section_size (dwarf_eh_frame_section); + unit->dwarf_frame_section = dwarf_eh_frame_section; /* FIXME: kettenis/20030602: This is the DW_EH_PE_datarel base that is used for the i386/amd64 target, which currently is the only target in GCC that supports/uses the DW_EH_PE_datarel encoding. */ - got = bfd_get_section_by_name (unit.abfd, ".got"); + got = bfd_get_section_by_name (unit->abfd, ".got"); if (got) - unit.dbase = got->vma; + unit->dbase = got->vma; /* GCC emits the DW_EH_PE_textrel encoding type on sh and ia64 so far. */ - txt = bfd_get_section_by_name (unit.abfd, ".text"); + txt = bfd_get_section_by_name (unit->abfd, ".text"); if (txt) - unit.tbase = txt->vma; + unit->tbase = txt->vma; - frame_ptr = unit.dwarf_frame_buffer; - while (frame_ptr < unit.dwarf_frame_buffer + unit.dwarf_frame_size) - frame_ptr = decode_frame_entry (&unit, frame_ptr, 1); + frame_ptr = unit->dwarf_frame_buffer; + while (frame_ptr < unit->dwarf_frame_buffer + unit->dwarf_frame_size) + frame_ptr = decode_frame_entry (unit, frame_ptr, 1); } if (dwarf_frame_section) { - unit.cie = NULL; - unit.dwarf_frame_buffer = dwarf2_read_section (objfile, - dwarf_frame_section); - unit.dwarf_frame_size = bfd_get_section_size (dwarf_frame_section); - unit.dwarf_frame_section = dwarf_frame_section; - - frame_ptr = unit.dwarf_frame_buffer; - while (frame_ptr < unit.dwarf_frame_buffer + unit.dwarf_frame_size) - frame_ptr = decode_frame_entry (&unit, frame_ptr, 0); + unit->cie = NULL; + unit->dwarf_frame_buffer = dwarf2_read_section (objfile, + dwarf_frame_section); + unit->dwarf_frame_size = bfd_get_section_size (dwarf_frame_section); + unit->dwarf_frame_section = dwarf_frame_section; + + frame_ptr = unit->dwarf_frame_buffer; + while (frame_ptr < unit->dwarf_frame_buffer + unit->dwarf_frame_size) + frame_ptr = decode_frame_entry (unit, frame_ptr, 0); } } diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c index 1102cf07b6..a099878f5e 100644 --- a/gdb/dwarf2expr.c +++ b/gdb/dwarf2expr.c @@ -32,7 +32,7 @@ static void execute_stack_op (struct dwarf_expr_context *, gdb_byte *, gdb_byte *); -static struct type *unsigned_address_type (void); +static struct type *unsigned_address_type (int); /* Create a new context for the expression evaluator. */ @@ -192,20 +192,17 @@ read_sleb128 (gdb_byte *buf, gdb_byte *buf_end, LONGEST * r) return buf; } -/* Read an address from BUF, and verify that it doesn't extend past - BUF_END. The address is returned, and *BYTES_READ is set to the - number of bytes read from BUF. */ +/* Read an address of size ADDR_SIZE from BUF, and verify that it + doesn't extend past BUF_END. */ CORE_ADDR -dwarf2_read_address (gdb_byte *buf, gdb_byte *buf_end, int *bytes_read) +dwarf2_read_address (gdb_byte *buf, gdb_byte *buf_end, int addr_size) { CORE_ADDR result; - if (buf_end - buf < gdbarch_addr_bit (current_gdbarch) / TARGET_CHAR_BIT) + if (buf_end - buf < addr_size) error (_("dwarf2_read_address: Corrupted DWARF expression.")); - *bytes_read = gdbarch_addr_bit (current_gdbarch) / TARGET_CHAR_BIT; - /* For most architectures, calling extract_unsigned_integer() alone is sufficient for extracting an address. However, some architectures (e.g. MIPS) use signed addresses and using @@ -229,21 +226,18 @@ dwarf2_read_address (gdb_byte *buf, gdb_byte *buf_end, int *bytes_read) address being returned. */ result = value_as_address (value_from_longest - (unsigned_address_type (), - extract_unsigned_integer - (buf, - gdbarch_addr_bit (current_gdbarch) - / TARGET_CHAR_BIT))); - + (unsigned_address_type (addr_size), + extract_unsigned_integer (buf, addr_size))); return result; } -/* Return the type of an address, for unsigned arithmetic. */ +/* Return the type of an address of size ADDR_SIZE, + for unsigned arithmetic. */ static struct type * -unsigned_address_type (void) +unsigned_address_type (int addr_size) { - switch (gdbarch_addr_bit (current_gdbarch) / TARGET_CHAR_BIT) + switch (addr_size) { case 2: return builtin_type_uint16; @@ -257,12 +251,13 @@ unsigned_address_type (void) } } -/* Return the type of an address, for signed arithmetic. */ +/* Return the type of an address of size ADDR_SIZE, + for signed arithmetic. */ static struct type * -signed_address_type (void) +signed_address_type (int addr_size) { - switch (gdbarch_addr_bit (current_gdbarch) / TARGET_CHAR_BIT) + switch (addr_size) { case 2: return builtin_type_int16; @@ -292,7 +287,6 @@ execute_stack_op (struct dwarf_expr_context *ctx, CORE_ADDR result; ULONGEST uoffset, reg; LONGEST offset; - int bytes_read; switch (op) { @@ -332,8 +326,8 @@ execute_stack_op (struct dwarf_expr_context *ctx, break; case DW_OP_addr: - result = dwarf2_read_address (op_ptr, op_end, &bytes_read); - op_ptr += bytes_read; + result = dwarf2_read_address (op_ptr, op_end, ctx->addr_size); + op_ptr += ctx->addr_size; break; case DW_OP_const1u: @@ -550,34 +544,20 @@ execute_stack_op (struct dwarf_expr_context *ctx, { case DW_OP_deref: { - gdb_byte *buf = alloca (gdbarch_addr_bit (current_gdbarch) - / TARGET_CHAR_BIT); - int bytes_read; - - (ctx->read_mem) (ctx->baton, buf, result, - gdbarch_addr_bit (current_gdbarch) - / TARGET_CHAR_BIT); - result = dwarf2_read_address (buf, - buf + (gdbarch_addr_bit - (current_gdbarch) - / TARGET_CHAR_BIT), - &bytes_read); + gdb_byte *buf = alloca (ctx->addr_size); + (ctx->read_mem) (ctx->baton, buf, result, ctx->addr_size); + result = dwarf2_read_address (buf, buf + ctx->addr_size, + ctx->addr_size); } break; case DW_OP_deref_size: { - gdb_byte *buf - = alloca (gdbarch_addr_bit (current_gdbarch) - / TARGET_CHAR_BIT); - int bytes_read; - - (ctx->read_mem) (ctx->baton, buf, result, *op_ptr++); - result = dwarf2_read_address (buf, - buf + (gdbarch_addr_bit - (current_gdbarch) - / TARGET_CHAR_BIT), - &bytes_read); + int addr_size = *op_ptr++; + gdb_byte *buf = alloca (addr_size); + (ctx->read_mem) (ctx->baton, buf, result, addr_size); + result = dwarf2_read_address (buf, buf + addr_size, + addr_size); } break; @@ -628,8 +608,10 @@ execute_stack_op (struct dwarf_expr_context *ctx, first = dwarf_expr_fetch (ctx, 0); dwarf_expr_pop (ctx); - val1 = value_from_longest (unsigned_address_type (), first); - val2 = value_from_longest (unsigned_address_type (), second); + val1 = value_from_longest + (unsigned_address_type (ctx->addr_size), first); + val2 = value_from_longest + (unsigned_address_type (ctx->addr_size), second); switch (op) { @@ -662,7 +644,8 @@ execute_stack_op (struct dwarf_expr_context *ctx, break; case DW_OP_shra: binop = BINOP_RSH; - val1 = value_from_longest (signed_address_type (), first); + val1 = value_from_longest + (signed_address_type (ctx->addr_size), first); break; case DW_OP_xor: binop = BINOP_BITWISE_XOR; diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h index 306ccb05b5..463c45261d 100644 --- a/gdb/dwarf2expr.h +++ b/gdb/dwarf2expr.h @@ -34,6 +34,9 @@ struct dwarf_expr_context number of elements allocated to the stack. */ int stack_len, stack_allocated; + /* Target address size in bytes. */ + int addr_size; + /* An opaque argument provided by the caller, which will be passed to all of the callback functions. */ void *baton; @@ -136,6 +139,6 @@ CORE_ADDR dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n); gdb_byte *read_uleb128 (gdb_byte *buf, gdb_byte *buf_end, ULONGEST * r); gdb_byte *read_sleb128 (gdb_byte *buf, gdb_byte *buf_end, LONGEST * r); CORE_ADDR dwarf2_read_address (gdb_byte *buf, gdb_byte *buf_end, - int *bytes_read); + int addr_size); #endif /* dwarf2expr.h */ diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index 7deb08e25b..4f4c0cab6b 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -54,11 +54,12 @@ find_location_expression (struct dwarf2_loclist_baton *baton, CORE_ADDR low, high; gdb_byte *loc_ptr, *buf_end; int length; - unsigned int addr_size = gdbarch_addr_bit (current_gdbarch) / TARGET_CHAR_BIT; + struct objfile *objfile = dwarf2_per_cu_objfile (baton->per_cu); + unsigned int addr_size = dwarf2_per_cu_addr_size (baton->per_cu); CORE_ADDR base_mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1)); /* Adjust base_address for relocatable objects. */ - CORE_ADDR base_offset = ANOFFSET (baton->objfile->section_offsets, - SECT_OFF_TEXT (baton->objfile)); + CORE_ADDR base_offset = ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); CORE_ADDR base_address = baton->base_address + base_offset; loc_ptr = baton->data; @@ -66,10 +67,10 @@ find_location_expression (struct dwarf2_loclist_baton *baton, while (1) { - low = dwarf2_read_address (loc_ptr, buf_end, &length); - loc_ptr += length; - high = dwarf2_read_address (loc_ptr, buf_end, &length); - loc_ptr += length; + low = dwarf2_read_address (loc_ptr, buf_end, addr_size); + loc_ptr += addr_size; + high = dwarf2_read_address (loc_ptr, buf_end, addr_size); + loc_ptr += addr_size; /* An end-of-list entry. */ if (low == 0 && high == 0) @@ -189,7 +190,7 @@ dwarf_expr_tls_address (void *baton, CORE_ADDR offset) static struct value * dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame, gdb_byte *data, unsigned short size, - struct objfile *objfile) + struct dwarf2_per_cu_data *per_cu) { struct gdbarch *arch = get_frame_arch (frame); struct value *retval; @@ -205,9 +206,10 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame, } baton.frame = frame; - baton.objfile = objfile; + baton.objfile = dwarf2_per_cu_objfile (per_cu); ctx = new_dwarf_expr_context (); + ctx->addr_size = dwarf2_per_cu_addr_size (per_cu); ctx->baton = &baton; ctx->read_reg = dwarf_expr_read_reg; ctx->read_mem = dwarf_expr_read_mem; @@ -318,7 +320,8 @@ needs_frame_tls_address (void *baton, CORE_ADDR offset) requires a frame to evaluate. */ static int -dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size) +dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size, + struct dwarf2_per_cu_data *per_cu) { struct needs_frame_baton baton; struct dwarf_expr_context *ctx; @@ -327,6 +330,7 @@ dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size) baton.needs_frame = 0; ctx = new_dwarf_expr_context (); + ctx->addr_size = dwarf2_per_cu_addr_size (per_cu); ctx->baton = &baton; ctx->read_reg = needs_frame_read_reg; ctx->read_mem = needs_frame_read_mem; @@ -429,7 +433,7 @@ locexpr_read_variable (struct symbol *symbol, struct frame_info *frame) struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol); struct value *val; val = dwarf2_evaluate_loc_desc (symbol, frame, dlbaton->data, dlbaton->size, - dlbaton->objfile); + dlbaton->per_cu); return val; } @@ -439,7 +443,8 @@ static int locexpr_read_needs_frame (struct symbol *symbol) { struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol); - return dwarf2_loc_desc_needs_frame (dlbaton->data, dlbaton->size); + return dwarf2_loc_desc_needs_frame (dlbaton->data, dlbaton->size, + dlbaton->per_cu); } /* Print a natural-language description of SYMBOL to STREAM. */ @@ -448,6 +453,7 @@ locexpr_describe_location (struct symbol *symbol, struct ui_file *stream) { /* FIXME: be more extensive. */ struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol); + int addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu); if (dlbaton->size == 1 && dlbaton->data[0] >= DW_OP_reg0 @@ -477,14 +483,14 @@ locexpr_describe_location (struct symbol *symbol, struct ui_file *stream) && dlbaton->data[dlbaton->size - 1] == DW_OP_GNU_push_tls_address) if (dlbaton->data[0] == DW_OP_addr) { - int bytes_read; + struct objfile *objfile = dwarf2_per_cu_objfile (dlbaton->per_cu); CORE_ADDR offset = dwarf2_read_address (&dlbaton->data[1], &dlbaton->data[dlbaton->size - 1], - &bytes_read); + addr_size); fprintf_filtered (stream, "a thread-local variable at offset %s in the " "thread-local storage for `%s'", - paddr_nz (offset), dlbaton->objfile->name); + paddr_nz (offset), objfile->name); return 1; } @@ -546,7 +552,7 @@ loclist_read_variable (struct symbol *symbol, struct frame_info *frame) } else val = dwarf2_evaluate_loc_desc (symbol, frame, data, size, - dlbaton->objfile); + dlbaton->per_cu); return val; } diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h index 22c66bd839..632568e1e8 100644 --- a/gdb/dwarf2loc.h +++ b/gdb/dwarf2loc.h @@ -21,10 +21,18 @@ #define DWARF2LOC_H struct symbol_ops; +struct objfile; +struct dwarf2_per_cu_data; /* This header is private to the DWARF-2 reader. It is shared between dwarf2read.c and dwarf2loc.c. */ +/* Return the OBJFILE associated with the compilation unit CU. */ +struct objfile *dwarf2_per_cu_objfile (struct dwarf2_per_cu_data *cu); + +/* Return the address size given in the compilation unit header for CU. */ +CORE_ADDR dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *cu); + /* The symbol location baton types used by the DWARF-2 reader (i.e. SYMBOL_LOCATION_BATON for a LOC_COMPUTED symbol). "struct dwarf2_locexpr_baton" is for a symbol with a single location @@ -39,8 +47,9 @@ struct dwarf2_locexpr_baton /* Length of the location expression. */ unsigned long size; - /* The objfile containing the symbol whose location we're computing. */ - struct objfile *objfile; + /* The compilation unit containing the symbol whose location + we're computing. */ + struct dwarf2_per_cu_data *per_cu; }; struct dwarf2_loclist_baton @@ -55,12 +64,9 @@ struct dwarf2_loclist_baton /* Length of the location list. */ unsigned long size; - /* The objfile containing the symbol whose location we're computing. */ - /* Used (only???) by thread local variables. The objfile in which - this symbol is defined. To find a thread-local variable (e.g., a - variable declared with the `__thread' storage class), we may need - to know which object file it's in. */ - struct objfile *objfile; + /* The compilation unit containing the symbol whose location + we're computing. */ + struct dwarf2_per_cu_data *per_cu; }; extern const struct symbol_ops dwarf2_locexpr_funcs; diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index af9585b8c8..7059ad2fc0 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -9818,13 +9818,6 @@ static void dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, struct dwarf2_cu *cu) { - struct objfile *objfile = cu->objfile; - - /* Save the master objfile, so that we can report and look up the - correct file containing this variable. */ - if (objfile->separate_debug_objfile_backlink) - objfile = objfile->separate_debug_objfile_backlink; - if (attr_form_is_section_offset (attr) /* ".debug_loc" may not exist at all, or the offset may be outside the section. If so, fall through to the complaint in the @@ -9835,7 +9828,8 @@ dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, baton = obstack_alloc (&cu->objfile->objfile_obstack, sizeof (struct dwarf2_loclist_baton)); - baton->objfile = objfile; + baton->per_cu = cu->per_cu; + gdb_assert (baton->per_cu); /* We don't know how long the location list is, but make sure we don't run off the edge of the section. */ @@ -9855,7 +9849,8 @@ dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, baton = obstack_alloc (&cu->objfile->objfile_obstack, sizeof (struct dwarf2_locexpr_baton)); - baton->objfile = objfile; + baton->per_cu = cu->per_cu; + gdb_assert (baton->per_cu); if (attr_form_is_block (attr)) { @@ -9880,6 +9875,43 @@ dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, } } +/* Return the OBJFILE associated with the compilation unit CU. */ + +struct objfile * +dwarf2_per_cu_objfile (struct dwarf2_per_cu_data *per_cu) +{ + struct objfile *objfile = per_cu->psymtab->objfile; + + /* Return the master objfile, so that we can report and look up the + correct file containing this variable. */ + if (objfile->separate_debug_objfile_backlink) + objfile = objfile->separate_debug_objfile_backlink; + + return objfile; +} + +/* Return the address size given in the compilation unit header for CU. */ + +CORE_ADDR +dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *per_cu) +{ + if (per_cu->cu) + return per_cu->cu->header.addr_size; + else + { + /* If the CU is not currently read in, we re-read its header. */ + struct objfile *objfile = per_cu->psymtab->objfile; + struct dwarf2_per_objfile *per_objfile + = objfile_data (objfile, dwarf2_objfile_data_key); + gdb_byte *info_ptr = per_objfile->info_buffer + per_cu->offset; + + struct comp_unit_head cu_header; + memset (&cu_header, 0, sizeof cu_header); + read_comp_unit_head (&cu_header, info_ptr, objfile->obfd); + return cu_header.addr_size; + } +} + /* Locate the compilation unit from CU's objfile which contains the DIE at OFFSET. Raises an error on failure. */ -- 2.34.1