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]

RFA: LOC_COMPUTED support


Here we go again.  I've been staring at this patch for a couple of days, so
my description of it may be slightly incoherent.  Let me know if I miss
anything major.

First, overview, pretty much unchanged from when Daniel Berlin posted it:
we add two new address classes, LOC_COMPUTED and LOC_COMPUTED_ARG, whose
address must be determined by calling some set of runtime functions provided
by the symbol reader.

There are a lot of little structural changes from Daniel's patch; for
instance, I moved some code from dwarf2read.c out into a new file, because
the idea of including things like "target.h" and "inferior.h" in a debug
reader bothered me a little.  I also shrunk the size of the batons a bit.

Two things that Jim commented on as problems with the original patch are
still here, because on reflection I thought it was better this way: the use
of get_frame_function and the function's aux_value union to hold the frame
base, and the use of pointers directly into the .debug_info (eventually
.debug_loc) data.  The former is for memory reasons, among others; Jim's
suggestion of each symbol having a pointer to the frame base would increase
the per-symbol memory for all LOC_COMPUTED* symbols, since we can't easily
tell which symbols will need the frame base and which won't.  The latter is
because we never get rid of it anyway, so why duplicate the data?  When
someone tackles cleanups in the reader to let us free the sections, then we
can talk about alternate memory management.

Of course, if you aren't convinced by my reasoning, let's talk about it.


Particularly notable bits are the comments in var_decode_location.  I've
verified that I got both the LOC_STATIC and relocated symbols bits correct;
it would be nice to kill the LOC_STATIC hack but that requires cleaning up
the ways we handle section offsets, and that's way too murky for me right
now.


Jim/Elena, I realize this patch is large and fairly dense but I'd appreciate
it if you could look over it soon.  I believe I'm going to wait on location
lists until I've at least gotten some feedback on this patch, and we're
under some pressure from the GCC side to get that working.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

2003-02-03  Daniel Jacobowitz  <drow@mvista.com>

	Based on a patch from Daniel Berlin (dberlin@dberlin.org).
	* symtab.h: Add opaque declarations of struct axs_value and
	struct agent_expr.
	(enum address_class): Add LOC_COMPUTED and LOC_COMPUTED_ARG.
	(struct location_funcs): New type.
	(struct symbol): Add "loc" to aux_value.
	(SYMBOL_LOCATION_BATON, SYMBOL_LOCATION_FUNCS): New macros.
	* dwarf2read.c: Include "dwarf2expr.h".
	(dwarf2_symbol_mark_computed): New function.
	(read_func_scope): Use it.
	(var_decode_location): New function.
	(new_symbol): Use it.
	* dwarf2expr.c, dwarf2expr.h, dwarf2loc.c: New files.

	* Makefile.in (SFILES): Add dwarf2loc.c and dwarf2expr.c.
	(dwarf2expr_h): New variable.
	(COMMON_OBS): Add dwarf2expr.o and dwarf2loc.o.
	(dwarf2expr.o, dwarf2loc.o): New rules.
	(dwarf2read.o): Add $(dwarf2expr_h).
	* buildsym.c (finish_block): Handle LOC_COMPUTED and
	LOC_COMPUTED_ARG.
	* findvar.c (symbol_read_needs_frame, read_var_value): Likewise.
	* m2-exp.y (yylex): Likewise.
	* printcmd.c (address_info, print_frame_args): Likewise.
	* stack.c (print_block_frame_locals, print_frame_arg_vars): Likewise.
	* symmisc.c (print_symbol, print_partial_symbols): Likewise.

Index: Makefile.in
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/Makefile.in,v
retrieving revision 1.323
diff -u -p -r1.323 Makefile.in
--- Makefile.in	31 Jan 2003 20:43:53 -0000	1.323
+++ Makefile.in	3 Feb 2003 16:24:14 -0000
@@ -510,7 +510,7 @@ SFILES = ada-exp.y ada-lang.c ada-typepr
 	charset.c cli-out.c coffread.c complaints.c completer.c corefile.c \
 	cp-abi.c cp-support.c cp-valprint.c \
 	dbxread.c demangle.c disasm.c doublest.c \
-	dummy-frame.c dwarfread.c dwarf2read.c \
+	dummy-frame.c dwarfread.c dwarf2expr.c dwarf2loc.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 frame.c \
 	frame-unwind.c \
@@ -622,6 +622,7 @@ doublest_h = doublest.h $(floatformat_h)
 dst_h = dst.h
 dummy_frame_h = dummy-frame.h
 dwarf2cfi_h = dwarf2cfi.h
+dwarf2expr_h = dwarf2expr.h
 environ_h = environ.h
 event_loop_h = event-loop.h
 event_top_h = event-top.h
@@ -827,6 +828,7 @@ COMMON_OBS = version.o blockframe.o brea
 	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 \
+	dwarf2expr.o dwarf2loc.o \
 	c-lang.o f-lang.o \
 	ui-out.o cli-out.o \
 	varobj.o wrapper.o \
@@ -1610,6 +1612,10 @@ disasm.o: disasm.c $(defs_h) $(gdb_strin
 doublest.o: doublest.c $(defs_h) $(doublest_h) $(floatformat_h) \
 	$(gdb_assert_h) $(gdb_string_h) $(gdbtypes_h)
 dpx2-nat.o: dpx2-nat.c $(defs_h) $(gdbcore_h) $(gdb_string_h)
+dwarf2expr.o: dwarf2expr.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(value_h) \
+	 $(gdbcore_h) $(dwarf2expr_h)
+dwarf2loc.o: dwarf2loc.c $(defs_h) $(ui_out_h) $(value_h) $(frame_h) \
+	$(gdbcore_h) $(target_h) $(inferior_h) $(dwarf2expr_h)
 dsrec.o: dsrec.c $(defs_h) $(serial_h) $(srec_h)
 dummy-frame.o: dummy-frame.c $(defs_h) $(dummy_frame_h) $(regcache_h) \
 	$(frame_h) $(inferior_h) $(gdb_assert_h) $(frame_unwind_h)
@@ -1621,8 +1627,8 @@ dwarf2cfi.o: dwarf2cfi.c $(defs_h) $(gdb
 dwarf2read.o: dwarf2read.c $(defs_h) $(bfd_h) $(symtab_h) $(gdbtypes_h) \
 	$(symfile_h) $(objfiles_h) $(elf_dwarf2_h) $(buildsym_h) \
 	$(demangle_h) $(expression_h) $(filenames_h) $(macrotab_h) \
-	$(language_h) $(complaints_h) $(bcache_h) $(gdb_string_h) \
-	$(gdb_assert_h)
+	$(language_h) $(complaints_h) $(bcache_h) $(dwarf2expr_h) \
+	$(gdb_string_h) $(gdb_assert_h)
 dwarfread.o: dwarfread.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(symfile_h) \
 	$(objfiles_h) $(elf_dwarf_h) $(buildsym_h) $(demangle_h) \
 	$(expression_h) $(language_h) $(complaints_h) $(gdb_string_h)
Index: buildsym.c
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/buildsym.c,v
retrieving revision 1.27
diff -u -p -r1.27 buildsym.c
--- buildsym.c	14 Jan 2003 00:15:05 -0000	1.27
+++ buildsym.c	3 Feb 2003 16:24:14 -0000
@@ -308,6 +308,7 @@ finish_block (struct symbol *symbol, str
 		case LOC_REGPARM_ADDR:
 		case LOC_BASEREG_ARG:
 		case LOC_LOCAL_ARG:
+		case LOC_COMPUTED_ARG:
 		  nparams++;
 		  break;
 		case LOC_UNDEF:
@@ -323,6 +324,7 @@ finish_block (struct symbol *symbol, str
 		case LOC_BASEREG:
 		case LOC_UNRESOLVED:
 		case LOC_OPTIMIZED_OUT:
+		case LOC_COMPUTED:
 		default:
 		  break;
 		}
@@ -344,6 +346,7 @@ finish_block (struct symbol *symbol, str
 		    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++;
@@ -361,6 +364,7 @@ finish_block (struct symbol *symbol, str
 		    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	3 Feb 2003 16:28:43 -0000
@@ -0,0 +1,626 @@
+/* Dwarf2 Expression Evaluator
+   Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+   Contributed by Daniel Berlin (dan@dberlin.org)
+
+   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 "gdbtypes.h"
+#include "value.h"
+#include "gdbcore.h"
+#include "elf/dwarf2.h"
+#include "dwarf2expr.h"
+
+/* Local prototypes.  */
+
+static void execute_stack_op (struct dwarf_expr_context *,
+			      unsigned char *, unsigned char *);
+
+/* Create a new context for the expression evaluator.  */
+
+struct dwarf_expr_context *
+new_dwarf_expr_context ()
+{
+  struct dwarf_expr_context *retval;
+  retval = xcalloc (1, sizeof (struct dwarf_expr_context));
+  retval->stack_len = 10;
+  retval->stack = xmalloc (10 * sizeof (CORE_ADDR));
+  return retval;
+}
+
+/* Release the memory allocated to CTX.  */
+
+void
+free_dwarf_expr_context (struct dwarf_expr_context *ctx)
+{
+  xfree (ctx->stack);
+  xfree (ctx);
+}
+
+/* Expand the memory allocated to CTX's stack to contain at least
+   NEED elements.  */
+
+static void
+dwarf_expr_grow_stack (struct dwarf_expr_context *ctx, size_t need)
+{
+  if (ctx->stack_len + need > ctx->stack_allocated)
+    {
+      size_t templen = ctx->stack_len * 2;
+      while (templen < (ctx->stack_len + need))
+	   templen *= 2;
+      ctx->stack = xrealloc (ctx->stack,
+			     templen * sizeof (CORE_ADDR));
+      ctx->stack_allocated = templen;
+    }
+}
+
+/* Push VALUE onto CTX's stack.  */
+
+void
+dwarf_expr_push (struct dwarf_expr_context *ctx, CORE_ADDR value)
+{
+  dwarf_expr_grow_stack (ctx, 1);
+  ctx->stack[ctx->stack_len++] = value;
+}
+
+/* Pop the top item off of CTX's stack.  */
+
+void
+dwarf_expr_pop (struct dwarf_expr_context *ctx)
+{
+  if (ctx->stack_len <= 0)
+    error ("dwarf expression stack underflow");
+  ctx->stack_len--;
+}
+
+/* Retrieve the N'th item on CTX's stack.  */
+
+CORE_ADDR
+dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n)
+{
+  if (ctx->stack_len < n)
+     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)];
+
+}
+
+/* Evaluate the expression at ADDR (LEN bytes long) using the context
+   CTX.  */
+
+void
+dwarf_expr_eval (struct dwarf_expr_context *ctx, unsigned char *addr,
+		 size_t len)
+{
+  execute_stack_op (ctx, addr, addr + len);
+}
+
+/* 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;
+}
+
+/* Read an address.  */
+
+static CORE_ADDR
+read_address (unsigned char *buf, int *bytes_read)
+{
+  CORE_ADDR result;
+  *bytes_read = TARGET_ADDR_BIT / TARGET_CHAR_BIT;
+  result = extract_address (buf, TARGET_ADDR_BIT / TARGET_CHAR_BIT);
+  return result;
+}
+
+/* The engine for the expression evaluator.  Using the context in CTX,
+   evaluate the expression between OP_PTR and OP_END.  */
+
+static void
+execute_stack_op (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++;
+      CORE_ADDR result, memaddr;
+      ULONGEST uoffset, reg;
+      LONGEST offset;
+      int bytes_read;
+      enum lval_type expr_lval;
+
+      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 = read_address (op_ptr, &bytes_read);
+	  op_ptr += bytes_read;
+	  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, &uoffset);
+	  result = uoffset;
+	  break;
+	case DW_OP_consts:
+	  op_ptr = read_sleb128 (op_ptr, &offset);
+	  result = offset;
+	  break;
+
+	/* The DW_OP_reg operations are required to occur alone in
+	   location expressions.  */
+	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:
+	  if (op_ptr != op_end)
+	    error ("DWARF-2 expression error: DW_OP_reg operations must be "
+		   "used alone.");
+
+	  result = (ctx->read_reg) (ctx->baton, op - DW_OP_reg0, &expr_lval,
+				    &memaddr);
+
+	  if (expr_lval == lval_register)
+	    {
+	      ctx->regnum = op - DW_OP_reg0;
+	      ctx->in_reg = 1;
+	    }
+	  else
+	    result = memaddr;
+
+	  break;
+
+	case DW_OP_regx:
+	  op_ptr = read_uleb128 (op_ptr, &reg);
+	  if (op_ptr != op_end)
+	    error ("DWARF-2 expression error: DW_OP_reg operations must be "
+		   "used alone.");
+
+	  result = (ctx->read_reg) (ctx->baton, reg, &expr_lval, &memaddr);
+
+	  if (expr_lval == lval_register)
+	    {
+	      ctx->regnum = reg;
+	      ctx->in_reg = 1;
+	    }
+	  else
+	    result = memaddr;
+
+	  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->baton, op - DW_OP_breg0,
+				      &expr_lval, &memaddr);
+	    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->baton, reg, &expr_lval, &memaddr);
+	    result += offset;
+	  }
+	  break;
+	case DW_OP_fbreg:
+	  {
+	    unsigned char *datastart;
+	    size_t datalen;
+	    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->baton, &datastart, &datalen);
+	    dwarf_expr_eval (ctx, datastart, datalen);
+	    result = dwarf_expr_fetch (ctx, 0);
+	    if (! ctx->in_reg)
+	      {
+		char *buf = alloca (TARGET_ADDR_BIT / TARGET_CHAR_BIT);
+		int bytes_read;
+
+		(ctx->read_mem) (ctx->baton, buf, result,
+				 TARGET_ADDR_BIT / TARGET_CHAR_BIT);
+		result = read_address (buf, &bytes_read);
+	      }
+	    result = result + 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)
+	       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:
+	      {
+		char *buf = alloca (TARGET_ADDR_BIT / TARGET_CHAR_BIT);
+		int bytes_read;
+
+		(ctx->read_mem) (ctx->baton, buf, result,
+				 TARGET_ADDR_BIT / TARGET_CHAR_BIT);
+		result = read_address (buf, &bytes_read);
+	      }
+	      break;
+
+	    case DW_OP_deref_size:
+	      {
+		char *buf = alloca (TARGET_ADDR_BIT / TARGET_CHAR_BIT);
+		int bytes_read;
+
+		(ctx->read_mem) (ctx->baton, buf, result, *op_ptr++);
+		result = read_address (buf, &bytes_read);
+	      }
+	      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_shl:
+	case DW_OP_shr:
+	case DW_OP_shra:
+	case DW_OP_xor:
+	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:
+		{
+		  struct value *ret1, *ret2;
+		  ret1 = value_from_pointer (builtin_type_CORE_ADDR, first);
+		  ret2 = value_from_pointer (builtin_type_CORE_ADDR, second);
+		  result = value_as_long (value_binop (ret2, ret1, BINOP_DIV));
+		  break;
+		}
+	      case DW_OP_minus:
+		result = second - first;
+		break;
+	      case DW_OP_mod:
+		{
+		  struct value *ret1, *ret2;
+		  ret1 = value_from_pointer (builtin_type_CORE_ADDR, first);
+		  ret2 = value_from_pointer (builtin_type_CORE_ADDR, second);
+		  result = value_as_long (value_binop (ret2, ret1, BINOP_MOD));
+		  break;
+		}
+		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;
+	      default:
+		internal_error (__FILE__, __LINE__,
+				"Can't be reached.");
+	      }
+	  }
+	  break;
+
+	case DW_OP_GNU_push_tls_address:
+	  result = dwarf_expr_fetch (ctx, 0);
+	  dwarf_expr_pop (ctx);
+	  result = (ctx->get_tls_address) (ctx->baton, result);
+	  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:
+	  error ("Unhandled dwarf expression opcode");
+	}
+
+      /* 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	3 Feb 2003 16:28:43 -0000
@@ -0,0 +1,111 @@
+/* Dwarf2 Expression Evaluator
+   Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+   Contributed by Daniel Berlin (dan@dberlin.org)
+   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.  */
+#if !defined (DWARF2EXPR_H)
+#define DWARF2EXPR_H
+
+/* The expression evaluator works with a dwarf_expr_context, describing
+   its current state and its callbacks.  */
+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;
+
+  /* An opaque argument provided by the caller, which will be passed
+     to all of the callback functions.  */
+  void *baton;
+
+  /* Return the value of register number REGNUM.  LVALP will be set
+     to the kind of lval this register is (generally lval_register
+     for the current frame's registers or lval_memory for a register
+     saved to the stack).  For lval_memory ADDRP will be set to the
+     saved location of the register.  */
+  CORE_ADDR (*read_reg) (void *baton, int regnum, enum lval_type *lvalp,
+			 CORE_ADDR *addrp);
+
+  /* Read LENGTH bytes at ADDR into BUF.  */
+  void (*read_mem) (void *baton, char *buf, CORE_ADDR addr,
+		    size_t length);
+
+  /* Return the location expression for the frame base attribute, in
+     START and LENGTH.  The result must be live until the current
+     expression evaluation is complete.  */
+  void (*get_frame_base) (void *baton, unsigned char **start,
+			 size_t *length);
+
+  /* Return the thread-local storage address for
+     DW_OP_GNU_push_tls_address.  */
+  CORE_ADDR (*get_tls_address) (void *baton, CORE_ADDR offset);
+
+#if 0
+  /* Not yet implemented.  */
+
+  /* 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, size_t *length);
+
+  /* Return the `object address' for DW_OP_push_object_address.  */
+  CORE_ADDR (*get_object_address) (void *baton);
+#endif
+
+  /* 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;
+
+  /* Non-zero if the result is in a register.  The register number
+     will be in REGNUM, and the result will be the contents of the
+     register.  */
+  int in_reg;
+
+  /* If the result is in a register, the register number.  */
+  int regnum;
+};
+
+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);
+
+
+/* The types and prototypes below are private to the DWARF-2 reader;
+   they are shared between dwarf2read.c and dwarf2loc.c.  */
+
+/* The symbol location baton type used by the DWARF-2 reader (i.e.
+   SYMBOL_LOCATION_BATON for a LOC_COMPUTED symbol).  */
+
+struct dwarf2_locexpr_baton
+{
+  unsigned char *data;
+  unsigned short size;
+};
+
+extern struct location_funcs dwarf2_locexpr_funcs;
+
+#endif
Index: dwarf2loc.c
===================================================================
RCS file: dwarf2loc.c
diff -N dwarf2loc.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ dwarf2loc.c	3 Feb 2003 16:28:43 -0000
@@ -0,0 +1,270 @@
+/* DWARF 2 location expression support for GDB.
+   Copyright 2003 Free Software Foundation, Inc.
+   Contributed by Daniel Jacobowitz, MontaVista Software, 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 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 "ui-out.h"
+#include "value.h"
+#include "frame.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "inferior.h"
+
+#include "elf/dwarf2.h"
+#include "dwarf2expr.h"
+
+#ifndef DWARF2_REG_TO_REGNUM
+#define DWARF2_REG_TO_REGNUM(REG) (REG)
+#endif
+
+/* This is the baton used when performing dwarf2 expression
+   evaluation.  */
+struct dwarf_expr_baton
+{
+  struct symbol *var;
+  struct frame_info *frame;
+};
+
+/* Helper functions for dwarf2_evaluate_loc_desc.  */
+
+/* Using the frame specified in BATON, read register REGNUM.  The lval
+   type will be returned in LVALP, and for lval_memory the register
+   save address will be returned in ADDRP.  */
+CORE_ADDR
+dwarf_expr_read_reg (void *baton, int regnum, enum lval_type *lvalp,
+		     CORE_ADDR *addrp)
+{
+  CORE_ADDR result;
+  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
+  char *buf = (char *) alloca (MAX_REGISTER_RAW_SIZE);
+  int optimized, realnum;
+
+  frame_register (debaton->frame, DWARF2_REG_TO_REGNUM (regnum),
+		  &optimized, lvalp, addrp, &realnum, buf);
+  result = extract_address (buf, REGISTER_RAW_SIZE (regnum));
+
+  return result;
+}
+
+/* Read memory at ADDR (length LEN) into BUF.  */
+
+void
+dwarf_expr_read_mem (void *baton, char *buf, CORE_ADDR addr, size_t len)
+{
+  read_memory (addr, buf, len);
+}
+
+/* Using the frame specified in BATON, find the location expression
+   describing the frame base.  Return a pointer to it in START and
+   its length in LENGTH.  */
+void
+dwarf_expr_frame_base (void *baton, unsigned char **start, size_t * length)
+{
+  struct symbol *framefunc;
+  struct dwarf2_locexpr_baton *symbaton;
+  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
+  framefunc = get_frame_function (debaton->frame);
+  symbaton = SYMBOL_LOCATION_BATON (framefunc);
+  *start = symbaton->data;
+  *length = symbaton->size;
+}
+
+/* Using the objfile specified in BATON, find the address for the
+   current thread's thread-local storage with offset OFFSET.  */
+CORE_ADDR
+dwarf_expr_tls_address (void *baton, CORE_ADDR offset)
+{
+  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
+  CORE_ADDR addr;
+
+  if (target_get_thread_local_address_p ())
+    addr = target_get_thread_local_address (inferior_ptid,
+					    SYMBOL_OBJFILE (debaton->var),
+					    offset);
+  else
+    error ("Cannot find thread-local variables on this target");
+
+  return addr;
+}
+
+/* Evaluate a location description, starting at DATA and with length
+   SIZE, to find the current location of variable VAR in the context
+   of FRAME.  */
+static struct value *
+dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
+			  unsigned char *data, unsigned short size)
+{
+  CORE_ADDR result;
+  struct value *retval;
+  struct dwarf_expr_baton *baton = xmalloc (sizeof (struct dwarf_expr_baton));
+  struct dwarf_expr_context *ctx;
+
+  baton->var = var;
+  baton->frame = frame;
+
+  ctx = new_dwarf_expr_context ();
+  ctx->baton = baton;
+  ctx->read_reg = dwarf_expr_read_reg;
+  ctx->read_mem = dwarf_expr_read_mem;
+  ctx->get_frame_base = dwarf_expr_frame_base;
+  ctx->get_tls_address = dwarf_expr_tls_address;
+
+  dwarf_expr_eval (ctx, data, size);
+
+  retval = allocate_value (SYMBOL_TYPE (var));
+  VALUE_BFD_SECTION (retval) = SYMBOL_BFD_SECTION (var);
+
+  if (ctx->in_reg)
+    {
+      store_unsigned_integer (VALUE_CONTENTS_RAW (retval),
+			      TYPE_LENGTH (SYMBOL_TYPE (var)),
+			      dwarf_expr_fetch (ctx, 0));
+      VALUE_LVAL (retval) = lval_register;
+      VALUE_REGNO (retval) = ctx->regnum;
+    }
+  else
+    {
+      result = dwarf_expr_fetch (ctx, 0);
+      VALUE_LVAL (retval) = lval_memory;
+      VALUE_LAZY (retval) = 1;
+      VALUE_ADDRESS (retval) = result;
+    }
+
+  free_dwarf_expr_context (ctx);
+  free (baton);
+
+  return retval;
+}
+
+
+
+
+
+/* Helper functions and baton for dwarf2_loc_desc_needs_frame.  */
+
+struct needs_frame_baton
+{
+  int needs_frame;
+};
+
+/* Reads from registers do require a frame.  */
+CORE_ADDR
+needs_frame_read_reg (void *baton, int regnum, enum lval_type *lvalp,
+			    CORE_ADDR *addrp)
+{
+  struct needs_frame_baton *nf_baton = baton;
+  nf_baton->needs_frame = 1;
+  return 1;
+}
+
+/* Reads from memory do not require a frame.  */
+void
+needs_frame_read_mem (void *baton, char *buf, CORE_ADDR addr, size_t len)
+{
+  memset (buf, 0, len);
+}
+
+/* Frame-relative accesses do require a frame.  */
+void
+needs_frame_frame_base (void *baton, unsigned char **start, size_t * length)
+{
+  static char lit0 = DW_OP_lit0;
+  struct needs_frame_baton *nf_baton = baton;
+
+  *start = &lit0;
+  *length = 1;
+
+  nf_baton->needs_frame = 1;
+}
+
+/* Thread-local accesses do require a frame.  */
+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;
+}
+
+/* Return non-zero iff the location expression at DATA (length SIZE)
+   requires a frame to evaluate.  */
+
+int
+dwarf2_loc_desc_needs_frame (unsigned char *data, unsigned short size)
+{
+  struct needs_frame_baton baton;
+  struct dwarf_expr_context *ctx;
+
+  baton.needs_frame = 0;
+
+  ctx = new_dwarf_expr_context ();
+  ctx->baton = &baton;
+  ctx->read_reg = needs_frame_read_reg;
+  ctx->read_mem = needs_frame_read_mem;
+  ctx->get_frame_base = needs_frame_frame_base;
+  ctx->get_tls_address = needs_frame_tls_address;
+
+  dwarf_expr_eval (ctx, data, size);
+
+  free_dwarf_expr_context (ctx);
+
+  return baton.needs_frame;
+}
+
+
+
+
+/* Return the value of SYMBOL in FRAME using the DWARF-2 expression
+   evaluator to calculate the location.  */
+static struct value *
+locexpr_read_variable (struct symbol *symbol, struct frame_info *frame)
+{
+  struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
+  struct value *val;
+  val = dwarf2_evaluate_loc_desc (symbol, frame, dlbaton->data, dlbaton->size);
+
+  return val;
+}
+
+/* Return non-zero iff we need a frame to evaluate SYMBOL.  */
+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);
+}
+
+/* Print a natural-language description of SYMBOL to STREAM.  */
+static int
+locexpr_describe_location (struct symbol *symbol, struct ui_file *stream)
+{
+  fprintf_filtered (stream,
+		    "a DWARF2 location expression evaluated at runtime");
+  return 1;
+}
+
+/* The set of location functions used with the DWARF-2 expression
+   evaluator.  */
+struct location_funcs dwarf2_locexpr_funcs = {
+  locexpr_read_variable,
+  locexpr_read_needs_frame,
+  locexpr_describe_location,
+  NULL
+};
Index: dwarf2read.c
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/dwarf2read.c,v
retrieving revision 1.82
diff -u -p -r1.82 dwarf2read.c
--- dwarf2read.c	1 Feb 2003 01:11:22 -0000	1.82
+++ dwarf2read.c	3 Feb 2003 16:27:29 -0000
@@ -38,10 +38,11 @@
 #include "expression.h"
 #include "filenames.h"	/* for DOSish file names */
 #include "macrotab.h"
-
 #include "language.h"
 #include "complaints.h"
 #include "bcache.h"
+#include "dwarf2expr.h"
+
 #include <fcntl.h>
 #include "gdb_string.h"
 #include "gdb_assert.h"
@@ -905,6 +906,11 @@ static void dwarf_decode_macros (struct 
 
 static int attr_form_is_block (struct attribute *);
 
+static void
+dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
+			     const struct comp_unit_head *,
+			     struct objfile *objfile);
+
 /* Try to locate the sections we need for DWARF 2 debugging
    information and return true if we have enough to do something.  */
 
@@ -1996,6 +2002,13 @@ read_func_scope (struct die_info *die, s
 
   new = push_context (0, lowpc);
   new->name = new_symbol (die, die->type, objfile, cu_header);
+
+  /* If there was a location expression for DW_AT_frame_base above,
+     record it.  We still need to decode it above because not all
+     symbols use location expressions exclusively.  */
+  if (attr)
+    dwarf2_symbol_mark_computed (attr, new->name, cu_header, objfile);
+
   list_in_scope = &local_symbols;
 
   if (die->has_children)
@@ -4917,6 +4930,61 @@ dwarf2_start_subfile (char *filename, ch
   start_subfile (filename, dirname);
 }
 
+static void
+var_decode_location (struct attribute *attr, struct symbol *sym,
+		     struct objfile *objfile,
+		     const struct comp_unit_head *cu_header)
+{
+  /* NOTE drow/2003-01-30: There used to be a comment and some special
+     code here to turn a symbol with DW_AT_external and a
+     SYMBOL_VALUE_ADDRESS of 0 into a LOC_UNRESOLVED symbol.  This was
+     necessary for platforms (maybe Alpha, certainly PowerPC GNU/Linux
+     with some versions of binutils) where shared libraries could have
+     relocations against symbols in their debug information - the
+     minimal symbol would have the right address, but the debug info
+     would not.  It's no longer necessary, because we will explicitly
+     apply relocations when we read in the debug information now.  */
+
+  /* A DW_AT_location attribute with no contents indicates that a
+     variable has been optimized away.  */
+  if (attr_form_is_block (attr) && DW_BLOCK (attr)->size == 0)
+    {
+      SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
+      return;
+    }
+
+  /* Handle one degenerate form of location expression specially, to
+     preserve GDB's previous behavior when section offsets are
+     specified.  If this is just a DW_OP_addr then mark this symbol
+     as LOC_STATIC.  */
+
+  if (attr_form_is_block (attr)
+      && DW_BLOCK (attr)->size == 1 + cu_header->addr_size
+      && DW_BLOCK (attr)->data[0] == DW_OP_addr)
+    {
+      int dummy;
+
+      SYMBOL_VALUE_ADDRESS (sym) =
+	read_address (objfile->obfd, DW_BLOCK (attr)->data + 1, cu_header,
+		      &dummy);
+      fixup_symbol_section (sym, objfile);
+      SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (objfile->section_offsets,
+					      SYMBOL_SECTION (sym));
+      SYMBOL_CLASS (sym) = LOC_STATIC;
+      return;
+    }
+
+  /* NOTE drow/2002-01-30: It might be worthwhile to have a static
+     expression evaluator, and use LOC_COMPUTED only when necessary
+     (i.e. when the value of a register or memory location is
+     referenced, or a thread-local block, etc.).  Then again, it might
+     not be worthwhile.  I'm assuming that it isn't unless performance
+     or memory numbers show me otherwise.  */
+
+  dwarf2_symbol_mark_computed (attr, sym, cu_header, objfile);
+  SYMBOL_CLASS (sym) = LOC_COMPUTED;
+}
+
 /* Given a pointer to a DWARF information entry, figure out if we need
    to make a symbol table entry for it, and if so, create a new entry
    and return a pointer to it.
@@ -5012,106 +5080,12 @@ new_symbol (struct die_info *die, struct
 	  attr = dwarf_attr (die, DW_AT_location);
 	  if (attr)
 	    {
+	      var_decode_location (attr, sym, objfile, cu_header);
 	      attr2 = dwarf_attr (die, DW_AT_external);
 	      if (attr2 && (DW_UNSND (attr2) != 0))
-		{
-                  /* Support the .debug_loc offsets */
-                  if (attr_form_is_block (attr))
-                    {
-		      SYMBOL_VALUE_ADDRESS (sym) =
-		        decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
-                    }
-                  else if (attr->form == DW_FORM_data4
-                           || attr->form == DW_FORM_data8)
-                    {
-		      dwarf2_complex_location_expr_complaint ();
-                    }
-                  else
-                    {
-		      dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
-							     "external variable");
-                    }
-		  add_symbol_to_list (sym, &global_symbols);
-                  if (is_thread_local)
-                    {
-                      /* SYMBOL_VALUE_ADDRESS contains at this point the
-		         offset of the variable within the thread local
-			 storage.  */
-                      SYMBOL_CLASS (sym) = LOC_THREAD_LOCAL_STATIC;
-                      SYMBOL_OBJFILE (sym) = objfile;
-                    }
-
-		  /* 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.  */
-		  else 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;
-		}
+		add_symbol_to_list (sym, &global_symbols);
 	      else
-		{
-                  /* Support the .debug_loc offsets */
-                  if (attr_form_is_block (attr))
-                    {
-		      SYMBOL_VALUE (sym) = addr =
-		        decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
-                    }
-                  else if (attr->form == DW_FORM_data4
-                           || attr->form == DW_FORM_data8)
-                    {
-		      dwarf2_complex_location_expr_complaint ();
-                    }
-                  else
-                    {
-		      dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
-							     "external variable");
-                      addr = 0;
-                    }
-		  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 if (is_thread_local)
-                    {
-                      SYMBOL_CLASS (sym) = LOC_THREAD_LOCAL_STATIC;
-                      SYMBOL_OBJFILE (sym) = objfile;
-                    }
-		  else
-		    {
-		      fixup_symbol_section (sym, objfile);
-		      SYMBOL_VALUE_ADDRESS (sym) =
-		        addr + ANOFFSET (objfile->section_offsets,
-			                 SYMBOL_SECTION (sym));
-		      SYMBOL_CLASS (sym) = LOC_STATIC;
-		    }
-		}
+		add_symbol_to_list (sym, list_in_scope);
 	    }
 	  else
 	    {
@@ -7335,4 +7309,27 @@ attr_form_is_block (struct attribute *at
       || attr->form == DW_FORM_block2
       || attr->form == DW_FORM_block4
       || attr->form == DW_FORM_block);
+}
+
+static void
+dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
+			     const struct comp_unit_head *cu_header,
+			     struct objfile *objfile)
+{
+  struct dwarf2_locexpr_baton *baton;
+
+  /* When support for location lists is added, this will go away.  */
+  if (!attr_form_is_block (attr))
+    {
+      dwarf2_complex_location_expr_complaint ();
+      return;
+    }
+
+  baton = obstack_alloc (&objfile->symbol_obstack,
+			 sizeof (struct dwarf2_locexpr_baton));
+  baton->size = DW_BLOCK (attr)->size;
+  baton->data = DW_BLOCK (attr)->data;
+
+  SYMBOL_LOCATION_FUNCS (sym) = &dwarf2_locexpr_funcs;
+  SYMBOL_LOCATION_BATON (sym) = baton;
 }
Index: findvar.c
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/findvar.c,v
retrieving revision 1.44
diff -u -p -r1.44 findvar.c
--- findvar.c	14 Jan 2003 00:49:03 -0000	1.44
+++ findvar.c	3 Feb 2003 16:24:14 -0000
@@ -383,6 +383,14 @@ symbol_read_needs_frame (struct symbol *
     {
       /* All cases listed explicitly so that gcc -Wall will detect it if
          we failed to consider one.  */
+    case LOC_COMPUTED:
+    case LOC_COMPUTED_ARG:
+      {
+	struct location_funcs *symfuncs = SYMBOL_LOCATION_FUNCS (sym);
+	return (symfuncs->read_needs_frame) (sym);
+      }
+      break;
+
     case LOC_REGISTER:
     case LOC_ARG:
     case LOC_REF_ARG:
@@ -601,6 +609,18 @@ addresses have not been bound by the dyn
 	      error ("Value of register variable not available.");
 	    return regval;
 	  }
+      }
+      break;
+
+    case LOC_COMPUTED:
+    case LOC_COMPUTED_ARG:
+      {
+	struct location_funcs *funcs = SYMBOL_LOCATION_FUNCS (var);
+
+	if (frame == 0 && (funcs->read_needs_frame) (var))
+	  return 0;
+	return (funcs->read_variable) (var, frame);
+
       }
       break;
 
Index: m2-exp.y
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/m2-exp.y,v
retrieving revision 1.7
diff -u -p -r1.7 m2-exp.y
--- m2-exp.y	6 Nov 2002 22:48:25 -0000	1.7
+++ m2-exp.y	3 Feb 2003 16:24:14 -0000
@@ -1040,6 +1040,8 @@ yylex ()
        case LOC_CONST:
        case LOC_CONST_BYTES:
        case LOC_OPTIMIZED_OUT:
+       case LOC_COMPUTED:
+       case LOC_COMPUTED_ARG:
 	  return NAME;
 
        case LOC_TYPEDEF:
Index: printcmd.c
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/printcmd.c,v
retrieving revision 1.50
diff -u -p -r1.50 printcmd.c
--- printcmd.c	21 Nov 2002 18:54:44 -0000	1.50
+++ printcmd.c	3 Feb 2003 16:24:14 -0000
@@ -1148,6 +1148,11 @@ address_info (char *exp, int from_tty)
 	}
       break;
 
+    case LOC_COMPUTED:
+    case LOC_COMPUTED_ARG:
+      (SYMBOL_LOCATION_FUNCS (sym)->describe_location) (sym, gdb_stdout);
+      break;
+
     case LOC_REGISTER:
       printf_filtered ("a variable in register %s", REGISTER_NAME (val));
       break;
@@ -1811,6 +1816,7 @@ print_frame_args (struct symbol *func, s
 	    case LOC_REGPARM_ADDR:
 	    case LOC_LOCAL_ARG:
 	    case LOC_BASEREG_ARG:
+	    case LOC_COMPUTED_ARG:
 	      break;
 
 	    /* Other types of symbols we just skip over.  */
Index: stack.c
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/stack.c,v
retrieving revision 1.65
diff -u -p -r1.65 stack.c
--- stack.c	2 Feb 2003 18:30:56 -0000	1.65
+++ stack.c	3 Feb 2003 16:24:14 -0000
@@ -1082,6 +1082,7 @@ print_block_frame_locals (struct block *
 	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);
@@ -1308,6 +1309,7 @@ print_frame_arg_vars (register struct fr
 	case LOC_REGPARM:
 	case LOC_REGPARM_ADDR:
 	case LOC_BASEREG_ARG:
+	case LOC_COMPUTED_ARG:
 	  values_printed = 1;
 	  fputs_filtered (SYMBOL_SOURCE_NAME (sym), stream);
 	  fputs_filtered (" = ", stream);
Index: symmisc.c
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/symmisc.c,v
retrieving revision 1.14
diff -u -p -r1.14 symmisc.c
--- symmisc.c	18 Jan 2003 15:55:53 -0000	1.14
+++ symmisc.c	3 Feb 2003 16:24:14 -0000
@@ -726,6 +726,11 @@ print_symbol (void *args)
 			       SYMBOL_BFD_SECTION (symbol)));
 	  break;
 
+	case LOC_COMPUTED:
+	case LOC_COMPUTED_ARG:
+	  fprintf_filtered (outfile, "computed at runtime");
+	  break;
+
 	case LOC_UNRESOLVED:
 	  fprintf_filtered (outfile, "unresolved");
 	  break;
@@ -876,6 +881,10 @@ print_partial_symbols (struct partial_sy
 	  break;
 	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);
Index: symtab.h
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/symtab.h,v
retrieving revision 1.55
diff -u -p -r1.55 symtab.h
--- symtab.h	19 Jan 2003 04:06:46 -0000	1.55
+++ symtab.h	3 Feb 2003 16:24:14 -0000
@@ -26,6 +26,8 @@
 
 /* Opaque declarations.  */
 struct obstack;
+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
@@ -621,7 +623,58 @@ enum address_class
    * with a level of indirection.
    */
 
-  LOC_INDIRECT
+  LOC_INDIRECT,
+
+  /* The variable's address is computed by a set of location
+     functions (see "struct location_funcs" below).  */
+  LOC_COMPUTED,
+
+  /* Same as LOC_COMPUTED, but for function arguments.  */
+  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 SYMBOL, relative to the stack
+     frame FRAME.  If the variable has been optimized out, return
+     zero.
+
+     Iff `read_needs_frame (SYMBOL)' is zero, then FRAME may be zero.  */
+
+  struct value *(*read_variable) (struct symbol *symbol,
+				  struct frame_info * frame);
+
+  /* Return non-zero if we need a frame to find the value of the SYMBOL.  */
+  int (*read_needs_frame) (struct symbol *symbol);
+
+  /* Write to STREAM a natural-language description of the location of
+     SYMBOL.  */
+  int (*describe_location) (struct symbol *symbol, struct ui_file * stream);
+
+  /* Tracepoint support.  Append bytecodes to the tracepoint agent
+     expression AX that push the address of the object SYMBOL.  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) (struct symbol *symbol, struct agent_expr * ax,
+			      struct axs_value * value);
 };
 
 /* Linked list of symbol's live ranges. */
@@ -683,6 +736,14 @@ struct symbol
        variable declared with the `__thread' storage class), we may
        need to know which object file it's in.  */
     struct objfile *objfile;
+
+    /* Used by LOC_COMPUTED and LOC_COMPUTED_ARG to calculate the variable's
+       location, and by LOC_BLOCK to locate the function's base register.  */
+    struct
+    {
+      void *baton;
+      struct location_funcs *funcs;
+    } loc;
   }
   aux_value;
 
@@ -707,6 +768,8 @@ struct symbol
 #define SYMBOL_OBJFILE(symbol)          (symbol)->aux_value.objfile
 #define SYMBOL_ALIASES(symbol)		(symbol)->aliases
 #define SYMBOL_RANGES(symbol)		(symbol)->ranges
+#define SYMBOL_LOCATION_BATON(symbol)   (symbol)->aux_value.loc.baton
+#define SYMBOL_LOCATION_FUNCS(symbol)   (symbol)->aux_value.loc.funcs
 
 /* 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]