#include "defs.h"
#include "ui-out.h"
#include "value.h"
#include "frame.h"
#include "gdbcore.h"
#include "target.h"
#include "inferior.h"
#include "ax.h"
#include "ax-gdb.h"
#include "regcache.h"
#include "objfiles.h"
#include "exceptions.h"
#include "elf/dwarf2.h"
#include "dwarf2expr.h"
#include "dwarf2loc.h"
#include "dwarf2read.h"
#include "gdb_string.h"
#ifndef DWARF2_REG_TO_REGNUM
#define DWARF2_REG_TO_REGNUM(REG) (REG)
#endif
static void
print_single_dwarf_location (struct ui_file *, gdb_byte **, gdb_byte *,
struct dwarf_expr_context *);
static gdb_byte *
find_location_expression (struct dwarf2_loclist_baton *baton,
size_t *locexpr_length, CORE_ADDR pc)
{
CORE_ADDR low, high;
gdb_byte *loc_ptr, *buf_end;
int length;
unsigned int addr_size = TARGET_ADDR_BIT / TARGET_CHAR_BIT;
CORE_ADDR base_mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
CORE_ADDR base_offset = objfile_text_section_offset (baton->objfile);
CORE_ADDR base_address = baton->base_address_untranslated;
loc_ptr = baton->data;
buf_end = baton->data + baton->size;
while (1)
{
low = dwarf2_read_address (loc_ptr, buf_end, &length);
loc_ptr += length;
high = dwarf2_read_address (loc_ptr, buf_end, &length);
loc_ptr += length;
if (low == 0 && high == 0)
return NULL;
if ((low & base_mask) == base_mask)
{
base_address = high;
continue;
}
low += base_address;
high += base_address;
if (baton->addr_map)
{
translate_debug_map_address (baton->addr_map, low, &low, 0);
translate_debug_map_address (baton->addr_map, high, &high, 1);
}
low += base_offset;
high += base_offset;
length = extract_unsigned_integer (loc_ptr, 2);
loc_ptr += 2;
if (pc >= low && pc < high)
{
*locexpr_length = length;
return loc_ptr;
}
loc_ptr += length;
}
}
struct dwarf_expr_baton
{
struct frame_info *frame;
struct objfile *objfile;
};
static CORE_ADDR
dwarf_expr_read_reg (void *baton, int dwarf_regnum)
{
struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
CORE_ADDR result, save_addr;
enum lval_type lval_type;
gdb_byte *buf;
enum opt_state optimized;
int regnum, realnum, regsize;
regnum = DWARF2_REG_TO_REGNUM (dwarf_regnum);
regsize = register_size (current_gdbarch, regnum);
buf = alloca (regsize);
frame_register (debaton->frame, regnum, &optimized, &lval_type, &save_addr,
&realnum, buf);
result = extract_unsigned_integer (buf, regsize);
return result;
}
static void
dwarf_expr_read_mem (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t len)
{
read_memory (addr, buf, len);
}
static void
dwarf_expr_frame_base (void *baton, gdb_byte **start, size_t * length)
{
struct symbol *framefunc;
struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
framefunc = get_frame_function (debaton->frame);
if (SYMBOL_OPS (framefunc) == &dwarf2_loclist_funcs)
{
struct dwarf2_loclist_baton *symbaton;
symbaton = SYMBOL_LOCATION_BATON (framefunc);
*start = find_location_expression (symbaton, length,
get_frame_pc (debaton->frame));
}
else
{
struct dwarf2_locexpr_baton *symbaton;
symbaton = SYMBOL_LOCATION_BATON (framefunc);
*length = symbaton->size;
*start = symbaton->data;
}
if (*start == NULL)
error (_("Could not find the frame base for \"%s\"."),
SYMBOL_NATURAL_NAME (framefunc));
}
static CORE_ADDR
dwarf_expr_tls_address (void *baton, CORE_ADDR offset)
{
struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
volatile CORE_ADDR addr = 0;
if (target_get_thread_local_address_p ()
&& gdbarch_fetch_tls_load_module_address_p (current_gdbarch))
{
ptid_t ptid = inferior_ptid;
struct objfile *objfile = debaton->objfile;
volatile struct gdb_exception ex;
TRY_CATCH (ex, RETURN_MASK_ALL)
{
CORE_ADDR lm_addr;
lm_addr = gdbarch_fetch_tls_load_module_address (current_gdbarch,
objfile);
if (lm_addr == 0)
throw_error (TLS_LOAD_MODULE_NOT_FOUND_ERROR,
_("TLS load module not found"));
addr = target_get_thread_local_address (ptid, lm_addr, offset);
}
if (ex.reason < 0)
{
int objfile_is_library = (objfile->flags & OBJF_SHARED);
switch (ex.error)
{
case TLS_NO_LIBRARY_SUPPORT_ERROR:
error (_("Cannot find thread-local variables in this thread library."));
break;
case TLS_LOAD_MODULE_NOT_FOUND_ERROR:
if (objfile_is_library)
error (_("Cannot find shared library `%s' in dynamic"
" linker's load module list"), objfile->name);
else
error (_("Cannot find executable file `%s' in dynamic"
" linker's load module list"), objfile->name);
break;
case TLS_NOT_ALLOCATED_YET_ERROR:
if (objfile_is_library)
error (_("The inferior has not yet allocated storage for"
" thread-local variables in\n"
"the shared library `%s'\n"
"for %s"),
objfile->name, target_pid_to_str (ptid));
else
error (_("The inferior has not yet allocated storage for"
" thread-local variables in\n"
"the executable `%s'\n"
"for %s"),
objfile->name, target_pid_to_str (ptid));
break;
case TLS_GENERIC_ERROR:
if (objfile_is_library)
error (_("Cannot find thread-local storage for %s, "
"shared library %s:\n%s"),
target_pid_to_str (ptid),
objfile->name, ex.message);
else
error (_("Cannot find thread-local storage for %s, "
"executable file %s:\n%s"),
target_pid_to_str (ptid),
objfile->name, ex.message);
break;
default:
throw_exception (ex);
break;
}
}
}
else
error (_("Cannot find thread-local variables on this target"));
return addr;
}
static struct value *
dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
gdb_byte *data, unsigned short size,
struct objfile *objfile)
{
struct value *retval;
struct dwarf_expr_baton baton;
struct dwarf_expr_context *ctx;
if (size == 0)
{
retval = allocate_value (SYMBOL_TYPE (var));
VALUE_LVAL (retval) = not_lval;
set_value_optimized_out (retval, opt_away);
}
baton.frame = frame;
baton.objfile = objfile;
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, 0);
if (ctx->num_pieces == 2
&& ctx->pieces[0].in_reg
&& ctx->pieces[1].in_reg
&& (ctx->pieces[0].value + 1) == ctx->pieces[1].value
&& CONVERT_REGISTER_P (ctx->pieces[0].value, SYMBOL_TYPE (var))
)
{
CORE_ADDR dwarf_regnum = ctx->pieces[0].value;
int gdb_regnum = DWARF2_REG_TO_REGNUM (dwarf_regnum);
retval = value_from_register (SYMBOL_TYPE (var), gdb_regnum, frame);
}
else
if (ctx->num_pieces > 0)
{
int i;
long offset = 0;
bfd_byte *contents;
retval = allocate_value (SYMBOL_TYPE (var));
contents = value_contents_raw (retval);
for (i = 0; i < ctx->num_pieces; i++)
{
struct dwarf_expr_piece *p = &ctx->pieces[i];
if (p->in_reg)
{
bfd_byte regval[MAX_REGISTER_SIZE];
int gdb_regnum = DWARF2_REG_TO_REGNUM (p->value);
get_frame_register (frame, gdb_regnum, regval);
memcpy (contents + offset, regval, p->size);
}
else
{
read_memory (p->value, contents + offset, p->size);
}
offset += p->size;
}
}
else if (ctx->in_reg)
{
CORE_ADDR dwarf_regnum = dwarf_expr_fetch (ctx, 0);
int gdb_regnum = DWARF2_REG_TO_REGNUM (dwarf_regnum);
if (gdb_regnum == -1)
{
retval = allocate_value (SYMBOL_TYPE (var));
VALUE_LVAL (retval) = not_lval;
set_value_optimized_out (retval, opt_other);
}
else
{
retval = value_from_register (SYMBOL_TYPE (var), gdb_regnum, frame);
}
}
else
{
CORE_ADDR address = dwarf_expr_fetch (ctx, 0);
retval = allocate_value (SYMBOL_TYPE (var));
VALUE_LVAL (retval) = lval_memory;
set_value_lazy (retval, 1);
VALUE_ADDRESS (retval) = address;
}
set_var_status (retval, ctx->var_status);
free_dwarf_expr_context (ctx);
return retval;
}
struct needs_frame_baton
{
int needs_frame;
};
static CORE_ADDR
needs_frame_read_reg (void *baton, int regnum)
{
struct needs_frame_baton *nf_baton = baton;
nf_baton->needs_frame = 1;
return 1;
}
static void
needs_frame_read_mem (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t len)
{
memset (buf, 0, len);
}
static void
needs_frame_frame_base (void *baton, gdb_byte **start, size_t * length)
{
static gdb_byte lit0 = DW_OP_lit0;
struct needs_frame_baton *nf_baton = baton;
*start = &lit0;
*length = 1;
nf_baton->needs_frame = 1;
}
static 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;
}
static int
dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size)
{
struct needs_frame_baton baton;
struct dwarf_expr_context *ctx;
int in_reg;
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, 0);
in_reg = ctx->in_reg;
if (ctx->num_pieces > 0)
{
int i;
for (i = 0; i < ctx->num_pieces; i++)
if (ctx->pieces[i].in_reg)
in_reg = 1;
}
free_dwarf_expr_context (ctx);
return baton.needs_frame || in_reg;
}
static void
dwarf2_tracepoint_var_ref (struct symbol *symbol, struct agent_expr *ax,
struct axs_value *value, gdb_byte *data,
int size)
{
if (size == 0)
error (_("Symbol \"%s\" has been optimized out."),
SYMBOL_PRINT_NAME (symbol));
if (size == 1
&& data[0] >= DW_OP_reg0
&& data[0] <= DW_OP_reg31)
{
value->kind = axs_lvalue_register;
value->u.reg = data[0] - DW_OP_reg0;
}
else if (data[0] == DW_OP_regx)
{
ULONGEST reg;
read_uleb128 (data + 1, data + size, ®);
value->kind = axs_lvalue_register;
value->u.reg = reg;
}
else if (data[0] == DW_OP_fbreg)
{
int frame_reg;
LONGEST frame_offset;
gdb_byte *buf_end;
buf_end = read_sleb128 (data + 1, data + size, &frame_offset);
if (buf_end != data + size)
error (_("Unexpected opcode after DW_OP_fbreg for symbol \"%s\"."),
SYMBOL_PRINT_NAME (symbol));
TARGET_VIRTUAL_FRAME_POINTER (ax->scope, &frame_reg, &frame_offset);
ax_reg (ax, frame_reg);
ax_const_l (ax, frame_offset);
ax_simple (ax, aop_add);
ax_const_l (ax, frame_offset);
ax_simple (ax, aop_add);
value->kind = axs_lvalue_memory;
}
else
error (_("Unsupported DWARF opcode in the location of \"%s\"."),
SYMBOL_PRINT_NAME (symbol));
}
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,
dlbaton->objfile);
return val;
}
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);
}
static int
locexpr_describe_location (struct symbol *symbol, struct ui_file *stream)
{
struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
struct dwarf_expr_context *ctx;
gdb_byte *loc_ptr;
gdb_byte *loc_end;
if (dlbaton->size == 1
&& dlbaton->data[0] >= DW_OP_reg0
&& dlbaton->data[0] <= DW_OP_reg31)
{
int regno = DWARF2_REG_TO_REGNUM (dlbaton->data[0] - DW_OP_reg0);
fprintf_filtered (stream,
"a variable in register %s", REGISTER_NAME (regno));
return 1;
}
if (dlbaton->size > 1
&& dlbaton->data[dlbaton->size - 1] == DW_OP_GNU_push_tls_address)
if (dlbaton->data[0] == DW_OP_addr)
{
int bytes_read;
CORE_ADDR offset = dwarf2_read_address (&dlbaton->data[1],
&dlbaton->data[dlbaton->size - 1],
&bytes_read);
fprintf_filtered (stream,
"a thread-local variable at offset %s in the "
"thread-local storage for `%s'",
paddr_nz (offset), dlbaton->objfile->name);
return 1;
}
ctx = new_dwarf_expr_context ();
ctx->baton = dlbaton;
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;
loc_ptr = &dlbaton->data[0];
loc_end = &dlbaton->data[dlbaton->size];
print_single_dwarf_location (stream, &loc_ptr, loc_end, ctx);
return 1;
}
static void
locexpr_tracepoint_var_ref (struct symbol * symbol, struct agent_expr * ax,
struct axs_value * value)
{
struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
dwarf2_tracepoint_var_ref (symbol, ax, value, dlbaton->data, dlbaton->size);
}
const struct symbol_ops dwarf2_locexpr_funcs = {
locexpr_read_variable,
locexpr_read_needs_frame,
locexpr_describe_location,
locexpr_tracepoint_var_ref
};
static struct value *
loclist_read_variable (struct symbol *symbol, struct frame_info *frame)
{
struct dwarf2_loclist_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
struct value *val;
gdb_byte *data;
size_t size;
data = find_location_expression (dlbaton, &size,
frame ? get_frame_pc (frame) : 0);
if (data == NULL)
{
val = allocate_value (SYMBOL_TYPE (symbol));
VALUE_LVAL (val) = not_lval;
set_value_optimized_out (val, opt_evicted);
}
else
val = dwarf2_evaluate_loc_desc (symbol, frame, data, size,
dlbaton->objfile);
return val;
}
static int
loclist_read_needs_frame (struct symbol *symbol)
{
return 1;
}
static void
print_single_dwarf_location (struct ui_file *stream, gdb_byte **loc_ptr,
gdb_byte *op_end,
struct dwarf_expr_context *ctx)
{
CORE_ADDR result;
int bytes_read;
ULONGEST uoffset, reg;
LONGEST offset;
gdb_byte *op_ptr = *loc_ptr;
while (op_ptr < op_end)
{
enum dwarf_location_atom op = *op_ptr++;
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:
fprintf_filtered (stream, "a literal");
break;
case DW_OP_addr:
result = dwarf2_read_address (op_ptr, op_end, &bytes_read);
fprintf_filtered (stream, "at address 0x%s", paddr_nz (result));
op_ptr += bytes_read;
break;
case DW_OP_const1u:
case DW_OP_const1s:
fprintf_filtered (stream, "a constant");
op_ptr += 1;
break;
case DW_OP_const2u:
case DW_OP_const2s:
fprintf_filtered (stream, "a constant");
op_ptr += 2;
break;
case DW_OP_const4u:
case DW_OP_const4s:
fprintf_filtered (stream, "a constant");
op_ptr += 4;
break;
case DW_OP_const8u:
case DW_OP_const8s:
fprintf_filtered (stream, "a constant");
op_ptr += 8;
break;
case DW_OP_constu:
op_ptr = read_uleb128 (op_ptr, op_end, &uoffset);
fprintf_filtered (stream, "a constant");
break;
case DW_OP_consts:
op_ptr = read_sleb128 (op_ptr, op_end, &offset);
fprintf_filtered (stream, "a constant");
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:
if (op_ptr != op_end
&& *op_ptr != DW_OP_piece
&& *op_ptr != DW_OP_APPLE_uninit)
error (_("DWARF-2 expression error: DW_OP_reg operations must be "
"used either alone or in conjuction with DW_OP_piece."));
result = op - DW_OP_reg0;
fprintf_filtered (stream, "in register %s",
REGISTER_NAME (DWARF2_REG_TO_REGNUM (result)));
break;
case DW_OP_regx:
op_ptr = read_uleb128 (op_ptr, op_end, ®);
if (op_ptr != op_end
&& *op_ptr != DW_OP_piece
&& *op_ptr != DW_OP_APPLE_uninit)
error (_("DWARF-2 expression error: DW_OP_reg operations must be "
"used either alone or in conjuction with DW_OP_piece."));
fprintf_filtered (stream, "in register %s",
REGISTER_NAME (DWARF2_REG_TO_REGNUM (reg)));
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, op_end, &offset);
result = op - DW_OP_breg0;
fprintf_filtered (stream, "at the address (reg %d + %d)",
(unsigned int) result, (signed int) offset);
}
break;
case DW_OP_bregx:
{
op_ptr = read_uleb128 (op_ptr, op_end, ®);
op_ptr = read_sleb128 (op_ptr, op_end, &offset);
fprintf_filtered (stream, "at the address (reg %d + %d)",
(unsigned int) reg, (signed int) offset);
}
break;
case DW_OP_fbreg:
{
unsigned int before_stack_len;
op_ptr = read_sleb128 (op_ptr, op_end, &offset);
fprintf_filtered (stream,
"at offset %d from the frame base pointer",
(signed int) offset);
before_stack_len = ctx->stack_len;
}
break;
case DW_OP_dup:
result = dwarf_expr_fetch (ctx, 0);
break;
case DW_OP_drop:
dwarf_expr_pop (ctx);
break;
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."),
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;
break;
}
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:
result = dwarf_expr_fetch (ctx, 0);
dwarf_expr_pop (ctx);
switch (op)
{
case DW_OP_deref:
{
fprintf_filtered (stream, "at address 0x%s", paddr_nz (result));
}
break;
case DW_OP_deref_size:
{
gdb_byte *buf = alloca (TARGET_ADDR_BIT / TARGET_CHAR_BIT);
(ctx->read_mem) (ctx->baton, buf, result, *op_ptr++);
fprintf_filtered (stream, "at address 0x%s", paddr_nz (result));
}
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, op_end, ®);
result += reg;
break;
default:
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:
{
CORE_ADDR first, second;
enum exp_opcode binop;
struct value *val1, *val2;
second = dwarf_expr_fetch (ctx, 0);
dwarf_expr_pop (ctx);
first = dwarf_expr_fetch (ctx, 0);
dwarf_expr_pop (ctx);
val1 = value_from_longest (unsigned_address_type (), first);
val2 = value_from_longest (unsigned_address_type (), second);
switch (op)
{
case DW_OP_and:
binop = BINOP_BITWISE_AND;
break;
case DW_OP_div:
binop = BINOP_DIV;
break;
case DW_OP_minus:
binop = BINOP_SUB;
break;
case DW_OP_mod:
binop = BINOP_MOD;
break;
case DW_OP_mul:
binop = BINOP_MUL;
break;
case DW_OP_or:
binop = BINOP_BITWISE_IOR;
break;
case DW_OP_plus:
binop = BINOP_ADD;
break;
case DW_OP_shl:
binop = BINOP_LSH;
break;
case DW_OP_shr:
binop = BINOP_RSH;
break;
case DW_OP_shra:
binop = BINOP_RSH;
val1 = value_from_longest (signed_address_type (), first);
break;
case DW_OP_xor:
binop = BINOP_BITWISE_XOR;
break;
case DW_OP_le:
binop = BINOP_LEQ;
break;
case DW_OP_ge:
binop = BINOP_GEQ;
break;
case DW_OP_eq:
binop = BINOP_EQUAL;
break;
case DW_OP_lt:
binop = BINOP_LESS;
break;
case DW_OP_gt:
binop = BINOP_GTR;
break;
case DW_OP_ne:
binop = BINOP_NOTEQUAL;
break;
default:
internal_error (__FILE__, __LINE__,
_("Can't be reached."));
}
result = value_as_long (value_binop (val1, val2, binop));
}
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);
fprintf_filtered (stream,
"at 0x%s offset from thread-local storage block",
paddr_nz (result));
break;
case DW_OP_skip:
offset = extract_signed_integer (op_ptr, 2);
op_ptr += 2;
op_ptr += offset;
break;
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);
break;
case DW_OP_nop:
break;
case DW_OP_piece:
{
ULONGEST size;
CORE_ADDR addr_or_regnum;
op_ptr = read_uleb128 (op_ptr, op_end, &size);
addr_or_regnum = dwarf_expr_fetch (ctx, 0);
add_piece (ctx, ctx->in_reg, addr_or_regnum, size);
dwarf_expr_pop (ctx);
ctx->in_reg = 0;
}
break;
case DW_OP_APPLE_uninit:
fprintf_filtered (stream, " [ uninitialized ]");
break;
default:
fprintf_filtered (stream, "unable to determine position");
}
}
*loc_ptr = op_ptr;
}
static int
loclist_describe_location (struct symbol *symbol, struct ui_file *stream)
{
struct dwarf2_loclist_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
struct dwarf_expr_context *ctx;
gdb_byte *loc_ptr, *buf_end, *loc_end;
int length;
CORE_ADDR low, high;
unsigned int addr_size = TARGET_ADDR_BIT / TARGET_CHAR_BIT;
CORE_ADDR base_mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
CORE_ADDR base_offset = objfile_text_section_offset (dlbaton->objfile);
CORE_ADDR base_address = dlbaton->base_address_untranslated;
loc_ptr = dlbaton->data;
buf_end = dlbaton->data + dlbaton->size;
fprintf_filtered (stream, "\n");
while (1)
{
low = dwarf2_read_address (loc_ptr, buf_end, &length);
loc_ptr += length;
high = dwarf2_read_address (loc_ptr, buf_end, &length);
loc_ptr += length;
if (low == 0 && high == 0)
break;
if ((low & base_mask) == base_mask)
{
base_address = high;
continue;
}
low += base_address;
high += base_address;
if (dlbaton->addr_map)
{
translate_debug_map_address (dlbaton->addr_map, low, &low, 0);
translate_debug_map_address (dlbaton->addr_map, high, &high, 1);
}
low += base_offset;
high += base_offset;
length = extract_unsigned_integer (loc_ptr, 2);
loc_ptr += 2;
loc_end = loc_ptr + length;
ctx = new_dwarf_expr_context ();
ctx->baton = dlbaton;
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;
fprintf_filtered (stream, "\n 0x%s - 0x%s: ", paddr_nz (low),
paddr_nz (high));
print_single_dwarf_location (stream, &loc_ptr, loc_end, ctx);
free_dwarf_expr_context (ctx);
}
return 1;
}
static void
loclist_tracepoint_var_ref (struct symbol * symbol, struct agent_expr * ax,
struct axs_value * value)
{
struct dwarf2_loclist_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
gdb_byte *data;
size_t size;
data = find_location_expression (dlbaton, &size, ax->scope);
if (data == NULL)
error (_("Variable \"%s\" is not available."), SYMBOL_NATURAL_NAME (symbol));
dwarf2_tracepoint_var_ref (symbol, ax, value, data, size);
}
const struct symbol_ops dwarf2_loclist_funcs = {
loclist_read_variable,
loclist_read_needs_frame,
loclist_describe_location,
loclist_tracepoint_var_ref
};