rpms/gdb/F-13 gdb-archer-next-over-throw-cxx-exec.patch, NONE, 1.1 gdb-bz589467-pieces-vla-compat.patch, NONE, 1.1 gdb-bz589467-pieces01of4.patch, NONE, 1.1 gdb-bz589467-pieces02of4.patch, NONE, 1.1 gdb-bz589467-pieces03of4.patch, NONE, 1.1 gdb-bz589467-pieces1of4.patch, NONE, 1.1 gdb-bz589467-pieces2of4.patch, NONE, 1.1 gdb-bz589467-pieces3of4.patch, NONE, 1.1 gdb-bz589467-pieces4of4.patch, NONE, 1.1 gdb.spec, 1.440, 1.441

Jan Kratochvil jkratoch at fedoraproject.org
Sun May 30 18:14:31 UTC 2010


Author: jkratoch

Update of /cvs/pkgs/rpms/gdb/F-13
In directory cvs01.phx2.fedoraproject.org:/tmp/cvs-serv4348

Modified Files:
	gdb.spec 
Added Files:
	gdb-archer-next-over-throw-cxx-exec.patch 
	gdb-bz589467-pieces-vla-compat.patch 
	gdb-bz589467-pieces01of4.patch gdb-bz589467-pieces02of4.patch 
	gdb-bz589467-pieces03of4.patch gdb-bz589467-pieces1of4.patch 
	gdb-bz589467-pieces2of4.patch gdb-bz589467-pieces3of4.patch 
	gdb-bz589467-pieces4of4.patch 
Log Message:
* Sun May 30 2010 Jan Kratochvil <jan.kratochvil at redhat.com> - 7.1-23.fc13
- Fix and support DW_OP_*piece (Tom Tromey, BZ 589467).
- Fix follow-exec for C++ programs (bugreported by Martin Stransky).


gdb-archer-next-over-throw-cxx-exec.patch:
 breakpoint.c                 |    7 +----
 testsuite/gdb.cp/cxxexec.cc  |   25 +++++++++++++++++++++
 testsuite/gdb.cp/cxxexec.exp |   51 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 78 insertions(+), 5 deletions(-)

--- NEW FILE gdb-archer-next-over-throw-cxx-exec.patch ---
Archer-upstreamed:
http://sourceware.org/ml/archer/2010-q2/msg00031.html

--- ./gdb/breakpoint.c	2010-05-29 01:12:32.000000000 +0200
+++ ./gdb/breakpoint.c	2010-05-29 01:22:21.000000000 +0200
@@ -1679,14 +1679,11 @@ create_exception_master_breakpoint (void
       debug_hook = lookup_minimal_symbol_text ("_Unwind_DebugHook", objfile);
       if (debug_hook != NULL)
 	{
-	  CORE_ADDR pc;
 	  struct breakpoint *b;
 
-	  pc = find_function_start_pc (get_objfile_arch (objfile),
-				       SYMBOL_VALUE_ADDRESS (debug_hook),
-				       SYMBOL_OBJ_SECTION (debug_hook));
 	  b = create_internal_breakpoint (get_objfile_arch (objfile),
-					  pc, bp_exception_master);
+					  SYMBOL_VALUE_ADDRESS (debug_hook),
+					  bp_exception_master);
 	  b->addr_string = xstrdup ("_Unwind_DebugHook");
 	  b->enable_state = bp_disabled;
 	}
--- ./gdb/testsuite/gdb.cp/cxxexec.cc	1970-01-01 01:00:00.000000000 +0100
+++ ./gdb/testsuite/gdb.cp/cxxexec.cc	2010-05-29 01:18:56.000000000 +0200
@@ -0,0 +1,25 @@
+/* This test script is part of GDB, the GNU debugger.
+
+   Copyright 2010 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <unistd.h>
+
+int
+main()
+{
+  execlp ("true", "true", NULL);
+  return 1;
+}
--- ./gdb/testsuite/gdb.cp/cxxexec.exp	1970-01-01 01:00:00.000000000 +0100
+++ ./gdb/testsuite/gdb.cp/cxxexec.exp	2010-05-29 01:29:25.000000000 +0200
@@ -0,0 +1,51 @@
+# Copyright 2010 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+if { [skip_cplus_tests] } { continue }
+
+set testfile cxxexec
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${testfile}.cc {c++ debug}] } {
+    return -1
+}
+
+runto_main
+
+# We could stop after `continue' again at `main'.
+delete_breakpoints
+
+set test "p _Unwind_DebugHook"
+gdb_test_multiple $test $test {
+    -re " = .* 0x\[0-9a-f\].*\r\n$gdb_prompt $" {
+	pass $test
+    }
+    -re "\r\nNo symbol .*\r\n$gdb_prompt $" {
+	xfail $test
+	untested ${testfile}.exp
+	return -1
+    }
+}
+
+set test continue
+gdb_test_multiple $test $test {
+    -re "Cannot access memory at address 0x\[0-9a-f\]+\r\n$gdb_prompt $" {
+	fail $test
+    }
+    -re "\r\n$gdb_prompt $" {
+	pass $test
+    }
+}
+
+# `info inferiors' can show <null> on older GDBs.
+gdb_test "info threads" "info threads" "program finished"

gdb-bz589467-pieces-vla-compat.patch:
 valarith.c |    4 ++++
 value.c    |   19 ++++++++++++++++++-
 2 files changed, 22 insertions(+), 1 deletion(-)

--- NEW FILE gdb-bz589467-pieces-vla-compat.patch ---
06e357f534abcf8912e4fd597daae8f1387d631c

Fix compatibility with: FYI: fix BINOP_SUBSCRIPT with pieced arrays
 	http://sourceware.org/ml/gdb-patches/2010-05/msg00281.html

2010-05-30  Jan Kratochvil  <jan.kratochvil at redhat.com>

	* valarith.c (binop_user_defined_p): Return 0 on ARG1 or ARG2 being
	TYPE_DYNAMIC.
	* value.c (coerce_ref): Use object_address_get_data resolution for
	TYPE_DYNAMIC ARG.

[ Backported.  ]

Index: gdb-7.1/gdb/valarith.c
===================================================================
--- gdb-7.1.orig/gdb/valarith.c	2010-05-30 18:54:28.000000000 +0200
+++ gdb-7.1/gdb/valarith.c	2010-05-30 18:54:43.000000000 +0200
@@ -309,6 +309,10 @@ int
 binop_user_defined_p (enum exp_opcode op,
 		      struct value *arg1, struct value *arg2)
 {
+  /* FIXME: We should support user defined ops for dynamic types.  */
+  if (TYPE_DYNAMIC (value_type (arg1)) || TYPE_DYNAMIC (value_type (arg2)))
+    return 0;
+
   return binop_types_user_defined_p (op, value_type (arg1), value_type (arg2));
 }
 
Index: gdb-7.1/gdb/value.c
===================================================================
--- gdb-7.1.orig/gdb/value.c	2010-05-30 18:54:36.000000000 +0200
+++ gdb-7.1/gdb/value.c	2010-05-30 18:55:52.000000000 +0200
@@ -2400,7 +2400,24 @@ value_from_decfloat (struct type *type, 
 struct value *
 coerce_ref (struct value *arg)
 {
-  struct type *value_type_arg_tmp = check_typedef (value_type (arg));
+  struct type *value_type_arg_tmp;
+
+  if (TYPE_DYNAMIC (value_type (arg)))
+    {
+      struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
+      CORE_ADDR address;
+
+      value_type_arg_tmp = value_type (arg);
+      address = value_raw_address (arg);
+      if (! object_address_get_data (value_type_arg_tmp, &address))
+	error (_("Attempt to coerce non-valid value."));
+      CHECK_TYPEDEF (value_type_arg_tmp);
+      arg = value_at_lazy (value_type_arg_tmp, address);
+      do_cleanups (cleanups);
+    }
+  else
+    value_type_arg_tmp = check_typedef (value_type (arg));
+
   if (TYPE_CODE (value_type_arg_tmp) == TYPE_CODE_REF)
     arg = value_at_lazy (TYPE_TARGET_TYPE (value_type_arg_tmp),
 			 unpack_pointer (value_type (arg),		

gdb-bz589467-pieces01of4.patch:
 dwarf2loc.c |   24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

--- NEW FILE gdb-bz589467-pieces01of4.patch ---
commit 96c23bfd2863bcca7388653a7bc4c9f8a64a03be
Author: Ulrich Weigand <uweigand at de.ibm.com>
Date:   Fri Feb 26 12:48:17 2010 +0000

    	* dwarf2loc.c (struct piece_closure): Remove ARCH member,
    	add ADDR_SIZE member.
    	(allocate_piece_closure): Update.
    	(copy_pieced_value_closure): Likewise.
    	(dwarf2_evaluate_loc_desc): Likewise.
    	(read_pieced_value): Use DWARF address size instead of
    	GDB's gdbarch_addr_bit as size of values on the DWARF stack.

diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 1c4d057..20ede3e 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -232,8 +232,8 @@ struct piece_closure
   /* The number of pieces used to describe this variable.  */
   int n_pieces;
 
-  /* The architecture, used only for DWARF_VALUE_STACK.  */
-  struct gdbarch *arch;
+  /* The target address size, used only for DWARF_VALUE_STACK.  */
+  int addr_size;
 
   /* The pieces themselves.  */
   struct dwarf_expr_piece *pieces;
@@ -244,12 +244,12 @@ struct piece_closure
 
 static struct piece_closure *
 allocate_piece_closure (int n_pieces, struct dwarf_expr_piece *pieces,
-			struct gdbarch *arch)
+			int addr_size)
 {
   struct piece_closure *c = XZALLOC (struct piece_closure);
 
   c->n_pieces = n_pieces;
-  c->arch = arch;
+  c->addr_size = addr_size;
   c->pieces = XCALLOC (n_pieces, struct dwarf_expr_piece);
 
   memcpy (c->pieces, pieces, n_pieces * sizeof (struct dwarf_expr_piece));
@@ -298,13 +298,12 @@ read_pieced_value (struct value *v)
 
 	case DWARF_VALUE_STACK:
 	  {
-	    size_t n;
-	    int addr_size = gdbarch_addr_bit (c->arch) / 8;
-	    n = p->size;
-	    if (n > addr_size)
-	      n = addr_size;
+	    struct gdbarch *gdbarch = get_type_arch (value_type (v));
+	    size_t n = p->size;
+	    if (n > c->addr_size)
+	      n = c->addr_size;
 	    store_unsigned_integer (contents + offset, n,
-				    gdbarch_byte_order (c->arch),
+				    gdbarch_byte_order (gdbarch),
 				    p->v.expr.value);
 	  }
 	  break;
@@ -377,7 +376,7 @@ copy_pieced_value_closure (struct value *v)
 {
   struct piece_closure *c = (struct piece_closure *) value_computed_closure (v);
   
-  return allocate_piece_closure (c->n_pieces, c->pieces, c->arch);
+  return allocate_piece_closure (c->n_pieces, c->pieces, c->addr_size);
 }
 
 static void
@@ -439,7 +438,8 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
       struct piece_closure *c;
       struct frame_id frame_id = get_frame_id (frame);
 
-      c = allocate_piece_closure (ctx->num_pieces, ctx->pieces, ctx->gdbarch);
+      c = allocate_piece_closure (ctx->num_pieces, ctx->pieces,
+				  ctx->addr_size);
       retval = allocate_computed_value (type, &pieced_value_funcs, c);
       VALUE_FRAME_ID (retval) = frame_id;
     }

gdb-bz589467-pieces02of4.patch:
 dwarf2loc.c |   35 ++++++++++++++++++++++++++++++-----
 1 file changed, 30 insertions(+), 5 deletions(-)

--- NEW FILE gdb-bz589467-pieces02of4.patch ---
commit 60d15ff6d78921d080aee681e60372abe6627570
Author: mgretton <mgretton>
Date:   Tue May 4 09:54:17 2010 +0000

    	* gdb/dwarf2loc.c (read_pieced_value, write_pieced_value,
    	dwarf2_evaluate_loc_desc): Handle not being able to access DWARF
    	registers gracefully.

Index: gdb-7.1/gdb/dwarf2loc.c
===================================================================
--- gdb-7.1.orig/gdb/dwarf2loc.c	2010-05-25 21:35:10.000000000 +0200
+++ gdb-7.1/gdb/dwarf2loc.c	2010-05-25 21:37:32.000000000 +0200
@@ -458,8 +458,16 @@ read_pieced_value (struct value *v)
 	      /* Big-endian, and we want less than full size.  */
 	      reg_offset = register_size (arch, gdb_regnum) - p->size;
 
-	    get_frame_register_bytes (frame, gdb_regnum, reg_offset, p->size,
-				      contents + offset);
+	    if (gdb_regnum != -1)
+	      {
+		get_frame_register_bytes (frame, gdb_regnum, reg_offset, 
+					  p->size, contents + offset);
+	      }
+	    else
+	      {
+		error (_("Unable to access DWARF register number %s"),
+		       paddress (arch, p->v.expr.value));
+	      }
 	  }
 	  break;
 
@@ -531,8 +539,16 @@ write_pieced_value (struct value *to, st
 	      /* Big-endian, and we want less than full size.  */
 	      reg_offset = register_size (arch, gdb_regnum) - p->size;
 
-	    put_frame_register_bytes (frame, gdb_regnum, reg_offset, p->size,
-				      contents + offset);
+	    if (gdb_regnum != -1)
+	      {
+		put_frame_register_bytes (frame, gdb_regnum, reg_offset, 
+					  p->size, contents + offset);
+	      }
+	    else
+	      {
+		error (_("Unable to write to DWARF register number %s"),
+		       paddress (arch, p->v.expr.value));
+	      }
 	  }
 	  break;
 	case DWARF_VALUE_MEMORY:
@@ -611,7 +627,16 @@ dwarf2_evaluate_loc_desc (struct type *t
 	    struct gdbarch *arch = get_frame_arch (frame);
 	    CORE_ADDR dwarf_regnum = dwarf_expr_fetch (ctx, 0);
 	    int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, dwarf_regnum);
-	    retval = value_from_register (type, gdb_regnum, frame);
+	    if (gdb_regnum != -1)
+	      {
+		retval = value_from_register (type,
+					      gdb_regnum, frame);
+	      }
+	    else
+	      {
+		error (_("Unable to access DWARF register number %s"),
+		       paddress (arch, dwarf_regnum));
+	      }
 	  }
 	  break;
 

gdb-bz589467-pieces03of4.patch:
 dwarf2loc.c |   10 ++++++++++
 1 file changed, 10 insertions(+)

--- NEW FILE gdb-bz589467-pieces03of4.patch ---
commit dacd66a53b559be9c26d2c523f168f1ef0261f4d
Author: Michael Snyder <msnyder at specifix.com>
Date:   Fri May 14 17:53:11 2010 +0000

    2010-05-14  Michael Snyder  <msnyder at vmware.com>
    
    	* dbxread.c: White space.
    	* dcache.c: White space.
    	* disasm.c: White space.
    	* doublest.c: White space.
    	* dsrec.c: White space.
    	* dummy-frame.c: White space.
    	* dwarf2expr.c: White space.
    	* dwarf2-frame.c: White space.
    	* dwarf2loc.c: White space.
    	* dwarf2read.c: White space.

--- gdb-7.1/gdb/dwarf2loc.c.orig	2010-05-25 23:06:46.000000000 +0200
+++ gdb-7.1/gdb/dwarf2loc.c	2010-05-25 23:06:46.000000000 +0200
@@ -236,6 +236,7 @@ static CORE_ADDR
 dwarf_expr_frame_cfa (void *baton)
 {
   struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
+
   return dwarf2_frame_cfa (debaton->frame);
 }
 
@@ -444,6 +445,7 @@ read_pieced_value (struct value *v)
   for (i = 0; i < c->n_pieces; i++)
     {
       struct dwarf_expr_piece *p = &c->pieces[i];
+
       switch (p->location)
 	{
 	case DWARF_VALUE_REGISTER:
@@ -482,6 +484,7 @@ read_pieced_value (struct value *v)
 	  {
 	    struct gdbarch *gdbarch = get_type_arch (value_type (v));
 	    size_t n = p->size;
+
 	    if (n > c->addr_size)
 	      n = c->addr_size;
 	    store_unsigned_integer (contents + offset, n,
@@ -493,6 +496,7 @@ read_pieced_value (struct value *v)
 	case DWARF_VALUE_LITERAL:
 	  {
 	    size_t n = p->size;
+
 	    if (n > p->v.literal.length)
 	      n = p->v.literal.length;
 	    memcpy (contents + offset, p->v.literal.data, n);
@@ -525,6 +529,7 @@ write_pieced_value (struct value *to, st
   for (i = 0; i < c->n_pieces; i++)
     {
       struct dwarf_expr_piece *p = &c->pieces[i];
+
       switch (p->location)
 	{
 	case DWARF_VALUE_REGISTER:
@@ -712,6 +717,7 @@ static CORE_ADDR
 needs_frame_read_reg (void *baton, int regnum)
 {
   struct needs_frame_baton *nf_baton = baton;
+
   nf_baton->needs_frame = 1;
   return 1;
 }
@@ -742,6 +748,7 @@ static CORE_ADDR
 needs_frame_frame_cfa (void *baton)
 {
   struct needs_frame_baton *nf_baton = baton;
+
   nf_baton->needs_frame = 1;
   return 1;
 }
@@ -751,6 +758,7 @@ static CORE_ADDR
 needs_frame_tls_address (void *baton, CORE_ADDR offset)
 {
   struct needs_frame_baton *nf_baton = baton;
+
   nf_baton->needs_frame = 1;
   return 1;
 }
@@ -907,6 +915,7 @@ locexpr_read_variable (struct symbol *sy
 {
   struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
   struct value *val;
+
   val = dwarf2_evaluate_loc_desc (SYMBOL_TYPE (symbol), frame, dlbaton->data,
 				  dlbaton->size, dlbaton->per_cu);
 
@@ -918,6 +927,7 @@ static int
 locexpr_read_needs_frame (struct symbol *symbol)
 {
   struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
+
   return dwarf2_loc_desc_needs_frame (dlbaton->data, dlbaton->size,
 				      dlbaton->per_cu);
 }

gdb-bz589467-pieces1of4.patch:
 dwarf2loc.c                     |  136 ++-
 testsuite/gdb.dwarf2/pieces.S   | 1655 ++++++++++++++++++++++++++++++++++++++++
 testsuite/gdb.dwarf2/pieces.c   |   98 ++
 testsuite/gdb.dwarf2/pieces.exp |   57 +
 4 files changed, 1919 insertions(+), 27 deletions(-)

--- NEW FILE gdb-bz589467-pieces1of4.patch ---
http://sourceware.org/ml/gdb-cvs/2010-05/msg00186.html

### src/gdb/ChangeLog	2010/05/21 20:34:45	1.11828
### src/gdb/ChangeLog	2010/05/21 20:39:50	1.11829
## -1,3 +1,9 @@
+2010-05-21  Tom Tromey  <tromey at redhat.com>
+
+	* dwarf2loc.c (read_pieced_value): Work properly when 'v' has an
+	offset.
+	(write_pieced_value): Likewise.
+
### src/gdb/testsuite/ChangeLog	2010/05/20 19:18:57	1.2272
### src/gdb/testsuite/ChangeLog	2010/05/21 20:39:50	1.2273
## -1,3 +1,9 @@
+2010-05-21  Tom Tromey  <tromey at redhat.com>
+
+	* gdb.dwarf2.pieces.exp: New file.
+	* gdb.dwarf2.pieces.S: New file.
+	* gdb.dwarf2.pieces.c: New file.
+
--- src/gdb/dwarf2loc.c	2010/05/14 17:53:16	1.78
+++ src/gdb/dwarf2loc.c	2010/05/21 20:39:50	1.79
@@ -264,14 +264,46 @@
 {
   int i;
   long offset = 0;
+  ULONGEST bytes_to_skip;
   gdb_byte *contents;
   struct piece_closure *c = (struct piece_closure *) value_computed_closure (v);
   struct frame_info *frame = frame_find_by_id (VALUE_FRAME_ID (v));
+  size_t type_len;
+
+  if (value_type (v) != value_enclosing_type (v))
+    internal_error (__FILE__, __LINE__,
+		    _("Should not be able to create a lazy value with "
+		      "an enclosing type"));
 
   contents = value_contents_raw (v);
-  for (i = 0; i < c->n_pieces; i++)
+  bytes_to_skip = value_offset (v);
+  type_len = TYPE_LENGTH (value_type (v));
+  for (i = 0; i < c->n_pieces && offset < type_len; i++)
     {
       struct dwarf_expr_piece *p = &c->pieces[i];
+      size_t this_size;
+      long dest_offset, source_offset;
+
+      if (bytes_to_skip > 0 && bytes_to_skip >= p->size)
+	{
+	  bytes_to_skip -= p->size;
+	  continue;
+	}
+      this_size = p->size;
+      if (this_size > type_len - offset)
+	this_size = type_len - offset;
+      if (bytes_to_skip > 0)
+	{
+	  dest_offset = 0;
+	  source_offset = bytes_to_skip;
+	  this_size -= bytes_to_skip;
+	  bytes_to_skip = 0;
+	}
+      else
+	{
+	  dest_offset = offset;
+	  source_offset = 0;
+	}
 
       switch (p->location)
 	{
@@ -280,17 +312,17 @@
 	    struct gdbarch *arch = get_frame_arch (frame);
 	    int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch,
 							   p->v.expr.value);
-	    int reg_offset = 0;
+	    int reg_offset = source_offset;
 
 	    if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG
-		&& p->size < register_size (arch, gdb_regnum))
+		&& this_size < register_size (arch, gdb_regnum))
 	      /* Big-endian, and we want less than full size.  */
-	      reg_offset = register_size (arch, gdb_regnum) - p->size;
+	      reg_offset = register_size (arch, gdb_regnum) - this_size;
 
 	    if (gdb_regnum != -1)
 	      {
 		get_frame_register_bytes (frame, gdb_regnum, reg_offset, 
-					  p->size, contents + offset);
+					  this_size, contents + dest_offset);
 	      }
 	    else
 	      {
@@ -302,38 +334,60 @@
 
 	case DWARF_VALUE_MEMORY:
 	  if (p->v.expr.in_stack_memory)
-	    read_stack (p->v.expr.value, contents + offset, p->size);
+	    read_stack (p->v.expr.value + source_offset,
+			contents + dest_offset, this_size);
 	  else
-	    read_memory (p->v.expr.value, contents + offset, p->size);
+	    read_memory (p->v.expr.value + source_offset,
+			 contents + dest_offset, this_size);
 	  break;
 
 	case DWARF_VALUE_STACK:
 	  {
 	    struct gdbarch *gdbarch = get_type_arch (value_type (v));
-	    size_t n = p->size;
+	    size_t n = this_size;
+
+	    if (n > c->addr_size - source_offset)
+	      n = (c->addr_size >= source_offset
+		   ? c->addr_size - source_offset
+		   : 0);
+	    if (n == 0)
+	      {
+		/* Nothing.  */
+	      }
+	    else if (source_offset == 0)
+	      store_unsigned_integer (contents + dest_offset, n,
+				      gdbarch_byte_order (gdbarch),
+				      p->v.expr.value);
+	    else
+	      {
+		gdb_byte bytes[sizeof (ULONGEST)];
 
-	    if (n > c->addr_size)
-	      n = c->addr_size;
-	    store_unsigned_integer (contents + offset, n,
-				    gdbarch_byte_order (gdbarch),
-				    p->v.expr.value);
+		store_unsigned_integer (bytes, n + source_offset,
+					gdbarch_byte_order (gdbarch),
+					p->v.expr.value);
+		memcpy (contents + dest_offset, bytes + source_offset, n);
+	      }
 	  }
 	  break;
 
 	case DWARF_VALUE_LITERAL:
 	  {
-	    size_t n = p->size;
+	    size_t n = this_size;
 
-	    if (n > p->v.literal.length)
-	      n = p->v.literal.length;
-	    memcpy (contents + offset, p->v.literal.data, n);
+	    if (n > p->v.literal.length - source_offset)
+	      n = (p->v.literal.length >= source_offset
+		   ? p->v.literal.length - source_offset
+		   : 0);
+	    if (n != 0)
+	      memcpy (contents + dest_offset,
+		      p->v.literal.data + source_offset, n);
 	  }
 	  break;
 
 	default:
 	  internal_error (__FILE__, __LINE__, _("invalid location type"));
 	}
-      offset += p->size;
+      offset += this_size;
     }
 }
 
@@ -342,9 +396,11 @@
 {
   int i;
   long offset = 0;
-  gdb_byte *contents;
+  ULONGEST bytes_to_skip;
+  const gdb_byte *contents;
   struct piece_closure *c = (struct piece_closure *) value_computed_closure (to);
   struct frame_info *frame = frame_find_by_id (VALUE_FRAME_ID (to));
+  size_t type_len;
 
   if (frame == NULL)
     {
@@ -352,10 +408,35 @@
       return;
     }
 
-  contents = value_contents_raw (from);
-  for (i = 0; i < c->n_pieces; i++)
+  contents = value_contents (from);
+  bytes_to_skip = value_offset (to);
+  type_len = TYPE_LENGTH (value_type (to));
+  for (i = 0; i < c->n_pieces && offset < type_len; i++)
     {
       struct dwarf_expr_piece *p = &c->pieces[i];
+      size_t this_size;
+      long dest_offset, source_offset;
+
+      if (bytes_to_skip > 0 && bytes_to_skip >= p->size)
+	{
+	  bytes_to_skip -= p->size;
+	  continue;
+	}
[...1676 lines suppressed...]
+	.ascii "f4\0"	# external name
+	.long	0x189	# DIE offset
+	.ascii "f5\0"	# external name
+	.long	0x1bf	# DIE offset
+	.ascii "main\0"	# external name
+	.long	0
+	.section	.debug_pubtypes,"", at progbits
+	.long	0x1a	# Length of Public Type Names Info
+	.value	0x2	# DWARF Version
+	.long	.Ldebug_info0	# Offset of Compilation Unit Info
+	.long	0x1e7	# Compilation Unit Length
+	.long	0x25	# DIE offset
+	.ascii "A\0"	# external name
+	.long	0x4f	# DIE offset
+	.ascii "B\0"	# external name
+	.long	0
+	.section	.debug_aranges,"", at progbits
+	.long	0x1c	# Length of Address Ranges Info
+	.value	0x2	# DWARF Version
+	.long	.Ldebug_info0	# Offset of Compilation Unit Info
+	.byte	0x4	# Size of Address
+	.byte	0	# Size of Segment Descriptor
+	.value	0	# Pad to 8 byte boundary
+	.value	0
+	.long	.Ltext0	# Address
+	.long	.Letext0-.Ltext0	# Length
+	.long	0
+	.long	0
+	.section	.debug_str,"MS", at 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]"
+.LASF0:
+	.string	"main"
+	.ident	"GCC: (GNU) 4.6.0 20100506 (experimental) [trunk revision 159117]"
+	.section	.note.GNU-stack,"", at progbits
--- src/gdb/testsuite/gdb.dwarf2/pieces.c
+++ src/gdb/testsuite/gdb.dwarf2/pieces.c	2010-05-25 20:18:00.627622000 +0000
@@ -0,0 +1,98 @@
+/* Copyright (C) 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* The original program corresponding to pieces.S.
+   This came from https://bugzilla.redhat.com/show_bug.cgi?id=589467
+   Note that it is not ever compiled, pieces.S is used instead.
+   However, it is used to extract breakpoint line numbers.  */
+
+struct A { int i; int j; };
+struct B { int : 4; int i : 12; int j : 12; int : 4; };
+
+__attribute__((noinline)) void
+bar (int x)
+{
+  asm volatile ("" : : "r" (x) : "memory");
+}
+
+__attribute__((noinline)) int
+f1 (int k)
+{
+  struct A a = { 4, k + 6 };
+  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;	/* f1 breakpoint */
+}
+
+__attribute__((noinline)) int
+f2 (int k)
+{
+  int a[2] = { 4, k + 6 };
+  asm ("" : "+r" (a[0]));
+  a[1]++;
+  bar (a[0]);		/* { dg-final { gdb-test 31 "a\[0\]" "4" } } */
+  bar (a[1]);		/* { dg-final { gdb-test 31 "a\[1\]" "14" } } */
+  return a[0] + a[1];	/* f2 breakpoint */
+}
+
+__attribute__((noinline)) int
+f3 (int k)
+{
+  struct B a = { 4, k + 6 };
+  asm ("" : "+r" (a.i));
+  a.j++;
+  bar (a.i);		/* { dg-final { gdb-test 42 "a.i" "4" } } */
+  bar (a.j);		/* { dg-final { gdb-test 42 "a.j" "14" } } */
+  return a.i + a.j;	/* f3 breakpoint */
+}
+
+__attribute__((noinline)) int
+f4 (int k)
+{
+  int a[2] = { k, k };
+  asm ("" : "+r" (a[0]));
+  a[1]++;
+  bar (a[0]);
+  bar (a[1]);
+  return a[0] + a[1];		/* f4 breakpoint */
+}
+
+__attribute__((noinline)) int
+f5 (int k)
+{
+  struct A a = { k, k };
+  asm ("" : "+r" (a.i));
+  a.j++;
+  bar (a.i);
+  bar (a.j);
+  return a.i + a.j;		/* f5 breakpoint */
+}
+
+int
+main (void)
+{
+  int k;
+  asm ("" : "=r" (k) : "0" (7));
+  f1 (k);
+  f2 (k);
+  f3 (k);
+  f4 (k);
+  f5 (k);
+  return 0;
+}
--- src/gdb/testsuite/gdb.dwarf2/pieces.exp
+++ src/gdb/testsuite/gdb.dwarf2/pieces.exp	2010-05-25 20:18:03.961111000 +0000
@@ -0,0 +1,57 @@
+# Copyright 2010 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test some DWARF piece operators.
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+# For now pick a sampling of likely targets.
+if {![istarget *-*-linux*]
+    && ![istarget *-*-gnu*]
+    && ![istarget *-*-elf*]
+    && ![istarget *-*-openbsd*]
+    && ![istarget arm-*-eabi*]
+    && ![istarget powerpc-*-eabi*]} {
+    return 0  
+}
+# This test can only be run on x86 targets.
+if {![istarget i?86-*]} {
+    return 0  
+}
+
+set testfile "pieces"
+set srcfile ${testfile}.S
+set csrcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}.x
+
+if {[prepare_for_testing ${testfile}.exp ${testfile}.x $srcfile]} {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
+}
+
+# Function f1 tests a particular gdb bug involving DW_OP_piece.
+proc pieces_test_f1 {} {
+    global csrcfile
+    set line [gdb_get_line_number "f1 breakpoint" $csrcfile]
+    gdb_test "break pieces.c:$line" "Breakpoint 2.*" \
+	"set f1 breakpoint for pieces"
+    gdb_continue_to_breakpoint "continue to f1 breakpoint for pieces"
+    gdb_test "print a" " = {i = 4, j = 14}" "print a in pieces:f1"
+    gdb_test "print a.j" " = 14" "print a.j in pieces:f1"
+}
+
+pieces_test_f1

gdb-bz589467-pieces2of4.patch:
 eval.c                          |    4 ++--
 testsuite/gdb.dwarf2/pieces.exp |   14 ++++++++++++++
 2 files changed, 16 insertions(+), 2 deletions(-)

--- NEW FILE gdb-bz589467-pieces2of4.patch ---
http://sourceware.org/ml/gdb-cvs/2010-05/msg00188.html
http://sourceware.org/ml/gdb-cvs/2010-05/msg00189.html

### src/gdb/ChangeLog	2010/05/21 20:45:18	1.11830
### src/gdb/ChangeLog	2010/05/21 20:56:48	1.11831
## -1,3 +1,8 @@
+2010-05-21  Tom Tromey  <tromey at redhat.com>
+
+	* eval.c (evaluate_subexp_standard) <BINOP_SUBSCRIPT>: Call
+	evaluate_subexp, not evaluate_subexp_with_coercion.
+
### src/gdb/testsuite/ChangeLog	2010/05/21 20:39:50	1.2273
### src/gdb/testsuite/ChangeLog	2010/05/21 20:56:49	1.2274
## -1,5 +1,10 @@
 2010-05-21  Tom Tromey  <tromey at redhat.com>
 
+	* gdb.dwarf2/pieces.exp (pieces_test_f2): New proc.
+	Call it.
+
--- src/gdb/eval.c	2010/05/14 18:35:11	1.134
+++ src/gdb/eval.c	2010/05/21 20:56:49	1.135
@@ -2059,8 +2059,8 @@
       error (_("':' operator used in invalid context"));
 
     case BINOP_SUBSCRIPT:
-      arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
-      arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
       if (noside == EVAL_SKIP)
 	goto nosideret;
       if (binop_user_defined_p (op, arg1, arg2))
--- src/gdb/testsuite/gdb.dwarf2/pieces.exp	2010/05/21 20:39:50	1.1
+++ src/gdb/testsuite/gdb.dwarf2/pieces.exp	2010/05/21 21:00:27	1.2
@@ -54,4 +54,18 @@
     gdb_test "print a.j" " = 14" "print a.j in pieces:f1"
 }
 
+# Function f2 tests for a bug when indexing into an array created
+# using DW_OP_piece.
+proc pieces_test_f2 {} {
+    global csrcfile
+    set line [gdb_get_line_number "f2 breakpoint" $csrcfile]
+    gdb_test "break pieces.c:$line" "Breakpoint 3.*" \
+       "set f2 breakpoint for pieces"
+    gdb_continue_to_breakpoint "continue to f2 breakpoint for pieces"
+    gdb_test "print a" " = .4, 14." "print a in pieces:f2"
+    gdb_test "print a\[0\]" " = 4" "print a\[0\] in pieces:f2"
+    gdb_test "print a\[1\]" " = 14" "print a\[1\] in pieces:f2"
+}
+
 pieces_test_f1
+pieces_test_f2

gdb-bz589467-pieces3of4.patch:
 dwarf2expr.c                    |   20 +
 dwarf2expr.h                    |    5 
 dwarf2loc.c                     |   13 
 testsuite/gdb.dwarf2/pieces.S   |  636 +++++++++++++++++++++++++++-------------
 testsuite/gdb.dwarf2/pieces.c   |   14 
 testsuite/gdb.dwarf2/pieces.exp |   23 +
 6 files changed, 512 insertions(+), 199 deletions(-)

--- NEW FILE gdb-bz589467-pieces3of4.patch ---
http://sourceware.org/ml/gdb-cvs/2010-05/msg00190.html

### src/gdb/ChangeLog	2010/05/21 20:56:48	1.11831
### src/gdb/ChangeLog	2010/05/21 21:01:46	1.11832
## -1,5 +1,16 @@
 2010-05-21  Tom Tromey  <tromey at 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.
+
### src/gdb/testsuite/ChangeLog	2010/05/21 20:56:49	1.2274
### src/gdb/testsuite/ChangeLog	2010/05/21 21:01:46	1.2275
## -1,5 +1,13 @@
 2010-05-21  Tom Tromey  <tromey at 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.
+
--- src/gdb/dwarf2expr.c	2010/05/14 17:53:16	1.42
+++ src/gdb/dwarf2expr.c	2010/05/21 21:01:46	1.43
@@ -143,6 +143,14 @@
 
 }
 
+/* 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)
@@ -167,6 +175,15 @@
       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);
@@ -859,7 +876,8 @@
 
             /* 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;
           }
--- src/gdb/dwarf2expr.h	2010/01/01 07:31:30	1.20
+++ src/gdb/dwarf2expr.h	2010/05/21 21:01:46	1.21
@@ -38,7 +38,10 @@
   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.  */
--- src/gdb/dwarf2loc.c	2010/05/21 20:39:50	1.79
+++ src/gdb/dwarf2loc.c	2010/05/21 21:01:46	1.80
@@ -384,6 +384,16 @@
 	  }
 	  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"));
 	}
@@ -609,6 +619,9 @@
 	  }
 	  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"));
 	}
--- src/gdb/testsuite/gdb.dwarf2/pieces.S	2010/05/21 20:39:50	1.1
+++ src/gdb/testsuite/gdb.dwarf2/pieces.S	2010/05/21 21:01:46	1.2
@@ -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 @@
 	.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 @@
 .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 @@
 	.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 @@
 .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 @@
 	.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 @@
 	.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 @@
 .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 @@
 	.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 @@
 .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 @@
 .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,"", at progbits
@@ -649,20 +707,57 @@
 	.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 @@
 	.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 @@
 	.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 @@
 	.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 @@
 	.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 @@
 	.byte	0
 	.byte	0
 	.section	.debug_pubnames,"", at 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,"", at 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,"", at progbits
 	.long	0x1c	# Length of Address Ranges Info
--- src/gdb/testsuite/gdb.dwarf2/pieces.c	2010/05/21 20:39:50	1.1
+++ src/gdb/testsuite/gdb.dwarf2/pieces.c	2010/05/21 21:01:46	1.2
@@ -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 @@
   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 @@
   f3 (k);
   f4 (k);
   f5 (k);
+  f6 (k);
   return 0;
 }
--- src/gdb/testsuite/gdb.dwarf2/pieces.exp	2010/05/21 21:00:27	1.2
+++ src/gdb/testsuite/gdb.dwarf2/pieces.exp	2010/05/21 21:01:46	1.3
@@ -67,5 +67,28 @@
     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

gdb-bz589467-pieces4of4.patch:
 dwarf2expr.c                    |   38 +++-
 dwarf2expr.h                    |    6 
 dwarf2loc.c                     |  367 ++++++++++++++++++++++++++++++++++------
 testsuite/gdb.dwarf2/pieces.S   |   54 ++---
 testsuite/gdb.dwarf2/pieces.c   |    4 
 testsuite/gdb.dwarf2/pieces.exp |   20 +-
 6 files changed, 384 insertions(+), 105 deletions(-)

--- NEW FILE gdb-bz589467-pieces4of4.patch ---
http://sourceware.org/ml/gdb-cvs/2010-05/msg00191.html

### src/gdb/ChangeLog	2010/05/21 21:01:46	1.11832
### src/gdb/ChangeLog	2010/05/21 21:13:10	1.11833
## -1,5 +1,20 @@
 2010-05-21  Tom Tromey  <tromey at redhat.com>
 
+	* dwarf2loc.c (extract_bits_primitive): New function.
+	(extract_bits): Likewise.
+	(insert_bits): Likewise.
+	(copy_bitwise): Likewise.
+	(read_pieced_value): Do all operations in bits.
+	(write_pieced_value): Likewise.
+	* dwarf2expr.h (struct dwarf_expr_piece) <offset>: New field.
+	* dwarf2expr.c (add_piece): New arguments bit_piece, offset.
+	Always use xrealloc to resize piece array.
+	(execute_stack_op) <DW_OP_reg0>: Handle DW_OP_bit_piece.
+	<DW_OP_piece>: Update.
+	<DW_OP_bit_piece>: New case.
+
### src/gdb/testsuite/ChangeLog	2010/05/21 21:01:46	1.2275
### src/gdb/testsuite/ChangeLog	2010/05/21 21:13:13	1.2276
## -1,5 +1,12 @@
 2010-05-21  Tom Tromey  <tromey at redhat.com>
 
+	* gdb.dwarf2/pieces.exp (pieces_test_f3): New proc.
+	Call it.
+	* gdb.dwarf2/pieces.S: Update.
+	* gdb.dwarf2/pieces.c (struct B): Remove initial field.
+
--- src/gdb/dwarf2expr.c	2010/05/21 21:01:46	1.43
+++ src/gdb/dwarf2expr.c	2010/05/21 21:13:10	1.44
@@ -153,23 +153,21 @@
 
 /* Add a new piece to CTX's piece list.  */
 static void
-add_piece (struct dwarf_expr_context *ctx, ULONGEST size)
+add_piece (struct dwarf_expr_context *ctx, ULONGEST size, ULONGEST offset)
 {
   struct dwarf_expr_piece *p;
 
   ctx->num_pieces++;
 
-  if (ctx->pieces)
-    ctx->pieces = xrealloc (ctx->pieces,
-                            (ctx->num_pieces
-                             * sizeof (struct dwarf_expr_piece)));
-  else
-    ctx->pieces = xmalloc (ctx->num_pieces
-                           * sizeof (struct dwarf_expr_piece));
+  ctx->pieces = xrealloc (ctx->pieces,
+			  (ctx->num_pieces
+			   * sizeof (struct dwarf_expr_piece)));
 
   p = &ctx->pieces[ctx->num_pieces - 1];
   p->location = ctx->location;
   p->size = size;
+  p->offset = offset;
+
   if (p->location == DWARF_VALUE_LITERAL)
     {
       p->v.literal.data = ctx->data;
@@ -499,9 +497,11 @@
 	case DW_OP_reg31:
 	  if (op_ptr != op_end 
 	      && *op_ptr != DW_OP_piece
+	      && *op_ptr != DW_OP_bit_piece
 	      && *op_ptr != DW_OP_GNU_uninit)
 	    error (_("DWARF-2 expression error: DW_OP_reg operations must be "
-		   "used either alone or in conjuction with DW_OP_piece."));
+		     "used either alone or in conjuction with DW_OP_piece "
+		     "or DW_OP_bit_piece."));
 
 	  result = op - DW_OP_reg0;
 	  ctx->location = DWARF_VALUE_REGISTER;
@@ -872,7 +872,7 @@
 
             /* Record the piece.  */
             op_ptr = read_uleb128 (op_ptr, op_end, &size);
-	    add_piece (ctx, size);
+	    add_piece (ctx, 8 * size, 0);
 
             /* Pop off the address/regnum, and reset the location
 	       type.  */
@@ -883,6 +883,24 @@
           }
           goto no_push;
 
+	case DW_OP_bit_piece:
+	  {
+	    ULONGEST size, offset;
+
+            /* Record the piece.  */
+	    op_ptr = read_uleb128 (op_ptr, op_end, &size);
+	    op_ptr = read_uleb128 (op_ptr, op_end, &offset);
+	    add_piece (ctx, size, offset);
+
+            /* Pop off the address/regnum, and reset the location
+	       type.  */
+	    if (ctx->location != DWARF_VALUE_LITERAL
+		&& ctx->location != DWARF_VALUE_OPTIMIZED_OUT)
+	      dwarf_expr_pop (ctx);
+            ctx->location = DWARF_VALUE_MEMORY;
+	  }
+	  goto no_push;
+
 	case DW_OP_GNU_uninit:
 	  if (op_ptr != op_end)
 	    error (_("DWARF-2 expression error: DW_OP_GNU_uninit must always "
--- src/gdb/dwarf2expr.h	2010/05/21 21:01:46	1.21
+++ src/gdb/dwarf2expr.h	2010/05/21 21:13:11	1.22
@@ -155,7 +155,7 @@
 };
 
 
-/* A piece of an object, as recorded by DW_OP_piece.  */
+/* A piece of an object, as recorded by DW_OP_piece or DW_OP_bit_piece.  */
 struct dwarf_expr_piece
 {
   enum dwarf_value_location location;
@@ -181,8 +181,10 @@
     } literal;
   } v;
 
-  /* The length of the piece, in bytes.  */
+  /* The length of the piece, in bits.  */
   ULONGEST size;
+  /* The piece offset, in bits.  */
+  ULONGEST offset;
 };
 
 struct dwarf_expr_context *new_dwarf_expr_context (void);
--- src/gdb/dwarf2loc.c	2010/05/21 21:01:46	1.80
+++ src/gdb/dwarf2loc.c	2010/05/21 21:13:11	1.81
@@ -259,52 +259,245 @@
   return c;
 }
 
+/* The lowest-level function to extract bits from a byte buffer.
+   SOURCE is the buffer.  It is updated if we read to the end of a
+   byte.
+   SOURCE_OFFSET_BITS is the offset of the first bit to read.  It is
+   updated to reflect the number of bits actually read.
+   NBITS is the number of bits we want to read.  It is updated to
+   reflect the number of bits actually read.  This function may read
+   fewer bits.
+   BITS_BIG_ENDIAN is taken directly from gdbarch.
+   This function returns the extracted bits.  */
+
+static unsigned int
+extract_bits_primitive (const gdb_byte **source,
+			unsigned int *source_offset_bits,
+			int *nbits, int bits_big_endian)
+{
+  unsigned int avail, mask, datum;
+
+  gdb_assert (*source_offset_bits < 8);
+
+  avail = 8 - *source_offset_bits;
+  if (avail > *nbits)
+    avail = *nbits;
+
+  mask = (1 << avail) - 1;
+  datum = **source;
+  if (bits_big_endian)
+    datum >>= 8 - (*source_offset_bits + *nbits);
+  else
+    datum >>= *source_offset_bits;
+  datum &= mask;
+
+  *nbits -= avail;
+  *source_offset_bits += avail;
+  if (*source_offset_bits >= 8)
+    {
+      *source_offset_bits -= 8;
+      ++*source;
+    }
+
+  return datum;
+}
+
+/* Extract some bits from a source buffer and move forward in the
+   buffer.
+   
+   SOURCE is the source buffer.  It is updated as bytes are read.
+   SOURCE_OFFSET_BITS is the offset into SOURCE.  It is updated as
+   bits are read.
+   NBITS is the number of bits to read.
+   BITS_BIG_ENDIAN is taken directly from gdbarch.
+   
+   This function returns the bits that were read.  */
+
+static unsigned int
+extract_bits (const gdb_byte **source, unsigned int *source_offset_bits,
+	      int nbits, int bits_big_endian)
+{
+  unsigned int datum;
+
+  gdb_assert (nbits > 0 && nbits <= 8);
+
+  datum = extract_bits_primitive (source, source_offset_bits, &nbits,
+				  bits_big_endian);
+  if (nbits > 0)
+    {
+      unsigned int more;
+
+      more = extract_bits_primitive (source, source_offset_bits, &nbits,
+				     bits_big_endian);
+      if (bits_big_endian)
+	datum <<= nbits;
+      else
+	more <<= nbits;
+      datum |= more;
+    }
+
+  return datum;
+}
+
+/* Write some bits into a buffer and move forward in the buffer.
+   
+   DATUM is the bits to write.  The low-order bits of DATUM are used.
+   DEST is the destination buffer.  It is updated as bytes are
+   written.
+   DEST_OFFSET_BITS is the bit offset in DEST at which writing is
+   done.
+   NBITS is the number of valid bits in DATUM.
+   BITS_BIG_ENDIAN is taken directly from gdbarch.  */
+
+static void
+insert_bits (unsigned int datum,
+	     gdb_byte *dest, unsigned int dest_offset_bits,
+	     int nbits, int bits_big_endian)
+{
+  unsigned int mask;
+
+  gdb_assert (dest_offset_bits >= 0 && dest_offset_bits + nbits <= 8);
+
+  mask = (1 << nbits) - 1;
+  if (bits_big_endian)
+    {
+      datum <<= 8 - (dest_offset_bits + nbits);
+      mask <<= 8 - (dest_offset_bits + nbits);
+    }
+  else
+    {
+      datum <<= dest_offset_bits;
+      mask <<= dest_offset_bits;
+    }
+
+  gdb_assert ((datum & ~mask) == 0);
+
+  *dest = (*dest & ~mask) | datum;
+}
+
+/* Copy bits from a source to a destination.
+   
+   DEST is where the bits should be written.
+   DEST_OFFSET_BITS is the bit offset into DEST.
+   SOURCE is the source of bits.
+   SOURCE_OFFSET_BITS is the bit offset into SOURCE.
+   BIT_COUNT is the number of bits to copy.
+   BITS_BIG_ENDIAN is taken directly from gdbarch.  */
+
+static void
+copy_bitwise (gdb_byte *dest, unsigned int dest_offset_bits,
+	      const gdb_byte *source, unsigned int source_offset_bits,
+	      unsigned int bit_count,
+	      int bits_big_endian)
+{
+  unsigned int dest_avail;
+  int datum;
+
+  /* Reduce everything to byte-size pieces.  */
+  dest += dest_offset_bits / 8;
+  dest_offset_bits %= 8;
+  source += source_offset_bits / 8;
+  source_offset_bits %= 8;
+
+  dest_avail = 8 - dest_offset_bits % 8;
+
+  /* See if we can fill the first destination byte.  */
+  if (dest_avail < bit_count)
+    {
+      datum = extract_bits (&source, &source_offset_bits, dest_avail,
+			    bits_big_endian);
+      insert_bits (datum, dest, dest_offset_bits, dest_avail, bits_big_endian);
+      ++dest;
+      dest_offset_bits = 0;
+      bit_count -= dest_avail;
+    }
+
+  /* Now, either DEST_OFFSET_BITS is byte-aligned, or we have fewer
+     than 8 bits remaining.  */
+  gdb_assert (dest_offset_bits % 8 == 0 || bit_count < 8);
+  for (; bit_count >= 8; bit_count -= 8)
+    {
+      datum = extract_bits (&source, &source_offset_bits, 8, bits_big_endian);
+      *dest++ = (gdb_byte) datum;
+    }
+
+  /* Finally, we may have a few leftover bits.  */
+  gdb_assert (bit_count <= 8 - dest_offset_bits % 8);
+  if (bit_count > 0)
+    {
+      datum = extract_bits (&source, &source_offset_bits, bit_count,
+			    bits_big_endian);
+      insert_bits (datum, dest, dest_offset_bits, bit_count, bits_big_endian);
+    }
+}
+
 static void
 read_pieced_value (struct value *v)
 {
   int i;
   long offset = 0;
-  ULONGEST bytes_to_skip;
+  ULONGEST bits_to_skip;
   gdb_byte *contents;
   struct piece_closure *c = (struct piece_closure *) value_computed_closure (v);
   struct frame_info *frame = frame_find_by_id (VALUE_FRAME_ID (v));
   size_t type_len;
+  size_t buffer_size = 0;
+  char *buffer = NULL;
+  struct cleanup *cleanup;
+  int bits_big_endian
+    = gdbarch_bits_big_endian (get_type_arch (value_type (v)));
 
   if (value_type (v) != value_enclosing_type (v))
     internal_error (__FILE__, __LINE__,
 		    _("Should not be able to create a lazy value with "
 		      "an enclosing type"));
 
+  cleanup = make_cleanup (free_current_contents, &buffer);
+
   contents = value_contents_raw (v);
-  bytes_to_skip = value_offset (v);
-  type_len = TYPE_LENGTH (value_type (v));
+  bits_to_skip = 8 * value_offset (v);
+  type_len = 8 * TYPE_LENGTH (value_type (v));
+
   for (i = 0; i < c->n_pieces && offset < type_len; i++)
     {
       struct dwarf_expr_piece *p = &c->pieces[i];
-      size_t this_size;
-      long dest_offset, source_offset;
-
-      if (bytes_to_skip > 0 && bytes_to_skip >= p->size)
+      size_t this_size, this_size_bits;
+      long dest_offset_bits, source_offset_bits, source_offset;
+      gdb_byte *intermediate_buffer;
+
+      /* Compute size, source, and destination offsets for copying, in
+	 bits.  */
+      this_size_bits = p->size;
+      if (bits_to_skip > 0 && bits_to_skip >= this_size_bits)
 	{
-	  bytes_to_skip -= p->size;
+	  bits_to_skip -= this_size_bits;
 	  continue;
 	}
-      this_size = p->size;
-      if (this_size > type_len - offset)
-	this_size = type_len - offset;
-      if (bytes_to_skip > 0)
-	{
-	  dest_offset = 0;
-	  source_offset = bytes_to_skip;
-	  this_size -= bytes_to_skip;
-	  bytes_to_skip = 0;
+      if (this_size_bits > type_len - offset)
+	this_size_bits = type_len - offset;
+      if (bits_to_skip > 0)
+	{
+	  dest_offset_bits = 0;
+	  source_offset_bits = bits_to_skip;
+	  this_size_bits -= bits_to_skip;
+	  bits_to_skip = 0;
 	}
       else
 	{
-	  dest_offset = offset;
-	  source_offset = 0;
+	  dest_offset_bits = offset;
+	  source_offset_bits = 0;
+	}
+
+      this_size = (this_size_bits + source_offset_bits % 8 + 7) / 8;
+      source_offset = source_offset_bits / 8;
+      if (buffer_size < this_size)
+	{
+	  buffer_size = this_size;
+	  buffer = xrealloc (buffer, buffer_size);
 	}
+      intermediate_buffer = buffer;
 
+      /* Copy from the source to DEST_BUFFER.  */
       switch (p->location)
 	{
 	case DWARF_VALUE_REGISTER:
@@ -316,13 +509,18 @@
 
 	    if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG
 		&& this_size < register_size (arch, gdb_regnum))
-	      /* Big-endian, and we want less than full size.  */
-	      reg_offset = register_size (arch, gdb_regnum) - this_size;
+	      {
+		/* Big-endian, and we want less than full size.  */
+		reg_offset = register_size (arch, gdb_regnum) - this_size;
+		/* We want the lower-order THIS_SIZE_BITS of the bytes
+		   we extract from the register.  */
+		source_offset_bits += 8 * this_size - this_size_bits;
+	      }
 
 	    if (gdb_regnum != -1)
 	      {
 		get_frame_register_bytes (frame, gdb_regnum, reg_offset, 
-					  this_size, contents + dest_offset);
+					  this_size, buffer);
 	      }
 	    else
 	      {
@@ -334,11 +532,9 @@
 
 	case DWARF_VALUE_MEMORY:
 	  if (p->v.expr.in_stack_memory)
-	    read_stack (p->v.expr.value + source_offset,
-			contents + dest_offset, this_size);
+	    read_stack (p->v.expr.value + source_offset, buffer, this_size);
 	  else
-	    read_memory (p->v.expr.value + source_offset,
-			 contents + dest_offset, this_size);
+	    read_memory (p->v.expr.value + source_offset, buffer, this_size);
 	  break;
 
 	case DWARF_VALUE_STACK:
@@ -355,7 +551,7 @@
 		/* Nothing.  */
 	      }
 	    else if (source_offset == 0)
-	      store_unsigned_integer (contents + dest_offset, n,
+	      store_unsigned_integer (buffer, n,
 				      gdbarch_byte_order (gdbarch),
 				      p->v.expr.value);
 	    else
@@ -365,7 +561,7 @@
 		store_unsigned_integer (bytes, n + source_offset,
 					gdbarch_byte_order (gdbarch),
 					p->v.expr.value);
-		memcpy (contents + dest_offset, bytes + source_offset, n);
+		memcpy (buffer, bytes + source_offset, n);
 	      }
 	  }
 	  break;
@@ -379,8 +575,7 @@
 		   ? p->v.literal.length - source_offset
 		   : 0);
 	    if (n != 0)
-	      memcpy (contents + dest_offset,
-		      p->v.literal.data + source_offset, n);
+	      intermediate_buffer = p->v.literal.data + source_offset;
 	  }
 	  break;
 
@@ -388,17 +583,25 @@
 	  /* 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; "
+	  warning (_("bits %ld-%ld in computed object were optimized out; "
 		     "replacing with zeroes"),
 		   offset,
-		   offset + (long) this_size);
+		   offset + (long) this_size_bits);
 	  break;
 
 	default:
 	  internal_error (__FILE__, __LINE__, _("invalid location type"));
 	}
-      offset += this_size;
+
+      if (p->location != DWARF_VALUE_OPTIMIZED_OUT)
+	copy_bitwise (contents, dest_offset_bits,
+		      intermediate_buffer, source_offset_bits % 8,
+		      this_size_bits, bits_big_endian);
+
+      offset += this_size_bits;
     }
+
+  do_cleanups (cleanup);
 }
 
 static void
@@ -406,11 +609,16 @@
 {
   int i;
   long offset = 0;
-  ULONGEST bytes_to_skip;
+  ULONGEST bits_to_skip;
   const gdb_byte *contents;
   struct piece_closure *c = (struct piece_closure *) value_computed_closure (to);
   struct frame_info *frame = frame_find_by_id (VALUE_FRAME_ID (to));
   size_t type_len;
+  size_t buffer_size = 0;
+  char *buffer = NULL;
+  struct cleanup *cleanup;
+  int bits_big_endian
+    = gdbarch_bits_big_endian (get_type_arch (value_type (to)));
 
   if (frame == NULL)
     {
@@ -418,34 +626,57 @@
       return;
     }
 
+  cleanup = make_cleanup (free_current_contents, &buffer);
+
   contents = value_contents (from);
-  bytes_to_skip = value_offset (to);
-  type_len = TYPE_LENGTH (value_type (to));
+  bits_to_skip = 8 * value_offset (to);
+  type_len = 8 * TYPE_LENGTH (value_type (to));
   for (i = 0; i < c->n_pieces && offset < type_len; i++)
     {
       struct dwarf_expr_piece *p = &c->pieces[i];
-      size_t this_size;
-      long dest_offset, source_offset;
+      size_t this_size_bits, this_size;
+      long dest_offset_bits, source_offset_bits, dest_offset, source_offset;
+      int need_bitwise;
+      const gdb_byte *source_buffer;
 
-      if (bytes_to_skip > 0 && bytes_to_skip >= p->size)
+      this_size_bits = p->size;
+      if (bits_to_skip > 0 && bits_to_skip >= this_size_bits)
 	{
-	  bytes_to_skip -= p->size;
+	  bits_to_skip -= this_size_bits;
 	  continue;
 	}
-      this_size = p->size;
-      if (this_size > type_len - offset)
-	this_size = type_len - offset;
-      if (bytes_to_skip > 0)
-	{
-	  dest_offset = bytes_to_skip;
-	  source_offset = 0;
-	  this_size -= bytes_to_skip;
-	  bytes_to_skip = 0;
+      if (this_size_bits > type_len - offset)
+	this_size_bits = type_len - offset;
+      if (bits_to_skip > 0)
+	{
+	  dest_offset_bits = bits_to_skip;
+	  source_offset_bits = 0;
+	  this_size_bits -= bits_to_skip;
+	  bits_to_skip = 0;
+	}
+      else
+	{
+	  dest_offset_bits = 0;
+	  source_offset_bits = offset;
+	}
+
+      this_size = (this_size_bits + source_offset_bits % 8 + 7) / 8;
+      source_offset = source_offset_bits / 8;
+      dest_offset = dest_offset_bits / 8;
+      if (dest_offset_bits % 8 == 0 && source_offset_bits % 8 == 0)
+	{
+	  source_buffer = contents + source_offset;
+	  need_bitwise = 0;
 	}
       else
 	{
-	  dest_offset = 0;
-	  source_offset = offset;
+	  if (buffer_size < this_size)
+	    {
+	      buffer_size = this_size;
+	      buffer = xrealloc (buffer, buffer_size);
+	    }
+	  source_buffer = buffer;
+	  need_bitwise = 1;
 	}
 
       switch (p->location)
@@ -463,8 +694,18 @@
 
 	    if (gdb_regnum != -1)
 	      {
+		if (need_bitwise)
+		  {
+		    get_frame_register_bytes (frame, gdb_regnum, reg_offset,
+					      this_size, buffer);
+		    copy_bitwise (buffer, dest_offset_bits,
+				  contents, source_offset_bits,
+				  this_size_bits,
+				  bits_big_endian);
+		  }
+
 		put_frame_register_bytes (frame, gdb_regnum, reg_offset, 
-					  this_size, contents + source_offset);
+					  this_size, source_buffer);
 	      }
 	    else
 	      {
@@ -474,15 +715,31 @@
 	  }
 	  break;
 	case DWARF_VALUE_MEMORY:
+	  if (need_bitwise)
+	    {
+	      /* Only the first and last bytes can possibly have any
+		 bits reused.  */
+	      read_memory (p->v.expr.value + dest_offset, buffer, 1);
+	      read_memory (p->v.expr.value + dest_offset + this_size - 1,
+			   buffer + this_size - 1, 1);
+	      copy_bitwise (buffer, dest_offset_bits,
+			    contents, source_offset_bits,
+			    this_size_bits,
+			    bits_big_endian);
+	    }
+
 	  write_memory (p->v.expr.value + dest_offset,
-			contents + source_offset, this_size);
+			source_buffer, this_size);
 	  break;
 	default:
 	  set_value_optimized_out (to, 1);
-	  return;
+	  goto done;
 	}
-      offset += this_size;
+      offset += this_size_bits;
     }
+
+ done:
+  do_cleanups (cleanup);
 }
 
 static void *
--- src/gdb/testsuite/gdb.dwarf2/pieces.S	2010/05/21 21:01:46	1.2
+++ src/gdb/testsuite/gdb.dwarf2/pieces.S	2010/05/21 21:13:13	1.3
@@ -989,23 +989,18 @@
 .LLST6:
 	.long	.LVL13-.Ltext0	# Location list begin address (*.LLST6)
 	.long	.LVL14-.Ltext0	# Location list end address (*.LLST6)
-	.value	0xa	# Location expression size
-	.byte	0x9d	# DW_OP_bit_piece
-	.uleb128 0x4
-	.uleb128 0
+	.value	0x8	# Location expression size
 	.byte	0x34	# DW_OP_lit4
 	.byte	0x9f	# DW_OP_stack_value
 	.byte	0x9d	# DW_OP_bit_piece
 	.uleb128 0xc
 	.uleb128 0
-	.byte	0x93	# DW_OP_piece
-	.uleb128 0x2
-	.long	.LVL14-.Ltext0	# Location list begin address (*.LLST6)
-	.long	.LVL15-.Ltext0	# Location list end address (*.LLST6)
-	.value	0x15	# Location expression size
 	.byte	0x9d	# DW_OP_bit_piece
-	.uleb128 0x4
+	.uleb128 0x14
 	.uleb128 0
+	.long	.LVL14-.Ltext0	# Location list begin address (*.LLST6)
+	.long	.LVL15-.Ltext0	# Location list end address (*.LLST6)
+	.value	0x11	# Location expression size
 	.byte	0x34	# DW_OP_lit4
 	.byte	0x9f	# DW_OP_stack_value
 	.byte	0x9d	# DW_OP_bit_piece
@@ -1021,15 +1016,11 @@
 	.byte	0x9d	# DW_OP_bit_piece
 	.uleb128 0xc
 	.uleb128 0
-	.byte	0x9d	# DW_OP_bit_piece
-	.uleb128 0x4
-	.uleb128 0
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x1
 	.long	.LVL15-.Ltext0	# Location list begin address (*.LLST6)
 	.long	.LVL16-1-.Ltext0	# Location list end address (*.LLST6)
-	.value	0x14	# Location expression size
-	.byte	0x9d	# DW_OP_bit_piece
-	.uleb128 0x4
-	.uleb128 0
+	.value	0x10	# Location expression size
 	.byte	0x52	# DW_OP_reg2
 	.byte	0x9d	# DW_OP_bit_piece
 	.uleb128 0xc
@@ -1044,15 +1035,11 @@
 	.byte	0x9d	# DW_OP_bit_piece
 	.uleb128 0xc
 	.uleb128 0
-	.byte	0x9d	# DW_OP_bit_piece
-	.uleb128 0x4
-	.uleb128 0
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x1
 	.long	.LVL16-1-.Ltext0	# Location list begin address (*.LLST6)
 	.long	.LVL17-.Ltext0	# Location list end address (*.LLST6)
-	.value	0x14	# Location expression size
-	.byte	0x9d	# DW_OP_bit_piece
-	.uleb128 0x4
-	.uleb128 0
+	.value	0x10	# Location expression size
 	.byte	0x56	# DW_OP_reg6
 	.byte	0x9d	# DW_OP_bit_piece
 	.uleb128 0xc
@@ -1067,14 +1054,14 @@
 	.byte	0x9d	# DW_OP_bit_piece
 	.uleb128 0xc
 	.uleb128 0
-	.byte	0x9d	# DW_OP_bit_piece
-	.uleb128 0x4
-	.uleb128 0
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x1
 	.long	.LVL17-.Ltext0	# Location list begin address (*.LLST6)
 	.long	.LFE3-.Ltext0	# Location list end address (*.LLST6)
 	.value	0xf	# Location expression size
-	.byte	0x93	# DW_OP_piece
-	.uleb128 0x2
+	.byte	0x9d	# DW_OP_bit_piece
+	.uleb128 0xc
+	.uleb128 0
 	.byte	0x91	# DW_OP_fbreg
 	.sleb128 0
 	.byte	0x94	# DW_OP_deref_size
@@ -1085,9 +1072,8 @@
 	.byte	0x9d	# DW_OP_bit_piece
 	.uleb128 0xc
 	.uleb128 0
-	.byte	0x9d	# DW_OP_bit_piece
-	.uleb128 0x4
-	.uleb128 0
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x1
 	.long	0	# Location list terminator begin (*.LLST6)
 	.long	0	# Location list terminator end (*.LLST6)
 .LLST7:
@@ -1356,7 +1342,7 @@
 	.long	0x48	# DW_AT_type
 	.byte	0x4	# DW_AT_byte_size
 	.byte	0xc	# DW_AT_bit_size
-	.byte	0x10	# DW_AT_bit_offset
+	.byte	0x14	# DW_AT_bit_offset
 	.byte	0x2	# DW_AT_data_member_location
 	.byte	0x23	# DW_OP_plus_uconst
 	.uleb128 0
@@ -1367,7 +1353,7 @@
 	.long	0x48	# DW_AT_type
 	.byte	0x4	# DW_AT_byte_size
 	.byte	0xc	# DW_AT_bit_size
-	.byte	0x4	# DW_AT_bit_offset
+	.byte	0x8	# DW_AT_bit_offset
 	.byte	0x2	# DW_AT_data_member_location
 	.byte	0x23	# DW_OP_plus_uconst
 	.uleb128 0
--- src/gdb/testsuite/gdb.dwarf2/pieces.c	2010/05/21 21:01:46	1.2
+++ src/gdb/testsuite/gdb.dwarf2/pieces.c	2010/05/21 21:13:13	1.3
@@ -21,7 +21,7 @@
    However, it is used to extract breakpoint line numbers.  */
 
 struct A { int i; int j; };
-struct B { int : 4; int i : 12; int j : 12; int : 4; };
+struct B { int i : 12; int j : 12; int : 4; };
 struct C { int i; int j; int q; };
 
 __attribute__((noinline)) void
@@ -89,7 +89,7 @@
 f6 (int k)
 {
   int z = 23;
-  struct C a = { k, k, z};
+  struct C a = { k, k, z };
   asm ("" : "+r" (a.i));
   a.j++;
   bar (a.i);
--- src/gdb/testsuite/gdb.dwarf2/pieces.exp	2010/05/21 21:01:46	1.3
+++ src/gdb/testsuite/gdb.dwarf2/pieces.exp	2010/05/21 21:13:13	1.4
@@ -67,15 +67,30 @@
     gdb_test "print a\[1\]" " = 14" "print a\[1\] in pieces:f2"
 }
 
+# Function f3 tests DW_OP_bit_piece.
+proc pieces_test_f3 {} {
+    global csrcfile
+    set line [gdb_get_line_number "f3 breakpoint" $csrcfile]
+    gdb_test "break pieces.c:$line" "Breakpoint 4.*" \
+       "set f3 breakpoint for pieces"
+    gdb_continue_to_breakpoint "continue to f3 breakpoint for pieces"
+    gdb_test "print a.i" " = 4" "print a.i in pieces:f3"
+    gdb_test "print a.j" " = 14" "print a.j in pieces:f3"
+    # Right now gdb says "value optimized out" here, but that is wrong.
+    setup_kfail "no bug yet" *-*-*
+    gdb_test "print a.i = 7" " = 7" "set a.i in pieces:f3"
+    gdb_test "print a.i" " = 7" "print new a.i in pieces:f3"
+}
+
 # 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.*" \
+    gdb_test "break pieces.c:$line" "Breakpoint 5.*" \
        "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}" \
+	"warning: 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" \
@@ -91,4 +106,5 @@
 
 pieces_test_f1
 pieces_test_f2
+pieces_test_f3
 pieces_test_f6


Index: gdb.spec
===================================================================
RCS file: /cvs/pkgs/rpms/gdb/F-13/gdb.spec,v
retrieving revision 1.440
retrieving revision 1.441
diff -u -p -r1.440 -r1.441
--- gdb.spec	24 May 2010 18:38:44 -0000	1.440
+++ gdb.spec	30 May 2010 18:14:31 -0000	1.441
@@ -36,7 +36,7 @@ Version: 7.1
 
 # The release always contains a leading reserved number, start it at 1.
 # `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing.
-Release: 22%{?_with_upstream:.upstream}%{dist}
+Release: 23%{?_with_upstream:.upstream}%{dist}
 
 License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ and GPLv2+ with exceptions and GPL+ and LGPLv2+ and GFDL and BSD and Public Domain
 Group: Development/Debuggers
@@ -486,6 +486,19 @@ Patch461: gdb-bz594560-core-vs-process.p
 # Import fix of TUI layout internal error (BZ 595475).
 Patch462: gdb-bz595475-tui-layout.patch
 
+# Fix and support DW_OP_*piece (Tom Tromey, BZ 589467).
+Patch463: gdb-bz589467-pieces01of4.patch
+Patch464: gdb-bz589467-pieces02of4.patch
+Patch465: gdb-bz589467-pieces03of4.patch
+Patch466: gdb-bz589467-pieces1of4.patch
+Patch467: gdb-bz589467-pieces2of4.patch
+Patch468: gdb-bz589467-pieces3of4.patch
+Patch469: gdb-bz589467-pieces4of4.patch
+Patch471: gdb-bz589467-pieces-vla-compat.patch
+
+# Fix follow-exec for C++ programs (bugreported by Martin Stransky).
+Patch470: gdb-archer-next-over-throw-cxx-exec.patch
+
 BuildRequires: ncurses-devel%{?_isa} texinfo gettext flex bison expat-devel%{?_isa}
 Requires: readline%{?_isa}
 BuildRequires: readline-devel%{?_isa}
@@ -763,6 +776,15 @@ rm -f gdb/jv-exp.c gdb/m2-exp.c gdb/objc
 %patch460 -p1
 %patch461 -p1
 %patch462 -p1
+%patch463 -p1
+%patch464 -p1
+%patch465 -p1
+%patch466 -p1
+%patch467 -p1
+%patch468 -p1
+%patch469 -p1
+%patch471 -p1
+%patch470 -p1
 
 %patch415 -p1
 %patch393 -p1
@@ -1095,6 +1117,10 @@ fi
 %endif
 
 %changelog
+* Sun May 30 2010 Jan Kratochvil <jan.kratochvil at redhat.com> - 7.1-23.fc13
+- Fix and support DW_OP_*piece (Tom Tromey, BZ 589467).
+- Fix follow-exec for C++ programs (bugreported by Martin Stransky).
+
 * Mon May 24 2010 Jan Kratochvil <jan.kratochvil at redhat.com> - 7.1-22.fc13
 - Remove core file when starting a process (BZ 594560).
 - Fix lock up on loops in the solib chain (BZ 593926).



More information about the scm-commits mailing list