This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[PATCH]: LOC_COMPUTED/LOC_COMPUTED_ARG + dwarf2 abstracted expressioneval
- From: Daniel Berlin <dberlin at dberlin dot org>
- To: gdb-patches at sources dot redhat dot com
- Date: Thu, 11 Apr 2002 17:42:01 -0400 (EDT)
- Subject: [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, ®);
+ 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, ®);
+ 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, ®);
+ 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