public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* RFC: partially fix empty DW_OP_piece
@ 2010-05-14  6:39 Tom Tromey
  2010-05-14 22:51 ` Jan Kratochvil
  2010-05-20 23:04 ` Joel Brobecker
  0 siblings, 2 replies; 12+ messages in thread
From: Tom Tromey @ 2010-05-14  6:39 UTC (permalink / raw)
  To: gdb-patches

I would appreciate comments on this patch.

In DWARF it is valid to have an empty DW_OP_piece.  This means that the
piece in question has been optimized out.  gdb currently does not handle
this (it will give an error), but the VTA+SRA patch that Jakub checked
in will cause gcc to start emitting such empty pieces.

This patch "fixes" the problem in a simple way.  Missing pieces are
filled with zeros, and read_pieced_value emits a warning, so that users
know not to fully trust the result.

This is not an excellent fix.  I think it is an improvement, but I can
understand if people would rather not see it go in.


I am interested in fully fixing this problem.  Doing this will mean
tracking validity of value contents on a bitwise basis (due to
DW_OP_bit_piece, coming soon).

I think there are two basic problems to solve.

First, preserving content validity when transforming values.  I suppose
this means modifying most value_* functions to track validity.

Second, fixing printing to do the right thing.  The tricky bit here is
that the val_print hierarchy would need at least an additional argument
to track the invalid bits.

I thought of two ways to implement the val_print part.  One way would be
to make a temporary 'struct type' instance that encodes the validity in
the type somehow.  The other way is to simply remove val_print entirely
and make all of printing work using values.  I think this is the route I
would prefer.

I'd appreciate comments on this plan.


I built and regtested this on x86-64 (compile farm).
I've updated pieces.exp (and pieces.[Sc]) to test this new functionality.

Tom

2010-05-13  Tom Tromey  <tromey@redhat.com>

	* dwarf2loc.c (read_pieced_value): Exit loop when result is full.
	<DWARF_VALUE_OPTIMIZED_OUT>: New case.
	* dwarf2expr.h (enum dwarf_value_location)
	<DWARF_VALUE_OPTIMIZED_OUT>: New constant.
	* dwarf2expr.c (dwarf_expr_stack_empty_p): New function.
	(add_piece): Handle empty piece.
	(execute_stack_op) <DW_OP_piece>: Handle
	DWARF_VALUE_OPTIMIZED_OUT.

2010-05-13  Tom Tromey  <tromey@redhat.com>

	* gdb.dwarf2/pieces.exp (pieces_test_f6): New proc.
	Call it.
	* gdb.dwarf2/pieces.c (struct C): New.
	(f6): New function.
	* gdb.dwarf2/pieces.S: Replace.

diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c
index 9e5ce61..482c293 100644
--- a/gdb/dwarf2expr.c
+++ b/gdb/dwarf2expr.c
@@ -141,6 +141,14 @@ dwarf_expr_fetch_in_stack_memory (struct dwarf_expr_context *ctx, int n)
 
 }
 
+/* Return true if the expression stack is empty.  */
+
+static int
+dwarf_expr_stack_empty_p (struct dwarf_expr_context *ctx)
+{
+  return ctx->stack_len == 0;
+}
+
 /* Add a new piece to CTX's piece list.  */
 static void
 add_piece (struct dwarf_expr_context *ctx, ULONGEST size)
@@ -165,6 +173,15 @@ add_piece (struct dwarf_expr_context *ctx, ULONGEST size)
       p->v.literal.data = ctx->data;
       p->v.literal.length = ctx->len;
     }
+  else if (dwarf_expr_stack_empty_p (ctx))
+    {
+      p->location = DWARF_VALUE_OPTIMIZED_OUT;
+      /* Also reset the context's location, for our callers.  This is
+	 a somewhat strange approach, but this lets us avoid setting
+	 the location to DWARF_VALUE_MEMORY in all the individual
+	 cases in the evaluator.  */
+      ctx->location = DWARF_VALUE_OPTIMIZED_OUT;
+    }
   else
     {
       p->v.expr.value = dwarf_expr_fetch (ctx, 0);
@@ -853,7 +870,8 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 
             /* Pop off the address/regnum, and reset the location
 	       type.  */
-	    if (ctx->location != DWARF_VALUE_LITERAL)
+	    if (ctx->location != DWARF_VALUE_LITERAL
+		&& ctx->location != DWARF_VALUE_OPTIMIZED_OUT)
 	      dwarf_expr_pop (ctx);
             ctx->location = DWARF_VALUE_MEMORY;
           }
diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h
index 437ca39..f24f193 100644
--- a/gdb/dwarf2expr.h
+++ b/gdb/dwarf2expr.h
@@ -38,7 +38,10 @@ enum dwarf_value_location
   DWARF_VALUE_STACK,
 
   /* The piece is a literal.  */
-  DWARF_VALUE_LITERAL
+  DWARF_VALUE_LITERAL,
+
+  /* The piece was optimized out.  */
+  DWARF_VALUE_OPTIMIZED_OUT
 };
 
 /* The dwarf expression stack.  */
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 7cd33c6..aa54551 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -366,6 +366,14 @@ read_pieced_value (struct value *v)
 	  }
 	  break;
 
+	case DWARF_VALUE_OPTIMIZED_OUT:
+	  /* We just leave the bits empty for now.  This is not ideal
+	     but gdb currently does not have a nice way to represent
+	     optimized-out pieces.  */
+	  warning (_("some bits in computed object were optimized out; "
+		     "replacing with zeroes"));
+	  break;
+
 	default:
 	  internal_error (__FILE__, __LINE__, _("invalid location type"));
 	}
@@ -593,6 +601,9 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
 	  }
 	  break;
 
+	  /* DWARF_VALUE_OPTIMIZED_OUT can't occur in this context --
+	     it can only be encountered when making a piece.  */
+	case DWARF_VALUE_OPTIMIZED_OUT:
 	default:
 	  internal_error (__FILE__, __LINE__, _("invalid location type"));
 	}
diff --git a/gdb/testsuite/gdb.dwarf2/pieces.S b/gdb/testsuite/gdb.dwarf2/pieces.S
index ec578a6..6ea55b8 100644
--- a/gdb/testsuite/gdb.dwarf2/pieces.S
+++ b/gdb/testsuite/gdb.dwarf2/pieces.S
@@ -37,19 +37,19 @@
 bar:
 .LFB0:
 	.file 1 "pieces.c"
-	# pieces.c:10
-	.loc 1 10 0
+	# pieces.c:11
+	.loc 1 11 0
 .LVL0:
 	# basic block 2
 	pushl	%ebp
 .LCFI0:
 	movl	%esp, %ebp
 .LCFI1:
-	# pieces.c:11
-	.loc 1 11 0
-	movl	8(%ebp), %eax
 	# pieces.c:12
 	.loc 1 12 0
+	movl	8(%ebp), %eax
+	# pieces.c:13
+	.loc 1 13 0
 	popl	%ebp
 .LCFI2:
 	ret
@@ -60,8 +60,8 @@ bar:
 	.type	f1, @function
 f1:
 .LFB1:
-	# pieces.c:16
-	.loc 1 16 0
+	# pieces.c:17
+	.loc 1 17 0
 .LVL1:
 	# basic block 2
 	pushl	%ebp
@@ -73,36 +73,36 @@ f1:
 .LCFI5:
 	movl	%esi, -4(%ebp)
 .LCFI6:
-	# pieces.c:19
-	.loc 1 19 0
+	# pieces.c:20
+	.loc 1 20 0
 	movl	8(%ebp), %esi
-	# pieces.c:16
-	.loc 1 16 0
+	# pieces.c:17
+	.loc 1 17 0
 	movl	%ebx, -8(%ebp)
 .LCFI7:
-	# pieces.c:18
-	.loc 1 18 0
+	# pieces.c:19
+	.loc 1 19 0
 	movl	$4, %ebx
 .LVL3:
+	# pieces.c:21
+	.loc 1 21 0
+	movl	%ebx, (%esp)
 	# pieces.c:20
 	.loc 1 20 0
-	movl	%ebx, (%esp)
-	# pieces.c:19
-	.loc 1 19 0
 	addl	$7, %esi
 .LVL4:
-	# pieces.c:20
-	.loc 1 20 0
-	call	bar
 	# pieces.c:21
 	.loc 1 21 0
-	movl	%esi, (%esp)
 	call	bar
 	# pieces.c:22
 	.loc 1 22 0
-	leal	(%ebx,%esi), %eax
+	movl	%esi, (%esp)
+	call	bar
 	# pieces.c:23
 	.loc 1 23 0
+	leal	(%ebx,%esi), %eax
+	# pieces.c:24
+	.loc 1 24 0
 	movl	-8(%ebp), %ebx
 .LVL5:
 	movl	-4(%ebp), %esi
@@ -119,8 +119,8 @@ f1:
 	.type	f2, @function
 f2:
 .LFB2:
-	# pieces.c:27
-	.loc 1 27 0
+	# pieces.c:28
+	.loc 1 28 0
 .LVL7:
 	# basic block 2
 	pushl	%ebp
@@ -132,36 +132,36 @@ f2:
 .LCFI12:
 	movl	%esi, -4(%ebp)
 .LCFI13:
-	# pieces.c:30
-	.loc 1 30 0
+	# pieces.c:31
+	.loc 1 31 0
 	movl	8(%ebp), %esi
-	# pieces.c:27
-	.loc 1 27 0
+	# pieces.c:28
+	.loc 1 28 0
 	movl	%ebx, -8(%ebp)
 .LCFI14:
-	# pieces.c:29
-	.loc 1 29 0
+	# pieces.c:30
+	.loc 1 30 0
 	movl	$4, %ebx
 .LVL9:
+	# pieces.c:32
+	.loc 1 32 0
+	movl	%ebx, (%esp)
 	# pieces.c:31
 	.loc 1 31 0
-	movl	%ebx, (%esp)
-	# pieces.c:30
-	.loc 1 30 0
 	addl	$7, %esi
 .LVL10:
-	# pieces.c:31
-	.loc 1 31 0
-	call	bar
 	# pieces.c:32
 	.loc 1 32 0
-	movl	%esi, (%esp)
 	call	bar
 	# pieces.c:33
 	.loc 1 33 0
-	leal	(%ebx,%esi), %eax
+	movl	%esi, (%esp)
+	call	bar
 	# pieces.c:34
 	.loc 1 34 0
+	leal	(%ebx,%esi), %eax
+	# pieces.c:35
+	.loc 1 35 0
 	movl	-8(%ebp), %ebx
 .LVL11:
 	movl	-4(%ebp), %esi
@@ -178,59 +178,59 @@ f2:
 	.type	f3, @function
 f3:
 .LFB3:
-	# pieces.c:38
-	.loc 1 38 0
+	# pieces.c:39
+	.loc 1 39 0
 .LVL13:
 	# basic block 2
 	pushl	%ebp
 .LCFI17:
-	# pieces.c:40
-	.loc 1 40 0
+	# pieces.c:41
+	.loc 1 41 0
 	movl	$4, %edx
-	# pieces.c:38
-	.loc 1 38 0
+	# pieces.c:39
+	.loc 1 39 0
 	movl	%esp, %ebp
 .LCFI18:
 .LVL14:
 	subl	$12, %esp
 .LCFI19:
-	# pieces.c:40
-	.loc 1 40 0
+	# pieces.c:41
+	.loc 1 41 0
 .LVL15:
-	# pieces.c:38
-	.loc 1 38 0
+	# pieces.c:39
+	.loc 1 39 0
 	movl	%esi, -4(%ebp)
 .LCFI20:
-	# pieces.c:42
-	.loc 1 42 0
+	# pieces.c:43
+	.loc 1 43 0
 	movswl	%dx, %esi
-	# pieces.c:38
-	.loc 1 38 0
+	# pieces.c:39
+	.loc 1 39 0
 	movl	%ebx, -8(%ebp)
 .LCFI21:
-	# pieces.c:42
-	.loc 1 42 0
+	# pieces.c:43
+	.loc 1 43 0
 	movl	%esi, (%esp)
 	call	bar
 .LVL16:
-	# pieces.c:39
-	.loc 1 39 0
+	# pieces.c:40
+	.loc 1 40 0
 	movl	8(%ebp), %edx
 	sall	$4, %edx
-	# pieces.c:41
-	.loc 1 41 0
+	# pieces.c:42
+	.loc 1 42 0
 	addl	$112, %edx
 	sarw	$4, %dx
-	# pieces.c:43
-	.loc 1 43 0
+	# pieces.c:44
+	.loc 1 44 0
 	movswl	%dx, %ebx
 	movl	%ebx, (%esp)
 	call	bar
-	# pieces.c:44
-	.loc 1 44 0
-	leal	(%esi,%ebx), %eax
 	# pieces.c:45
 	.loc 1 45 0
+	leal	(%esi,%ebx), %eax
+	# pieces.c:46
+	.loc 1 46 0
 	movl	-8(%ebp), %ebx
 	movl	-4(%ebp), %esi
 .LVL17:
@@ -246,8 +246,8 @@ f3:
 	.type	f4, @function
 f4:
 .LFB4:
-	# pieces.c:49
-	.loc 1 49 0
+	# pieces.c:50
+	.loc 1 50 0
 .LVL18:
 	# basic block 2
 	pushl	%ebp
@@ -262,28 +262,28 @@ f4:
 .LVL19:
 	movl	%ebx, -8(%ebp)
 .LCFI28:
-	# pieces.c:51
-	.loc 1 51 0
-	movl	%esi, %ebx
 	# pieces.c:52
 	.loc 1 52 0
-	addl	$1, %esi
-	# pieces.c:51
-	.loc 1 51 0
-.LVL20:
+	movl	%esi, %ebx
 	# pieces.c:53
 	.loc 1 53 0
-	movl	%ebx, (%esp)
-	call	bar
+	addl	$1, %esi
+	# pieces.c:52
+	.loc 1 52 0
+.LVL20:
 	# pieces.c:54
 	.loc 1 54 0
-	movl	%esi, (%esp)
+	movl	%ebx, (%esp)
 	call	bar
 	# pieces.c:55
 	.loc 1 55 0
-	leal	(%ebx,%esi), %eax
+	movl	%esi, (%esp)
+	call	bar
 	# pieces.c:56
 	.loc 1 56 0
+	leal	(%ebx,%esi), %eax
+	# pieces.c:57
+	.loc 1 57 0
 	movl	-8(%ebp), %ebx
 .LVL21:
 	movl	-4(%ebp), %esi
@@ -300,8 +300,8 @@ f4:
 	.type	f5, @function
 f5:
 .LFB5:
-	# pieces.c:60
-	.loc 1 60 0
+	# pieces.c:61
+	.loc 1 61 0
 .LVL23:
 	# basic block 2
 	pushl	%ebp
@@ -316,28 +316,28 @@ f5:
 .LVL24:
 	movl	%ebx, -8(%ebp)
 .LCFI35:
-	# pieces.c:62
-	.loc 1 62 0
-	movl	%esi, %ebx
 	# pieces.c:63
 	.loc 1 63 0
-	addl	$1, %esi
-	# pieces.c:62
-	.loc 1 62 0
-.LVL25:
+	movl	%esi, %ebx
 	# pieces.c:64
 	.loc 1 64 0
-	movl	%ebx, (%esp)
-	call	bar
+	addl	$1, %esi
+	# pieces.c:63
+	.loc 1 63 0
+.LVL25:
 	# pieces.c:65
 	.loc 1 65 0
-	movl	%esi, (%esp)
+	movl	%ebx, (%esp)
 	call	bar
 	# pieces.c:66
 	.loc 1 66 0
-	leal	(%ebx,%esi), %eax
+	movl	%esi, (%esp)
+	call	bar
 	# pieces.c:67
 	.loc 1 67 0
+	leal	(%ebx,%esi), %eax
+	# pieces.c:68
+	.loc 1 68 0
 	movl	-8(%ebp), %ebx
 .LVL26:
 	movl	-4(%ebp), %esi
@@ -350,60 +350,118 @@ f5:
 .LFE5:
 	.size	f5, .-f5
 	.p2align 4,,15
-.globl _start
-	.type	_start, @function
-_start:
+.globl f6
+	.type	f6, @function
+f6:
 .LFB6:
-	# pieces.c:71
-	.loc 1 71 0
+	# pieces.c:72
+	.loc 1 72 0
+.LVL28:
 	# basic block 2
 	pushl	%ebp
 .LCFI38:
 	movl	%esp, %ebp
 .LCFI39:
-	pushl	%ebx
+	subl	$12, %esp
 .LCFI40:
-	# pieces.c:73
-	.loc 1 73 0
-	movl	$7, %ebx
-	# pieces.c:71
-	.loc 1 71 0
-	subl	$4, %esp
+	movl	%esi, -4(%ebp)
 .LCFI41:
-	# pieces.c:73
-	.loc 1 73 0
-.LVL28:
-	# pieces.c:74
-	.loc 1 74 0
-	movl	%ebx, (%esp)
-	call	f1
+	movl	8(%ebp), %esi
+.LVL29:
+	movl	%ebx, -8(%ebp)
+.LCFI42:
 	# pieces.c:75
 	.loc 1 75 0
-	movl	%ebx, (%esp)
-	call	f2
+	movl	%esi, %ebx
 	# pieces.c:76
 	.loc 1 76 0
-	movl	%ebx, (%esp)
-	call	f3
+	addl	$1, %esi
+	# pieces.c:75
+	.loc 1 75 0
+.LVL30:
 	# pieces.c:77
 	.loc 1 77 0
 	movl	%ebx, (%esp)
-	call	f4
+	call	bar
 	# pieces.c:78
 	.loc 1 78 0
-	movl	%ebx, (%esp)
-	call	f5
+	movl	%esi, (%esp)
+	call	bar
+	# pieces.c:79
+	.loc 1 79 0
+	leal	(%ebx,%esi), %eax
 	# pieces.c:80
 	.loc 1 80 0
+	movl	-8(%ebp), %ebx
+.LVL31:
+	movl	-4(%ebp), %esi
+.LVL32:
+	movl	%ebp, %esp
+.LCFI43:
+	popl	%ebp
+.LCFI44:
+	ret
+.LFE6:
+	.size	f6, .-f6
+	.p2align 4,,15
+.globl _start
+	.type	_start, @function
+_start:
+.LFB7:
+	# pieces.c:84
+	.loc 1 84 0
+	# basic block 2
+	pushl	%ebp
+.LCFI45:
+	movl	%esp, %ebp
+.LCFI46:
+	pushl	%ebx
+.LCFI47:
+	# pieces.c:86
+	.loc 1 86 0
+	movl	$7, %ebx
+	# pieces.c:84
+	.loc 1 84 0
+	subl	$4, %esp
+.LCFI48:
+	# pieces.c:86
+	.loc 1 86 0
+.LVL33:
+	# pieces.c:87
+	.loc 1 87 0
+	movl	%ebx, (%esp)
+	call	f1
+	# pieces.c:88
+	.loc 1 88 0
+	movl	%ebx, (%esp)
+	call	f2
+	# pieces.c:89
+	.loc 1 89 0
+	movl	%ebx, (%esp)
+	call	f3
+	# pieces.c:90
+	.loc 1 90 0
+	movl	%ebx, (%esp)
+	call	f4
+	# pieces.c:91
+	.loc 1 91 0
+	movl	%ebx, (%esp)
+	call	f5
+	# pieces.c:92
+	.loc 1 92 0
+	movl	%ebx, (%esp)
+	call	f6
+	# pieces.c:94
+	.loc 1 94 0
 	addl	$4, %esp
 	xorl	%eax, %eax
 	popl	%ebx
-.LCFI42:
-.LVL29:
+.LCFI49:
+.LVL34:
 	popl	%ebp
-.LCFI43:
+.LCFI50:
 	ret
-.LFE6:
+.LFE7:
 	.size	_start, .-_start
 #APP
 	.section	.debug_frame,"",@progbits
@@ -649,20 +707,57 @@ _start:
 	.byte	0xd	# DW_CFA_def_cfa_register
 	.uleb128 0x5
 	.byte	0x4	# DW_CFA_advance_loc4
-	.long	.LCFI40-.LCFI39
+	.long	.LCFI41-.LCFI39
+	.byte	0x86	# DW_CFA_offset, column 0x6
+	.uleb128 0x3
+	.byte	0x4	# DW_CFA_advance_loc4
+	.long	.LCFI42-.LCFI41
+	.byte	0x83	# DW_CFA_offset, column 0x3
+	.uleb128 0x4
+	.byte	0x4	# DW_CFA_advance_loc4
+	.long	.LCFI43-.LCFI42
+	.byte	0xd	# DW_CFA_def_cfa_register
+	.uleb128 0x4
+	.byte	0xc6	# DW_CFA_restore, column 0x6
+	.byte	0xc3	# DW_CFA_restore, column 0x3
+	.byte	0x4	# DW_CFA_advance_loc4
+	.long	.LCFI44-.LCFI43
+	.byte	0xc5	# DW_CFA_restore, column 0x5
+	.byte	0xe	# DW_CFA_def_cfa_offset
+	.uleb128 0x4
+	.align 4
+.LEFDE12:
+.LSFDE14:
+	.long	.LEFDE14-.LASFDE14	# FDE Length
+.LASFDE14:
+	.long	.Lframe0	# FDE CIE offset
+	.long	.LFB7	# FDE initial location
+	.long	.LFE7-.LFB7	# FDE address range
+	.byte	0x4	# DW_CFA_advance_loc4
+	.long	.LCFI45-.LFB7
+	.byte	0xe	# DW_CFA_def_cfa_offset
+	.uleb128 0x8
+	.byte	0x85	# DW_CFA_offset, column 0x5
+	.uleb128 0x2
+	.byte	0x4	# DW_CFA_advance_loc4
+	.long	.LCFI46-.LCFI45
+	.byte	0xd	# DW_CFA_def_cfa_register
+	.uleb128 0x5
+	.byte	0x4	# DW_CFA_advance_loc4
+	.long	.LCFI47-.LCFI46
 	.byte	0x83	# DW_CFA_offset, column 0x3
 	.uleb128 0x3
 	.byte	0x4	# DW_CFA_advance_loc4
-	.long	.LCFI42-.LCFI40
+	.long	.LCFI49-.LCFI47
 	.byte	0xc3	# DW_CFA_restore, column 0x3
 	.byte	0x4	# DW_CFA_advance_loc4
-	.long	.LCFI43-.LCFI42
+	.long	.LCFI50-.LCFI49
 	.byte	0xc5	# DW_CFA_restore, column 0x5
 	.byte	0xc	# DW_CFA_def_cfa
 	.uleb128 0x4
 	.uleb128 0x4
 	.align 4
-.LEFDE12:
+.LEFDE14:
 #NO_APP
 	.text
 .Letext0:
@@ -1130,6 +1225,11 @@ _start:
 	.byte	0x75	# DW_OP_breg5
 	.sleb128 8
 	.long	.LCFI43-.Ltext0	# Location list begin address (*.LLST11)
+	.long	.LCFI44-.Ltext0	# Location list end address (*.LLST11)
+	.value	0x2	# Location expression size
+	.byte	0x74	# DW_OP_breg4
+	.sleb128 8
+	.long	.LCFI44-.Ltext0	# Location list begin address (*.LLST11)
 	.long	.LFE6-.Ltext0	# Location list end address (*.LLST11)
 	.value	0x2	# Location expression size
 	.byte	0x74	# DW_OP_breg4
@@ -1137,14 +1237,74 @@ _start:
 	.long	0	# Location list terminator begin (*.LLST11)
 	.long	0	# Location list terminator end (*.LLST11)
 .LLST12:
-	.long	.LVL28-.Ltext0	# Location list begin address (*.LLST12)
-	.long	.LVL29-.Ltext0	# Location list end address (*.LLST12)
-	.value	0x1	# Location expression size
+	.long	.LVL29-.Ltext0	# Location list begin address (*.LLST12)
+	.long	.LVL30-.Ltext0	# Location list end address (*.LLST12)
+	.value	0xa	# Location expression size
+	.byte	0x91	# DW_OP_fbreg
+	.sleb128 0
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x4
+	.byte	0x91	# DW_OP_fbreg
+	.sleb128 0
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x4
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x4
+	.long	.LVL30-.Ltext0	# Location list begin address (*.LLST12)
+	.long	.LVL31-.Ltext0	# Location list end address (*.LLST12)
+	.value	0x8	# Location expression size
 	.byte	0x53	# DW_OP_reg3
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x4
+	.byte	0x56	# DW_OP_reg6
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x4
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x4
+	.long	.LVL31-.Ltext0	# Location list begin address (*.LLST12)
+	.long	.LVL32-.Ltext0	# Location list end address (*.LLST12)
+	.value	0x7	# Location expression size
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x4
+	.byte	0x56	# DW_OP_reg6
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x4
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x4
 	.long	0	# Location list terminator begin (*.LLST12)
 	.long	0	# Location list terminator end (*.LLST12)
+.LLST13:
+	.long	.LFB7-.Ltext0	# Location list begin address (*.LLST13)
+	.long	.LCFI45-.Ltext0	# Location list end address (*.LLST13)
+	.value	0x2	# Location expression size
+	.byte	0x74	# DW_OP_breg4
+	.sleb128 4
+	.long	.LCFI45-.Ltext0	# Location list begin address (*.LLST13)
+	.long	.LCFI46-.Ltext0	# Location list end address (*.LLST13)
+	.value	0x2	# Location expression size
+	.byte	0x74	# DW_OP_breg4
+	.sleb128 8
+	.long	.LCFI46-.Ltext0	# Location list begin address (*.LLST13)
+	.long	.LCFI50-.Ltext0	# Location list end address (*.LLST13)
+	.value	0x2	# Location expression size
+	.byte	0x75	# DW_OP_breg5
+	.sleb128 8
+	.long	.LCFI50-.Ltext0	# Location list begin address (*.LLST13)
+	.long	.LFE7-.Ltext0	# Location list end address (*.LLST13)
+	.value	0x2	# Location expression size
+	.byte	0x74	# DW_OP_breg4
+	.sleb128 4
+	.long	0	# Location list terminator begin (*.LLST13)
+	.long	0	# Location list terminator end (*.LLST13)
+.LLST14:
+	.long	.LVL33-.Ltext0	# Location list begin address (*.LLST14)
+	.long	.LVL34-.Ltext0	# Location list end address (*.LLST14)
+	.value	0x1	# Location expression size
+	.byte	0x53	# DW_OP_reg3
+	.long	0	# Location list terminator begin (*.LLST14)
+	.long	0	# Location list terminator end (*.LLST14)
 	.section	.debug_info
-	.long	0x1e3	# Length of Compilation Unit Info
+	.long	0x252	# Length of Compilation Unit Info
 	.value	0x2	# DWARF version number
 	.long	.Ldebug_abbrev0	# Offset Into Abbrev. Section
 	.byte	0x4	# Pointer Size (in bytes)
@@ -1152,7 +1312,7 @@ _start:
 	.long	.LASF1	# DW_AT_producer: "GNU C 4.6.0 20100506 (experimental) [trunk revision 159117]"
 	.byte	0x1	# DW_AT_language
 	.long	.LASF2	# DW_AT_name: "pieces.c"
-	.long	.LASF3	# DW_AT_comp_dir: "/home/tromey/gnu/PRS/rh589467"
+	.long	.LASF3	# DW_AT_comp_dir: "/home/tromey/gnu/archer/archer/gdb/testsuite/gdb.dwarf2"
 	.long	.Ltext0	# DW_AT_low_pc
 	.long	.Letext0	# DW_AT_high_pc
 	.long	.Ldebug_line0	# DW_AT_stmt_list
@@ -1212,182 +1372,245 @@ _start:
 	.byte	0x23	# DW_OP_plus_uconst
 	.uleb128 0
 	.byte	0	# end of children of DIE 0x4f
-	.uleb128 0x6	# (DIE (0x78) DW_TAG_subprogram)
+	.uleb128 0x2	# (DIE (0x78) DW_TAG_structure_type)
+	.ascii "C\0"	# DW_AT_name
+	.byte	0xc	# DW_AT_byte_size
+	.byte	0x1	# DW_AT_decl_file (pieces.c)
+	.byte	0x7	# DW_AT_decl_line
+	.long	0xa7	# DW_AT_sibling
+	.uleb128 0x3	# (DIE (0x82) DW_TAG_member)
+	.ascii "i\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (pieces.c)
+	.byte	0x7	# DW_AT_decl_line
+	.long	0x48	# DW_AT_type
+	.byte	0x2	# DW_AT_data_member_location
+	.byte	0x23	# DW_OP_plus_uconst
+	.uleb128 0
+	.uleb128 0x3	# (DIE (0x8e) DW_TAG_member)
+	.ascii "j\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (pieces.c)
+	.byte	0x7	# DW_AT_decl_line
+	.long	0x48	# DW_AT_type
+	.byte	0x2	# DW_AT_data_member_location
+	.byte	0x23	# DW_OP_plus_uconst
+	.uleb128 0x4
+	.uleb128 0x3	# (DIE (0x9a) DW_TAG_member)
+	.ascii "q\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (pieces.c)
+	.byte	0x7	# DW_AT_decl_line
+	.long	0x48	# DW_AT_type
+	.byte	0x2	# DW_AT_data_member_location
+	.byte	0x23	# DW_OP_plus_uconst
+	.uleb128 0x8
+	.byte	0	# end of children of DIE 0x78
+	.uleb128 0x6	# (DIE (0xa7) DW_TAG_subprogram)
 	.byte	0x1	# DW_AT_external
 	.ascii "bar\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x9	# DW_AT_decl_line
+	.byte	0xa	# DW_AT_decl_line
 	.byte	0x1	# DW_AT_prototyped
 	.long	.LFB0	# DW_AT_low_pc
 	.long	.LFE0	# DW_AT_high_pc
 	.long	.LLST0	# DW_AT_frame_base
-	.long	0x9e	# DW_AT_sibling
-	.uleb128 0x7	# (DIE (0x91) DW_TAG_formal_parameter)
+	.long	0xcd	# DW_AT_sibling
+	.uleb128 0x7	# (DIE (0xc0) DW_TAG_formal_parameter)
 	.ascii "x\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x9	# DW_AT_decl_line
+	.byte	0xa	# DW_AT_decl_line
 	.long	0x48	# DW_AT_type
 	.byte	0x2	# DW_AT_location
 	.byte	0x91	# DW_OP_fbreg
 	.sleb128 0
-	.byte	0	# end of children of DIE 0x78
-	.uleb128 0x8	# (DIE (0x9e) DW_TAG_subprogram)
+	.byte	0	# end of children of DIE 0xa7
+	.uleb128 0x8	# (DIE (0xcd) DW_TAG_subprogram)
 	.byte	0x1	# DW_AT_external
 	.ascii "f1\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0xf	# DW_AT_decl_line
+	.byte	0x10	# DW_AT_decl_line
 	.byte	0x1	# DW_AT_prototyped
 	.long	0x48	# DW_AT_type
 	.long	.LFB1	# DW_AT_low_pc
 	.long	.LFE1	# DW_AT_high_pc
 	.long	.LLST1	# DW_AT_frame_base
-	.long	0xd4	# DW_AT_sibling
-	.uleb128 0x7	# (DIE (0xba) DW_TAG_formal_parameter)
+	.long	0x103	# DW_AT_sibling
+	.uleb128 0x7	# (DIE (0xe9) DW_TAG_formal_parameter)
 	.ascii "k\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0xf	# DW_AT_decl_line
+	.byte	0x10	# DW_AT_decl_line
 	.long	0x48	# DW_AT_type
 	.byte	0x2	# DW_AT_location
 	.byte	0x91	# DW_OP_fbreg
 	.sleb128 0
-	.uleb128 0x9	# (DIE (0xc6) DW_TAG_variable)
+	.uleb128 0x9	# (DIE (0xf5) DW_TAG_variable)
 	.ascii "a\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x11	# DW_AT_decl_line
+	.byte	0x12	# DW_AT_decl_line
 	.long	0x25	# DW_AT_type
 	.long	.LLST2	# DW_AT_location
-	.byte	0	# end of children of DIE 0x9e
-	.uleb128 0x8	# (DIE (0xd4) DW_TAG_subprogram)
+	.byte	0	# end of children of DIE 0xcd
+	.uleb128 0x8	# (DIE (0x103) DW_TAG_subprogram)
 	.byte	0x1	# DW_AT_external
 	.ascii "f2\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x1a	# DW_AT_decl_line
+	.byte	0x1b	# DW_AT_decl_line
 	.byte	0x1	# DW_AT_prototyped
 	.long	0x48	# DW_AT_type
 	.long	.LFB2	# DW_AT_low_pc
 	.long	.LFE2	# DW_AT_high_pc
 	.long	.LLST3	# DW_AT_frame_base
-	.long	0x10a	# DW_AT_sibling
-	.uleb128 0x7	# (DIE (0xf0) DW_TAG_formal_parameter)
+	.long	0x139	# DW_AT_sibling
+	.uleb128 0x7	# (DIE (0x11f) DW_TAG_formal_parameter)
 	.ascii "k\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x1a	# DW_AT_decl_line
+	.byte	0x1b	# DW_AT_decl_line
 	.long	0x48	# DW_AT_type
 	.byte	0x2	# DW_AT_location
 	.byte	0x91	# DW_OP_fbreg
 	.sleb128 0
-	.uleb128 0x9	# (DIE (0xfc) DW_TAG_variable)
+	.uleb128 0x9	# (DIE (0x12b) DW_TAG_variable)
 	.ascii "a\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x1c	# DW_AT_decl_line
-	.long	0x10a	# DW_AT_type
+	.byte	0x1d	# DW_AT_decl_line
+	.long	0x139	# DW_AT_type
 	.long	.LLST4	# DW_AT_location
-	.byte	0	# end of children of DIE 0xd4
-	.uleb128 0xa	# (DIE (0x10a) DW_TAG_array_type)
+	.byte	0	# end of children of DIE 0x103
+	.uleb128 0xa	# (DIE (0x139) DW_TAG_array_type)
 	.long	0x48	# DW_AT_type
-	.long	0x11a	# DW_AT_sibling
-	.uleb128 0xb	# (DIE (0x113) DW_TAG_subrange_type)
-	.long	0x11a	# DW_AT_type
+	.long	0x149	# DW_AT_sibling
+	.uleb128 0xb	# (DIE (0x142) DW_TAG_subrange_type)
+	.long	0x149	# DW_AT_type
 	.byte	0x1	# DW_AT_upper_bound
-	.byte	0	# end of children of DIE 0x10a
-	.uleb128 0xc	# (DIE (0x11a) DW_TAG_base_type)
+	.byte	0	# end of children of DIE 0x139
+	.uleb128 0xc	# (DIE (0x149) DW_TAG_base_type)
 	.byte	0x4	# DW_AT_byte_size
 	.byte	0x7	# DW_AT_encoding
-	.uleb128 0x8	# (DIE (0x11d) DW_TAG_subprogram)
+	.uleb128 0x8	# (DIE (0x14c) DW_TAG_subprogram)
 	.byte	0x1	# DW_AT_external
 	.ascii "f3\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x25	# DW_AT_decl_line
+	.byte	0x26	# DW_AT_decl_line
 	.byte	0x1	# DW_AT_prototyped
 	.long	0x48	# DW_AT_type
 	.long	.LFB3	# DW_AT_low_pc
 	.long	.LFE3	# DW_AT_high_pc
 	.long	.LLST5	# DW_AT_frame_base
-	.long	0x153	# DW_AT_sibling
-	.uleb128 0x7	# (DIE (0x139) DW_TAG_formal_parameter)
+	.long	0x182	# DW_AT_sibling
+	.uleb128 0x7	# (DIE (0x168) DW_TAG_formal_parameter)
 	.ascii "k\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x25	# DW_AT_decl_line
+	.byte	0x26	# DW_AT_decl_line
 	.long	0x48	# DW_AT_type
 	.byte	0x2	# DW_AT_location
 	.byte	0x91	# DW_OP_fbreg
 	.sleb128 0
-	.uleb128 0x9	# (DIE (0x145) DW_TAG_variable)
+	.uleb128 0x9	# (DIE (0x174) DW_TAG_variable)
 	.ascii "a\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x27	# DW_AT_decl_line
+	.byte	0x28	# DW_AT_decl_line
 	.long	0x4f	# DW_AT_type
 	.long	.LLST6	# DW_AT_location
-	.byte	0	# end of children of DIE 0x11d
-	.uleb128 0x8	# (DIE (0x153) DW_TAG_subprogram)
+	.byte	0	# end of children of DIE 0x14c
+	.uleb128 0x8	# (DIE (0x182) DW_TAG_subprogram)
 	.byte	0x1	# DW_AT_external
 	.ascii "f4\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x30	# DW_AT_decl_line
+	.byte	0x31	# DW_AT_decl_line
 	.byte	0x1	# DW_AT_prototyped
 	.long	0x48	# DW_AT_type
 	.long	.LFB4	# DW_AT_low_pc
 	.long	.LFE4	# DW_AT_high_pc
 	.long	.LLST7	# DW_AT_frame_base
-	.long	0x189	# DW_AT_sibling
-	.uleb128 0x7	# (DIE (0x16f) DW_TAG_formal_parameter)
+	.long	0x1b8	# DW_AT_sibling
+	.uleb128 0x7	# (DIE (0x19e) DW_TAG_formal_parameter)
 	.ascii "k\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x30	# DW_AT_decl_line
+	.byte	0x31	# DW_AT_decl_line
 	.long	0x48	# DW_AT_type
 	.byte	0x2	# DW_AT_location
 	.byte	0x91	# DW_OP_fbreg
 	.sleb128 0
-	.uleb128 0x9	# (DIE (0x17b) DW_TAG_variable)
+	.uleb128 0x9	# (DIE (0x1aa) DW_TAG_variable)
 	.ascii "a\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x32	# DW_AT_decl_line
-	.long	0x10a	# DW_AT_type
+	.byte	0x33	# DW_AT_decl_line
+	.long	0x139	# DW_AT_type
 	.long	.LLST8	# DW_AT_location
-	.byte	0	# end of children of DIE 0x153
-	.uleb128 0x8	# (DIE (0x189) DW_TAG_subprogram)
+	.byte	0	# end of children of DIE 0x182
+	.uleb128 0x8	# (DIE (0x1b8) DW_TAG_subprogram)
 	.byte	0x1	# DW_AT_external
 	.ascii "f5\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x3b	# DW_AT_decl_line
+	.byte	0x3c	# DW_AT_decl_line
 	.byte	0x1	# DW_AT_prototyped
 	.long	0x48	# DW_AT_type
 	.long	.LFB5	# DW_AT_low_pc
 	.long	.LFE5	# DW_AT_high_pc
 	.long	.LLST9	# DW_AT_frame_base
-	.long	0x1bf	# DW_AT_sibling
-	.uleb128 0x7	# (DIE (0x1a5) DW_TAG_formal_parameter)
+	.long	0x1ee	# DW_AT_sibling
+	.uleb128 0x7	# (DIE (0x1d4) DW_TAG_formal_parameter)
 	.ascii "k\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x3b	# DW_AT_decl_line
+	.byte	0x3c	# DW_AT_decl_line
 	.long	0x48	# DW_AT_type
 	.byte	0x2	# DW_AT_location
 	.byte	0x91	# DW_OP_fbreg
 	.sleb128 0
-	.uleb128 0x9	# (DIE (0x1b1) DW_TAG_variable)
+	.uleb128 0x9	# (DIE (0x1e0) DW_TAG_variable)
 	.ascii "a\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x3d	# DW_AT_decl_line
+	.byte	0x3e	# DW_AT_decl_line
 	.long	0x25	# DW_AT_type
 	.long	.LLST10	# DW_AT_location
-	.byte	0	# end of children of DIE 0x189
-	.uleb128 0xd	# (DIE (0x1bf) DW_TAG_subprogram)
+	.byte	0	# end of children of DIE 0x1b8
+	.uleb128 0x8	# (DIE (0x1ee) DW_TAG_subprogram)
 	.byte	0x1	# DW_AT_external
-	.long	.LASF0	# DW_AT_name: "main"
+	.ascii "f6\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x46	# DW_AT_decl_line
+	.byte	0x47	# DW_AT_decl_line
 	.byte	0x1	# DW_AT_prototyped
 	.long	0x48	# DW_AT_type
 	.long	.LFB6	# DW_AT_low_pc
 	.long	.LFE6	# DW_AT_high_pc
 	.long	.LLST11	# DW_AT_frame_base
-	.uleb128 0x9	# (DIE (0x1d8) DW_TAG_variable)
+	.long	0x22e	# DW_AT_sibling
+	.uleb128 0x7	# (DIE (0x20a) DW_TAG_formal_parameter)
 	.ascii "k\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x48	# DW_AT_decl_line
+	.byte	0x47	# DW_AT_decl_line
 	.long	0x48	# DW_AT_type
+	.byte	0x2	# DW_AT_location
+	.byte	0x91	# DW_OP_fbreg
+	.sleb128 0
+	.uleb128 0xd	# (DIE (0x216) DW_TAG_variable)
+	.ascii "z\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (pieces.c)
+	.byte	0x49	# DW_AT_decl_line
+	.long	0x48	# DW_AT_type
+	.byte	0x17	# DW_AT_const_value
+	.uleb128 0x9	# (DIE (0x220) DW_TAG_variable)
+	.ascii "a\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (pieces.c)
+	.byte	0x4a	# DW_AT_decl_line
+	.long	0x78	# DW_AT_type
 	.long	.LLST12	# DW_AT_location
-	.byte	0	# end of children of DIE 0x1bf
+	.byte	0	# end of children of DIE 0x1ee
+	.uleb128 0xe	# (DIE (0x22e) DW_TAG_subprogram)
+	.byte	0x1	# DW_AT_external
+	.long	.LASF0	# DW_AT_name: "main"
+	.byte	0x1	# DW_AT_decl_file (pieces.c)
+	.byte	0x53	# DW_AT_decl_line
+	.byte	0x1	# DW_AT_prototyped
+	.long	0x48	# DW_AT_type
+	.long	.LFB7	# DW_AT_low_pc
+	.long	.LFE7	# DW_AT_high_pc
+	.long	.LLST13	# DW_AT_frame_base
+	.uleb128 0x9	# (DIE (0x247) DW_TAG_variable)
+	.ascii "k\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (pieces.c)
+	.byte	0x55	# DW_AT_decl_line
+	.long	0x48	# DW_AT_type
+	.long	.LLST14	# DW_AT_location
+	.byte	0	# end of children of DIE 0x22e
 	.byte	0	# end of children of DIE 0xb
 	.section	.debug_abbrev
 	.uleb128 0x1	# (abbrev code)
@@ -1577,6 +1800,21 @@ _start:
 	.byte	0
 	.byte	0
 	.uleb128 0xd	# (abbrev code)
+	.uleb128 0x34	# (TAG: DW_TAG_variable)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x1c	# (DW_AT_const_value)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.byte	0
+	.byte	0
+	.uleb128 0xe	# (abbrev code)
 	.uleb128 0x2e	# (TAG: DW_TAG_subprogram)
 	.byte	0x1	# DW_children_yes
 	.uleb128 0x3f	# (DW_AT_external)
@@ -1601,34 +1839,38 @@ _start:
 	.byte	0
 	.byte	0
 	.section	.debug_pubnames,"",@progbits
-	.long	0x42	# Length of Public Names Info
+	.long	0x49	# Length of Public Names Info
 	.value	0x2	# DWARF Version
 	.long	.Ldebug_info0	# Offset of Compilation Unit Info
-	.long	0x1e7	# Compilation Unit Length
-	.long	0x78	# DIE offset
+	.long	0x256	# Compilation Unit Length
+	.long	0xa7	# DIE offset
 	.ascii "bar\0"	# external name
-	.long	0x9e	# DIE offset
+	.long	0xcd	# DIE offset
 	.ascii "f1\0"	# external name
-	.long	0xd4	# DIE offset
+	.long	0x103	# DIE offset
 	.ascii "f2\0"	# external name
-	.long	0x11d	# DIE offset
+	.long	0x14c	# DIE offset
 	.ascii "f3\0"	# external name
-	.long	0x153	# DIE offset
+	.long	0x182	# DIE offset
 	.ascii "f4\0"	# external name
-	.long	0x189	# DIE offset
+	.long	0x1b8	# DIE offset
 	.ascii "f5\0"	# external name
-	.long	0x1bf	# DIE offset
+	.long	0x1ee	# DIE offset
+	.ascii "f6\0"	# external name
+	.long	0x22e	# DIE offset
 	.ascii "main\0"	# external name
 	.long	0
 	.section	.debug_pubtypes,"",@progbits
-	.long	0x1a	# Length of Public Type Names Info
+	.long	0x20	# Length of Public Type Names Info
 	.value	0x2	# DWARF Version
 	.long	.Ldebug_info0	# Offset of Compilation Unit Info
-	.long	0x1e7	# Compilation Unit Length
+	.long	0x256	# Compilation Unit Length
 	.long	0x25	# DIE offset
 	.ascii "A\0"	# external name
 	.long	0x4f	# DIE offset
 	.ascii "B\0"	# external name
+	.long	0x78	# DIE offset
+	.ascii "C\0"	# external name
 	.long	0
 	.section	.debug_aranges,"",@progbits
 	.long	0x1c	# Length of Address Ranges Info
@@ -1645,10 +1887,10 @@ _start:
 	.section	.debug_str,"MS",@progbits,1
 .LASF2:
 	.string	"pieces.c"
+.LASF3:
+	.string	"/home/tromey/gnu/archer/archer/gdb/testsuite/gdb.dwarf2"
 .LASF1:
 	.string	"GNU C 4.6.0 20100506 (experimental) [trunk revision 159117]"
-.LASF3:
-	.string	"/home/tromey/gnu/PRS/rh589467"
 .LASF0:
 	.string	"main"
 	.ident	"GCC: (GNU) 4.6.0 20100506 (experimental) [trunk revision 159117]"
diff --git a/gdb/testsuite/gdb.dwarf2/pieces.c b/gdb/testsuite/gdb.dwarf2/pieces.c
index 07fae64..2736f9f 100644
--- a/gdb/testsuite/gdb.dwarf2/pieces.c
+++ b/gdb/testsuite/gdb.dwarf2/pieces.c
@@ -4,6 +4,7 @@
 
 struct A { int i; int j; };
 struct B { int : 4; int i : 12; int j : 12; int : 4; };
+struct C { int i; int j; int q; };
 
 __attribute__((noinline)) void
 bar (int x)
@@ -66,6 +67,18 @@ f5 (int k)
   return a.i + a.j;
 }
 
+__attribute__((noinline)) int
+f6 (int k)
+{
+  int z = 23;
+  struct C a = { k, k, z};
+  asm ("" : "+r" (a.i));
+  a.j++;
+  bar (a.i);		/* { dg-final { gdb-test 20 "a.i" "4" } } */
+  bar (a.j);		/* { dg-final { gdb-test 20 "a.j" "14" } } */
+  return a.i + a.j;
+}
+
 int
 main (void)
 {
@@ -76,5 +89,6 @@ main (void)
   f3 (k);
   f4 (k);
   f5 (k);
+  f6 (k);
   return 0;
 }
diff --git a/gdb/testsuite/gdb.dwarf2/pieces.exp b/gdb/testsuite/gdb.dwarf2/pieces.exp
index e6c1431..3ec67d4 100644
--- a/gdb/testsuite/gdb.dwarf2/pieces.exp
+++ b/gdb/testsuite/gdb.dwarf2/pieces.exp
@@ -68,5 +68,26 @@ proc pieces_test_f2 {} {
     gdb_test "print a\[1\]" " = 14" "print a\[1\] in pieces:f2"
 }
 
+# Function f6 tests for an empty DW_OP_piece.
+proc pieces_test_f6 {} {
+    gdb_test "break pieces.c:79" "Breakpoint 4.*" \
+       "set third breakpoint for pieces"
+    gdb_continue_to_breakpoint "third continue to breakpoint for pieces"
+    gdb_test "print a" \
+	"warning: some bits in computed object were.* = {i = 7, j = 8, q = 0}" \
+	"print a with optimized out piece"
+    # Note: no warning for this case.
+    gdb_test_multiple "print a.i" \
+	"print a.i with optimized out piece" {
+	    -re "warning: some bits in computed object" {
+		fail "print a.i with optimized out piece"
+	    }
+	    -re " = 7" {
+		pass "print a.i with optimized out piece"
+	    }
+	}
+}
+
 pieces_test_f1
 pieces_test_f2
+pieces_test_f6

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: RFC: partially fix empty DW_OP_piece
  2010-05-14  6:39 RFC: partially fix empty DW_OP_piece Tom Tromey
@ 2010-05-14 22:51 ` Jan Kratochvil
  2010-05-21 19:48   ` Tom Tromey
  2010-06-01 17:34   ` Tom Tromey
  2010-05-20 23:04 ` Joel Brobecker
  1 sibling, 2 replies; 12+ messages in thread
From: Jan Kratochvil @ 2010-05-14 22:51 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Fri, 14 May 2010 04:03:37 +0200, Tom Tromey wrote:
> The other way is to simply remove val_print entirely and make all of
> printing work using values.  I think this is the route I would prefer.

That could hopefully solve the problem of missing type-associated object
address for DW_OP_push_object_address for the VLA (variable length arrays)
patch.


> @@ -366,6 +366,14 @@ read_pieced_value (struct value *v)
> +	case DWARF_VALUE_OPTIMIZED_OUT:
> +	  /* We just leave the bits empty for now.  This is not ideal
> +	     but gdb currently does not have a nice way to represent
> +	     optimized-out pieces.  */
> +	  warning (_("some bits in computed object were optimized out; "
> +		     "replacing with zeroes"));
> +	  break;

If it would go in I would prefer to at least print the bit/byte range.



Thanks,
Jan

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: RFC: partially fix empty DW_OP_piece
  2010-05-14  6:39 RFC: partially fix empty DW_OP_piece Tom Tromey
  2010-05-14 22:51 ` Jan Kratochvil
@ 2010-05-20 23:04 ` Joel Brobecker
  1 sibling, 0 replies; 12+ messages in thread
From: Joel Brobecker @ 2010-05-20 23:04 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

> This patch "fixes" the problem in a simple way.  Missing pieces are
> filled with zeros, and read_pieced_value emits a warning, so that users
> know not to fully trust the result.
> 
> This is not an excellent fix.  I think it is an improvement, but I can
> understand if people would rather not see it go in.

I also think that this is an improvement, and that it should go in.

> I thought of two ways to implement the val_print part.  One way would be
> to make a temporary 'struct type' instance that encodes the validity in
> the type somehow.  The other way is to simply remove val_print entirely
> and make all of printing work using values.  I think this is the route I
> would prefer.

FWIW:
I think that would be my preference indeed. Generally speaking, it looks
like our struct type is headed for some major upgrades, once we start
thinking about making some elements of a type dynamic (Eg: range type
bounds, array bounds). But using a temporary type to track the validity
of a field for a given entity does not seem to be the right idiom...

-- 
Joel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: RFC: partially fix empty DW_OP_piece
  2010-05-14 22:51 ` Jan Kratochvil
@ 2010-05-21 19:48   ` Tom Tromey
  2010-06-01 17:34   ` Tom Tromey
  1 sibling, 0 replies; 12+ messages in thread
From: Tom Tromey @ 2010-05-21 19:48 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

>>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:

Jan> If it would go in I would prefer to at least print the bit/byte range.

Good idea, I made this change.

Here is the updated patch, which I am going to commit shortly.

Tom


2010-05-13  Tom Tromey  <tromey@redhat.com>

	* dwarf2loc.c (read_pieced_value): Exit loop when result is full.
	<DWARF_VALUE_OPTIMIZED_OUT>: New case.
	* dwarf2expr.h (enum dwarf_value_location)
	<DWARF_VALUE_OPTIMIZED_OUT>: New constant.
	* dwarf2expr.c (dwarf_expr_stack_empty_p): New function.
	(add_piece): Handle empty piece.
	(execute_stack_op) <DW_OP_piece>: Handle
	DWARF_VALUE_OPTIMIZED_OUT.

2010-05-13  Tom Tromey  <tromey@redhat.com>

	* gdb.dwarf2/pieces.exp (pieces_test_f6): New proc.
	Call it.
	* gdb.dwarf2/pieces.c (struct C): New.
	(f6): New function.
	* gdb.dwarf2/pieces.S: Replace.

diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c
index 9e5ce61..482c293 100644
--- a/gdb/dwarf2expr.c
+++ b/gdb/dwarf2expr.c
@@ -141,6 +141,14 @@ dwarf_expr_fetch_in_stack_memory (struct dwarf_expr_context *ctx, int n)
 
 }
 
+/* Return true if the expression stack is empty.  */
+
+static int
+dwarf_expr_stack_empty_p (struct dwarf_expr_context *ctx)
+{
+  return ctx->stack_len == 0;
+}
+
 /* Add a new piece to CTX's piece list.  */
 static void
 add_piece (struct dwarf_expr_context *ctx, ULONGEST size)
@@ -165,6 +173,15 @@ add_piece (struct dwarf_expr_context *ctx, ULONGEST size)
       p->v.literal.data = ctx->data;
       p->v.literal.length = ctx->len;
     }
+  else if (dwarf_expr_stack_empty_p (ctx))
+    {
+      p->location = DWARF_VALUE_OPTIMIZED_OUT;
+      /* Also reset the context's location, for our callers.  This is
+	 a somewhat strange approach, but this lets us avoid setting
+	 the location to DWARF_VALUE_MEMORY in all the individual
+	 cases in the evaluator.  */
+      ctx->location = DWARF_VALUE_OPTIMIZED_OUT;
+    }
   else
     {
       p->v.expr.value = dwarf_expr_fetch (ctx, 0);
@@ -853,7 +870,8 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 
             /* Pop off the address/regnum, and reset the location
 	       type.  */
-	    if (ctx->location != DWARF_VALUE_LITERAL)
+	    if (ctx->location != DWARF_VALUE_LITERAL
+		&& ctx->location != DWARF_VALUE_OPTIMIZED_OUT)
 	      dwarf_expr_pop (ctx);
             ctx->location = DWARF_VALUE_MEMORY;
           }
diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h
index 437ca39..f24f193 100644
--- a/gdb/dwarf2expr.h
+++ b/gdb/dwarf2expr.h
@@ -38,7 +38,10 @@ enum dwarf_value_location
   DWARF_VALUE_STACK,
 
   /* The piece is a literal.  */
-  DWARF_VALUE_LITERAL
+  DWARF_VALUE_LITERAL,
+
+  /* The piece was optimized out.  */
+  DWARF_VALUE_OPTIMIZED_OUT
 };
 
 /* The dwarf expression stack.  */
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 66fee27..2900f22 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -380,6 +380,16 @@ read_pieced_value (struct value *v)
 	  }
 	  break;
 
+	case DWARF_VALUE_OPTIMIZED_OUT:
+	  /* We just leave the bits empty for now.  This is not ideal
+	     but gdb currently does not have a nice way to represent
+	     optimized-out pieces.  */
+	  warning (_("bytes %ld-%ld in computed object were optimized out; "
+		     "replacing with zeroes"),
+		   offset,
+		   offset + (long) this_size);
+	  break;
+
 	default:
 	  internal_error (__FILE__, __LINE__, _("invalid location type"));
 	}
@@ -610,6 +620,9 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
 	  }
 	  break;
 
+	  /* DWARF_VALUE_OPTIMIZED_OUT can't occur in this context --
+	     it can only be encountered when making a piece.  */
+	case DWARF_VALUE_OPTIMIZED_OUT:
 	default:
 	  internal_error (__FILE__, __LINE__, _("invalid location type"));
 	}
diff --git a/gdb/testsuite/gdb.dwarf2/pieces.S b/gdb/testsuite/gdb.dwarf2/pieces.S
index d6791c1..0ecdbb0 100644
--- a/gdb/testsuite/gdb.dwarf2/pieces.S
+++ b/gdb/testsuite/gdb.dwarf2/pieces.S
@@ -37,19 +37,19 @@
 bar:
 .LFB0:
 	.file 1 "pieces.c"
-	# pieces.c:28
-	.loc 1 28 0
+	# pieces.c:29
+	.loc 1 29 0
 .LVL0:
 	# basic block 2
 	pushl	%ebp
 .LCFI0:
 	movl	%esp, %ebp
 .LCFI1:
-	# pieces.c:29
-	.loc 1 29 0
-	movl	8(%ebp), %eax
 	# pieces.c:30
 	.loc 1 30 0
+	movl	8(%ebp), %eax
+	# pieces.c:31
+	.loc 1 31 0
 	popl	%ebp
 .LCFI2:
 	ret
@@ -60,8 +60,8 @@ bar:
 	.type	f1, @function
 f1:
 .LFB1:
-	# pieces.c:34
-	.loc 1 34 0
+	# pieces.c:35
+	.loc 1 35 0
 .LVL1:
 	# basic block 2
 	pushl	%ebp
@@ -73,36 +73,36 @@ f1:
 .LCFI5:
 	movl	%esi, -4(%ebp)
 .LCFI6:
-	# pieces.c:37
-	.loc 1 37 0
+	# pieces.c:38
+	.loc 1 38 0
 	movl	8(%ebp), %esi
-	# pieces.c:34
-	.loc 1 34 0
+	# pieces.c:35
+	.loc 1 35 0
 	movl	%ebx, -8(%ebp)
 .LCFI7:
-	# pieces.c:36
-	.loc 1 36 0
+	# pieces.c:37
+	.loc 1 37 0
 	movl	$4, %ebx
 .LVL3:
+	# pieces.c:39
+	.loc 1 39 0
+	movl	%ebx, (%esp)
 	# pieces.c:38
 	.loc 1 38 0
-	movl	%ebx, (%esp)
-	# pieces.c:37
-	.loc 1 37 0
 	addl	$7, %esi
 .LVL4:
-	# pieces.c:38
-	.loc 1 38 0
-	call	bar
 	# pieces.c:39
 	.loc 1 39 0
-	movl	%esi, (%esp)
 	call	bar
 	# pieces.c:40
 	.loc 1 40 0
-	leal	(%ebx,%esi), %eax
+	movl	%esi, (%esp)
+	call	bar
 	# pieces.c:41
 	.loc 1 41 0
+	leal	(%ebx,%esi), %eax
+	# pieces.c:42
+	.loc 1 42 0
 	movl	-8(%ebp), %ebx
 .LVL5:
 	movl	-4(%ebp), %esi
@@ -119,8 +119,8 @@ f1:
 	.type	f2, @function
 f2:
 .LFB2:
-	# pieces.c:45
-	.loc 1 45 0
+	# pieces.c:46
+	.loc 1 46 0
 .LVL7:
 	# basic block 2
 	pushl	%ebp
@@ -132,36 +132,36 @@ f2:
 .LCFI12:
 	movl	%esi, -4(%ebp)
 .LCFI13:
-	# pieces.c:48
-	.loc 1 48 0
+	# pieces.c:49
+	.loc 1 49 0
 	movl	8(%ebp), %esi
-	# pieces.c:45
-	.loc 1 45 0
+	# pieces.c:46
+	.loc 1 46 0
 	movl	%ebx, -8(%ebp)
 .LCFI14:
-	# pieces.c:47
-	.loc 1 47 0
+	# pieces.c:48
+	.loc 1 48 0
 	movl	$4, %ebx
 .LVL9:
+	# pieces.c:50
+	.loc 1 50 0
+	movl	%ebx, (%esp)
 	# pieces.c:49
 	.loc 1 49 0
-	movl	%ebx, (%esp)
-	# pieces.c:48
-	.loc 1 48 0
 	addl	$7, %esi
 .LVL10:
-	# pieces.c:49
-	.loc 1 49 0
-	call	bar
 	# pieces.c:50
 	.loc 1 50 0
-	movl	%esi, (%esp)
 	call	bar
 	# pieces.c:51
 	.loc 1 51 0
-	leal	(%ebx,%esi), %eax
+	movl	%esi, (%esp)
+	call	bar
 	# pieces.c:52
 	.loc 1 52 0
+	leal	(%ebx,%esi), %eax
+	# pieces.c:53
+	.loc 1 53 0
 	movl	-8(%ebp), %ebx
 .LVL11:
 	movl	-4(%ebp), %esi
@@ -178,59 +178,59 @@ f2:
 	.type	f3, @function
 f3:
 .LFB3:
-	# pieces.c:56
-	.loc 1 56 0
+	# pieces.c:57
+	.loc 1 57 0
 .LVL13:
 	# basic block 2
 	pushl	%ebp
 .LCFI17:
-	# pieces.c:58
-	.loc 1 58 0
+	# pieces.c:59
+	.loc 1 59 0
 	movl	$4, %edx
-	# pieces.c:56
-	.loc 1 56 0
+	# pieces.c:57
+	.loc 1 57 0
 	movl	%esp, %ebp
 .LCFI18:
 .LVL14:
 	subl	$12, %esp
 .LCFI19:
-	# pieces.c:58
-	.loc 1 58 0
+	# pieces.c:59
+	.loc 1 59 0
 .LVL15:
-	# pieces.c:56
-	.loc 1 56 0
+	# pieces.c:57
+	.loc 1 57 0
 	movl	%esi, -4(%ebp)
 .LCFI20:
-	# pieces.c:60
-	.loc 1 60 0
+	# pieces.c:61
+	.loc 1 61 0
 	movswl	%dx, %esi
-	# pieces.c:56
-	.loc 1 56 0
+	# pieces.c:57
+	.loc 1 57 0
 	movl	%ebx, -8(%ebp)
 .LCFI21:
-	# pieces.c:60
-	.loc 1 60 0
+	# pieces.c:61
+	.loc 1 61 0
 	movl	%esi, (%esp)
 	call	bar
 .LVL16:
-	# pieces.c:57
-	.loc 1 57 0
+	# pieces.c:58
+	.loc 1 58 0
 	movl	8(%ebp), %edx
 	sall	$4, %edx
-	# pieces.c:59
-	.loc 1 59 0
+	# pieces.c:60
+	.loc 1 60 0
 	addl	$112, %edx
 	sarw	$4, %dx
-	# pieces.c:61
-	.loc 1 61 0
+	# pieces.c:62
+	.loc 1 62 0
 	movswl	%dx, %ebx
 	movl	%ebx, (%esp)
 	call	bar
-	# pieces.c:62
-	.loc 1 62 0
-	leal	(%esi,%ebx), %eax
 	# pieces.c:63
 	.loc 1 63 0
+	leal	(%esi,%ebx), %eax
+	# pieces.c:64
+	.loc 1 64 0
 	movl	-8(%ebp), %ebx
 	movl	-4(%ebp), %esi
 .LVL17:
@@ -246,8 +246,8 @@ f3:
 	.type	f4, @function
 f4:
 .LFB4:
-	# pieces.c:67
-	.loc 1 67 0
+	# pieces.c:68
+	.loc 1 68 0
 .LVL18:
 	# basic block 2
 	pushl	%ebp
@@ -262,28 +262,28 @@ f4:
 .LVL19:
 	movl	%ebx, -8(%ebp)
 .LCFI28:
-	# pieces.c:69
-	.loc 1 69 0
-	movl	%esi, %ebx
 	# pieces.c:70
 	.loc 1 70 0
-	addl	$1, %esi
-	# pieces.c:69
-	.loc 1 69 0
-.LVL20:
+	movl	%esi, %ebx
 	# pieces.c:71
 	.loc 1 71 0
-	movl	%ebx, (%esp)
-	call	bar
+	addl	$1, %esi
+	# pieces.c:70
+	.loc 1 70 0
+.LVL20:
 	# pieces.c:72
 	.loc 1 72 0
-	movl	%esi, (%esp)
+	movl	%ebx, (%esp)
 	call	bar
 	# pieces.c:73
 	.loc 1 73 0
-	leal	(%ebx,%esi), %eax
+	movl	%esi, (%esp)
+	call	bar
 	# pieces.c:74
 	.loc 1 74 0
+	leal	(%ebx,%esi), %eax
+	# pieces.c:75
+	.loc 1 75 0
 	movl	-8(%ebp), %ebx
 .LVL21:
 	movl	-4(%ebp), %esi
@@ -300,8 +300,8 @@ f4:
 	.type	f5, @function
 f5:
 .LFB5:
-	# pieces.c:78
-	.loc 1 78 0
+	# pieces.c:79
+	.loc 1 79 0
 .LVL23:
 	# basic block 2
 	pushl	%ebp
@@ -316,28 +316,28 @@ f5:
 .LVL24:
 	movl	%ebx, -8(%ebp)
 .LCFI35:
-	# pieces.c:80
-	.loc 1 80 0
-	movl	%esi, %ebx
 	# pieces.c:81
 	.loc 1 81 0
-	addl	$1, %esi
-	# pieces.c:80
-	.loc 1 80 0
-.LVL25:
+	movl	%esi, %ebx
 	# pieces.c:82
 	.loc 1 82 0
-	movl	%ebx, (%esp)
-	call	bar
+	addl	$1, %esi
+	# pieces.c:81
+	.loc 1 81 0
+.LVL25:
 	# pieces.c:83
 	.loc 1 83 0
-	movl	%esi, (%esp)
+	movl	%ebx, (%esp)
 	call	bar
 	# pieces.c:84
 	.loc 1 84 0
-	leal	(%ebx,%esi), %eax
+	movl	%esi, (%esp)
+	call	bar
 	# pieces.c:85
 	.loc 1 85 0
+	leal	(%ebx,%esi), %eax
+	# pieces.c:86
+	.loc 1 86 0
 	movl	-8(%ebp), %ebx
 .LVL26:
 	movl	-4(%ebp), %esi
@@ -350,60 +350,118 @@ f5:
 .LFE5:
 	.size	f5, .-f5
 	.p2align 4,,15
-.globl main
-	.type	main, @function
-main:
+.globl f6
+	.type	f6, @function
+f6:
 .LFB6:
-	# pieces.c:89
-	.loc 1 89 0
+	# pieces.c:90
+	.loc 1 90 0
+.LVL28:
 	# basic block 2
 	pushl	%ebp
 .LCFI38:
 	movl	%esp, %ebp
 .LCFI39:
-	pushl	%ebx
+	subl	$12, %esp
 .LCFI40:
-	# pieces.c:91
-	.loc 1 91 0
-	movl	$7, %ebx
-	# pieces.c:89
-	.loc 1 89 0
-	subl	$4, %esp
+	movl	%esi, -4(%ebp)
 .LCFI41:
-	# pieces.c:91
-	.loc 1 91 0
-.LVL28:
-	# pieces.c:92
-	.loc 1 92 0
-	movl	%ebx, (%esp)
-	call	f1
+	movl	8(%ebp), %esi
+.LVL29:
+	movl	%ebx, -8(%ebp)
+.LCFI42:
 	# pieces.c:93
 	.loc 1 93 0
-	movl	%ebx, (%esp)
-	call	f2
+	movl	%esi, %ebx
 	# pieces.c:94
 	.loc 1 94 0
-	movl	%ebx, (%esp)
-	call	f3
+	addl	$1, %esi
+	# pieces.c:93
+	.loc 1 93 0
+.LVL30:
 	# pieces.c:95
 	.loc 1 95 0
 	movl	%ebx, (%esp)
-	call	f4
+	call	bar
 	# pieces.c:96
 	.loc 1 96 0
-	movl	%ebx, (%esp)
-	call	f5
+	movl	%esi, (%esp)
+	call	bar
+	# pieces.c:97
+	.loc 1 97 0
+	leal	(%ebx,%esi), %eax
 	# pieces.c:98
 	.loc 1 98 0
+	movl	-8(%ebp), %ebx
+.LVL31:
+	movl	-4(%ebp), %esi
+.LVL32:
+	movl	%ebp, %esp
+.LCFI43:
+	popl	%ebp
+.LCFI44:
+	ret
+.LFE6:
+	.size	f6, .-f6
+	.p2align 4,,15
+.globl main
+	.type	main, @function
+main:
+.LFB7:
+	# pieces.c:102
+	.loc 1 102 0
+	# basic block 2
+	pushl	%ebp
+.LCFI45:
+	movl	%esp, %ebp
+.LCFI46:
+	pushl	%ebx
+.LCFI47:
+	# pieces.c:104
+	.loc 1 104 0
+	movl	$7, %ebx
+	# pieces.c:102
+	.loc 1 102 0
+	subl	$4, %esp
+.LCFI48:
+	# pieces.c:104
+	.loc 1 104 0
+.LVL33:
+	# pieces.c:105
+	.loc 1 105 0
+	movl	%ebx, (%esp)
+	call	f1
+	# pieces.c:106
+	.loc 1 106 0
+	movl	%ebx, (%esp)
+	call	f2
+	# pieces.c:107
+	.loc 1 107 0
+	movl	%ebx, (%esp)
+	call	f3
+	# pieces.c:108
+	.loc 1 108 0
+	movl	%ebx, (%esp)
+	call	f4
+	# pieces.c:109
+	.loc 1 109 0
+	movl	%ebx, (%esp)
+	call	f5
+	# pieces.c:110
+	.loc 1 110 0
+	movl	%ebx, (%esp)
+	call	f6
+	# pieces.c:112
+	.loc 1 112 0
 	addl	$4, %esp
 	xorl	%eax, %eax
 	popl	%ebx
-.LCFI42:
-.LVL29:
+.LCFI49:
+.LVL34:
 	popl	%ebp
-.LCFI43:
+.LCFI50:
 	ret
-.LFE6:
+.LFE7:
 	.size	main, .-main
 #APP
 	.section	.debug_frame,"",@progbits
@@ -649,20 +707,57 @@ main:
 	.byte	0xd	# DW_CFA_def_cfa_register
 	.uleb128 0x5
 	.byte	0x4	# DW_CFA_advance_loc4
-	.long	.LCFI40-.LCFI39
+	.long	.LCFI41-.LCFI39
+	.byte	0x86	# DW_CFA_offset, column 0x6
+	.uleb128 0x3
+	.byte	0x4	# DW_CFA_advance_loc4
+	.long	.LCFI42-.LCFI41
+	.byte	0x83	# DW_CFA_offset, column 0x3
+	.uleb128 0x4
+	.byte	0x4	# DW_CFA_advance_loc4
+	.long	.LCFI43-.LCFI42
+	.byte	0xd	# DW_CFA_def_cfa_register
+	.uleb128 0x4
+	.byte	0xc6	# DW_CFA_restore, column 0x6
+	.byte	0xc3	# DW_CFA_restore, column 0x3
+	.byte	0x4	# DW_CFA_advance_loc4
+	.long	.LCFI44-.LCFI43
+	.byte	0xc5	# DW_CFA_restore, column 0x5
+	.byte	0xe	# DW_CFA_def_cfa_offset
+	.uleb128 0x4
+	.align 4
+.LEFDE12:
+.LSFDE14:
+	.long	.LEFDE14-.LASFDE14	# FDE Length
+.LASFDE14:
+	.long	.Lframe0	# FDE CIE offset
+	.long	.LFB7	# FDE initial location
+	.long	.LFE7-.LFB7	# FDE address range
+	.byte	0x4	# DW_CFA_advance_loc4
+	.long	.LCFI45-.LFB7
+	.byte	0xe	# DW_CFA_def_cfa_offset
+	.uleb128 0x8
+	.byte	0x85	# DW_CFA_offset, column 0x5
+	.uleb128 0x2
+	.byte	0x4	# DW_CFA_advance_loc4
+	.long	.LCFI46-.LCFI45
+	.byte	0xd	# DW_CFA_def_cfa_register
+	.uleb128 0x5
+	.byte	0x4	# DW_CFA_advance_loc4
+	.long	.LCFI47-.LCFI46
 	.byte	0x83	# DW_CFA_offset, column 0x3
 	.uleb128 0x3
 	.byte	0x4	# DW_CFA_advance_loc4
-	.long	.LCFI42-.LCFI40
+	.long	.LCFI49-.LCFI47
 	.byte	0xc3	# DW_CFA_restore, column 0x3
 	.byte	0x4	# DW_CFA_advance_loc4
-	.long	.LCFI43-.LCFI42
+	.long	.LCFI50-.LCFI49
 	.byte	0xc5	# DW_CFA_restore, column 0x5
 	.byte	0xc	# DW_CFA_def_cfa
 	.uleb128 0x4
 	.uleb128 0x4
 	.align 4
-.LEFDE12:
+.LEFDE14:
 #NO_APP
 	.text
 .Letext0:
@@ -1130,6 +1225,11 @@ main:
 	.byte	0x75	# DW_OP_breg5
 	.sleb128 8
 	.long	.LCFI43-.Ltext0	# Location list begin address (*.LLST11)
+	.long	.LCFI44-.Ltext0	# Location list end address (*.LLST11)
+	.value	0x2	# Location expression size
+	.byte	0x74	# DW_OP_breg4
+	.sleb128 8
+	.long	.LCFI44-.Ltext0	# Location list begin address (*.LLST11)
 	.long	.LFE6-.Ltext0	# Location list end address (*.LLST11)
 	.value	0x2	# Location expression size
 	.byte	0x74	# DW_OP_breg4
@@ -1137,14 +1237,74 @@ main:
 	.long	0	# Location list terminator begin (*.LLST11)
 	.long	0	# Location list terminator end (*.LLST11)
 .LLST12:
-	.long	.LVL28-.Ltext0	# Location list begin address (*.LLST12)
-	.long	.LVL29-.Ltext0	# Location list end address (*.LLST12)
-	.value	0x1	# Location expression size
+	.long	.LVL29-.Ltext0	# Location list begin address (*.LLST12)
+	.long	.LVL30-.Ltext0	# Location list end address (*.LLST12)
+	.value	0xa	# Location expression size
+	.byte	0x91	# DW_OP_fbreg
+	.sleb128 0
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x4
+	.byte	0x91	# DW_OP_fbreg
+	.sleb128 0
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x4
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x4
+	.long	.LVL30-.Ltext0	# Location list begin address (*.LLST12)
+	.long	.LVL31-.Ltext0	# Location list end address (*.LLST12)
+	.value	0x8	# Location expression size
 	.byte	0x53	# DW_OP_reg3
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x4
+	.byte	0x56	# DW_OP_reg6
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x4
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x4
+	.long	.LVL31-.Ltext0	# Location list begin address (*.LLST12)
+	.long	.LVL32-.Ltext0	# Location list end address (*.LLST12)
+	.value	0x7	# Location expression size
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x4
+	.byte	0x56	# DW_OP_reg6
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x4
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x4
 	.long	0	# Location list terminator begin (*.LLST12)
 	.long	0	# Location list terminator end (*.LLST12)
+.LLST13:
+	.long	.LFB7-.Ltext0	# Location list begin address (*.LLST13)
+	.long	.LCFI45-.Ltext0	# Location list end address (*.LLST13)
+	.value	0x2	# Location expression size
+	.byte	0x74	# DW_OP_breg4
+	.sleb128 4
+	.long	.LCFI45-.Ltext0	# Location list begin address (*.LLST13)
+	.long	.LCFI46-.Ltext0	# Location list end address (*.LLST13)
+	.value	0x2	# Location expression size
+	.byte	0x74	# DW_OP_breg4
+	.sleb128 8
+	.long	.LCFI46-.Ltext0	# Location list begin address (*.LLST13)
+	.long	.LCFI50-.Ltext0	# Location list end address (*.LLST13)
+	.value	0x2	# Location expression size
+	.byte	0x75	# DW_OP_breg5
+	.sleb128 8
+	.long	.LCFI50-.Ltext0	# Location list begin address (*.LLST13)
+	.long	.LFE7-.Ltext0	# Location list end address (*.LLST13)
+	.value	0x2	# Location expression size
+	.byte	0x74	# DW_OP_breg4
+	.sleb128 4
+	.long	0	# Location list terminator begin (*.LLST13)
+	.long	0	# Location list terminator end (*.LLST13)
+.LLST14:
+	.long	.LVL33-.Ltext0	# Location list begin address (*.LLST14)
+	.long	.LVL34-.Ltext0	# Location list end address (*.LLST14)
+	.value	0x1	# Location expression size
+	.byte	0x53	# DW_OP_reg3
+	.long	0	# Location list terminator begin (*.LLST14)
+	.long	0	# Location list terminator end (*.LLST14)
 	.section	.debug_info
-	.long	0x1e3	# Length of Compilation Unit Info
+	.long	0x252	# Length of Compilation Unit Info
 	.value	0x2	# DWARF version number
 	.long	.Ldebug_abbrev0	# Offset Into Abbrev. Section
 	.byte	0x4	# Pointer Size (in bytes)
@@ -1212,182 +1372,245 @@ main:
 	.byte	0x23	# DW_OP_plus_uconst
 	.uleb128 0
 	.byte	0	# end of children of DIE 0x4f
-	.uleb128 0x6	# (DIE (0x78) DW_TAG_subprogram)
+	.uleb128 0x2	# (DIE (0x78) DW_TAG_structure_type)
+	.ascii "C\0"	# DW_AT_name
+	.byte	0xc	# DW_AT_byte_size
+	.byte	0x1	# DW_AT_decl_file (pieces.c)
+	.byte	0x19	# DW_AT_decl_line
+	.long	0xa7	# DW_AT_sibling
+	.uleb128 0x3	# (DIE (0x82) DW_TAG_member)
+	.ascii "i\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (pieces.c)
+	.byte	0x19	# DW_AT_decl_line
+	.long	0x48	# DW_AT_type
+	.byte	0x2	# DW_AT_data_member_location
+	.byte	0x23	# DW_OP_plus_uconst
+	.uleb128 0
+	.uleb128 0x3	# (DIE (0x8e) DW_TAG_member)
+	.ascii "j\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (pieces.c)
+	.byte	0x19	# DW_AT_decl_line
+	.long	0x48	# DW_AT_type
+	.byte	0x2	# DW_AT_data_member_location
+	.byte	0x23	# DW_OP_plus_uconst
+	.uleb128 0x4
+	.uleb128 0x3	# (DIE (0x9a) DW_TAG_member)
+	.ascii "q\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (pieces.c)
+	.byte	0x19	# DW_AT_decl_line
+	.long	0x48	# DW_AT_type
+	.byte	0x2	# DW_AT_data_member_location
+	.byte	0x23	# DW_OP_plus_uconst
+	.uleb128 0x8
+	.byte	0	# end of children of DIE 0x78
+	.uleb128 0x6	# (DIE (0xa7) DW_TAG_subprogram)
 	.byte	0x1	# DW_AT_external
 	.ascii "bar\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x1b	# DW_AT_decl_line
+	.byte	0x1c	# DW_AT_decl_line
 	.byte	0x1	# DW_AT_prototyped
 	.long	.LFB0	# DW_AT_low_pc
 	.long	.LFE0	# DW_AT_high_pc
 	.long	.LLST0	# DW_AT_frame_base
-	.long	0x9e	# DW_AT_sibling
-	.uleb128 0x7	# (DIE (0x91) DW_TAG_formal_parameter)
+	.long	0xcd	# DW_AT_sibling
+	.uleb128 0x7	# (DIE (0xc0) DW_TAG_formal_parameter)
 	.ascii "x\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x1b	# DW_AT_decl_line
+	.byte	0x1c	# DW_AT_decl_line
 	.long	0x48	# DW_AT_type
 	.byte	0x2	# DW_AT_location
 	.byte	0x91	# DW_OP_fbreg
 	.sleb128 0
-	.byte	0	# end of children of DIE 0x78
-	.uleb128 0x8	# (DIE (0x9e) DW_TAG_subprogram)
+	.byte	0	# end of children of DIE 0xa7
+	.uleb128 0x8	# (DIE (0xcd) DW_TAG_subprogram)
 	.byte	0x1	# DW_AT_external
 	.ascii "f1\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x21	# DW_AT_decl_line
+	.byte	0x22	# DW_AT_decl_line
 	.byte	0x1	# DW_AT_prototyped
 	.long	0x48	# DW_AT_type
 	.long	.LFB1	# DW_AT_low_pc
 	.long	.LFE1	# DW_AT_high_pc
 	.long	.LLST1	# DW_AT_frame_base
-	.long	0xd4	# DW_AT_sibling
-	.uleb128 0x7	# (DIE (0xba) DW_TAG_formal_parameter)
+	.long	0x103	# DW_AT_sibling
+	.uleb128 0x7	# (DIE (0xe9) DW_TAG_formal_parameter)
 	.ascii "k\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x21	# DW_AT_decl_line
+	.byte	0x22	# DW_AT_decl_line
 	.long	0x48	# DW_AT_type
 	.byte	0x2	# DW_AT_location
 	.byte	0x91	# DW_OP_fbreg
 	.sleb128 0
-	.uleb128 0x9	# (DIE (0xc6) DW_TAG_variable)
+	.uleb128 0x9	# (DIE (0xf5) DW_TAG_variable)
 	.ascii "a\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x23	# DW_AT_decl_line
+	.byte	0x24	# DW_AT_decl_line
 	.long	0x25	# DW_AT_type
 	.long	.LLST2	# DW_AT_location
-	.byte	0	# end of children of DIE 0x9e
-	.uleb128 0x8	# (DIE (0xd4) DW_TAG_subprogram)
+	.byte	0	# end of children of DIE 0xcd
+	.uleb128 0x8	# (DIE (0x103) DW_TAG_subprogram)
 	.byte	0x1	# DW_AT_external
 	.ascii "f2\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x2c	# DW_AT_decl_line
+	.byte	0x2d	# DW_AT_decl_line
 	.byte	0x1	# DW_AT_prototyped
 	.long	0x48	# DW_AT_type
 	.long	.LFB2	# DW_AT_low_pc
 	.long	.LFE2	# DW_AT_high_pc
 	.long	.LLST3	# DW_AT_frame_base
-	.long	0x10a	# DW_AT_sibling
-	.uleb128 0x7	# (DIE (0xf0) DW_TAG_formal_parameter)
+	.long	0x139	# DW_AT_sibling
+	.uleb128 0x7	# (DIE (0x11f) DW_TAG_formal_parameter)
 	.ascii "k\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x2c	# DW_AT_decl_line
+	.byte	0x2d	# DW_AT_decl_line
 	.long	0x48	# DW_AT_type
 	.byte	0x2	# DW_AT_location
 	.byte	0x91	# DW_OP_fbreg
 	.sleb128 0
-	.uleb128 0x9	# (DIE (0xfc) DW_TAG_variable)
+	.uleb128 0x9	# (DIE (0x12b) DW_TAG_variable)
 	.ascii "a\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x2e	# DW_AT_decl_line
-	.long	0x10a	# DW_AT_type
+	.byte	0x2f	# DW_AT_decl_line
+	.long	0x139	# DW_AT_type
 	.long	.LLST4	# DW_AT_location
-	.byte	0	# end of children of DIE 0xd4
-	.uleb128 0xa	# (DIE (0x10a) DW_TAG_array_type)
+	.byte	0	# end of children of DIE 0x103
+	.uleb128 0xa	# (DIE (0x139) DW_TAG_array_type)
 	.long	0x48	# DW_AT_type
-	.long	0x11a	# DW_AT_sibling
-	.uleb128 0xb	# (DIE (0x113) DW_TAG_subrange_type)
-	.long	0x11a	# DW_AT_type
+	.long	0x149	# DW_AT_sibling
+	.uleb128 0xb	# (DIE (0x142) DW_TAG_subrange_type)
+	.long	0x149	# DW_AT_type
 	.byte	0x1	# DW_AT_upper_bound
-	.byte	0	# end of children of DIE 0x10a
-	.uleb128 0xc	# (DIE (0x11a) DW_TAG_base_type)
+	.byte	0	# end of children of DIE 0x139
+	.uleb128 0xc	# (DIE (0x149) DW_TAG_base_type)
 	.byte	0x4	# DW_AT_byte_size
 	.byte	0x7	# DW_AT_encoding
-	.uleb128 0x8	# (DIE (0x11d) DW_TAG_subprogram)
+	.uleb128 0x8	# (DIE (0x14c) DW_TAG_subprogram)
 	.byte	0x1	# DW_AT_external
 	.ascii "f3\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x37	# DW_AT_decl_line
+	.byte	0x38	# DW_AT_decl_line
 	.byte	0x1	# DW_AT_prototyped
 	.long	0x48	# DW_AT_type
 	.long	.LFB3	# DW_AT_low_pc
 	.long	.LFE3	# DW_AT_high_pc
 	.long	.LLST5	# DW_AT_frame_base
-	.long	0x153	# DW_AT_sibling
-	.uleb128 0x7	# (DIE (0x139) DW_TAG_formal_parameter)
+	.long	0x182	# DW_AT_sibling
+	.uleb128 0x7	# (DIE (0x168) DW_TAG_formal_parameter)
 	.ascii "k\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x37	# DW_AT_decl_line
+	.byte	0x38	# DW_AT_decl_line
 	.long	0x48	# DW_AT_type
 	.byte	0x2	# DW_AT_location
 	.byte	0x91	# DW_OP_fbreg
 	.sleb128 0
-	.uleb128 0x9	# (DIE (0x145) DW_TAG_variable)
+	.uleb128 0x9	# (DIE (0x174) DW_TAG_variable)
 	.ascii "a\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x39	# DW_AT_decl_line
+	.byte	0x3a	# DW_AT_decl_line
 	.long	0x4f	# DW_AT_type
 	.long	.LLST6	# DW_AT_location
-	.byte	0	# end of children of DIE 0x11d
-	.uleb128 0x8	# (DIE (0x153) DW_TAG_subprogram)
+	.byte	0	# end of children of DIE 0x14c
+	.uleb128 0x8	# (DIE (0x182) DW_TAG_subprogram)
 	.byte	0x1	# DW_AT_external
 	.ascii "f4\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x42	# DW_AT_decl_line
+	.byte	0x43	# DW_AT_decl_line
 	.byte	0x1	# DW_AT_prototyped
 	.long	0x48	# DW_AT_type
 	.long	.LFB4	# DW_AT_low_pc
 	.long	.LFE4	# DW_AT_high_pc
 	.long	.LLST7	# DW_AT_frame_base
-	.long	0x189	# DW_AT_sibling
-	.uleb128 0x7	# (DIE (0x16f) DW_TAG_formal_parameter)
+	.long	0x1b8	# DW_AT_sibling
+	.uleb128 0x7	# (DIE (0x19e) DW_TAG_formal_parameter)
 	.ascii "k\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x42	# DW_AT_decl_line
+	.byte	0x43	# DW_AT_decl_line
 	.long	0x48	# DW_AT_type
 	.byte	0x2	# DW_AT_location
 	.byte	0x91	# DW_OP_fbreg
 	.sleb128 0
-	.uleb128 0x9	# (DIE (0x17b) DW_TAG_variable)
+	.uleb128 0x9	# (DIE (0x1aa) DW_TAG_variable)
 	.ascii "a\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x44	# DW_AT_decl_line
-	.long	0x10a	# DW_AT_type
+	.byte	0x45	# DW_AT_decl_line
+	.long	0x139	# DW_AT_type
 	.long	.LLST8	# DW_AT_location
-	.byte	0	# end of children of DIE 0x153
-	.uleb128 0x8	# (DIE (0x189) DW_TAG_subprogram)
+	.byte	0	# end of children of DIE 0x182
+	.uleb128 0x8	# (DIE (0x1b8) DW_TAG_subprogram)
 	.byte	0x1	# DW_AT_external
 	.ascii "f5\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x4d	# DW_AT_decl_line
+	.byte	0x4e	# DW_AT_decl_line
 	.byte	0x1	# DW_AT_prototyped
 	.long	0x48	# DW_AT_type
 	.long	.LFB5	# DW_AT_low_pc
 	.long	.LFE5	# DW_AT_high_pc
 	.long	.LLST9	# DW_AT_frame_base
-	.long	0x1bf	# DW_AT_sibling
-	.uleb128 0x7	# (DIE (0x1a5) DW_TAG_formal_parameter)
+	.long	0x1ee	# DW_AT_sibling
+	.uleb128 0x7	# (DIE (0x1d4) DW_TAG_formal_parameter)
 	.ascii "k\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x4d	# DW_AT_decl_line
+	.byte	0x4e	# DW_AT_decl_line
 	.long	0x48	# DW_AT_type
 	.byte	0x2	# DW_AT_location
 	.byte	0x91	# DW_OP_fbreg
 	.sleb128 0
-	.uleb128 0x9	# (DIE (0x1b1) DW_TAG_variable)
+	.uleb128 0x9	# (DIE (0x1e0) DW_TAG_variable)
 	.ascii "a\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x4f	# DW_AT_decl_line
+	.byte	0x50	# DW_AT_decl_line
 	.long	0x25	# DW_AT_type
 	.long	.LLST10	# DW_AT_location
-	.byte	0	# end of children of DIE 0x189
-	.uleb128 0xd	# (DIE (0x1bf) DW_TAG_subprogram)
+	.byte	0	# end of children of DIE 0x1b8
+	.uleb128 0x8	# (DIE (0x1ee) DW_TAG_subprogram)
 	.byte	0x1	# DW_AT_external
-	.long	.LASF0	# DW_AT_name: "main"
+	.ascii "f6\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x58	# DW_AT_decl_line
+	.byte	0x59	# DW_AT_decl_line
 	.byte	0x1	# DW_AT_prototyped
 	.long	0x48	# DW_AT_type
 	.long	.LFB6	# DW_AT_low_pc
 	.long	.LFE6	# DW_AT_high_pc
 	.long	.LLST11	# DW_AT_frame_base
-	.uleb128 0x9	# (DIE (0x1d8) DW_TAG_variable)
+	.long	0x22e	# DW_AT_sibling
+	.uleb128 0x7	# (DIE (0x20a) DW_TAG_formal_parameter)
 	.ascii "k\0"	# DW_AT_name
 	.byte	0x1	# DW_AT_decl_file (pieces.c)
-	.byte	0x5a	# DW_AT_decl_line
+	.byte	0x59	# DW_AT_decl_line
 	.long	0x48	# DW_AT_type
+	.byte	0x2	# DW_AT_location
+	.byte	0x91	# DW_OP_fbreg
+	.sleb128 0
+	.uleb128 0xd	# (DIE (0x216) DW_TAG_variable)
+	.ascii "z\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (pieces.c)
+	.byte	0x5b	# DW_AT_decl_line
+	.long	0x48	# DW_AT_type
+	.byte	0x17	# DW_AT_const_value
+	.uleb128 0x9	# (DIE (0x220) DW_TAG_variable)
+	.ascii "a\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (pieces.c)
+	.byte	0x5c	# DW_AT_decl_line
+	.long	0x78	# DW_AT_type
 	.long	.LLST12	# DW_AT_location
-	.byte	0	# end of children of DIE 0x1bf
+	.byte	0	# end of children of DIE 0x1ee
+	.uleb128 0xe	# (DIE (0x22e) DW_TAG_subprogram)
+	.byte	0x1	# DW_AT_external
+	.long	.LASF0	# DW_AT_name: "main"
+	.byte	0x1	# DW_AT_decl_file (pieces.c)
+	.byte	0x65	# DW_AT_decl_line
+	.byte	0x1	# DW_AT_prototyped
+	.long	0x48	# DW_AT_type
+	.long	.LFB7	# DW_AT_low_pc
+	.long	.LFE7	# DW_AT_high_pc
+	.long	.LLST13	# DW_AT_frame_base
+	.uleb128 0x9	# (DIE (0x247) DW_TAG_variable)
+	.ascii "k\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (pieces.c)
+	.byte	0x67	# DW_AT_decl_line
+	.long	0x48	# DW_AT_type
+	.long	.LLST14	# DW_AT_location
+	.byte	0	# end of children of DIE 0x22e
 	.byte	0	# end of children of DIE 0xb
 	.section	.debug_abbrev
 	.uleb128 0x1	# (abbrev code)
@@ -1577,6 +1800,21 @@ main:
 	.byte	0
 	.byte	0
 	.uleb128 0xd	# (abbrev code)
+	.uleb128 0x34	# (TAG: DW_TAG_variable)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x1c	# (DW_AT_const_value)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.byte	0
+	.byte	0
+	.uleb128 0xe	# (abbrev code)
 	.uleb128 0x2e	# (TAG: DW_TAG_subprogram)
 	.byte	0x1	# DW_children_yes
 	.uleb128 0x3f	# (DW_AT_external)
@@ -1601,34 +1839,38 @@ main:
 	.byte	0
 	.byte	0
 	.section	.debug_pubnames,"",@progbits
-	.long	0x42	# Length of Public Names Info
+	.long	0x49	# Length of Public Names Info
 	.value	0x2	# DWARF Version
 	.long	.Ldebug_info0	# Offset of Compilation Unit Info
-	.long	0x1e7	# Compilation Unit Length
-	.long	0x78	# DIE offset
+	.long	0x256	# Compilation Unit Length
+	.long	0xa7	# DIE offset
 	.ascii "bar\0"	# external name
-	.long	0x9e	# DIE offset
+	.long	0xcd	# DIE offset
 	.ascii "f1\0"	# external name
-	.long	0xd4	# DIE offset
+	.long	0x103	# DIE offset
 	.ascii "f2\0"	# external name
-	.long	0x11d	# DIE offset
+	.long	0x14c	# DIE offset
 	.ascii "f3\0"	# external name
-	.long	0x153	# DIE offset
+	.long	0x182	# DIE offset
 	.ascii "f4\0"	# external name
-	.long	0x189	# DIE offset
+	.long	0x1b8	# DIE offset
 	.ascii "f5\0"	# external name
-	.long	0x1bf	# DIE offset
+	.long	0x1ee	# DIE offset
+	.ascii "f6\0"	# external name
+	.long	0x22e	# DIE offset
 	.ascii "main\0"	# external name
 	.long	0
 	.section	.debug_pubtypes,"",@progbits
-	.long	0x1a	# Length of Public Type Names Info
+	.long	0x20	# Length of Public Type Names Info
 	.value	0x2	# DWARF Version
 	.long	.Ldebug_info0	# Offset of Compilation Unit Info
-	.long	0x1e7	# Compilation Unit Length
+	.long	0x256	# Compilation Unit Length
 	.long	0x25	# DIE offset
 	.ascii "A\0"	# external name
 	.long	0x4f	# DIE offset
 	.ascii "B\0"	# external name
+	.long	0x78	# DIE offset
+	.ascii "C\0"	# external name
 	.long	0
 	.section	.debug_aranges,"",@progbits
 	.long	0x1c	# Length of Address Ranges Info
diff --git a/gdb/testsuite/gdb.dwarf2/pieces.c b/gdb/testsuite/gdb.dwarf2/pieces.c
index 49028b0..04ea8a2 100644
--- a/gdb/testsuite/gdb.dwarf2/pieces.c
+++ b/gdb/testsuite/gdb.dwarf2/pieces.c
@@ -22,6 +22,7 @@
 
 struct A { int i; int j; };
 struct B { int : 4; int i : 12; int j : 12; int : 4; };
+struct C { int i; int j; int q; };
 
 __attribute__((noinline)) void
 bar (int x)
@@ -84,6 +85,18 @@ f5 (int k)
   return a.i + a.j;		/* f5 breakpoint */
 }
 
+__attribute__((noinline)) int
+f6 (int k)
+{
+  int z = 23;
+  struct C a = { k, k, z};
+  asm ("" : "+r" (a.i));
+  a.j++;
+  bar (a.i);
+  bar (a.j);
+  return a.i + a.j;		/* f6 breakpoint */
+}
+
 int
 main (void)
 {
@@ -94,5 +107,6 @@ main (void)
   f3 (k);
   f4 (k);
   f5 (k);
+  f6 (k);
   return 0;
 }
diff --git a/gdb/testsuite/gdb.dwarf2/pieces.exp b/gdb/testsuite/gdb.dwarf2/pieces.exp
index 3515586..c7608cd 100644
--- a/gdb/testsuite/gdb.dwarf2/pieces.exp
+++ b/gdb/testsuite/gdb.dwarf2/pieces.exp
@@ -67,5 +67,28 @@ proc pieces_test_f2 {} {
     gdb_test "print a\[1\]" " = 14" "print a\[1\] in pieces:f2"
 }
 
+# Function f6 tests for an empty DW_OP_piece.
+proc pieces_test_f6 {} {
+    global csrcfile
+    set line [gdb_get_line_number "f6 breakpoint" $csrcfile]
+    gdb_test "break pieces.c:$line" "Breakpoint 4.*" \
+       "set f6 breakpoint for pieces"
+    gdb_continue_to_breakpoint "continue to f6 breakpoint for pieces"
+    gdb_test "print a" \
+	"warning: bytes .* in computed object were.* = {i = 7, j = 8, q = 0}" \
+	"print a with optimized out piece"
+    # Note: no warning for this case.
+    gdb_test_multiple "print a.i" \
+	"print a.i with optimized out piece" {
+	    -re "warning: some bits in computed object" {
+		fail "print a.i with optimized out piece"
+	    }
+	    -re " = 7" {
+		pass "print a.i with optimized out piece"
+	    }
+	}
+}
+
 pieces_test_f1
 pieces_test_f2
+pieces_test_f6

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: RFC: partially fix empty DW_OP_piece
  2010-05-14 22:51 ` Jan Kratochvil
  2010-05-21 19:48   ` Tom Tromey
@ 2010-06-01 17:34   ` Tom Tromey
  2010-06-02 18:54     ` Jan Kratochvil
  1 sibling, 1 reply; 12+ messages in thread
From: Tom Tromey @ 2010-06-01 17:34 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

>>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:

We were talking on irc and Jan asked for more information about part of
my plan...

Tom> The other way is to simply remove val_print entirely and make all of
Tom> printing work using values.  I think this is the route I would prefer.

Jan> That could hopefully solve the problem of missing type-associated object
Jan> address for DW_OP_push_object_address for the VLA (variable length arrays)
Jan> patch.

I am curious to know what you need here.

I started by looking briefly at replacing val_print.  This looks pretty
big, though.  So I looked into other solutions.

I wrote a big patch to pass lval_funcs through all the val_print code.
However, it turns out that this is not sufficient: the code has to
handle value_offset() as well, which means either adding another
argument (the offset) or just passing the original value through.

So, currently I am thinking I will go through my existing patch and have
it pass a value instead of lval_funcs.  Of course this means a lot of
redundant info, which is ugly.

There are barriers to removing val_print.  I think the biggest one,
conceptually, is that recursion in val_print means making new values,
which means copying the value contents.  This can be expensive.  (Of
course there are solutions to that, reference counting the value
contents comes to mind.)

Tom

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: RFC: partially fix empty DW_OP_piece
  2010-06-01 17:34   ` Tom Tromey
@ 2010-06-02 18:54     ` Jan Kratochvil
  2010-06-02 20:07       ` Tom Tromey
  0 siblings, 1 reply; 12+ messages in thread
From: Jan Kratochvil @ 2010-06-02 18:54 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Tue, 01 Jun 2010 18:41:51 +0200, Tom Tromey wrote:
> >>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:
> Tom> The other way is to simply remove val_print entirely and make all of
> Tom> printing work using values.  I think this is the route I would prefer.
> 
> Jan> That could hopefully solve the problem of missing type-associated object
> Jan> address for DW_OP_push_object_address for the VLA (variable length arrays)
> Jan> patch.
> 
> I am curious to know what you need here.

I do not understand the prototype:
int
val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
           CORE_ADDR address, struct ui_file *stream, int recurse,
           const struct value_print_options *options,
           const struct language_defn *language)
struct language_defn:
    int (*la_val_print) (struct type *type,
                         const gdb_byte *contents,
                         int embedded_offset, CORE_ADDR address,
                         struct ui_file *stream, int recurse,
                         const struct value_print_options *options);

There cannot be any `const gdb_byte *contents' for types with DWARF_block* as
their attribute (=TYPE_DYNAMIC from archer-jankratochvil-vla) as DWARF
expression evaluation arbitrarily accesses inferior memory during DWARF_block*
evaluation for DW_AT_upper_bound and others.  VLA patchset also deals with two
ADDRESSes - object address (needed for DWARF_block*'s
DW_OP_push_object_address evaluation) and data address (DW_AT_data_location,
neede for the content printing - but data address can be derived from the
object address; apparently data address cannot be converted to object
address).

OTOH there cannot be any `CORE_ADDR address' where the content could be read
from - for example for internal variables.

Therefore we need to use both accesses depending on the object class.
I believe `struct value' stricly being LAZY can be used for inferior objects
(and non-LAZY `struct value' for internal variables).  Only in some final
moment (of arrays dereferencing etc.) the inferior LAZY vary can be fetched.


> I started by looking briefly at replacing val_print.

Here you probably mean la_val_print->la_value_print unification:
struct language_defn:
    int (*la_val_print) (struct type *type,
                         const gdb_byte *contents,
                         int embedded_offset, CORE_ADDR address,
                         struct ui_file *stream, int recurse,
                         const struct value_print_options *options);

by keeping only existing:
struct language_defn:
    int (*la_value_print) (struct value *, struct ui_file *,
                           const struct value_print_options *);


> This looks pretty big, though.  So I looked into other solutions.

I believe it will need to be done anyway for the sane integration of the VLA
patchset.


> So, currently I am thinking I will go through my existing patch and have
> it pass a value instead of lval_funcs.  Of course this means a lot of
> redundant info, which is ugly.

Do you mean the unification proposed above or some other extension?


> There are barriers to removing val_print.  I think the biggest one,
> conceptually, is that recursion in val_print means making new values,

Yes, I think it is required for the case of Pascal arrays of strings - each
element of Pascal array is a VLA array (=string); gdb.pascal/arrays.exp by
Joost van der Sluis in archer-jankratochvil-vla.  Each element is a full-blown
dynamic objects without much possibilities of a simplication.


> which means copying the value contents.  This can be expensive.  (Of
> course there are solutions to that, reference counting the value
> contents comes to mind.)

Couldn't be just the `struct value' kept LAZY and creating struct values for
the dereferenced elements only with properly adjusted object address?


Thanks,
Jan

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: RFC: partially fix empty DW_OP_piece
  2010-06-02 18:54     ` Jan Kratochvil
@ 2010-06-02 20:07       ` Tom Tromey
  2010-06-03 17:46         ` Jan Kratochvil
  0 siblings, 1 reply; 12+ messages in thread
From: Tom Tromey @ 2010-06-02 20:07 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

>>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:

Jan>     int (*la_val_print) (struct type *type,
Jan>                          const gdb_byte *contents,
Jan>                          int embedded_offset, CORE_ADDR address,
Jan>                          struct ui_file *stream, int recurse,
Jan>                          const struct value_print_options *options);

Jan> There cannot be any `const gdb_byte *contents' for types with
Jan> DWARF_block* as their attribute (=TYPE_DYNAMIC from
Jan> archer-jankratochvil-vla) as DWARF expression evaluation
Jan> arbitrarily accesses inferior memory during DWARF_block* evaluation
Jan> for DW_AT_upper_bound and others.

I think the current gdb model is that a value is a snapshot of some
inferior state at a particular moment.

So, for VLA I would say that the bounds ought to be fixed at the time
the snapshot is taken.  I suppose this would mean introducing some copy
of the type.

Jan> OTOH there cannot be any `CORE_ADDR address' where the content
Jan> could be read from - for example for internal variables.

Yeah.  val_print doesn't usually read memory, though.  The address is
only occasionally used.

Tom> I started by looking briefly at replacing val_print.

Jan> Here you probably mean la_val_print->la_value_print unification:

Yes.

Tom> So, currently I am thinking I will go through my existing patch and have
Tom> it pass a value instead of lval_funcs.  Of course this means a lot of
Tom> redundant info, which is ugly.

Jan> Do you mean the unification proposed above or some other extension?

Right now what I've done is change val_print to:

int
val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
	   CORE_ADDR address, struct ui_file *stream, int recurse,
	   const struct value *val,
	   const struct value_print_options *options,
	   const struct language_defn *language)

That is, I added the new 'val' argument.  This is only used for bit
validity testing.

Jan> Couldn't be just the `struct value' kept LAZY and creating struct
Jan> values for the dereferenced elements only with properly adjusted
Jan> object address?

One problem is that not all values are lazy.  Also, record_latest_value
specifically makes a value not lazy, but this could be fixed somehow.

Maybe this problem is not very important though.

Tom

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: RFC: partially fix empty DW_OP_piece
  2010-06-02 20:07       ` Tom Tromey
@ 2010-06-03 17:46         ` Jan Kratochvil
  2010-06-04 19:05           ` Tom Tromey
  0 siblings, 1 reply; 12+ messages in thread
From: Jan Kratochvil @ 2010-06-03 17:46 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Wed, 02 Jun 2010 22:07:41 +0200, Tom Tromey wrote:
> I think the current gdb model is that a value is a snapshot of some
> inferior state at a particular moment.
> 
> So, for VLA I would say that the bounds ought to be fixed at the time
> the snapshot is taken.  I suppose this would mean introducing some copy
> of the type.

That is interesting idea (and currently in the VLA patch it happens that way).
Still it is probably really needed only for the GDB values history.


> Right now what I've done is change val_print to:
> 
> int
> val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
> 	   CORE_ADDR address, struct ui_file *stream, int recurse,
> 	   const struct value *val,
> 	   const struct value_print_options *options,
> 	   const struct language_defn *language)
> 
> That is, I added the new 'val' argument.  This is only used for bit
> validity testing.

As we talked with Tom he has already the patch coded+working.  I thought only
a plan for his coding is being discussed now.  Therefore leaving the VLA
design decision for a later point unrelated to his current patch.


Thanks,
Jan

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: RFC: partially fix empty DW_OP_piece
  2010-06-03 17:46         ` Jan Kratochvil
@ 2010-06-04 19:05           ` Tom Tromey
  2010-06-04 19:10             ` Jan Kratochvil
  0 siblings, 1 reply; 12+ messages in thread
From: Tom Tromey @ 2010-06-04 19:05 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

>>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:

Tom> So, for VLA I would say that the bounds ought to be fixed at the time
Tom> the snapshot is taken.  I suppose this would mean introducing some copy
Tom> of the type.

Jan> That is interesting idea (and currently in the VLA patch it happens
Jan> that way).  Still it is probably really needed only for the GDB
Jan> values history.

Yeah, and Python.

Jan> As we talked with Tom he has already the patch coded+working.  I
Jan> thought only a plan for his coding is being discussed now.
Jan> Therefore leaving the VLA design decision for a later point
Jan> unrelated to his current patch.

Ok.  I'm going to submit my patch in a minute.

Tom

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: RFC: partially fix empty DW_OP_piece
  2010-06-04 19:05           ` Tom Tromey
@ 2010-06-04 19:10             ` Jan Kratochvil
  2010-06-04 21:39               ` Tom Tromey
  0 siblings, 1 reply; 12+ messages in thread
From: Jan Kratochvil @ 2010-06-04 19:10 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Fri, 04 Jun 2010 21:05:36 +0200, Tom Tromey wrote:
> >>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:
> 
> Tom> So, for VLA I would say that the bounds ought to be fixed at the time
> Tom> the snapshot is taken.  I suppose this would mean introducing some copy
> Tom> of the type.
> 
> Jan> That is interesting idea (and currently in the VLA patch it happens
> Jan> that way).  Still it is probably really needed only for the GDB
> Jan> values history.
> 
> Yeah, and Python.

OK, that probably means there really must remain a way to convert `inferior
dependent struct value' into an `inferior independent struct value'.


Thanks,
Jan

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: RFC: partially fix empty DW_OP_piece
  2010-06-04 19:10             ` Jan Kratochvil
@ 2010-06-04 21:39               ` Tom Tromey
  2010-06-04 21:47                 ` Jan Kratochvil
  0 siblings, 1 reply; 12+ messages in thread
From: Tom Tromey @ 2010-06-04 21:39 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

>>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:

Jan> OK, that probably means there really must remain a way to convert
Jan> `inferior dependent struct value' into an `inferior independent
Jan> struct value'.

Yeah, at least as far as the bounds are concerned.  IMO.

The current gdb model is sort of mixed.  A struct value is a snapshot of
some bit of state.  But, when printing a value, we might refer to other
state in the target.  For example:

    struct x { char *name; };

If we have a value of that type, gdb will try to dereference the pointer
when printing.  But, we make no attempt to save this memory alongside
the value somewhere.  So, if you have a complicated debug session and
then after many re-runs or whatever do "print $1", you can get weird
answers.

There may be some other odd cases, too.

We could fix this, of course, but it isn't clear that it is worth the
effort.

Tom

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: RFC: partially fix empty DW_OP_piece
  2010-06-04 21:39               ` Tom Tromey
@ 2010-06-04 21:47                 ` Jan Kratochvil
  0 siblings, 0 replies; 12+ messages in thread
From: Jan Kratochvil @ 2010-06-04 21:47 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Fri, 04 Jun 2010 23:39:06 +0200, Tom Tromey wrote:
> >>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:
> 
> Jan> OK, that probably means there really must remain a way to convert
> Jan> `inferior dependent struct value' into an `inferior independent
> Jan> struct value'.
> 
> Yeah, at least as far as the bounds are concerned.  IMO.
> 
> The current gdb model is sort of mixed.  A struct value is a snapshot of
> some bit of state.  But, when printing a value, we might refer to other
> state in the target.  For example:
> 
>     struct x { char *name; };

Understood but I find it more wrong in (plain) C as it has no `string' type.

The same problem happens for other data types being PythonPrettyPrinted.


Thanks,
Jan

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2010-06-04 21:47 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-05-14  6:39 RFC: partially fix empty DW_OP_piece Tom Tromey
2010-05-14 22:51 ` Jan Kratochvil
2010-05-21 19:48   ` Tom Tromey
2010-06-01 17:34   ` Tom Tromey
2010-06-02 18:54     ` Jan Kratochvil
2010-06-02 20:07       ` Tom Tromey
2010-06-03 17:46         ` Jan Kratochvil
2010-06-04 19:05           ` Tom Tromey
2010-06-04 19:10             ` Jan Kratochvil
2010-06-04 21:39               ` Tom Tromey
2010-06-04 21:47                 ` Jan Kratochvil
2010-05-20 23:04 ` Joel Brobecker

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).