From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8263 invoked by alias); 9 Dec 2007 19:40:14 -0000 Received: (qmail 8250 invoked by uid 22791); 9 Dec 2007 19:40:12 -0000 X-Spam-Check-By: sourceware.org Received: from mtagate8.de.ibm.com (HELO mtagate8.de.ibm.com) (195.212.29.157) by sourceware.org (qpsmtpd/0.31) with ESMTP; Sun, 09 Dec 2007 19:39:59 +0000 Received: from d12nrmr1607.megacenter.de.ibm.com (d12nrmr1607.megacenter.de.ibm.com [9.149.167.49]) by mtagate8.de.ibm.com (8.13.8/8.13.8) with ESMTP id lB9Jdufg092834 for ; Sun, 9 Dec 2007 19:39:56 GMT Received: from d12av02.megacenter.de.ibm.com (d12av02.megacenter.de.ibm.com [9.149.165.228]) by d12nrmr1607.megacenter.de.ibm.com (8.13.8/8.13.8/NCO v8.7) with ESMTP id lB9JduCC3023058 for ; Sun, 9 Dec 2007 20:39:56 +0100 Received: from d12av02.megacenter.de.ibm.com (loopback [127.0.0.1]) by d12av02.megacenter.de.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id lB9Jdt4m019622 for ; Sun, 9 Dec 2007 20:39:56 +0100 Received: from tuxmaker.boeblingen.de.ibm.com (tuxmaker.boeblingen.de.ibm.com [9.152.85.9]) by d12av02.megacenter.de.ibm.com (8.12.11.20060308/8.12.11) with SMTP id lB9Jdt17019619 for ; Sun, 9 Dec 2007 20:39:55 +0100 Message-Id: <200712091939.lB9Jdt17019619@d12av02.megacenter.de.ibm.com> Received: by tuxmaker.boeblingen.de.ibm.com (sSMTP sendmail emulation); Sun, 9 Dec 2007 20:39:55 +0100 Subject: [rfc] Make DWARF-2 "address size" explicit To: gdb-patches@sourceware.org Date: Sun, 09 Dec 2007 19:40:00 -0000 From: "Ulrich Weigand" X-Mailer: ELM [version 2.5 PL2] MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2007-12/txt/msg00142.txt.bz2 Hello, the DWARF-2 standard in some places refers to the "size of an address on the target machine", and uses this parameter implicitly to define the semantics of several opcodes (e.g. DW_OP_deref). GDB currently implements this as gdbarch_addr_bit (current_gdbarch) / TARGET_CHAR_BIT buried deep inside the call chain, which makes it difficult to eliminate those uses of the current_gdbarch global variable. This patch changes this by making the parameter explicit as member of the dwarf_expr_context structure. The core DWARF expresssion engine thus no longer needs to make this assumption. At those places where new expression contexts are initialized, the addr_size member can now be set according to a frame architecture or (by a follow-on patch) an objfile architecture. This patch does not change the behaviour of the code, with one exception: it appears the DW_OP_deref_size operator was implemented incorrectly, as it always converts a full address-sized buffer even if only a smaller amount of data was read from the target. This is fixed now by passed the proper size to dwarf2_read_address. Tested on amd64-linux. Bye, Ulrich ChangeLog: * 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. * dwarf2-frame.c (execute_stack_op): Set ctx->addr_size. (execute_cfa_program): Update calls to dwarf2_read_address. * dwarf2loc.c (find_location_expression): Update calls to dwarf2_read_address. (locexpr_describe_location): Likewise. (dwarf2_evaluate_loc_desc): Set ctx->addr_size. (dwarf2_loc_desc_needs_frame): Likewise. diff -urNp gdb-orig/gdb/dwarf2expr.c gdb-head/gdb/dwarf2expr.c --- gdb-orig/gdb/dwarf2expr.c 2007-12-08 18:47:58.000000000 +0100 +++ gdb-head/gdb/dwarf2expr.c 2007-12-08 18:48:58.000000000 +0100 @@ -31,7 +31,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. */ @@ -191,20 +191,17 @@ read_sleb128 (gdb_byte *buf, gdb_byte *b 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 @@ -228,21 +225,18 @@ dwarf2_read_address (gdb_byte *buf, gdb_ 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; @@ -256,12 +250,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; @@ -291,7 +286,6 @@ execute_stack_op (struct dwarf_expr_cont CORE_ADDR result; ULONGEST uoffset, reg; LONGEST offset; - int bytes_read; switch (op) { @@ -331,8 +325,8 @@ execute_stack_op (struct dwarf_expr_cont 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: @@ -549,34 +543,20 @@ execute_stack_op (struct dwarf_expr_cont { 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; @@ -627,8 +607,10 @@ execute_stack_op (struct dwarf_expr_cont 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) { @@ -661,7 +643,8 @@ execute_stack_op (struct dwarf_expr_cont 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 -urNp gdb-orig/gdb/dwarf2expr.h gdb-head/gdb/dwarf2expr.h --- gdb-orig/gdb/dwarf2expr.h 2007-12-08 18:47:58.000000000 +0100 +++ gdb-head/gdb/dwarf2expr.h 2007-12-08 18:47:53.000000000 +0100 @@ -33,6 +33,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; @@ -135,6 +138,6 @@ CORE_ADDR dwarf_expr_fetch (struct dwarf 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 -urNp gdb-orig/gdb/dwarf2-frame.c gdb-head/gdb/dwarf2-frame.c --- gdb-orig/gdb/dwarf2-frame.c 2007-12-08 18:47:58.000000000 +0100 +++ gdb-head/gdb/dwarf2-frame.c 2007-12-08 18:47:53.000000000 +0100 @@ -272,10 +272,12 @@ static CORE_ADDR execute_stack_op (gdb_byte *exp, ULONGEST len, struct frame_info *next_frame, CORE_ADDR initial) { + struct gdbarch *gdbarch = get_frame_arch (next_frame); struct dwarf_expr_context *ctx; CORE_ADDR result; ctx = new_dwarf_expr_context (); + ctx->addr_size = gdbarch_addr_bit (gdbarch) / TARGET_CHAR_BIT; ctx->baton = next_frame; ctx->read_reg = read_reg; ctx->read_mem = read_mem; @@ -301,8 +303,8 @@ execute_cfa_program (gdb_byte *insn_ptr, struct dwarf2_frame_state *fs, int eh_frame_p) { CORE_ADDR pc = frame_pc_unwind (next_frame); - int bytes_read; struct gdbarch *gdbarch = get_frame_arch (next_frame); + int addr_size = gdbarch_addr_bit (gdbarch) / TARGET_CHAR_BIT; while (insn_ptr < insn_end && fs->pc <= pc) { @@ -347,8 +349,8 @@ register %s (#%d) at 0x%s"), switch (insn) { case DW_CFA_set_loc: - fs->pc = dwarf2_read_address (insn_ptr, insn_end, &bytes_read); - insn_ptr += bytes_read; + fs->pc = dwarf2_read_address (insn_ptr, insn_end, addr_size); + insn_ptr += addr_size; break; case DW_CFA_advance_loc1: diff -urNp gdb-orig/gdb/dwarf2loc.c gdb-head/gdb/dwarf2loc.c --- gdb-orig/gdb/dwarf2loc.c 2007-12-08 18:47:58.000000000 +0100 +++ gdb-head/gdb/dwarf2loc.c 2007-12-08 18:47:53.000000000 +0100 @@ -66,10 +66,10 @@ find_location_expression (struct dwarf2_ 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) @@ -208,6 +208,7 @@ dwarf2_evaluate_loc_desc (struct symbol baton.objfile = objfile; ctx = new_dwarf_expr_context (); + ctx->addr_size = gdbarch_addr_bit (arch) / TARGET_CHAR_BIT; ctx->baton = &baton; ctx->read_reg = dwarf_expr_read_reg; ctx->read_mem = dwarf_expr_read_mem; @@ -327,6 +328,7 @@ dwarf2_loc_desc_needs_frame (gdb_byte *d baton.needs_frame = 0; ctx = new_dwarf_expr_context (); + ctx->addr_size = gdbarch_addr_bit (current_gdbarch) / TARGET_CHAR_BIT; ctx->baton = &baton; ctx->read_reg = needs_frame_read_reg; ctx->read_mem = needs_frame_read_mem; @@ -448,6 +450,7 @@ locexpr_describe_location (struct symbol { /* FIXME: be more extensive. */ struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol); + int addr_size = gdbarch_addr_bit (current_gdbarch) / TARGET_CHAR_BIT; if (dlbaton->size == 1 && dlbaton->data[0] >= DW_OP_reg0 @@ -477,10 +480,9 @@ locexpr_describe_location (struct symbol && dlbaton->data[dlbaton->size - 1] == DW_OP_GNU_push_tls_address) if (dlbaton->data[0] == DW_OP_addr) { - int bytes_read; 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'", -- Dr. Ulrich Weigand GNU Toolchain for Linux on System z and Cell BE Ulrich.Weigand@de.ibm.com