svn commit: r283029 - in head/contrib: gcc gdb/gdb

Sean Bruno sbruno at FreeBSD.org
Sun May 17 15:49:41 UTC 2015


Author: sbruno
Date: Sun May 17 15:49:38 2015
New Revision: 283029
URL: https://svnweb.freebsd.org/changeset/base/283029

Log:
  Update intree gdb/kgdb to handle 2 dwarf types:
  DW_OP_GNU_uninit
  DW_OP_piece
  
  This squashes the warnings about type 0x93 not known in kgdb when opening a kernel crash dump.
  
  Upstream refs:
  https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=87808bd699575a850139a1f916512ab7a47fd496
  https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=42be36b328ae784ae6981da7c7cab95b67ed7737
  https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=23572ecadc89af384c1804ad7692f32c55fbfc80
  
  Differential Revision:	https://reviews.freebsd.org/D2534
  Reviewed by:	emaste, jhb, davide

Modified:
  head/contrib/gcc/dwarf2.h
  head/contrib/gdb/gdb/c-valprint.c
  head/contrib/gdb/gdb/dwarf2expr.c
  head/contrib/gdb/gdb/dwarf2expr.h
  head/contrib/gdb/gdb/dwarf2loc.c
  head/contrib/gdb/gdb/dwarf2read.c
  head/contrib/gdb/gdb/value.h
  head/contrib/gdb/gdb/values.c

Modified: head/contrib/gcc/dwarf2.h
==============================================================================
--- head/contrib/gcc/dwarf2.h	Sun May 17 15:12:55 2015	(r283028)
+++ head/contrib/gcc/dwarf2.h	Sun May 17 15:49:38 2015	(r283029)
@@ -547,6 +547,7 @@ enum dwarf_location_atom
     DW_OP_bit_piece = 0x9d,
     /* GNU extensions.  */
     DW_OP_GNU_push_tls_address = 0xe0,
+    DW_OP_GNU_uninit     = 0xf0,
     /* HP extensions.  */
     DW_OP_HP_unknown     = 0xe0, /* Ouch, the same as GNU_push_tls_address.  */
     DW_OP_HP_is_value    = 0xe1,

Modified: head/contrib/gdb/gdb/c-valprint.c
==============================================================================
--- head/contrib/gdb/gdb/c-valprint.c	Sun May 17 15:12:55 2015	(r283028)
+++ head/contrib/gdb/gdb/c-valprint.c	Sun May 17 15:49:38 2015	(r283029)
@@ -559,6 +559,10 @@ c_value_print (struct value *val, struct
 	  fprintf_filtered (stream, ") ");
 	}
     }
+
+    if (!value_initialized (val))
+      fprintf_filtered (stream, " [uninitialized] ");
+
   if (objectprint && (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_CLASS))
     {
       /* Attempt to determine real type of object */

Modified: head/contrib/gdb/gdb/dwarf2expr.c
==============================================================================
--- head/contrib/gdb/gdb/dwarf2expr.c	Sun May 17 15:12:55 2015	(r283028)
+++ head/contrib/gdb/gdb/dwarf2expr.c	Sun May 17 15:49:38 2015	(r283029)
@@ -42,6 +42,8 @@ new_dwarf_expr_context (void)
   retval->stack_len = 0;
   retval->stack_allocated = 10;
   retval->stack = xmalloc (retval->stack_allocated * sizeof (CORE_ADDR));
+  retval->num_pieces = 0;
+  retval->pieces = 0;
   return retval;
 }
 
@@ -51,6 +53,7 @@ void
 free_dwarf_expr_context (struct dwarf_expr_context *ctx)
 {
   xfree (ctx->stack);
+  xfree (ctx->pieces);
   xfree (ctx);
 }
 
@@ -100,6 +103,29 @@ dwarf_expr_fetch (struct dwarf_expr_cont
 
 }
 
+/* Add a new piece to CTX's piece list.  */
+static void
+add_piece (struct dwarf_expr_context *ctx,
+           int in_reg, CORE_ADDR value, ULONGEST size)
+{
+  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));
+
+  p = &ctx->pieces[ctx->num_pieces - 1];
+  p->in_reg = in_reg;
+  p->value = value;
+  p->size = size;
+}
+
 /* Evaluate the expression at ADDR (LEN bytes long) using the context
    CTX.  */
 
@@ -230,6 +256,7 @@ execute_stack_op (struct dwarf_expr_cont
 		  unsigned char *op_end)
 {
   ctx->in_reg = 0;
+  ctx->initialized = 1;  /* Default is initialized.  */
 
   while (op_ptr < op_end)
     {
@@ -356,9 +383,12 @@ execute_stack_op (struct dwarf_expr_cont
 	case DW_OP_reg29:
 	case DW_OP_reg30:
 	case DW_OP_reg31:
-	  if (op_ptr != op_end && *op_ptr != DW_OP_piece)
-	    error ("DWARF-2 expression error: DW_OP_reg operations must be "
-		   "used either alone or in conjuction with DW_OP_piece.");
+ 	  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."));
 
 	  result = op - DW_OP_reg0;
 	  ctx->in_reg = 1;
@@ -661,6 +691,30 @@ execute_stack_op (struct dwarf_expr_cont
 	case DW_OP_nop:
 	  goto no_push;
 
+	case DW_OP_piece:
+	{
+	  ULONGEST size;
+	  CORE_ADDR addr_or_regnum;
+
+	  /* Record the piece.  */
+	  op_ptr = read_uleb128 (op_ptr, op_end, &size);
+          addr_or_regnum = dwarf_expr_fetch (ctx, 0);
+          add_piece (ctx, ctx->in_reg, addr_or_regnum, size);
+
+	  /* Pop off the address/regnum, and clear the in_reg flag.  */
+	  dwarf_expr_pop (ctx);
+	  ctx->in_reg = 0;
+	}
+	  goto no_push;
+
+       case DW_OP_GNU_uninit:
+         if (op_ptr != op_end)
+           error (_("DWARF-2 expression error: DW_OP_GNU_unint must always "
+                  "be the very last op."));
+
+         ctx->initialized = 0;
+         goto no_push;
+
 	default:
 	  error ("Unhandled dwarf expression opcode 0x%x", op);
 	}

Modified: head/contrib/gdb/gdb/dwarf2expr.h
==============================================================================
--- head/contrib/gdb/gdb/dwarf2expr.h	Sun May 17 15:12:55 2015	(r283028)
+++ head/contrib/gdb/gdb/dwarf2expr.h	Sun May 17 15:49:38 2015	(r283029)
@@ -74,6 +74,51 @@ struct dwarf_expr_context
   /* Non-zero if the result is in a register.  The register number
      will be on the expression stack.  */
   int in_reg;
+  /* Initialization status of variable: Non-zero if variable has been
+     initialized; zero otherwise.  */
+  int initialized;
+
+  /* An array of pieces.  PIECES points to its first element;
+     NUM_PIECES is its length.
+
+     Each time DW_OP_piece is executed, we add a new element to the
+     end of this array, recording the current top of the stack, the
+     current in_reg flag, and the size given as the operand to
+     DW_OP_piece.  We then pop the top value from the stack, clear the
+     in_reg flag, and resume evaluation.
+
+     The Dwarf spec doesn't say whether DW_OP_piece pops the top value
+     from the stack.  We do, ensuring that clients of this interface
+     expecting to see a value left on the top of the stack (say, code
+     evaluating frame base expressions or CFA's specified with
+     DW_CFA_def_cfa_expression) will get an error if the expression
+     actually marks all the values it computes as pieces.
+
+     If an expression never uses DW_OP_piece, num_pieces will be zero.
+     (It would be nice to present these cases as expressions yielding
+     a single piece, with in_reg clear, so that callers need not
+     distinguish between the no-DW_OP_piece and one-DW_OP_piece cases.
+     But expressions with no DW_OP_piece operations have no value to
+     place in a piece's 'size' field; the size comes from the
+     surrounding data.  So the two cases need to be handled
+     separately.)  */
+  int num_pieces;
+  struct dwarf_expr_piece *pieces;
+};
+
+/* A piece of an object, as recorded by DW_OP_piece or DW_OP_bit_piece.  */
+struct dwarf_expr_piece
+{
+  /* If IN_REG is zero, then the piece is in memory, and VALUE is its address.
+     If IN_REG is non-zero, then the piece is in a register, and VALUE
+     is the register number.  */
+  int in_reg;
+
+  /* This piece's address or register number.  */
+  CORE_ADDR value;
+
+  /* The length of the piece, in bytes.  */
+  ULONGEST size;
 };
 
 struct dwarf_expr_context *new_dwarf_expr_context (void);

Modified: head/contrib/gdb/gdb/dwarf2loc.c
==============================================================================
--- head/contrib/gdb/gdb/dwarf2loc.c	Sun May 17 15:12:55 2015	(r283028)
+++ head/contrib/gdb/gdb/dwarf2loc.c	Sun May 17 15:49:38 2015	(r283029)
@@ -206,6 +206,7 @@ dwarf2_evaluate_loc_desc (struct symbol 
 			  struct objfile *objfile)
 {
   CORE_ADDR result;
+  struct gdbarch *arch = get_frame_arch (frame);
   struct value *retval;
   struct dwarf_expr_baton baton;
   struct dwarf_expr_context *ctx;
@@ -230,7 +231,32 @@ dwarf2_evaluate_loc_desc (struct symbol 
   dwarf_expr_eval (ctx, data, size);
   result = dwarf_expr_fetch (ctx, 0);
 
-  if (ctx->in_reg)
+  if (ctx->num_pieces > 0)
+    {
+      int i;
+      long offset = 0;
+      bfd_byte *contents;
+
+      retval = allocate_value (SYMBOL_TYPE (var));
+      contents = VALUE_CONTENTS_RAW (retval);
+      for (i = 0; i < ctx->num_pieces; i++)
+       {
+         struct dwarf_expr_piece *p = &ctx->pieces[i];
+         if (p->in_reg)
+           {
+             bfd_byte regval[MAX_REGISTER_SIZE];
+             int gdb_regnum = DWARF2_REG_TO_REGNUM (p->value);
+             get_frame_register (frame, gdb_regnum, regval);
+             memcpy (contents + offset, regval, p->size);
+           }
+         else /* In memory?  */
+           {
+             read_memory (p->value, contents + offset, p->size);
+           }
+         offset += p->size;
+       }
+     }
+  else if (ctx->in_reg)
     {
       int regnum = DWARF2_REG_TO_REGNUM (result);
       retval = value_from_register (SYMBOL_TYPE (var), regnum, frame);
@@ -245,6 +271,8 @@ dwarf2_evaluate_loc_desc (struct symbol 
       VALUE_ADDRESS (retval) = result;
     }
 
+  set_value_initialized (retval, ctx->initialized);
+
   free_dwarf_expr_context (ctx);
 
   return retval;
@@ -322,6 +350,17 @@ dwarf2_loc_desc_needs_frame (unsigned ch
 
   in_reg = ctx->in_reg;
 
+  if (ctx->num_pieces > 0)
+    {
+      int i;
+
+      /* If the location has several pieces, and any of them are in
+         registers, then we will need a frame to fetch them from.  */
+      for (i = 0; i < ctx->num_pieces; i++)
+        if (ctx->pieces[i].in_reg)
+          in_reg = 1;
+    }
+
   free_dwarf_expr_context (ctx);
 
   return baton.needs_frame || in_reg;

Modified: head/contrib/gdb/gdb/dwarf2read.c
==============================================================================
--- head/contrib/gdb/gdb/dwarf2read.c	Sun May 17 15:12:55 2015	(r283028)
+++ head/contrib/gdb/gdb/dwarf2read.c	Sun May 17 15:49:38 2015	(r283029)
@@ -7110,6 +7110,8 @@ dwarf_stack_op_name (unsigned op)
       /* GNU extensions.  */
     case DW_OP_GNU_push_tls_address:
       return "DW_OP_GNU_push_tls_address";
+    case DW_OP_GNU_uninit:
+      return "DW_OP_GNU_uninit";
     default:
       return "OP_<unknown>";
     }
@@ -7634,6 +7636,9 @@ decode_locdesc (struct dwarf_block *blk,
 	    dwarf2_complex_location_expr_complaint ();
           break;
 
+	case DW_OP_GNU_uninit:
+	  break;
+
 	default:
 	  complaint (&symfile_complaints, "unsupported stack op: '%s'",
 		     dwarf_stack_op_name (op));

Modified: head/contrib/gdb/gdb/value.h
==============================================================================
--- head/contrib/gdb/gdb/value.h	Sun May 17 15:12:55 2015	(r283028)
+++ head/contrib/gdb/gdb/value.h	Sun May 17 15:49:38 2015	(r283029)
@@ -165,6 +165,9 @@ struct value
     /* The BFD section associated with this value.  */
     asection *bfd_section;
 
+    /* If value is a variable, is it initialized or not.  */
+    int initialized;
+
     /* Actual contents of the value.  For use of this value; setting
        it uses the stuff above.  Not valid if lazy is nonzero.
        Target byte-order.  We force it to be aligned properly for any

Modified: head/contrib/gdb/gdb/values.c
==============================================================================
--- head/contrib/gdb/gdb/values.c	Sun May 17 15:12:55 2015	(r283028)
+++ head/contrib/gdb/gdb/values.c	Sun May 17 15:49:38 2015	(r283029)
@@ -101,6 +101,7 @@ allocate_value (struct type *type)
   VALUE_EMBEDDED_OFFSET (val) = 0;
   VALUE_POINTED_TO_OFFSET (val) = 0;
   val->modifiable = 1;
+  val->initialized = 1;  /* Default to initialized.  */
   return val;
 }
 
@@ -1311,6 +1312,22 @@ using_struct_return (struct type *value_
 	  == RETURN_VALUE_STRUCT_CONVENTION);
 }
 
+/* Set the initialized field in a value struct.  */
+
+void
+set_value_initialized (struct value *val, int status)
+{
+  val->initialized = status;
+}
+
+/* Return the initialized field in a value struct.  */
+
+int
+value_initialized (struct value *val)
+{
+  return val->initialized;
+}
+
 void
 _initialize_values (void)
 {


More information about the svn-src-all mailing list