[RFA] Symeval stuff

Daniel Berlin dan@cgsoftware.com
Wed Jun 27 20:37:00 GMT 2001


Okay, I changed the interface to remove the varargs, since Jim
mentioned both he and Andrew despise them with a passion.

Unfortunately, this dirties the code a little, because it means to be
able to do checking that you are trying to push/pop the right type of
operand, means keeping state through cookies.
And in order to not have to keep two different cookie structures, but
make sure you are done pushing/popping before starting the other
operation, means even more fun.
Before someone claims this is all overkill, and that we don't need to
check the arguments match the parameters of the opcode, realize that
this is the type of bug that happens occasionaly, and takes forever to
track down if you don't do the checking.
This is because you accidently push a signed number when it's
expecting a ulongest, or pop an unsigned number when the argument is
signed, and it'll work *most* of the time, or all of the time, on some
platforms, and just bomb in some unrelated part on other platforms
(this is because it's not till we go to actually *use* the value we
get from the evaluation of the location expression that we run into
problems).
But this is all hidden in the implementation. The interface is pretty
nice now.
I think, anyway.
I only could address the problems, as people saw them, pointed out to
me earlier.

I don't want to move to obstacks for the expressions until i get some
stats. We might want more than one obstack, or an obstack for some
types of expressions, and a bcache for other types. Or whatever.
Immediately using obstacks just doesn't seem right when they force a
lifetime onto you, and we have no idea what the lifetime of these
things is going to be on average.  Obviously, for symbols, it'll live
till the objfile goes away, but if you wanted to use it to describe
where a vtable pointer is, that probably needs to live forever, and if
you want to use it in a value structure, another different lifetime.
We also don't want to just allocate these on the symbol obstack or
something, because we may want to bcache them.
It just seems a better idea at this point to leave it using
xrealloc/xmalloc/xfree until we know more, especially since it depends
on where else besides symbol readers the location expressions are used.


Two changes necessary to symtab.h, one to add the location expression/list
type to the location class enum, one to add the dynamic location
fields to the symbol struct.  Other than that, it affects no other
part of gdb.

For kicks, I verified there are no regressions (Not surprising, since
nothing uses this stuff yet).



2001-05-29  Daniel Berlin  <dan@cgsoftware.com>

	* symtab.h: Add LOC_LOC_EXPR and LOC_LOC_LIST to the location types.
	Add dynamic_location and loc/frameloc to the symbol structure.
	(SYMBOL_LOC_EXPR): New macro.
	(SYMBOL_FRAME_LOC_EXPR): Ditto.
	Add forward declaration of locexpr struct.

	* symeval.c: New file.

	* symeval.def: New file.

	* symeval.h: New file.
        
        * Makefile.in: Add approriate dependencies for symeval.o. 
          Add symeval.o to list of objects. 
          Add symeval.c to list of source files.
          Add symeval_h to be used to specify something has a
          dependency on the symeval stuff (it includes symeval.h and
          symeval.def) 


Index: symeval.c
===================================================================
RCS file: symeval.c
diff -N symeval.c
*** /dev/null	Tue May  5 13:32:27 1998
--- symeval.c	Wed Jun 27 20:31:53 2001
***************
*** 0 ****
--- 1,696 ----
+ /* Location expression evaluation for the GNU debugger, GDB.
+    Copyright 2001
+    Free Software Foundation, Inc.
+ 
+    Contributed by Daniel Berlin <dan@cgsoftware.com>
+ 
+    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 2 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, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.  */
+ #include "defs.h"
+ #include "symtab.h"
+ #include "frame.h"
+ #include "value.h"
+ #include "gdbcore.h"
+ #include "symeval.h"
+ #include "gdb_assert.h"
+ 
+ 
+ #define MORE_BYTES 0x80
+ #define DATA_MASK 0x7f
+ #define DIGIT_WIDTH 7
+ #define SIGN_BIT 0x40
+ 
+ /* Decode the unsigned LEB128 constant at BUF into the variable pointed to
+    by R, and return the new value of BUF.  */
+ 
+ static unsigned char *
+ read_uleb128 (unsigned char *buf, ULONGEST * r)
+ {
+   unsigned shift = 0;
+   ULONGEST result = 0;
+ 
+   while (1)
+     {
+       unsigned char byte = *buf++;
+       result |= (byte & DATA_MASK) << shift;
+       if ((byte & MORE_BYTES) == 0)
+ 	break;
+       shift += DIGIT_WIDTH;
+     }
+   *r = result;
+   return buf;
+ }
+ 
+ /* Decode the signed LEB128 constant at BUF into the variable pointed to
+    by R, and return the new value of BUF.  */
+ 
+ static unsigned char *
+ read_sleb128 (unsigned char *buf, LONGEST * r)
+ {
+   unsigned shift = 0;
+   LONGEST result = 0;
+   unsigned char byte;
+ 
+   while (1)
+     {
+       byte = *buf++;
+       result |= (byte & DATA_MASK) << shift;
+       shift += DIGIT_WIDTH;
+       if ((byte & MORE_BYTES) == 0)
+ 	break;
+     }
+   if (shift < (sizeof (*r) * 8) && (byte & SIGN_BIT) != 0)
+     result |= -(1 << shift);
+ 
+   *r = result;
+   return buf;
+ }
+ 
+ /* This is what a location expression actually looks like internally.
+    But the only thing that should know this is symeval.c  Any propagation
+    of this structure, or assumptions made based on this internal
+    structure, that aren't being done by the routines made to read from
+    the internal structure (IE the routines in this file), will break, and
+    no sympathy will be afforded to the person whose code broke.
+ 
+    In other words, DON'T DEPEND ON THIS NOT CHANGING.
+    :)
+ */
+ 
+ struct locexpr
+ {
+   unsigned int size;
+   unsigned char *data;
+ };
+ /* To share cookies, and still be able to do all the checking we want
+    to do, we need to also make sure they don't pass a cookie whose state
+    is for a set of pops, to a push, and vice versa. */
+ enum locexpr_cookie_state
+ {
+   NONE,
+   PUSHING,
+   POPPING
+ };
+ /* The actual cookie structure. Depending on anything in here is even
+    worse than depending on the internal structure of a locexpr.
+ */
+ struct locexpr_cookie
+ {
+   enum locexpr_cookie_state state;
+   struct locexpr *expr;
+   union
+   {
+     struct
+     {
+       unsigned int position;
+       enum locexpr_opcode lastopcode;
+       unsigned char operands_left;
+     }
+     popinfo;
+     struct
+     {
+       const char *fmt_left;
+     }
+     pushinfo;
+   }
+   d;
+ };
+ 
+ /* Given an unsigned value, determine how bytes of uleb128 it will
+    take to represent it */
+ static int
+ sizeof_uleb128 (ULONGEST value)
+ {
+   int size = 0, byte;
+   do
+     {
+       byte = value & DATA_MASK;
+       value >>= DIGIT_WIDTH;
+       size++;
+     }
+   while (value != 0);
+   return size;
+ }
+ 
+ /* Given a signed value, determine how many bytes of sleb128 it will
+    take to represent it. */
+ static int
+ sizeof_sleb128 (LONGEST value)
+ {
+   int size = 0, byte;
+   do
+     {
+       byte = value & DATA_MASK;
+       value >>= DIGIT_WIDTH;
+       size++;
+     }
+   while (!
+ 	 ((value == 0 && (byte & SIGN_BIT) == 0)
+ 	  || (value == -1 && (byte & SIGN_BIT) != 0)));
+   return size;
+ }
+ 
+ 
+ /* Encode the value into ULEB128 into the expr->data */
+ 
+ static void
+ encode_uleb128 (struct locexpr *expr, ULONGEST value)
+ {
+   char *place;
+   int size = sizeof_uleb128 (value);
+   expr->data = xrealloc (expr->data, expr->size + size);
+   place = expr->data + expr->size;
+   expr->size += size;
+   do
+     {
+       unsigned char uc;
+       uc = value & DATA_MASK;
+       value >>= DIGIT_WIDTH;
+       if (value != 0)
+ 	uc |= MORE_BYTES;
+       *place = uc;
+       place++;
+     }
+   while (value);
+ 
+ }
+ 
+ /* Encode the value into SLEB128 into the expr->data */
+ 
+ static void
+ encode_sleb128 (struct locexpr *expr, LONGEST value)
+ {
+   char *place;
+   int size = sizeof_sleb128 (value);
+   int sign = -(value < 0);
+   int more = 1;
+   expr->data = xrealloc (expr->data, expr->size + size);
+   place = expr->data + expr->size;
+   expr->size += size;
+   do
+     {
+       unsigned char uc = value & DATA_MASK;
+       value >>= DIGIT_WIDTH;
+       if (value == sign && ((uc & SIGN_BIT) == (sign & SIGN_BIT)))
+ 	more = 0;
+       else
+ 	uc |= MORE_BYTES;
+       *place = uc;
+       place++;
+     }
+   while (more);
+ }
+ 
+ /* Encode an unsigned character into the expr->data */
+ static void
+ encode_uchar (struct locexpr *expr, unsigned char value)
+ {
+   expr->data = xrealloc (expr->data, expr->size + 1);
+   *(expr->data + expr->size) = value;
+   expr->size++;
+ }
+ 
+ /* Initialize the given location expression */
+ void
+ init_locexpr (struct locexpr **expr)
+ {
+   *expr = xmalloc (sizeof (struct locexpr));
+   memset (*expr, 0, sizeof (struct locexpr));
+ }
+ 
+ /* Destroy the given location expression */
+ void
+ destroy_locexpr (struct locexpr **expr)
+ {
+   xfree ((*expr)->data);
+   xfree (*expr);
+ 
+ }
+ 
+ /* These are various tables made up from pieces of the location
+    expression definition macros, and used to determine things like
+    operand count of a given operator, format of a given operator, etc.
+ */
+ #define DEFINE_LOCEXPR_OPCODE(opcode, desc, numargs, argtypes) numargs,
+ static const int locexpr_opcount[] = {
+ #include "symeval.def"
+ };
+ #undef DEFINE_LOCEXPR_OPCODE
+ #define DEFINE_LOCEXPR_OPCODE(opcode, desc, numargs, argtypes) argtypes,
+ static const char *locexpr_opfmt[] = {
+ #include "symeval.def"
+ };
+ #undef DEFINE_LOCEXPR_OPCODE
+ #define DEFINE_LOCEXPR_OPCODE(opcode, desc, numargs, argtypes)  #opcode,
+ static const char *locexpr_opstring[] = {
+ #include "symeval.def"
+ };
+ #undef DEFINE_LOCEXPR_OPCODE
+ 
+ /* Start or continue a location expression by putting an opcode of
+    type OPERATION into the data, and setting up the cookie so that we can
+    make sure you put in the remaining arguments necessary. */
+ void
+ locexpr_push_op (struct locexpr *expr, struct locexpr_cookie *cookie,
+ 		 enum locexpr_opcode operation)
+ {
+   /* Make sure they've given us either a cookie, or an expression */
+   gdb_assert (!(expr == NULL && (cookie == NULL || cookie->expr == NULL)));
+   /* And make sure the cookie says the last opcode was finished, or
+      that there was no last opcode. */
+   gdb_assert (cookie->d.pushinfo.fmt_left == NULL);
+ 
+   /* If they gave us a cookie which is completely clear, set it up with the
+      expression, state, and format string. */
+   if (cookie->expr == NULL)
+     {
+       cookie->expr = expr;
+       cookie->state = PUSHING;
+       cookie->d.pushinfo.fmt_left = locexpr_opfmt[operation];
+     }
+   /* Otherwise, take the expression from the cookie, and append to that. */
+   else
+     {
+       expr = cookie->expr;
+     }
+   /* Add the opcode to the expression data */
+   expr->data = xrealloc (expr->data, expr->size + 1);
+   expr->data[expr->size] = operation;
+   expr->size++;
+ }
+ 
+ /* Push the LONGEST value in DATA onto the location expression whose
+    cookie is COOKIE. */
+ void
+ locexpr_push_longest (struct locexpr_cookie *cookie, LONGEST data)
+ {
+   gdb_assert (cookie != NULL);
+   gdb_assert (cookie->d.pushinfo.fmt_left != NULL
+ 	      && *cookie->d.pushinfo.fmt_left == 's');
+   gdb_assert (cookie->state == PUSHING);
+   encode_sleb128 (cookie->expr, data);
+   cookie->d.pushinfo.fmt_left++;
+ }
+ 
+ /* Push the ULONGEST value in DATA onto the location expression whose
+    cookie is COOKIE. */
+ void
+ locexpr_push_ulongest (struct locexpr_cookie *cookie, ULONGEST data)
+ {
+   gdb_assert (cookie != NULL);
+   gdb_assert (cookie->d.pushinfo.fmt_left != NULL
+ 	      && *cookie->d.pushinfo.fmt_left == 'u');
+   gdb_assert (cookie->state == PUSHING);
+   encode_uleb128 (cookie->expr, data);
+   cookie->d.pushinfo.fmt_left++;
+ }
+ 
+ /* Push the unsigned char whose data is in DATA onto the location
+    expression whose cookie is COOKIE */
+ void
+ locexpr_push_uchar (struct locexpr_cookie *cookie, unsigned char data)
+ {
+   gdb_assert (cookie != NULL);
+   gdb_assert (cookie->d.pushinfo.fmt_left != NULL
+ 	      && *cookie->d.pushinfo.fmt_left == 'c');
+   gdb_assert (cookie->state == PUSHING);
+   encode_uchar (cookie->expr, data);
+   cookie->d.pushinfo.fmt_left++;
+ }
+ 
+ /* Get the opcode of the first operation in expr, if the cookie is a
+    blank cookie (and setup the cookie in this case */
+ void
+ locexpr_get_op (struct locexpr *expr, struct locexpr_cookie *cookie,
+ 		enum locexpr_opcode *op)
+ {
+   struct locexpr *realexpr;
+   unsigned int position = 0;
+   gdb_assert (!(expr == NULL && (cookie == NULL || cookie->expr == NULL)));
+   gdb_assert (op != NULL);
+   gdb_assert (cookie != NULL && (cookie->d.popinfo.operands_left == 0));
+   gdb_assert (cookie->state == NONE);
+ 
+   if (cookie->expr != NULL)
+     {
+       realexpr = cookie->expr;
+       position = cookie->d.popinfo.position;
+     }
+   else
+     {
+       realexpr = expr;
+       position = 0;
+     }
+   *op = realexpr->data[position];
+   cookie->d.popinfo.lastopcode = *op;
+   cookie->d.popinfo.operands_left = locexpr_opcount[*op];
+   cookie->expr = realexpr;
+   cookie->d.popinfo.position++;
+   cookie->state = POPPING;
+ }
+ 
+ void
+ locexpr_get_longest (struct locexpr_cookie *cookie, LONGEST * value)
+ {
+   unsigned char *newdata;
+   gdb_assert (cookie != NULL && cookie->expr != NULL);
+   gdb_assert (cookie->d.popinfo.operands_left > 0);
+   gdb_assert (cookie->state == POPPING);
+ 
+   newdata =
+     read_sleb128 (cookie->expr->data + cookie->d.popinfo.position, value);
+   cookie->d.popinfo.position = newdata - (unsigned char *) cookie->expr->data;
+   cookie->d.popinfo.operands_left--;
+   if (cookie->d.popinfo.operands_left == 0)
+     cookie->state = NONE;
+ 
+ }
+ 
+ void
+ locexpr_get_ulongest (struct locexpr_cookie *cookie, ULONGEST * value)
+ {
+   unsigned char *newdata;
+   gdb_assert (cookie != NULL && cookie->expr != NULL);
+   gdb_assert (cookie->d.popinfo.operands_left > 0);
+   gdb_assert (cookie->state == POPPING);
+ 
+   newdata =
+     read_uleb128 (cookie->expr->data + cookie->d.popinfo.position, value);
+   cookie->d.popinfo.position = newdata - (unsigned char *) cookie->expr->data;
+   cookie->d.popinfo.operands_left--;
+   if (cookie->d.popinfo.operands_left == 0)
+     cookie->state = NONE;
+ 
+ }
+ 
+ void
+ locexpr_get_uchar (struct locexpr_cookie *cookie, unsigned char *value)
+ {
+   gdb_assert (cookie != NULL && cookie->expr != NULL);
+   gdb_assert (cookie->d.popinfo.operands_left > 0);
+   gdb_assert (cookie->state == POPPING);
+ 
+   *value = (unsigned char) *(cookie->expr->data + cookie->d.popinfo.position);
+   cookie->d.popinfo.position++;
+   cookie->d.popinfo.operands_left--;
+   if (cookie->d.popinfo.operands_left == 0)
+     cookie->state = NONE;
+ }
+ 
+ static CORE_ADDR
+ execute_stack_op (struct symbol *var, unsigned char *op_ptr,
+ 		  unsigned char *op_end, struct frame_info *frame,
+ 		  CORE_ADDR initial, value_ptr * currval)
+ {
+   CORE_ADDR stack[64];		/* ??? Assume this is enough. */
+   int stack_elt;
+   stack[0] = initial;
+   stack_elt = 1;
+   while (op_ptr < op_end)
+     {
+       enum locexpr_opcode op = *op_ptr++;
+       ULONGEST result, reg;
+       LONGEST offset;
+       switch (op)
+ 	{
+ 	case GLO_addr:
+ 	  result =
+ 	    (CORE_ADDR) extract_unsigned_integer (op_ptr,
+ 						  TARGET_PTR_BIT /
+ 						  TARGET_CHAR_BIT);
+ 	  op_ptr += TARGET_PTR_BIT / TARGET_CHAR_BIT;
+ 	  break;
+ 
+ 	case GLO_constu:
+ 	  op_ptr = read_uleb128 (op_ptr, &result);
+ 	  break;
+ 	case GLO_consts:
+ 	  op_ptr = read_sleb128 (op_ptr, &offset);
+ 	  result = offset;
+ 	  break;
+ 
+ 	case GLO_regx:
+ 	  {
+ 	    char *buf = (char *) alloca (MAX_REGISTER_RAW_SIZE);
+ 
+ 	    op_ptr = read_uleb128 (op_ptr, &reg);
+ 	    get_saved_register (buf, NULL, NULL, frame, reg, NULL);
+ 	    result = extract_address (buf, REGISTER_RAW_SIZE (reg));
+ 	    if (currval != NULL)
+ 	      {
+ 		store_typed_address (VALUE_CONTENTS_RAW (*currval),
+ 				     SYMBOL_TYPE (var), result);
+ 		VALUE_LVAL (*currval) = not_lval;
+ 	      }
+ 	  }
+ 	  break;
+ 	case GLO_fbreg:
+ 	  {
+ 	    struct symbol *framefunc;
+ 	    unsigned char *datastart;
+ 	    unsigned char *dataend;
+ 	    struct locexpr *theblock;
+ 
+ 	    framefunc = get_frame_function (frame);
+ 	    op_ptr = read_sleb128 (op_ptr, &offset);
+ 	    theblock = SYMBOL_FRAME_LOC_EXPR (framefunc);
+ 	    datastart = theblock->data;
+ 	    dataend = theblock->data + theblock->size;
+ 	    result =
+ 	      execute_stack_op (var, datastart, dataend, frame, 0,
+ 				NULL) + offset;
+ 	  }
+ 	  break;
+ 	case GLO_dup:
+ 	  if (stack_elt < 1)
+ 	    abort ();
+ 	  result = stack[stack_elt - 1];
+ 	  break;
+ 
+ 	case GLO_drop:
+ 	  if (--stack_elt < 0)
+ 	    abort ();
+ 	  goto no_push;
+ 
+ 	case GLO_pick:
+ 	  offset = *op_ptr++;
+ 	  if (offset >= stack_elt - 1)
+ 	    abort ();
+ 	  result = stack[stack_elt - 1 - offset];
+ 	  break;
+ 
+ 	case GLO_over:
+ 	  if (stack_elt < 2)
+ 	    abort ();
+ 	  result = stack[stack_elt - 2];
+ 	  break;
+ 
+ 	case GLO_rot:
+ 	  {
+ 	    CORE_ADDR t1, t2, t3;
+ 
+ 	    if (stack_elt < 3)
+ 	      abort ();
+ 	    t1 = stack[stack_elt - 1];
+ 	    t2 = stack[stack_elt - 2];
+ 	    t3 = stack[stack_elt - 3];
+ 	    stack[stack_elt - 1] = t2;
+ 	    stack[stack_elt - 2] = t3;
+ 	    stack[stack_elt - 3] = t1;
+ 	    goto no_push;
+ 	  }
+ 
+ 	case GLO_deref:
+ 	case GLO_abs:
+ 	case GLO_neg:
+ 	case GLO_not:
+ 	  /* Unary operations.  */
+ 	  if (--stack_elt < 0)
+ 	    abort ();
+ 	  result = stack[stack_elt];
+ 
+ 	  switch (op)
+ 	    {
+ 	    case GLO_deref:
+ 	      {
+ 		switch (*op_ptr++)
+ 		  {
+ 		  case 1:
+ 		    result = read_memory_unsigned_integer (result, 1);
+ 		    break;
+ 		  case 2:
+ 		    result = read_memory_unsigned_integer (result, 2);
+ 		    break;
+ 		  case 4:
+ 		    result = read_memory_unsigned_integer (result, 4);
+ 		    break;
+ 		  case 8:
+ 		    result = read_memory_unsigned_integer (result, 8);
+ 		    break;
+ 		  default:
+ 		    abort ();
+ 		  }
+ 	      }
+ 	      break;
+ 
+ 	    case GLO_abs:
+ 	      if ((signed int) result < 0)
+ 		result = -result;
+ 	      break;
+ 	    case GLO_neg:
+ 	      result = -result;
+ 	      break;
+ 	    case GLO_not:
+ 	      result = ~result;
+ 	      break;
+ 	    }
+ 	  break;
+ 
+ 	case GLO_and:
+ 	case GLO_div:
+ 	case GLO_minus:
+ 	case GLO_mod:
+ 	case GLO_mul:
+ 	case GLO_or:
+ 	case GLO_plus:
+ 	case GLO_le:
+ 	case GLO_ge:
+ 	case GLO_eq:
+ 	case GLO_lt:
+ 	case GLO_gt:
+ 	case GLO_ne:
+ 	  {
+ 	    /* Binary operations.  */
+ 	    CORE_ADDR first, second;
+ 	    if ((stack_elt -= 2) < 0)
+ 	      abort ();
+ 	    second = stack[stack_elt];
+ 	    first = stack[stack_elt + 1];
+ 
+ 	    switch (op)
+ 	      {
+ 	      case GLO_and:
+ 		result = second & first;
+ 		break;
+ 	      case GLO_div:
+ 		result = (LONGEST) second / (LONGEST) first;
+ 		break;
+ 	      case GLO_minus:
+ 		result = second - first;
+ 		break;
+ 	      case GLO_mod:
+ 		result = (LONGEST) second % (LONGEST) first;
+ 		break;
+ 	      case GLO_mul:
+ 		result = second * first;
+ 		break;
+ 	      case GLO_or:
+ 		result = second | first;
+ 		break;
+ 	      case GLO_plus:
+ 		result = second + first;
+ 		break;
+ 	      case GLO_shl:
+ 		result = second << first;
+ 		break;
+ 	      case GLO_shr:
+ 		result = second >> first;
+ 		break;
+ 	      case GLO_shra:
+ 		result = (LONGEST) second >> first;
+ 		break;
+ 	      case GLO_xor:
+ 		result = second ^ first;
+ 		break;
+ 	      case GLO_le:
+ 		result = (LONGEST) first <= (LONGEST) second;
+ 		break;
+ 	      case GLO_ge:
+ 		result = (LONGEST) first >= (LONGEST) second;
+ 		break;
+ 	      case GLO_eq:
+ 		result = (LONGEST) first == (LONGEST) second;
+ 		break;
+ 	      case GLO_lt:
+ 		result = (LONGEST) first < (LONGEST) second;
+ 		break;
+ 	      case GLO_gt:
+ 		result = (LONGEST) first > (LONGEST) second;
+ 		break;
+ 	      case GLO_ne:
+ 		result = (LONGEST) first != (LONGEST) second;
+ 		break;
+ 	      }
+ 	  }
+ 	  break;
+ 
+ 	case GLO_skip:
+ 	  op_ptr = read_sleb128 (op_ptr, &offset);
+ 	  op_ptr += offset;
+ 	  goto no_push;
+ 
+ 	case GLO_bra:
+ 	  if (--stack_elt < 0)
+ 	    abort ();
+ 	  op_ptr = read_sleb128 (op_ptr, &offset);
+ 	  if (stack[stack_elt] != 0)
+ 	    op_ptr += offset;
+ 	  goto no_push;
+ 
+ 	case GLO_nop:
+ 	  goto no_push;
+ 
+ 	default:
+ 	  abort ();
+ 	}
+ 
+       /* Most things push a result value.  */
+       if ((size_t) stack_elt >= sizeof (stack) / sizeof (*stack))
+ 	abort ();
+       stack[++stack_elt] = result;
+     no_push:;
+     }
+ 
+   /* We were executing this program to get a value.  It should be
+      at top of stack.  */
+   if (stack_elt - 1 < 0)
+     abort ();
+   return stack[stack_elt];
+ }
+ 
+ /* Evaluate a location description, given in THEBLOCK, in the
+    context of frame FRAME.  Return a value whose BFD section is the
+    same as VAR, and which has a type of TYPE.*/
+ value_ptr
+ evaluate_loc_expr (struct symbol * var, struct frame_info * frame,
+ 		   struct locexpr * theblock, struct type * type)
+ {
+   CORE_ADDR result;
+   value_ptr retval;
+   retval = allocate_value (type);
+   VALUE_LVAL (retval) = lval_memory;
+   VALUE_BFD_SECTION (retval) = SYMBOL_BFD_SECTION (var);
+   result =
+     execute_stack_op (var, theblock->data, theblock->data + theblock->size,
+ 		      frame, 0, &retval);
+   if (VALUE_LVAL (retval) == lval_memory)
+     {
+       VALUE_LAZY (retval) = 1;
+       VALUE_ADDRESS (retval) = result;
+     }
+   return retval;
+ }
Index: symeval.def
===================================================================
RCS file: symeval.def
diff -N symeval.def
*** /dev/null	Tue May  5 13:32:27 1998
--- symeval.def	Wed Jun 27 20:31:53 2001
***************
*** 0 ****
--- 1,39 ----
+ /* DEFINE_LOCEXPR_OPCODE (opcode, description, numargs, argtypes) */
+ DEFINE_LOCEXPR_OPCODE (GLO_addr, "Address", 1, "u")
+ DEFINE_LOCEXPR_OPCODE (GLO_constu, "Unsigned constant", 1, "u")
+ DEFINE_LOCEXPR_OPCODE (GLO_consts, "Signed constant", 1, "s")
+ DEFINE_LOCEXPR_OPCODE (GLO_dup, "Duplicate top of stack", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_drop, "Pop top of stack", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_over, "Push second entry of stack onto top of stack", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_pick, "Push a stack entry onto top of stack", 1, "c")
+ DEFINE_LOCEXPR_OPCODE (GLO_swap, "Swap top two stack entries", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_rot, "Rotate first three stack entries", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_xderef, "Extended dereference of top of stack", 1, "c")
+ DEFINE_LOCEXPR_OPCODE (GLO_deref, "Dereference top of stack", 1, "c")
+ DEFINE_LOCEXPR_OPCODE (GLO_abs, "Absolute value", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_and, "Bitwise AND", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_div, "Signed division", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_minus, "Subtraction", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_mod, "Modulo", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_mul, "Multiply", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_neg, "Negate", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_not, "Bitwise NOT", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_or, "Bitwise OR", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_plus, "Addition", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_shl, "Logical bitshift left", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_shr, "Logical bitshift right", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_shra, "Arithmetic bitshift right", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_xor, "Bitwise XOR", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_bra, "Conditional branch", 1, "s")
+ DEFINE_LOCEXPR_OPCODE (GLO_eq, "==", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_ge, ">=", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_gt, ">", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_le, "<=", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_lt, "<", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_ne, "!=", 0, "")
+ DEFINE_LOCEXPR_OPCODE (GLO_skip, "Unconditional branch", 1, "s")
+ DEFINE_LOCEXPR_OPCODE (GLO_regx, "Get register value", 1, "u")
+ DEFINE_LOCEXPR_OPCODE (GLO_fbreg, "Frame based value", 1, "s")
+ DEFINE_LOCEXPR_OPCODE (GLO_piece, "Piece of object", 1, "u")
+ DEFINE_LOCEXPR_OPCODE (GLO_nop, "No operation", 0, "")
+ 
Index: symeval.h
===================================================================
RCS file: symeval.h
diff -N symeval.h
*** /dev/null	Tue May  5 13:32:27 1998
--- symeval.h	Wed Jun 27 20:31:53 2001
***************
*** 0 ****
--- 1,27 ----
+ #ifndef SYMEVAL_H
+ #define SYMEVAL_H
+ /* Make up the enum from the list of opcodes */
+ #define DEFINE_LOCEXPR_OPCODE(opcode, desc, numargs, argtypes) opcode,
+ enum locexpr_opcode
+   {
+ #include "symeval.def"
+   };
+ #undef DEFINE_LOCEXPR_OPCODE
+ struct locexpr_cookie;
+ struct locexpr;
+ void init_locexpr (struct locexpr **);
+ void destroy_locexpr (struct locexpr **);
+ void locexpr_push_op  (struct locexpr *, struct locexpr_cookie *, 
+ 		       enum locexpr_opcode);
+ void locexpr_push_longest (struct locexpr_cookie *, LONGEST);
+ void locexpr_push_ulongest (struct locexpr_cookie *, ULONGEST);
+ void locexpr_push_uchar (struct locexpr_cookie *, unsigned char);
+ void locexpr_get_op (struct locexpr *,  struct locexpr_cookie *, 
+ 		     enum locexpr_opcode *);
+ void locexpr_get_longest (struct locexpr_cookie *, LONGEST *);
+ void locexpr_get_ulongest (struct locexpr_cookie *, ULONGEST *);
+ void locexpr_get_uchar (struct locexpr_cookie *, unsigned char *);
+ value_ptr evaluate_loc_expr (struct symbol *, struct frame_info *, 
+ 			     struct locexpr *, struct type *);
+ 
+ #endif
Index: symtab.h
===================================================================
RCS file: /cvs/src/src/gdb/symtab.h,v
retrieving revision 1.23
diff -c -3 -p -r1.23 symtab.h
*** symtab.h	2001/06/12 15:03:04	1.23
--- symtab.h	2001/06/28 03:31:55
*************** enum address_class
*** 654,661 ****
       * with a level of indirection.
       */
  
!     LOC_INDIRECT
  
    };
  
  /* Linked list of symbol's live ranges. */
--- 654,666 ----
       * with a level of indirection.
       */
  
!     LOC_INDIRECT,
  
+     /* Location is a location expression */
+     LOC_LOC_EXPR,
+     /* Location is a location list (ranges + location expressions) */
+     LOC_LOC_LIST
+ 
    };
  
  /* Linked list of symbol's live ranges. */
*************** struct alias_list
*** 674,679 ****
--- 679,685 ----
      struct alias_list *next;
    };
  
+ struct locexpr;
  struct symbol
    {
  
*************** struct symbol
*** 713,718 ****
--- 719,729 ----
  	short basereg;
        }
      aux_value;
+     struct 
+     {
+ 	    struct locexpr *loc;
+ 	    struct locexpr *frameloc;
+     } dynamic_location;
  
  
      /* Link to a list of aliases for this symbol.
*************** struct symbol
*** 730,735 ****
--- 741,748 ----
  #define SYMBOL_TYPE(symbol)		(symbol)->type
  #define SYMBOL_LINE(symbol)		(symbol)->line
  #define SYMBOL_BASEREG(symbol)		(symbol)->aux_value.basereg
+ #define SYMBOL_LOC_EXPR(symbol)  	(symbol)->dynamic_location.loc
+ #define SYMBOL_FRAME_LOC_EXPR(symbol)   (symbol)->dynamic_location.frameloc
  #define SYMBOL_ALIASES(symbol)		(symbol)->aliases
  #define SYMBOL_RANGES(symbol)		(symbol)->ranges
  
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.90
diff -c -3 -p -r1.90 Makefile.in
*** Makefile.in	2001/06/10 00:47:02	1.90
--- Makefile.in	2001/06/28 03:31:57
*************** SFILES = ax-general.c ax-gdb.c bcache.c 
*** 541,547 ****
  	tui/tui-file.h tui/tui-file.c \
  	ui-file.h ui-file.c \
  	frame.c \
! 	gnu-v2-abi.c gnu-v3-abi.c hpacc-abi.c cp-abi.c
  
  LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
  
--- 541,547 ----
  	tui/tui-file.h tui/tui-file.c \
  	ui-file.h ui-file.c \
  	frame.c \
! 	gnu-v2-abi.c gnu-v3-abi.c hpacc-abi.c cp-abi.c symeval.c
  
  LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
  
*************** symfile_h =	symfile.h
*** 584,590 ****
  gdbtypes_h =	gdbtypes.h
  expression_h =	expression.h
  value_h =	value.h $(symtab_h) $(gdbtypes_h) $(expression_h)
! 
  breakpoint_h =	breakpoint.h $(frame_h) $(value_h)
  
  command_h =	command.h
--- 584,590 ----
  gdbtypes_h =	gdbtypes.h
  expression_h =	expression.h
  value_h =	value.h $(symtab_h) $(gdbtypes_h) $(expression_h)
! symeval_h = 	symeval.h symeval.def
  breakpoint_h =	breakpoint.h $(frame_h) $(value_h)
  
  command_h =	command.h
*************** COMMON_OBS = version.o blockframe.o brea
*** 695,701 ****
  	nlmread.o serial.o mdebugread.o os9kread.o top.o utils.o \
  	ui-file.o tui-file.o \
  	frame.o \
! 	gnu-v2-abi.o gnu-v3-abi.o hpacc-abi.o cp-abi.o
  
  OBS = $(COMMON_OBS) $(ANNOTATE_OBS)
  
--- 695,701 ----
  	nlmread.o serial.o mdebugread.o os9kread.o top.o utils.o \
  	ui-file.o tui-file.o \
  	frame.o \
! 	gnu-v2-abi.o gnu-v3-abi.o hpacc-abi.o cp-abi.o symeval.o
  
  OBS = $(COMMON_OBS) $(ANNOTATE_OBS)
  
*************** findvar.o: findvar.c $(defs_h) $(gdbcore
*** 1351,1356 ****
--- 1351,1357 ----
  
  frame.o: frame.c $(defs_h) $(frame_h) $(target_h) $(value_h) $(inferior_h) \
  	$(regcache_h)
+ symeval.o: symeval.c $(defs_h) $(gdbcore_h) $(symeval_h) $(symtab_h) 
  
  regcache.o: regcache.c $(defs_h) $(inferior_h) target.h $(regcache_h)
  






-- 
"When I was a kid, I went to the store and asked the guy, "Do you
have any toy train schedules?"
"-Steven Wright



More information about the Gdb-patches mailing list