This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH]: LOC_COMPUTED/LOC_COMPUTED_ARG + dwarf2 abstracted expressioneval


The only real things left to do is give some *real* description in 
locexpr_describe_location, add tracepoint support, and remove the 
dwarf2cfi.c evaluator.  None of which I see as blockers, unless someone 
sees it otherwise.
It would also be nice to use location expressions in *all* cases 
(currently, it only does it for variables) so you can get rid of 
decode_loc_desc, but i'll leave that for the next patch.
 
There are a few lines that are too long (<10, i *think*), sorry about 
that, i couldn't see an easy way to break them up and have them make 
sense.


This patch has been tested on both powerpc-linux and 686-linux.


2002-04-11  Daniel Berlin  <dberlin@dberlin.org>

	* dwarf2read.c: Add value.h, frame.h, gdbcore.h, dwarf2expr.h,
	needed for the new location expression functions. 
	(read_func_scope): Set location expression and location funcs on
	symbol.
	(new_symbol): Ditto.
	(locexpr_read_needs_frame): New function, used  in struct
	location for dwarf2 location expressions.
	(locexpr_read_variable): Ditto.
	(locexpr_describe_location): Ditto.
	(dwarf_expr_read_reg): New function, used to read register for
	dwarf2 expression eval.
	(dwarf_expr_read_mem): Ditto for memory.
	(dwarf_expr_frame_base): Ditto for returning the frame base.
	(evaluate_loc_desc): New function, helper for
	locexpr_read_variable.
	

2002-04-11  Daniel Berlin  <dan@dberlin.org>
	
	* stack.c (print_block_frame_locals): LOC_COMPUTED symbols are
	locals, too.

	* dwarf2expr.c: New file, abstracted dwarf2 expression evaluator.

	* dwarf2expr.h: New file, header for dwarf2 expression evaluator.
	
	(Simple cases of *.c containing LOC_): Handle LOC_COMPUTED and
	LOC_COMPUTED_ARG. 

2002-04-11  Daniel Berlin  <dan@dberlin.org>

	* buildsym.c (finish_block): Handle LOC_COMPUTED and
	LOC_COMPUTED_ARG. 

	* findvar.c (symbol_read_needs_frame): Handle LOC_COMPUTED and
	LOC_COMPUTED_ARG. 
	(read_var_value): Ditto.

	* printcmd.c (address_info): Ditto.

	* symmisc.c (print_partial_symbols): Ditto.

	* symtab.h: Add struct location, LOC_COMPUTED, and LOC_COMPUTED_ARG.
	

2002-04-11  Daniel Jacobowitz  <drow@mvista.com>
  
  	* gdbserver/linux-low.c (usr_store_inferior_registers): Support
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.169
diff -c -3 -p -w -B -b -r1.169 Makefile.in
*** Makefile.in	9 Apr 2002 03:06:13 -0000	1.169
--- Makefile.in	11 Apr 2002 21:34:44 -0000
*************** SFILES = ax-general.c ax-gdb.c bcache.c 
*** 523,529 ****
  	buildsym.c c-exp.y c-lang.c c-typeprint.c c-valprint.c \
  	ch-exp.c ch-lang.c ch-typeprint.c ch-valprint.c coffread.c \
  	complaints.c completer.c corefile.c cp-valprint.c dbxread.c \
! 	demangle.c dwarfread.c dwarf2read.c elfread.c environ.c eval.c \
  	event-loop.c event-top.c \
  	expprint.c f-exp.y f-lang.c f-typeprint.c f-valprint.c \
  	findvar.c regcache.c gdbarch.c arch-utils.c gdbtypes.c \
--- 523,530 ----
  	buildsym.c c-exp.y c-lang.c c-typeprint.c c-valprint.c \
  	ch-exp.c ch-lang.c ch-typeprint.c ch-valprint.c coffread.c \
  	complaints.c completer.c corefile.c cp-valprint.c dbxread.c \
! 	demangle.c dwarfread.c dwarf2cfi.c dwarf2expr.c dwarf2read.c \
!         elfread.c environ.c eval.c \
  	event-loop.c event-top.c \
  	expprint.c f-exp.y f-lang.c f-typeprint.c f-valprint.c \
  	findvar.c regcache.c gdbarch.c arch-utils.c gdbtypes.c \
*************** COMMON_OBS = version.o blockframe.o brea
*** 716,722 ****
  	gdb-events.o \
  	exec.o bcache.o objfiles.o minsyms.o maint.o demangle.o \
  	dbxread.o coffread.o elfread.o \
! 	dwarfread.o dwarf2read.o mipsread.o stabsread.o corefile.o \
  	c-lang.o ch-exp.o ch-lang.o f-lang.o \
  	ui-out.o cli-out.o \
  	varobj.o wrapper.o \
--- 717,724 ----
  	gdb-events.o \
  	exec.o bcache.o objfiles.o minsyms.o maint.o demangle.o \
  	dbxread.o coffread.o elfread.o \
! 	dwarfread.o dwarf2cfi.o dwarf2expr.o \
!         dwarf2read.o mipsread.o stabsread.o corefile.o \
  	c-lang.o ch-exp.o ch-lang.o f-lang.o \
  	ui-out.o cli-out.o \
  	varobj.o wrapper.o \
*************** dwarfread.o: dwarfread.c $(bfd_h) $(buil
*** 1384,1389 ****
--- 1386,1395 ----
  	$(symfile_h) $(symtab_h) $(gdb_string_h)
  
  dwarf2read.o: dwarf2read.c $(bfd_h) $(buildsym_h) $(defs_h) \
+ 	$(expression_h) $(gdbtypes_h) $(language_h) $(objfiles_h) \
+ 	$(symfile_h) $(symtab_h) $(gdb_string_h)
+ 
+ dwarf2expr.o: dwarf2expr.c $(bfd_h) $(buildsym_h) $(defs_h) \
  	$(expression_h) $(gdbtypes_h) $(language_h) $(objfiles_h) \
  	$(symfile_h) $(symtab_h) $(gdb_string_h)
  
Index: buildsym.c
===================================================================
RCS file: /cvs/src/src/gdb/buildsym.c,v
retrieving revision 1.14
diff -c -3 -p -w -B -b -r1.14 buildsym.c
*** buildsym.c	20 Jan 2002 19:42:04 -0000	1.14
--- buildsym.c	11 Apr 2002 21:34:45 -0000
*************** finish_block (struct symbol *symbol, str
*** 285,290 ****
--- 285,291 ----
  		case LOC_REGPARM_ADDR:
  		case LOC_BASEREG_ARG:
  		case LOC_LOCAL_ARG:
+ 		case LOC_COMPUTED_ARG:
  		  nparams++;
  		  break;
  		case LOC_UNDEF:
*************** finish_block (struct symbol *symbol, str
*** 300,305 ****
--- 301,307 ----
  		case LOC_BASEREG:
  		case LOC_UNRESOLVED:
  		case LOC_OPTIMIZED_OUT:
+ 		case LOC_COMPUTED:
  		default:
  		  break;
  		}
*************** finish_block (struct symbol *symbol, str
*** 321,326 ****
--- 323,329 ----
  		    case LOC_REGPARM_ADDR:
  		    case LOC_BASEREG_ARG:
  		    case LOC_LOCAL_ARG:
+ 		    case LOC_COMPUTED_ARG:
  		      TYPE_FIELD_TYPE (ftype, iparams) = SYMBOL_TYPE (sym);
  		      TYPE_FIELD_ARTIFICIAL (ftype, iparams) = 0;
  		      iparams++;
*************** finish_block (struct symbol *symbol, str
*** 338,343 ****
--- 341,347 ----
  		    case LOC_BASEREG:
  		    case LOC_UNRESOLVED:
  		    case LOC_OPTIMIZED_OUT:
+ 		    case LOC_COMPUTED:
  		    default:
  		      break;
  		    }
Index: dwarf2expr.c
===================================================================
RCS file: dwarf2expr.c
diff -N dwarf2expr.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- dwarf2expr.c	11 Apr 2002 21:34:45 -0000
***************
*** 0 ****
--- 1,467 ----
+ 
+ #include "defs.h"
+ #include "symtab.h"
+ #include "gdbtypes.h"
+ #include "elf/dwarf2.h"
+ #include "dwarf2expr.h"
+ struct dwarf_expr_context * new_dwarf_expr_context()
+ {
+   struct dwarf_expr_context *retval = xcalloc (1, sizeof (struct dwarf_expr_context));
+   return retval;
+ }
+ void free_dwarf_expr_context (struct dwarf_expr_context *ctx)
+ {
+   free (ctx->stack);
+   free (ctx);  
+ }
+ static void dwarf_expr_grow_stack (struct dwarf_expr_context *ctx, size_t need)
+ {
+   if (ctx->stack_len + need > ctx->stack_allocated)
+     {
+       ctx->stack = xrealloc (ctx->stack, (ctx->stack_len + need) * sizeof (CORE_ADDR));
+       ctx->stack_allocated = ctx->stack_len + need;
+     }
+ }
+ void dwarf_expr_push (struct dwarf_expr_context *ctx, CORE_ADDR value)
+ {
+   dwarf_expr_grow_stack (ctx, 1);
+   ctx->stack[ctx->stack_len++] = value;
+ }
+ void dwarf_expr_pop (struct dwarf_expr_context *ctx)
+ {
+   ctx->stack_len--;
+ }
+ static void execute_stack_op2 (struct dwarf_expr_context *, unsigned char *, unsigned char *);
+ void dwarf_expr_eval (struct dwarf_expr_context *ctx, unsigned char *addr, size_t len)
+ {
+   execute_stack_op2 (ctx, addr, addr + len);
+ }
+ 
+ CORE_ADDR dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n)
+ {
+   if (ctx->stack_len < n)
+     (ctx->error) ("Asked for position %d of stack, stack only has %d elements on it\n", n, ctx->stack_len);
+   return ctx->stack[ctx->stack_len - (1+n)];
+ 
+ }     
+ /* 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 & 0x7f) << shift;
+       if ((byte & 0x80) == 0)
+ 	break;
+       shift += 7;
+     }
+   *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 & 0x7f) << shift;
+       shift += 7;
+       if ((byte & 0x80) == 0)
+ 	break;
+     }
+   if (shift < (sizeof (*r) * 8) && (byte & 0x40) != 0)
+     result |= - (1 << shift);
+   
+   *r = result;
+   return buf;
+ }
+ static void
+ execute_stack_op2 (struct dwarf_expr_context *ctx, unsigned char *op_ptr, unsigned char *op_end)
+ {
+   while (op_ptr < op_end)
+     {
+       enum dwarf_location_atom op = *op_ptr++;      
+       ULONGEST result, reg;
+       LONGEST offset;
+       ctx->in_reg = 0;
+       switch (op)
+ 	{
+ 	case DW_OP_lit0:
+ 	case DW_OP_lit1:
+ 	case DW_OP_lit2:
+ 	case DW_OP_lit3:
+ 	case DW_OP_lit4:
+ 	case DW_OP_lit5:
+ 	case DW_OP_lit6:
+ 	case DW_OP_lit7:
+ 	case DW_OP_lit8:
+ 	case DW_OP_lit9:
+ 	case DW_OP_lit10:
+ 	case DW_OP_lit11:
+ 	case DW_OP_lit12:
+ 	case DW_OP_lit13:
+ 	case DW_OP_lit14:
+ 	case DW_OP_lit15:
+ 	case DW_OP_lit16:
+ 	case DW_OP_lit17:
+ 	case DW_OP_lit18:
+ 	case DW_OP_lit19:
+ 	case DW_OP_lit20:
+ 	case DW_OP_lit21:
+ 	case DW_OP_lit22:
+ 	case DW_OP_lit23:
+ 	case DW_OP_lit24:
+ 	case DW_OP_lit25:
+ 	case DW_OP_lit26:
+ 	case DW_OP_lit27:
+ 	case DW_OP_lit28:
+ 	case DW_OP_lit29:
+ 	case DW_OP_lit30:
+ 	case DW_OP_lit31:
+ 	  result = op - DW_OP_lit0;
+ 	  break;
+           
+ 	case DW_OP_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 DW_OP_const1u:
+ 	  result = extract_unsigned_integer (op_ptr, 1);
+ 	  op_ptr += 1;
+ 	  break;
+ 	case DW_OP_const1s:
+ 	  result = extract_signed_integer (op_ptr, 1);
+ 	  op_ptr += 1;
+ 	  break;
+ 	case DW_OP_const2u:
+ 	  result = extract_unsigned_integer (op_ptr, 2);
+ 	  op_ptr += 2;
+ 	  break;
+ 	case DW_OP_const2s:
+ 	  result = extract_signed_integer (op_ptr, 2);
+ 	  op_ptr += 2;
+ 	  break;
+ 	case DW_OP_const4u:
+ 	  result = extract_unsigned_integer (op_ptr, 4);
+ 	  op_ptr += 4;
+ 	  break;
+ 	case DW_OP_const4s:
+ 	  result = extract_signed_integer (op_ptr, 4);
+ 	  op_ptr += 4;
+ 	  break;
+ 	case DW_OP_const8u:
+ 	  result = extract_unsigned_integer (op_ptr, 8);
+ 	  op_ptr += 8;
+ 	  break;
+ 	case DW_OP_const8s:
+ 	  result = extract_signed_integer (op_ptr, 8);
+ 	  op_ptr += 8;
+ 	  break;
+ 	case DW_OP_constu:
+ 	  op_ptr = read_uleb128 (op_ptr, &result);
+ 	  break;
+ 	case DW_OP_consts:
+ 	  op_ptr = read_sleb128 (op_ptr, &offset);
+ 	  result = offset;
+ 	  break;
+ 	  
+ 	case DW_OP_reg0:
+ 	case DW_OP_reg1:
+ 	case DW_OP_reg2:
+ 	case DW_OP_reg3:
+ 	case DW_OP_reg4:
+ 	case DW_OP_reg5:
+ 	case DW_OP_reg6:
+ 	case DW_OP_reg7:
+ 	case DW_OP_reg8:
+ 	case DW_OP_reg9:
+ 	case DW_OP_reg10:
+ 	case DW_OP_reg11:
+ 	case DW_OP_reg12:
+ 	case DW_OP_reg13:
+ 	case DW_OP_reg14:
+ 	case DW_OP_reg15:
+ 	case DW_OP_reg16:
+ 	case DW_OP_reg17:
+ 	case DW_OP_reg18:
+ 	case DW_OP_reg19:
+ 	case DW_OP_reg20:
+ 	case DW_OP_reg21:
+ 	case DW_OP_reg22:
+ 	case DW_OP_reg23:
+ 	case DW_OP_reg24:
+ 	case DW_OP_reg25:
+ 	case DW_OP_reg26:
+ 	case DW_OP_reg27:
+ 	case DW_OP_reg28:
+ 	case DW_OP_reg29:
+ 	case DW_OP_reg30:
+ 	case DW_OP_reg31:      
+ 	  {
+ 	    result = (ctx->read_reg) (ctx->read_reg_baton, op - DW_OP_reg0);
+ 	    ctx->in_reg = 1;
+ 	  }
+ 	  break;
+ 	case DW_OP_regx:  
+ 	  {
+ 	    op_ptr = read_uleb128 (op_ptr, &reg);
+ 	    result = (ctx->read_reg) (ctx->read_reg_baton, reg);
+ 	    ctx->in_reg = 1;
+ 	  }
+ 	  break;
+ 	case DW_OP_breg0:
+ 	case DW_OP_breg1:
+ 	case DW_OP_breg2:
+ 	case DW_OP_breg3:
+ 	case DW_OP_breg4:
+ 	case DW_OP_breg5:
+ 	case DW_OP_breg6:
+ 	case DW_OP_breg7:
+ 	case DW_OP_breg8:
+ 	case DW_OP_breg9:
+ 	case DW_OP_breg10:
+ 	case DW_OP_breg11:
+ 	case DW_OP_breg12:
+ 	case DW_OP_breg13:
+ 	case DW_OP_breg14:
+ 	case DW_OP_breg15:
+ 	case DW_OP_breg16:
+ 	case DW_OP_breg17:
+ 	case DW_OP_breg18:
+ 	case DW_OP_breg19:
+ 	case DW_OP_breg20:
+ 	case DW_OP_breg21:
+ 	case DW_OP_breg22:
+ 	case DW_OP_breg23:
+ 	case DW_OP_breg24:
+ 	case DW_OP_breg25:
+ 	case DW_OP_breg26:
+ 	case DW_OP_breg27:
+ 	case DW_OP_breg28:
+ 	case DW_OP_breg29:
+ 	case DW_OP_breg30:
+ 	case DW_OP_breg31:
+ 	  {           
+ 	    op_ptr = read_sleb128 (op_ptr, &offset);
+ 	    result = (ctx->read_reg) (ctx->read_reg_baton, op - DW_OP_breg0);
+ 	    result += offset;
+ 	  }
+ 	  break;
+ 	case DW_OP_bregx:
+ 	  {
+ 	    op_ptr = read_uleb128 (op_ptr, &reg);
+ 	    op_ptr = read_sleb128 (op_ptr, &offset);
+ 	    result = (ctx->read_reg) (ctx->read_reg_baton, reg);
+ 	    result += offset;
+ 	  }
+ 	  break;
+ 	case DW_OP_fbreg:
+ 	  {
+ 	    unsigned char *datastart;
+ 	    unsigned char *dataend;
+ 	    unsigned int before_stack_len;
+ 	    
+ 	    op_ptr = read_sleb128 (op_ptr, &offset);
+ 	    /* Rather than create a whole new context, we simply
+ 	       record the stack length before execution, then reset it
+ 	       afterwards, effectively erasing whatever the recursive
+ 	       call put there.  */
+ 	    before_stack_len = ctx->stack_len;
+ 	    (ctx->get_frame_base)(ctx->get_frame_base_baton, &datastart, &dataend);
+             dwarf_expr_eval (ctx, datastart, dataend - datastart);
+             result = dwarf_expr_fetch (ctx, 0) + offset;
+ 	    ctx->stack_len = before_stack_len;
+ 	    ctx->in_reg = 0;
+ 	  }
+ 	  break;
+ 	case DW_OP_dup:
+ 	  result = dwarf_expr_fetch (ctx, 0);
+ 	  break;
+           
+ 	case DW_OP_drop:
+           dwarf_expr_pop(ctx);
+ 	  goto no_push;
+           
+ 	case DW_OP_pick:
+ 	  offset = *op_ptr++;
+ 	  result = dwarf_expr_fetch (ctx, offset);
+ 	  break;
+           
+ 	case DW_OP_over:
+ 	  result = dwarf_expr_fetch (ctx, 1);
+ 	  break;
+ 	  
+ 	case DW_OP_rot:
+ 	  {
+ 	    CORE_ADDR t1, t2, t3;
+             
+ 	    if (ctx->stack_len < 3)
+ 	      (ctx->error) ("Not enough elements for DW_OP_rot. Need 3, have %d\n", ctx->stack_len);
+ 	    t1 = ctx->stack[ctx->stack_len - 1];
+ 	    t2 = ctx->stack[ctx->stack_len - 2];
+ 	    t3 = ctx->stack[ctx->stack_len - 3];
+ 	    ctx->stack[ctx->stack_len - 1] = t2;
+ 	    ctx->stack[ctx->stack_len - 2] = t3;
+ 	    ctx->stack[ctx->stack_len - 3] = t1;
+ 	    goto no_push;
+ 	  }
+           
+ 	case DW_OP_deref:
+ 	case DW_OP_deref_size:
+ 	case DW_OP_abs:
+ 	case DW_OP_neg:
+ 	case DW_OP_not:
+ 	case DW_OP_plus_uconst:
+ 	  /* Unary operations.  */
+ 	  result = dwarf_expr_fetch (ctx, 0);
+ 	  dwarf_expr_pop (ctx);
+ 
+ 	  switch (op)
+ 	    {
+ 	    case DW_OP_deref:
+ 	      {
+ 		result = (CORE_ADDR) (ctx->read_mem) (ctx->read_mem_baton, result, TARGET_PTR_BIT / TARGET_CHAR_BIT);
+ 	      }
+ 	      break;
+               
+ 	    case DW_OP_deref_size:
+ 	      {
+ 		result = (ctx->read_mem) (ctx->read_mem_baton, result, *op_ptr++);		
+ 	      }
+ 	      break;
+               
+ 	    case DW_OP_abs:
+ 	      if ((signed int) result < 0)
+ 		result = -result;
+ 	      break;
+ 	    case DW_OP_neg:
+ 	      result = -result;
+ 	      break;
+ 	    case DW_OP_not:
+ 	      result = ~result;
+ 	      break;
+ 	    case DW_OP_plus_uconst:
+ 	      op_ptr = read_uleb128 (op_ptr, &reg);
+ 	      result += reg;
+ 	      break;
+ 	    }
+ 	  break;
+           
+ 	case DW_OP_and:
+ 	case DW_OP_div:
+ 	case DW_OP_minus:
+ 	case DW_OP_mod:
+ 	case DW_OP_mul:
+ 	case DW_OP_or:
+ 	case DW_OP_plus:
+ 	case DW_OP_le:
+ 	case DW_OP_ge:
+ 	case DW_OP_eq:
+ 	case DW_OP_lt:
+ 	case DW_OP_gt:
+ 	case DW_OP_ne:
+ 	  {
+ 	    /* Binary operations.  */
+ 	    CORE_ADDR first, second;
+ 	    second = dwarf_expr_fetch (ctx, 0);
+ 	    first = dwarf_expr_fetch (ctx, 1);
+ 	    dwarf_expr_pop (ctx);
+ 	    dwarf_expr_pop (ctx);
+ 	    switch (op)
+ 	      {
+ 	      case DW_OP_and:
+ 		result = second & first;
+ 		break;
+ 	      case DW_OP_div:
+ 		result = (LONGEST)second / (LONGEST)first;
+ 		break;
+ 	      case DW_OP_minus:
+ 		result = second - first;
+ 		break;
+ 	      case DW_OP_mod:
+ 		result = (LONGEST)second % (LONGEST)first;
+ 		break;
+ 	      case DW_OP_mul:
+ 		result = second * first;
+ 		break;
+ 	      case DW_OP_or:
+ 		result = second | first;
+ 		break;
+ 	      case DW_OP_plus:
+ 		result = second + first;
+ 		break;
+ 	      case DW_OP_shl:
+ 		result = second << first;
+ 		break;
+ 	      case DW_OP_shr:
+ 		result = second >> first;
+ 		break;
+ 	      case DW_OP_shra:
+ 		result = (LONGEST)second >> first;
+ 		break;
+ 	      case DW_OP_xor:
+ 		result = second ^ first;
+ 		break;
+ 	      case DW_OP_le:
+ 		result = (LONGEST)first <= (LONGEST)second;
+ 		break;
+ 	      case DW_OP_ge:
+ 		result = (LONGEST)first >= (LONGEST)second;
+ 		break;
+ 	      case DW_OP_eq:
+ 		result = (LONGEST)first == (LONGEST)second;
+ 		break;
+ 	      case DW_OP_lt:
+ 		result = (LONGEST)first < (LONGEST)second;
+ 		break;
+ 	      case DW_OP_gt:
+ 		result = (LONGEST)first > (LONGEST)second;
+ 		break;
+ 	      case DW_OP_ne:
+ 		result = (LONGEST)first != (LONGEST)second;
+ 		break;
+ 	      }
+ 	  }
+ 	  break;
+           
+ 	case DW_OP_skip:
+ 	  offset = extract_signed_integer (op_ptr, 2);
+ 	  op_ptr += 2;
+ 	  op_ptr += offset;
+ 	  goto no_push;
+           
+ 	case DW_OP_bra:
+ 	  offset = extract_signed_integer (op_ptr, 2);
+ 	  op_ptr += 2;
+ 	  if (dwarf_expr_fetch (ctx, 0) != 0)
+ 	    op_ptr += offset;
+ 	  dwarf_expr_pop (ctx);
+ 	  goto no_push;
+           
+ 	case DW_OP_nop:
+ 	  goto no_push;
+           
+ 	default:
+ 	  abort ();
+          }
+       
+       /* Most things push a result value.  */
+       dwarf_expr_push (ctx, result);
+     no_push:;
+     }   
+ }
Index: dwarf2expr.h
===================================================================
RCS file: dwarf2expr.h
diff -N dwarf2expr.h
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- dwarf2expr.h	11 Apr 2002 21:34:45 -0000
***************
*** 0 ****
--- 1,55 ----
+ #if !defined (DWARF2EXPR_H)
+ #define DWARF2EXPR_H
+ struct dwarf_expr_context
+ {
+   /* The stack of values, allocated with xmalloc.  */
+   CORE_ADDR *stack;
+ 
+   /* The number of values currently pushed on the stack, and the
+      number of elements allocated to the stack.  */
+   int stack_len, stack_allocated;
+ 
+   /* The size of an address, in bits.  */
+   int addr_size;
+ 
+   /* Return the value of register number REGNUM.  */
+   CORE_ADDR (*read_reg) (void *baton, int regnum);
+   void *read_reg_baton;
+ 
+   /* Return the LEN-byte value at ADDR.  */
+   CORE_ADDR (*read_mem) (void *baton, CORE_ADDR addr, size_t len);
+   void *read_mem_baton;
+ 
+   /* Return the location expression for the frame base attribute.  The
+      result must be live until the current expression evaluation is
+      complete.  */
+   void (*get_frame_base) (void *baton, unsigned char **begin, unsigned char **end);
+   void *get_frame_base_baton;
+ 
+   /* Return the location expression for the dwarf expression
+      subroutine in the die at OFFSET in the current compilation unit.
+      The result must be live until the current expression evaluation
+      is complete.  */
+   unsigned char *(*get_subr) (void *baton, off_t offset);
+   void *get_subr_baton;
+ 
+   /* Return the `object address' for DW_OP_push_object_address.  */
+   CORE_ADDR (*get_object_address) (void *baton);
+   void *get_object_address_baton;
+ 
+   /* The current depth of dwarf expression recursion, via DW_OP_call*,
+      DW_OP_fbreg, DW_OP_push_object_address, etc., and the maximum
+      depth we'll tolerate before raising an error.  */
+   int recursion_depth, max_recursion_depth;
+ 
+   int in_reg;
+ 
+   void (*error) (const char *fmt, ...);
+ };
+ struct dwarf_expr_context * new_dwarf_expr_context();
+ void free_dwarf_expr_context (struct dwarf_expr_context *ctx);
+ void dwarf_expr_push (struct dwarf_expr_context *ctx, CORE_ADDR value);
+ void dwarf_expr_pop (struct dwarf_expr_context *ctx);
+ void dwarf_expr_eval (struct dwarf_expr_context *ctx, unsigned char *addr, size_t len);
+ CORE_ADDR dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n);
+ #endif
Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.52
diff -c -3 -p -w -B -b -r1.52 dwarf2read.c
*** dwarf2read.c	4 Apr 2002 22:26:43 -0000	1.52
--- dwarf2read.c	11 Apr 2002 21:34:47 -0000
***************
*** 45,50 ****
--- 45,55 ----
  #include "gdb_string.h"
  #include "gdb_assert.h"
  #include <sys/types.h>
+ #include "ui-out.h"
+ #include "value.h"
+ #include "frame.h"
+ #include "gdbcore.h"
+ #include "dwarf2expr.h"
  
  #ifndef DWARF2_REG_TO_REGNUM
  #define DWARF2_REG_TO_REGNUM(REG) (REG)
*************** static struct abbrev_info *dwarf_alloc_a
*** 808,813 ****
--- 813,839 ----
  
  static struct die_info *dwarf_alloc_die (void);
  
+ 
+ static struct value * locexpr_read_variable (void *baton, struct frame_info *frame);
+ 
+ static int locexpr_read_needs_frame (void *baton);
+ 
+ static int locexpr_describe_location (void *baton, struct ui_file *stream);
+ 
+ static struct location_funcs locexpr_funcs = { 
+   locexpr_read_variable,
+   locexpr_read_needs_frame,
+   locexpr_describe_location,
+   NULL
+ };
+ 
+ struct locexpr_baton
+ {
+   struct symbol * sym;
+   struct dwarf_block locexpr;
+   struct objfile *obj;
+ };
+ 
  static void initialize_cu_func_list (void);
  
  static void add_to_cu_func_list (const char *, CORE_ADDR, CORE_ADDR);
*************** read_func_scope (struct die_info *die, s
*** 1710,1716 ****
    struct die_info *child_die;
    struct attribute *attr;
    char *name;
! 
    name = dwarf2_linkage_name (die);
  
    /* Ignore functions with missing or empty names and functions with
--- 1737,1743 ----
    struct die_info *child_die;
    struct attribute *attr;
    char *name;
!   struct locexpr_baton *baton;
    name = dwarf2_linkage_name (die);
  
    /* Ignore functions with missing or empty names and functions with
*************** read_func_scope (struct die_info *die, s
*** 1754,1759 ****
--- 1781,1800 ----
  
    new = push_context (0, lowpc);
    new->name = new_symbol (die, die->type, objfile, cu_header);
+ 
+   /* If it has a location expression for fbreg, record it.  
+      Since not all symbols use location expressions exclusively yet,
+      we still need to decode it above. */
+   if (attr)
+     {
+       baton = obstack_alloc (&objfile->symbol_obstack, sizeof (struct locexpr_baton));
+       baton->sym = new->name;
+       baton->obj = objfile;
+       memcpy (&baton->locexpr, DW_BLOCK (attr), sizeof (struct dwarf_block));
+       SYMBOL_LOCATION_FUNCS (new->name) = &locexpr_funcs;
+       SYMBOL_LOCATION_BATON (new->name) = baton;
+     }
+ 
    list_in_scope = &local_symbols;
  
    if (die->has_children)
*************** new_symbol (struct die_info *die, struct
*** 4397,4460 ****
  	  attr = dwarf_attr (die, DW_AT_location);
  	  if (attr)
  	    {
  	      attr2 = dwarf_attr (die, DW_AT_external);
  	      if (attr2 && (DW_UNSND (attr2) != 0))
- 		{
- 		  SYMBOL_VALUE_ADDRESS (sym) =
- 		    decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
  		  add_symbol_to_list (sym, &global_symbols);
- 
- 		  /* In shared libraries the address of the variable
- 		     in the location descriptor might still be relocatable,
- 		     so its value could be zero.
- 		     Enter the symbol as a LOC_UNRESOLVED symbol, if its
- 		     value is zero, the address of the variable will then
- 		     be determined from the minimal symbol table whenever
- 		     the variable is referenced.  */
- 		  if (SYMBOL_VALUE_ADDRESS (sym))
- 		    {
- 		      fixup_symbol_section (sym, objfile);
- 		      SYMBOL_VALUE_ADDRESS (sym) +=
- 			ANOFFSET (objfile->section_offsets,
- 			          SYMBOL_SECTION (sym));
- 		      SYMBOL_CLASS (sym) = LOC_STATIC;
- 		    }
- 		  else
- 		    SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
- 		}
  	      else
- 		{
- 		  SYMBOL_VALUE (sym) = addr =
- 		    decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
  		  add_symbol_to_list (sym, list_in_scope);
- 		  if (optimized_out)
- 		    {
- 		      SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
- 		    }
- 		  else if (isreg)
- 		    {
- 		      SYMBOL_CLASS (sym) = LOC_REGISTER;
- 		      SYMBOL_VALUE (sym) = 
- 			DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym));
- 		    }
- 		  else if (offreg)
- 		    {
- 		      SYMBOL_CLASS (sym) = LOC_BASEREG;
- 		      SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
- 		    }
- 		  else if (islocal)
- 		    {
- 		      SYMBOL_CLASS (sym) = LOC_LOCAL;
- 		    }
- 		  else
- 		    {
- 		      fixup_symbol_section (sym, objfile);
- 		      SYMBOL_VALUE_ADDRESS (sym) =
- 		        addr + ANOFFSET (objfile->section_offsets,
- 			                 SYMBOL_SECTION (sym));
- 		      SYMBOL_CLASS (sym) = LOC_STATIC;
- 		    }
- 		}
  	    }
  	  else
  	    {
--- 4438,4457 ----
  	  attr = dwarf_attr (die, DW_AT_location);
  	  if (attr)
  	    {
+ 	      struct locexpr_baton *baton = obstack_alloc (&objfile->symbol_obstack, 
+ 							   sizeof (struct locexpr_baton));
+ 	      baton->sym = sym;
+ 	      memcpy (&baton->locexpr, DW_BLOCK (attr), sizeof (struct dwarf_block));
+ 	      baton->obj = objfile;
+ 	      SYMBOL_CLASS (sym) = LOC_COMPUTED;
+ 	      SYMBOL_LOCATION_FUNCS (sym) = &locexpr_funcs;
+ 	      SYMBOL_LOCATION_BATON (sym) = baton;
+ 	      
  	      attr2 = dwarf_attr (die, DW_AT_external);
                if (attr2 && (DW_UNSND (attr2) != 0))
  		add_symbol_to_list (sym, &global_symbols);
                else
  		add_symbol_to_list (sym, list_in_scope);
  	    }
  	  else
  	    {
*************** dwarf_alloc_die (void)
*** 6218,6221 ****
--- 6215,6338 ----
    die = (struct die_info *) xmalloc (sizeof (struct die_info));
    memset (die, 0, sizeof (struct die_info));
    return (die);
+ }
+ 
+ static struct value * evaluate_loc_desc (struct symbol *, struct frame_info *, 
+ 					 struct dwarf_block *, struct type *);
+ 
+ /* This is one of the struct location functions. It returns the value
+    of a variable, given our baton and a frame.  */
+ static struct value *
+ locexpr_read_variable (void *baton, struct frame_info *frame)
+ {
+   struct locexpr_baton *dlbaton = (struct locexpr_baton *) baton;
+   struct value * val;
+   val = evaluate_loc_desc (dlbaton->sym, frame, 
+ 			   &dlbaton->locexpr, SYMBOL_TYPE (dlbaton->sym));
+   return val;
+ }
+ 
+ /* This is a struct location function, this one returns 1 if we need a
+    frame to read the value of the variable. */
+ static int 
+ locexpr_read_needs_frame (void *baton)
+ {
+   return 1;
+ }
+ 
+ /* This is a struct location function, it describes the location in
+    english. */
+ static int 
+ locexpr_describe_location (void *baton, struct ui_file *stream)
+ {
+   fprintf_filtered (stream, "a DWARF2 location expression evaluated at runtime");
+   return 1;
+ }
+ 
+ /* This is the baton used when performing dwarf2 expression
+    evaluation.  */
+ struct dwarf_expr_baton
+ {
+   struct symbol *var;
+   struct frame_info *frame;
+ };
+ 
+ /* Read a register for the dwarf2 expression evaluator.  */
+ CORE_ADDR dwarf_expr_read_reg (void *baton, int regnum)
+ {
+   CORE_ADDR result;
+   struct dwarf_expr_baton  *debaton = (struct dwarf_expr_baton *)baton;
+   char * buf = (char *) alloca (MAX_REGISTER_RAW_SIZE);
+   get_saved_register (buf, NULL, NULL, debaton->frame, regnum, NULL);
+   result = extract_address  (buf, REGISTER_RAW_SIZE (regnum));
+   return result;
+ }
+ 
+ /* Read memory for the dwarf2 expression evaluator.  */
+ CORE_ADDR dwarf_expr_read_mem (void *baton, CORE_ADDR addr, size_t len)
+ {
+   return (CORE_ADDR) read_memory_unsigned_integer (addr, len);
+ }
+ 
+ /* Get the frame base location expression for the dwarf2 expression
+    evaluator.  */
+ void dwarf_expr_frame_base (void *baton, unsigned char **begin, unsigned char **end)
+ {
+   struct symbol *framefunc;
+   struct locexpr_baton *symbaton; 
+   struct dwarf_block *theblock;
+   struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *)baton;
+   framefunc = get_frame_function (debaton->frame);
+   symbaton = SYMBOL_LOCATION_BATON (framefunc);
+   theblock = &symbaton->locexpr;
+   *begin = theblock->data;
+   *end = theblock->data + theblock->size;
+ }
+ 
+ /* Evaluate a location description, given in THEBLOCK, in the
+    context of frame FRAME. */
+ static struct value *
+ evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
+ 		   struct dwarf_block *theblock, struct type *type)
+ {
+   CORE_ADDR result;
+   struct value * retval;
+   struct dwarf_expr_baton *baton = xmalloc (sizeof (struct dwarf_expr_baton));
+   struct dwarf_expr_context *ctx;
+   
+   retval = allocate_value(type);
+   baton->var = var;
+   baton->frame = frame;
+   
+   VALUE_LVAL (retval) = lval_memory;
+   VALUE_BFD_SECTION (retval) = SYMBOL_BFD_SECTION (var);
+   
+   ctx = new_dwarf_expr_context ();
+   ctx->read_reg_baton = baton;
+   ctx->read_reg = dwarf_expr_read_reg;
+   ctx->read_mem_baton = baton;
+   ctx->read_mem = dwarf_expr_read_mem;
+   ctx->get_frame_base_baton = baton;
+   ctx->get_frame_base = dwarf_expr_frame_base;
+   ctx->error = error;
+   
+   dwarf_expr_eval (ctx, theblock->data, theblock->size);
+   
+   if (ctx->in_reg)
+     {
+       store_typed_address (VALUE_CONTENTS_RAW (retval), 
+ 			   SYMBOL_TYPE (var), dwarf_expr_fetch (ctx, 0));
+       VALUE_LVAL (retval) = not_lval;
+     }
+   else
+     {
+       result = dwarf_expr_fetch (ctx, 0);
+       VALUE_LAZY (retval) = 1;
+       VALUE_ADDRESS (retval) = result;
+     }
+   
+   free_dwarf_expr_context (ctx);
+   free (baton);
+   
+   return retval;
  }
Index: findvar.c
===================================================================
RCS file: /cvs/src/src/gdb/findvar.c,v
retrieving revision 1.31
diff -c -3 -p -w -B -b -r1.31 findvar.c
*** findvar.c	9 Apr 2002 03:06:13 -0000	1.31
--- findvar.c	11 Apr 2002 21:34:47 -0000
*************** symbol_read_needs_frame (struct symbol *
*** 375,380 ****
--- 375,384 ----
      {
        /* All cases listed explicitly so that gcc -Wall will detect it if
           we failed to consider one.  */
+     case LOC_COMPUTED:
+     case LOC_COMPUTED_ARG:
+       return (SYMBOL_LOCATION_FUNCS(sym)->read_needs_frame) (SYMBOL_LOCATION_BATON(sym));
+ 
      case LOC_REGISTER:
      case LOC_ARG:
      case LOC_REF_ARG:
*************** addresses have not been bound by the dyn
*** 581,587 ****
--- 585,602 ----
  	  }
        }
        break;
+     case LOC_COMPUTED:
+     case LOC_COMPUTED_ARG:
+       {
+ 	struct location_funcs *funcs = SYMBOL_LOCATION_FUNCS (var);
+ 	void *baton = SYMBOL_LOCATION_BATON (var);
+ 	
+ 	if (frame == 0 && (funcs->read_needs_frame)(baton))
+ 	  return 0;
+ 	return (funcs->read_variable) (baton, frame);
  	
+       }
+       break;
      case LOC_UNRESOLVED:
        {
  	struct minimal_symbol *msym;
Index: printcmd.c
===================================================================
RCS file: /cvs/src/src/gdb/printcmd.c,v
retrieving revision 1.38
diff -c -3 -p -w -B -b -r1.38 printcmd.c
*** printcmd.c	5 Apr 2002 22:04:41 -0000	1.38
--- printcmd.c	11 Apr 2002 21:34:48 -0000
*************** address_info (char *exp, int from_tty)
*** 1181,1186 ****
--- 1181,1190 ----
  	}
        break;
  
+     case LOC_COMPUTED:
+     case LOC_COMPUTED_ARG:
+       (SYMBOL_LOCATION_FUNCS (sym)->describe_location)(SYMBOL_LOCATION_BATON (sym), gdb_stdout);
+       break;
      case LOC_REGISTER:
        printf_filtered ("a variable in register %s", REGISTER_NAME (val));
        break;
Index: stack.c
===================================================================
RCS file: /cvs/src/src/gdb/stack.c,v
retrieving revision 1.33
diff -c -3 -p -w -B -b -r1.33 stack.c
*** stack.c	10 Apr 2002 23:32:33 -0000	1.33
--- stack.c	11 Apr 2002 21:34:50 -0000
*************** print_block_frame_locals (struct block *
*** 1173,1178 ****
--- 1173,1179 ----
  	case LOC_REGISTER:
  	case LOC_STATIC:
  	case LOC_BASEREG:
+         case LOC_COMPUTED:
  	  values_printed = 1;
  	  for (j = 0; j < num_tabs; j++)
  	    fputs_filtered ("\t", stream);
Index: symmisc.c
===================================================================
RCS file: /cvs/src/src/gdb/symmisc.c,v
retrieving revision 1.8
diff -c -3 -p -w -B -b -r1.8 symmisc.c
*** symmisc.c	22 Mar 2002 18:57:08 -0000	1.8
--- symmisc.c	11 Apr 2002 21:34:50 -0000
*************** print_partial_symbols (struct partial_sy
*** 860,865 ****
--- 860,869 ----
  	case LOC_OPTIMIZED_OUT:
  	  fputs_filtered ("optimized out", outfile);
  	  break;
+ 	case LOC_COMPUTED:
+ 	case LOC_COMPUTED_ARG:
+ 	  fputs_filtered ("computed at runtime", outfile);
+ 	  break;
  	default:
  	  fputs_filtered ("<invalid location>", outfile);
  	  break;
Index: symtab.h
===================================================================
RCS file: /cvs/src/src/gdb/symtab.h,v
retrieving revision 1.30
diff -c -3 -p -w -B -b -r1.30 symtab.h
*** symtab.h	9 Apr 2002 20:51:33 -0000	1.30
--- symtab.h	11 Apr 2002 21:34:51 -0000
***************
*** 29,35 ****
  #define obstack_chunk_alloc xmalloc
  #define obstack_chunk_free xfree
  #include "bcache.h"
! 
  /* Don't do this; it means that if some .o's are compiled with GNU C
     and some are not (easy to do accidentally the way we configure
     things; also it is a pain to have to "make clean" every time you
--- 29,36 ----
  #define obstack_chunk_alloc xmalloc
  #define obstack_chunk_free xfree
  #include "bcache.h"
! struct axs_value;
! struct agent_expr;
  /* Don't do this; it means that if some .o's are compiled with GNU C
     and some are not (easy to do accidentally the way we configure
     things; also it is a pain to have to "make clean" every time you
*************** enum address_class
*** 604,610 ****
       * with a level of indirection.
       */
  
!     LOC_INDIRECT
  
    };
  
--- 605,661 ----
       * with a level of indirection.
       */
  
!     LOC_INDIRECT,
!     
!     /* The variable address is computed by a set of location
!        functions.  */
!     LOC_COMPUTED,
!     
!     /* The variable is an argument, and it's address is computed by a
!        set of location functions.  */
!     LOC_COMPUTED_ARG
! 
!   };
! 
! /* A structure of function pointers describing the location of a
!    variable, structure member, or structure base class.
!    
!    These functions' BATON arguments are generic data pointers, holding
!    whatever data the functions need --- the code which provides this
!    structure also provides the actual contents of the baton, and
!    decides its form.  However, there may be other rules about where
!    the baton data must be allocated; whoever is pointing to this
!    `struct location_funcs' object will know the rules.  For example,
!    when a symbol S's location is LOC_COMPUTED, then
!    SYMBOL_LOCATION_FUNCS(S) is pointing to a location_funcs structure,
!    and SYMBOL_LOCATION_BATON(S) is the baton, which must be allocated
!    on the same obstack as the symbol itself.  */
! 
! struct location_funcs {
!   
!   /* Return the value of the variable described by BATON, relative to
!      the stack frame FRAME.  If the variable has been optimized
!      out, return zero.
! 
!      If `read_needs_frame (BATON)' is zero, then FRAME may be
!      zero.  */
!   struct value *(*read_variable) (void *baton, struct frame_info *frame);
!   
!   /* Return true if we need a frame to find the value of the object
!      described by BATON.  */
!   int (*read_needs_frame) (void *baton);
!   
!   /* Write to STREAM a natural-language description of the location of
!      the object described by BATON.  */
!   int (*describe_location) (void *baton, struct ui_file *stream);
!   
!   /* Tracepoint support.  Append bytecodes to the tracepoint agent
!      expression AX that push the address of the object described by
!      BATON.  Set VALUE appropriately.  Note --- for objects in
!      registers, this needn't emit any code; as long as it sets VALUE
!      properly, then the caller will generate the right code in the
!      process of treating this as an lvalue or rvalue.  */ void
!    (*tracepoint_var_ref) (void *baton, struct agent_expr *ax, struct axs_value *value);
  
  };
  
*************** struct symbol
*** 661,666 ****
--- 712,719 ----
        {
  	/* Used by LOC_BASEREG and LOC_BASEREG_ARG.  */
  	short basereg;
+ 	/* Location baton to pass to location functions.  */
+ 	void *locbaton;
        }
      aux_value;
  
*************** struct symbol
*** 672,677 ****
--- 725,734 ----
      /* List of ranges where this symbol is active.  This is only
         used by alias symbols at the current time.  */
      struct range_list *ranges;
+     
+     /* Location functions for LOC_COMPUTED and LOC_COMPUTED_ARGS.  */
+     struct location_funcs *locfuncs;
+     
    };
  
  
*************** struct symbol
*** 682,687 ****
--- 739,746 ----
  #define SYMBOL_BASEREG(symbol)		(symbol)->aux_value.basereg
  #define SYMBOL_ALIASES(symbol)		(symbol)->aliases
  #define SYMBOL_RANGES(symbol)		(symbol)->ranges
+ #define SYMBOL_LOCATION_BATON(symbol)   (symbol)->aux_value.locbaton
+ #define SYMBOL_LOCATION_FUNCS(symbol)   (symbol)->locfuncs
  
  /* A partial_symbol records the name, namespace, and address class of
     symbols whose types we have not parsed yet.  For functions, it also


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]