[RFA]: LOC_COMPUTED + abstracted dwarf2 evaluator, again

Daniel Berlin
2002-07-08T17:03:10Z

For yer convenience, I rediffed it against the current gdb sources.
I'll update the changelog dates if it ever gets reviewed or approved.
Slightly updated accompanying text (from the april submission):
"
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 these should be blockers to committing it or reviewing it.

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.

Splitting this patch into loc_computed addition, and dwarf2 implementation
of loc_computed, doesn't make it much smaller (loc_computed_addition is
maybe 5% of the patch), so if size is a concern, sorry, but it's pretty
much unsplittable beyond that (the biggest portion is the addition of the
abstracted evaluator, but the dwarf2 implementation doesn't work without
it).

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.

Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.218
diff -c -3 -p -w -B -b -r1.218 Makefile.in
*** Makefile.in 3 Jul 2002 20:36:54 -0000 1.218
--- Makefile.in 8 Jul 2002 16:52:38 -0000
*************** SFILES = ax-general.c ax-gdb.c bcache.c
*** 527,533 ****
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 osabi.c \
--- 527,534 ----
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 osabi.c \
*************** COMMON_OBS = version.o blockframe.o brea
*** 734,740 ****
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 \
--- 735,742 ----
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
*** 1435,1440 ****
--- 1437,1446 ----
$(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) $(macrotab_h)

Index: buildsym.c
===================================================================
RCS file: /cvs/src/src/gdb/buildsym.c,v
retrieving revision 1.16
diff -c -3 -p -w -B -b -r1.16 buildsym.c
*** buildsym.c 15 May 2002 21:19:18 -0000 1.16
--- buildsym.c 8 Jul 2002 16:52:38 -0000
*************** finish_block (struct symbol *symbol, str
*** 289,294 ****
--- 289,295 ----
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
*** 304,309 ****
--- 305,311 ----
case LOC_BASEREG:
case LOC_UNRESOLVED:
case LOC_OPTIMIZED_OUT:
+ case LOC_COMPUTED:
default:
break;
}
*************** finish_block (struct symbol *symbol, str
*** 325,330 ****
--- 327,333 ----
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
*** 342,347 ****
--- 345,351 ----
case LOC_BASEREG:
case LOC_UNRESOLVED:
case LOC_OPTIMIZED_OUT:
+ case LOC_COMPUTED:
default:
break;
}
Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.60
diff -c -3 -p -w -B -b -r1.60 dwarf2read.c
*** dwarf2read.c 22 Jun 2002 00:05:59 -0000 1.60
--- dwarf2read.c 8 Jul 2002 16:52:39 -0000
***************
*** 46,51 ****
--- 46,56 ----
#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
*** 898,903 ****
--- 903,929 ----

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
*** 1842,1848 ****
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
--- 1868,1874 ----
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
*** 1886,1891 ****
--- 1912,1931 ----

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
*** 4603,4666 ****
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
{
--- 4643,4662 ----
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)
*** 6420,6425 ****
--- 6416,6541 ----
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;
}

\f
Index: findvar.c
===================================================================
RCS file: /cvs/src/src/gdb/findvar.c,v
retrieving revision 1.34
diff -c -3 -p -w -B -b -r1.34 findvar.c
*** findvar.c 15 May 2002 01:01:56 -0000 1.34
--- findvar.c 8 Jul 2002 16:52:39 -0000
*************** symbol_read_needs_frame (struct symbol *
*** 382,387 ****
--- 382,391 ----
{
/* 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
*** 589,594 ****
--- 593,610 ----
}
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.39
diff -c -3 -p -w -B -b -r1.39 printcmd.c
*** printcmd.c 11 May 2002 23:48:23 -0000 1.39
--- printcmd.c 8 Jul 2002 16:52:40 -0000
*************** address_info (char *exp, int from_tty)
*** 1162,1167 ****
--- 1162,1171 ----
}
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.39
diff -c -3 -p -w -B -b -r1.39 stack.c
*** stack.c 10 Jun 2002 23:25:50 -0000 1.39
--- stack.c 8 Jul 2002 16:52:40 -0000
*************** print_block_frame_locals (struct block *
*** 1229,1234 ****
--- 1229,1235 ----
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.9
diff -c -3 -p -w -B -b -r1.9 symmisc.c
*** symmisc.c 15 May 2002 21:19:21 -0000 1.9
--- symmisc.c 8 Jul 2002 16:52:40 -0000
*************** print_partial_symbols (struct partial_sy
*** 862,867 ****
--- 862,871 ----
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.33
diff -c -3 -p -w -B -b -r1.33 symtab.h
*** symtab.h 28 Jun 2002 22:09:11 -0000 1.33
--- symtab.h 8 Jul 2002 16:52:40 -0000
***************
*** 28,34 ****
#include "obstack.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free xfree
!
/* 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
--- 28,36 ----
#include "obstack.h"
#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
*** 603,609 ****
* 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
*** 660,665 ****
--- 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
*** 671,676 ****
--- 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
*** 681,686 ****
--- 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
\f
/* A partial_symbol records the name, namespace, and address class of
symbols whose types we have not parsed yet. For functions, it also