/* Decode the unsigned LEB128 constant at BUF into the variable pointed to
by R, and return the new value of BUF. Verify that it doesn't extend
- past BUF_END. */
+ past BUF_END. R can be NULL, the constant is then only skipped. */
const gdb_byte *
read_uleb128 (const gdb_byte *buf, const gdb_byte *buf_end, ULONGEST * r)
break;
shift += 7;
}
- *r = result;
+ if (r)
+ *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. Verify that it doesn't extend
- past BUF_END. */
+ past BUF_END. R can be NULL, the constant is then only skipped. */
const gdb_byte *
read_sleb128 (const gdb_byte *buf, const gdb_byte *buf_end, LONGEST * r)
break;
}
if (shift < (sizeof (*r) * 8) && (byte & 0x40) != 0)
- result |= -(1 << shift);
+ result |= -(((LONGEST) 1) << shift);
- *r = result;
+ if (r)
+ *r = result;
return buf;
}
\f
checked at the other place that this function is called. */
if (op_ptr != op_end && *op_ptr != DW_OP_piece && *op_ptr != DW_OP_bit_piece)
error (_("DWARF-2 expression error: `%s' operations must be "
- "used either alone or in conjuction with DW_OP_piece "
+ "used either alone or in conjunction with DW_OP_piece "
"or DW_OP_bit_piece."),
op_name);
}
{
struct type *result;
- if (ctx->get_base_type)
+ if (ctx->funcs->get_base_type)
{
- result = ctx->get_base_type (ctx, die);
+ result = ctx->funcs->get_base_type (ctx, die);
if (result == NULL)
error (_("Could not find type for DW_OP_GNU_const_type"));
if (size != 0 && TYPE_LENGTH (result) != size)
return result;
}
+/* If <BUF..BUF_END] contains DW_FORM_block* with single DW_OP_reg* return the
+ DWARF register number. Otherwise return -1. */
+
+int
+dwarf_block_to_dwarf_reg (const gdb_byte *buf, const gdb_byte *buf_end)
+{
+ ULONGEST dwarf_reg;
+
+ if (buf_end <= buf)
+ return -1;
+ if (*buf >= DW_OP_reg0 && *buf <= DW_OP_reg31)
+ {
+ if (buf_end - buf != 1)
+ return -1;
+ return *buf - DW_OP_reg0;
+ }
+
+ if (*buf == DW_OP_GNU_regval_type)
+ {
+ buf++;
+ buf = read_uleb128 (buf, buf_end, &dwarf_reg);
+ buf = read_uleb128 (buf, buf_end, NULL);
+ }
+ else if (*buf == DW_OP_regx)
+ {
+ buf++;
+ buf = read_uleb128 (buf, buf_end, &dwarf_reg);
+ }
+ else
+ return -1;
+ if (buf != buf_end || (int) dwarf_reg != dwarf_reg)
+ return -1;
+ return dwarf_reg;
+}
+
+/* If <BUF..BUF_END] contains DW_FORM_block* with single DW_OP_fbreg(X) fill
+ in FB_OFFSET_RETURN with the X offset and return 1. Otherwise return 0. */
+
+int
+dwarf_block_to_fb_offset (const gdb_byte *buf, const gdb_byte *buf_end,
+ CORE_ADDR *fb_offset_return)
+{
+ LONGEST fb_offset;
+
+ if (buf_end <= buf)
+ return 0;
+
+ if (*buf != DW_OP_fbreg)
+ return 0;
+ buf++;
+
+ buf = read_sleb128 (buf, buf_end, &fb_offset);
+ *fb_offset_return = fb_offset;
+ if (buf != buf_end || fb_offset != (LONGEST) *fb_offset_return)
+ return 0;
+
+ return 1;
+}
+
+/* If <BUF..BUF_END] contains DW_FORM_block* with single DW_OP_bregSP(X) fill
+ in SP_OFFSET_RETURN with the X offset and return 1. Otherwise return 0.
+ The matched SP register number depends on GDBARCH. */
+
+int
+dwarf_block_to_sp_offset (struct gdbarch *gdbarch, const gdb_byte *buf,
+ const gdb_byte *buf_end, CORE_ADDR *sp_offset_return)
+{
+ ULONGEST dwarf_reg;
+ LONGEST sp_offset;
+
+ if (buf_end <= buf)
+ return 0;
+ if (*buf >= DW_OP_breg0 && *buf <= DW_OP_breg31)
+ {
+ dwarf_reg = *buf - DW_OP_breg0;
+ buf++;
+ }
+ else
+ {
+ if (*buf != DW_OP_bregx)
+ return 0;
+ buf++;
+ buf = read_uleb128 (buf, buf_end, &dwarf_reg);
+ }
+
+ if (gdbarch_dwarf2_reg_to_regnum (gdbarch, dwarf_reg)
+ != gdbarch_sp_regnum (gdbarch))
+ return 0;
+
+ buf = read_sleb128 (buf, buf_end, &sp_offset);
+ *sp_offset_return = sp_offset;
+ if (buf != buf_end || sp_offset != (LONGEST) *sp_offset_return)
+ return 0;
+
+ return 1;
+}
+
/* The engine for the expression evaluator. Using the context in CTX,
evaluate the expression between OP_PTR and OP_END. */
LONGEST offset;
struct value *result_val = NULL;
+ /* The DWARF expression might have a bug causing an infinite
+ loop. In that case, quitting is the only way out. */
+ QUIT;
+
switch (op)
{
case DW_OP_lit0:
&& *op_ptr != DW_OP_bit_piece
&& *op_ptr != DW_OP_GNU_uninit)
error (_("DWARF-2 expression error: DW_OP_reg operations must be "
- "used either alone or in conjuction with DW_OP_piece "
+ "used either alone or in conjunction with DW_OP_piece "
"or DW_OP_bit_piece."));
result = op - DW_OP_reg0;
ULONGEST die;
LONGEST len;
+ if (ctx->ref_addr_size == -1)
+ error (_("DWARF-2 expression error: DW_OP_GNU_implicit_pointer "
+ "is not allowed in frame context"));
+
/* The referred-to DIE. */
- ctx->len = extract_unsigned_integer (op_ptr, ctx->addr_size,
+ ctx->len = extract_unsigned_integer (op_ptr, ctx->ref_addr_size,
byte_order);
- op_ptr += ctx->addr_size;
+ op_ptr += ctx->ref_addr_size;
/* The byte offset into the data. */
op_ptr = read_sleb128 (op_ptr, op_end, &len);
case DW_OP_breg31:
{
op_ptr = read_sleb128 (op_ptr, op_end, &offset);
- result = (ctx->read_reg) (ctx->baton, op - DW_OP_breg0);
+ result = (ctx->funcs->read_reg) (ctx->baton, op - DW_OP_breg0);
result += offset;
result_val = value_from_ulongest (address_type, result);
}
{
op_ptr = read_uleb128 (op_ptr, op_end, ®);
op_ptr = read_sleb128 (op_ptr, op_end, &offset);
- result = (ctx->read_reg) (ctx->baton, reg);
+ result = (ctx->funcs->read_reg) (ctx->baton, reg);
result += offset;
result_val = value_from_ulongest (address_type, result);
}
/* FIXME: cagney/2003-03-26: This code should be using
get_frame_base_address(), and then implement a dwarf2
specific this_base method. */
- (ctx->get_frame_base) (ctx->baton, &datastart, &datalen);
+ (ctx->funcs->get_frame_base) (ctx->baton, &datastart, &datalen);
dwarf_expr_eval (ctx, datastart, datalen);
if (ctx->location == DWARF_VALUE_MEMORY)
result = dwarf_expr_fetch_address (ctx, 0);
else if (ctx->location == DWARF_VALUE_REGISTER)
- result
- = (ctx->read_reg) (ctx->baton,
- value_as_long (dwarf_expr_fetch (ctx, 0)));
+ result = (ctx->funcs->read_reg) (ctx->baton,
+ value_as_long (dwarf_expr_fetch (ctx, 0)));
else
error (_("Not implemented: computing frame "
"base using explicit value operator"));
else
type = address_type;
- (ctx->read_mem) (ctx->baton, buf, addr, addr_size);
+ (ctx->funcs->read_mem) (ctx->baton, buf, addr, addr_size);
/* If the size of the object read from memory is different
from the type length, we need to zero-extend it. */
break;
case DW_OP_call_frame_cfa:
- result = (ctx->get_frame_cfa) (ctx->baton);
+ result = (ctx->funcs->get_frame_cfa) (ctx->baton);
result_val = value_from_ulongest (address_type, result);
in_stack_memory = 1;
break;
returned. */
result = value_as_long (dwarf_expr_fetch (ctx, 0));
dwarf_expr_pop (ctx);
- result = (ctx->get_tls_address) (ctx->baton, result);
+ result = (ctx->funcs->get_tls_address) (ctx->baton, result);
result_val = value_from_ulongest (address_type, result);
break;
case DW_OP_call2:
result = extract_unsigned_integer (op_ptr, 2, byte_order);
op_ptr += 2;
- ctx->dwarf_call (ctx, result);
+ ctx->funcs->dwarf_call (ctx, result);
goto no_push;
case DW_OP_call4:
result = extract_unsigned_integer (op_ptr, 4, byte_order);
op_ptr += 4;
- ctx->dwarf_call (ctx, result);
+ ctx->funcs->dwarf_call (ctx, result);
goto no_push;
case DW_OP_GNU_entry_value:
- /* This operation is not yet supported by GDB. */
- ctx->location = DWARF_VALUE_OPTIMIZED_OUT;
- ctx->stack_len = 0;
- ctx->num_pieces = 0;
- goto abort_expression;
+ {
+ ULONGEST len;
+ int dwarf_reg;
+ CORE_ADDR deref_size;
+
+ op_ptr = read_uleb128 (op_ptr, op_end, &len);
+ if (op_ptr + len > op_end)
+ error (_("DW_OP_GNU_entry_value: too few bytes available."));
+
+ dwarf_reg = dwarf_block_to_dwarf_reg (op_ptr, op_ptr + len);
+ if (dwarf_reg != -1)
+ {
+ op_ptr += len;
+ ctx->funcs->push_dwarf_reg_entry_value (ctx, dwarf_reg,
+ 0 /* unused */);
+ goto no_push;
+ }
+
+ error (_("DWARF-2 expression error: DW_OP_GNU_entry_value is "
+ "supported only for single DW_OP_reg*"));
+ }
case DW_OP_GNU_const_type:
{
op_ptr = read_uleb128 (op_ptr, op_end, &type_die);
type = dwarf_get_base_type (ctx, type_die, 0);
- result = (ctx->read_reg) (ctx->baton, reg);
- result_val = value_from_ulongest (type, result);
+ result = (ctx->funcs->read_reg) (ctx->baton, reg);
+ result_val = value_from_ulongest (address_type, result);
+ result_val = value_from_contents (type,
+ value_contents_all (result_val));
}
break;
op_ptr = read_uleb128 (op_ptr, op_end, &type_die);
- type = dwarf_get_base_type (ctx, type_die, 0);
+ if (type_die == 0)
+ type = address_type;
+ else
+ type = dwarf_get_base_type (ctx, type_die, 0);
result_val = dwarf_expr_fetch (ctx, 0);
dwarf_expr_pop (ctx);
gdb_assert (ctx->recursion_depth >= 0);
}
+/* Stub dwarf_expr_context_funcs.read_reg implementation. */
+
+CORE_ADDR
+ctx_no_read_reg (void *baton, int regnum)
+{
+ error (_("Registers access is invalid in this context"));
+}
+
+/* Stub dwarf_expr_context_funcs.get_frame_base implementation. */
+
+void
+ctx_no_get_frame_base (void *baton, const gdb_byte **start, size_t *length)
+{
+ error (_("%s is invalid in this context"), "DW_OP_fbreg");
+}
+
+/* Stub dwarf_expr_context_funcs.get_frame_cfa implementation. */
+
+CORE_ADDR
+ctx_no_get_frame_cfa (void *baton)
+{
+ error (_("%s is invalid in this context"), "DW_OP_call_frame_cfa");
+}
+
+/* Stub dwarf_expr_context_funcs.get_frame_pc implementation. */
+
+CORE_ADDR
+ctx_no_get_frame_pc (void *baton)
+{
+ error (_("%s is invalid in this context"), "DW_OP_GNU_implicit_pointer");
+}
+
+/* Stub dwarf_expr_context_funcs.get_tls_address implementation. */
+
+CORE_ADDR
+ctx_no_get_tls_address (void *baton, CORE_ADDR offset)
+{
+ error (_("%s is invalid in this context"), "DW_OP_GNU_push_tls_address");
+}
+
+/* Stub dwarf_expr_context_funcs.dwarf_call implementation. */
+
+void
+ctx_no_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset)
+{
+ error (_("%s is invalid in this context"), "DW_OP_call*");
+}
+
+/* Stub dwarf_expr_context_funcs.get_base_type implementation. */
+
+struct type *
+ctx_no_get_base_type (struct dwarf_expr_context *ctx, size_t die)
+{
+ error (_("Support for typed DWARF is not supported in this context"));
+}
+
+/* Stub dwarf_expr_context_funcs.push_dwarf_block_entry_value
+ implementation. */
+
+void
+ctx_no_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
+ int dwarf_reg, CORE_ADDR fb_offset)
+{
+ internal_error (__FILE__, __LINE__,
+ _("Support for DW_OP_GNU_entry_value is unimplemented"));
+}
+
void
_initialize_dwarf2expr (void)
{