[rfc] Make DWARF-2 "address size" explicit

Ulrich Weigand uweigand@de.ibm.com
Sun Dec 9 19:40:00 GMT 2007


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



More information about the Gdb-patches mailing list