Index: gdb/dwarf2expr.c |
diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c |
index 222fcc302bbf25ee429efe5584c68f4bcd5f212f..214b371e569f083bdf9cf98a3cca120e299a4f58 100644 |
--- a/gdb/dwarf2expr.c |
+++ b/gdb/dwarf2expr.c |
@@ -342,7 +342,7 @@ add_piece (struct dwarf_expr_context *ctx, ULONGEST size, ULONGEST offset) |
} |
else if (p->location == DWARF_VALUE_IMPLICIT_POINTER) |
{ |
- p->v.ptr.die = ctx->len; |
+ p->v.ptr.die.cu_off = ctx->len; |
p->v.ptr.offset = value_as_long (dwarf_expr_fetch (ctx, 0)); |
} |
else if (p->location == DWARF_VALUE_REGISTER) |
@@ -369,60 +369,36 @@ dwarf_expr_eval (struct dwarf_expr_context *ctx, const gdb_byte *addr, |
gdb_assert (ctx->recursion_depth == old_recursion_depth); |
} |
-/* 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. R can be NULL, the constant is then only skipped. */ |
+/* Helper to read a uleb128 value or throw an error. */ |
const gdb_byte * |
-read_uleb128 (const gdb_byte *buf, const gdb_byte *buf_end, ULONGEST * r) |
+safe_read_uleb128 (const gdb_byte *buf, const gdb_byte *buf_end, |
+ uint64_t *r) |
{ |
- unsigned shift = 0; |
- ULONGEST result = 0; |
- gdb_byte byte; |
- |
- while (1) |
- { |
- if (buf >= buf_end) |
- error (_("read_uleb128: Corrupted DWARF expression.")); |
- |
- byte = *buf++; |
- result |= ((ULONGEST) (byte & 0x7f)) << shift; |
- if ((byte & 0x80) == 0) |
- break; |
- shift += 7; |
- } |
- if (r) |
- *r = result; |
+ buf = gdb_read_uleb128 (buf, buf_end, r); |
+ if (buf == NULL) |
+ error (_("DWARF expression error: ran off end of buffer reading uleb128 value")); |
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. R can be NULL, the constant is then only skipped. */ |
+/* Helper to read a sleb128 value or throw an error. */ |
const gdb_byte * |
-read_sleb128 (const gdb_byte *buf, const gdb_byte *buf_end, LONGEST * r) |
+safe_read_sleb128 (const gdb_byte *buf, const gdb_byte *buf_end, |
+ int64_t *r) |
{ |
- unsigned shift = 0; |
- LONGEST result = 0; |
- gdb_byte byte; |
- |
- while (1) |
- { |
- if (buf >= buf_end) |
- error (_("read_sleb128: Corrupted DWARF expression.")); |
- |
- byte = *buf++; |
- result |= ((ULONGEST) (byte & 0x7f)) << shift; |
- shift += 7; |
- if ((byte & 0x80) == 0) |
- break; |
- } |
- if (shift < (sizeof (*r) * 8) && (byte & 0x40) != 0) |
- result |= -(((LONGEST) 1) << shift); |
+ buf = gdb_read_sleb128 (buf, buf_end, r); |
+ if (buf == NULL) |
+ error (_("DWARF expression error: ran off end of buffer reading sleb128 value")); |
+ return buf; |
+} |
- if (r) |
- *r = result; |
+const gdb_byte * |
+safe_skip_leb128 (const gdb_byte *buf, const gdb_byte *buf_end) |
+{ |
+ buf = gdb_skip_leb128 (buf, buf_end); |
+ if (buf == NULL) |
+ error (_("DWARF expression error: ran off end of buffer reading leb128 value")); |
return buf; |
} |
@@ -464,7 +440,7 @@ base_types_equal_p (struct type *t1, struct type *t2) |
size. */ |
static struct type * |
-dwarf_get_base_type (struct dwarf_expr_context *ctx, ULONGEST die, int size) |
+dwarf_get_base_type (struct dwarf_expr_context *ctx, cu_offset die, int size) |
{ |
struct type *result; |
@@ -489,7 +465,7 @@ dwarf_get_base_type (struct dwarf_expr_context *ctx, ULONGEST die, int size) |
int |
dwarf_block_to_dwarf_reg (const gdb_byte *buf, const gdb_byte *buf_end) |
{ |
- ULONGEST dwarf_reg; |
+ uint64_t dwarf_reg; |
if (buf_end <= buf) |
return -1; |
@@ -503,13 +479,19 @@ dwarf_block_to_dwarf_reg (const gdb_byte *buf, const gdb_byte *buf_end) |
if (*buf == DW_OP_GNU_regval_type) |
{ |
buf++; |
- buf = read_uleb128 (buf, buf_end, &dwarf_reg); |
- buf = read_uleb128 (buf, buf_end, NULL); |
+ buf = gdb_read_uleb128 (buf, buf_end, &dwarf_reg); |
+ if (buf == NULL) |
+ return -1; |
+ buf = gdb_skip_leb128 (buf, buf_end); |
+ if (buf == NULL) |
+ return -1; |
} |
else if (*buf == DW_OP_regx) |
{ |
buf++; |
- buf = read_uleb128 (buf, buf_end, &dwarf_reg); |
+ buf = gdb_read_uleb128 (buf, buf_end, &dwarf_reg); |
+ if (buf == NULL) |
+ return -1; |
} |
else |
return -1; |
@@ -527,31 +509,35 @@ int |
dwarf_block_to_dwarf_reg_deref (const gdb_byte *buf, const gdb_byte *buf_end, |
CORE_ADDR *deref_size_return) |
{ |
- ULONGEST dwarf_reg; |
- LONGEST offset; |
+ uint64_t dwarf_reg; |
+ int64_t offset; |
if (buf_end <= buf) |
return -1; |
+ |
if (*buf >= DW_OP_breg0 && *buf <= DW_OP_breg31) |
{ |
dwarf_reg = *buf - DW_OP_breg0; |
buf++; |
+ if (buf >= buf_end) |
+ return -1; |
} |
else if (*buf == DW_OP_bregx) |
{ |
buf++; |
- buf = read_uleb128 (buf, buf_end, &dwarf_reg); |
+ buf = gdb_read_uleb128 (buf, buf_end, &dwarf_reg); |
+ if (buf == NULL) |
+ return -1; |
if ((int) dwarf_reg != dwarf_reg) |
return -1; |
} |
else |
return -1; |
- buf = read_sleb128 (buf, buf_end, &offset); |
- if (offset != 0) |
+ buf = gdb_read_sleb128 (buf, buf_end, &offset); |
+ if (buf == NULL) |
return -1; |
- |
- if (buf >= buf_end) |
+ if (offset != 0) |
return -1; |
if (*buf == DW_OP_deref) |
@@ -582,7 +568,7 @@ int |
dwarf_block_to_fb_offset (const gdb_byte *buf, const gdb_byte *buf_end, |
CORE_ADDR *fb_offset_return) |
{ |
- LONGEST fb_offset; |
+ int64_t fb_offset; |
if (buf_end <= buf) |
return 0; |
@@ -591,7 +577,9 @@ dwarf_block_to_fb_offset (const gdb_byte *buf, const gdb_byte *buf_end, |
return 0; |
buf++; |
- buf = read_sleb128 (buf, buf_end, &fb_offset); |
+ buf = gdb_read_sleb128 (buf, buf_end, &fb_offset); |
+ if (buf == NULL) |
+ return 0; |
*fb_offset_return = fb_offset; |
if (buf != buf_end || fb_offset != (LONGEST) *fb_offset_return) |
return 0; |
@@ -607,8 +595,8 @@ 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; |
+ uint64_t dwarf_reg; |
+ int64_t sp_offset; |
if (buf_end <= buf) |
return 0; |
@@ -622,14 +610,18 @@ dwarf_block_to_sp_offset (struct gdbarch *gdbarch, const gdb_byte *buf, |
if (*buf != DW_OP_bregx) |
return 0; |
buf++; |
- buf = read_uleb128 (buf, buf_end, &dwarf_reg); |
+ buf = gdb_read_uleb128 (buf, buf_end, &dwarf_reg); |
+ if (buf == NULL) |
+ return 0; |
} |
if (gdbarch_dwarf2_reg_to_regnum (gdbarch, dwarf_reg) |
!= gdbarch_sp_regnum (gdbarch)) |
return 0; |
- buf = read_sleb128 (buf, buf_end, &sp_offset); |
+ buf = gdb_read_sleb128 (buf, buf_end, &sp_offset); |
+ if (buf == NULL) |
+ return 0; |
*sp_offset_return = sp_offset; |
if (buf != buf_end || sp_offset != (LONGEST) *sp_offset_return) |
return 0; |
@@ -673,8 +665,8 @@ execute_stack_op (struct dwarf_expr_context *ctx, |
This is just an optimization, so it's always ok to punt |
and leave this as 0. */ |
int in_stack_memory = 0; |
- ULONGEST uoffset, reg; |
- LONGEST offset; |
+ uint64_t uoffset, reg; |
+ int64_t offset; |
struct value *result_val = NULL; |
/* The DWARF expression might have a bug causing an infinite |
@@ -732,6 +724,18 @@ execute_stack_op (struct dwarf_expr_context *ctx, |
result_val = value_from_ulongest (address_type, result); |
break; |
+ case DW_OP_GNU_addr_index: |
+ op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset); |
+ result = (ctx->funcs->get_addr_index) (ctx->baton, uoffset); |
+ result += ctx->offset; |
+ result_val = value_from_ulongest (address_type, result); |
+ break; |
+ case DW_OP_GNU_const_index: |
+ op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset); |
+ result = (ctx->funcs->get_addr_index) (ctx->baton, uoffset); |
+ result_val = value_from_ulongest (address_type, result); |
+ break; |
+ |
case DW_OP_const1u: |
result = extract_unsigned_integer (op_ptr, 1, byte_order); |
result_val = value_from_ulongest (address_type, result); |
@@ -773,12 +777,12 @@ execute_stack_op (struct dwarf_expr_context *ctx, |
op_ptr += 8; |
break; |
case DW_OP_constu: |
- op_ptr = read_uleb128 (op_ptr, op_end, &uoffset); |
+ op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset); |
result = uoffset; |
result_val = value_from_ulongest (address_type, result); |
break; |
case DW_OP_consts: |
- op_ptr = read_sleb128 (op_ptr, op_end, &offset); |
+ op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset); |
result = offset; |
result_val = value_from_ulongest (address_type, result); |
break; |
@@ -831,7 +835,7 @@ execute_stack_op (struct dwarf_expr_context *ctx, |
break; |
case DW_OP_regx: |
- op_ptr = read_uleb128 (op_ptr, op_end, ®); |
+ op_ptr = safe_read_uleb128 (op_ptr, op_end, ®); |
dwarf_expr_require_composition (op_ptr, op_end, "DW_OP_regx"); |
result = reg; |
@@ -841,9 +845,9 @@ execute_stack_op (struct dwarf_expr_context *ctx, |
case DW_OP_implicit_value: |
{ |
- ULONGEST len; |
+ uint64_t len; |
- op_ptr = read_uleb128 (op_ptr, op_end, &len); |
+ op_ptr = safe_read_uleb128 (op_ptr, op_end, &len); |
if (op_ptr + len > op_end) |
error (_("DW_OP_implicit_value: too few bytes available.")); |
ctx->len = len; |
@@ -862,20 +866,19 @@ execute_stack_op (struct dwarf_expr_context *ctx, |
case DW_OP_GNU_implicit_pointer: |
{ |
- ULONGEST die; |
- LONGEST len; |
+ int64_t 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. */ |
+ /* The referred-to DIE of cu_offset kind. */ |
ctx->len = extract_unsigned_integer (op_ptr, ctx->ref_addr_size, |
byte_order); |
op_ptr += ctx->ref_addr_size; |
/* The byte offset into the data. */ |
- op_ptr = read_sleb128 (op_ptr, op_end, &len); |
+ op_ptr = safe_read_sleb128 (op_ptr, op_end, &len); |
result = (ULONGEST) len; |
result_val = value_from_ulongest (address_type, result); |
@@ -918,7 +921,7 @@ execute_stack_op (struct dwarf_expr_context *ctx, |
case DW_OP_breg30: |
case DW_OP_breg31: |
{ |
- op_ptr = read_sleb128 (op_ptr, op_end, &offset); |
+ op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset); |
result = (ctx->funcs->read_reg) (ctx->baton, op - DW_OP_breg0); |
result += offset; |
result_val = value_from_ulongest (address_type, result); |
@@ -926,8 +929,8 @@ execute_stack_op (struct dwarf_expr_context *ctx, |
break; |
case DW_OP_bregx: |
{ |
- op_ptr = read_uleb128 (op_ptr, op_end, ®); |
- op_ptr = read_sleb128 (op_ptr, op_end, &offset); |
+ op_ptr = safe_read_uleb128 (op_ptr, op_end, ®); |
+ op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset); |
result = (ctx->funcs->read_reg) (ctx->baton, reg); |
result += offset; |
result_val = value_from_ulongest (address_type, result); |
@@ -939,7 +942,7 @@ execute_stack_op (struct dwarf_expr_context *ctx, |
size_t datalen; |
unsigned int before_stack_len; |
- op_ptr = read_sleb128 (op_ptr, op_end, &offset); |
+ op_ptr = safe_read_sleb128 (op_ptr, op_end, &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 |
@@ -1031,9 +1034,10 @@ execute_stack_op (struct dwarf_expr_context *ctx, |
if (op == DW_OP_GNU_deref_type) |
{ |
- ULONGEST type_die; |
+ cu_offset type_die; |
- op_ptr = read_uleb128 (op_ptr, op_end, &type_die); |
+ op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset); |
+ type_die.cu_off = uoffset; |
type = dwarf_get_base_type (ctx, type_die, 0); |
} |
else |
@@ -1083,7 +1087,7 @@ execute_stack_op (struct dwarf_expr_context *ctx, |
case DW_OP_plus_uconst: |
dwarf_require_integral (value_type (result_val)); |
result = value_as_long (result_val); |
- op_ptr = read_uleb128 (op_ptr, op_end, ®); |
+ op_ptr = safe_read_uleb128 (op_ptr, op_end, ®); |
result += reg; |
result_val = value_from_ulongest (address_type, result); |
break; |
@@ -1293,10 +1297,10 @@ execute_stack_op (struct dwarf_expr_context *ctx, |
case DW_OP_piece: |
{ |
- ULONGEST size; |
+ uint64_t size; |
/* Record the piece. */ |
- op_ptr = read_uleb128 (op_ptr, op_end, &size); |
+ op_ptr = safe_read_uleb128 (op_ptr, op_end, &size); |
add_piece (ctx, 8 * size, 0); |
/* Pop off the address/regnum, and reset the location |
@@ -1310,11 +1314,11 @@ execute_stack_op (struct dwarf_expr_context *ctx, |
case DW_OP_bit_piece: |
{ |
- ULONGEST size, offset; |
+ uint64_t size, offset; |
/* Record the piece. */ |
- op_ptr = read_uleb128 (op_ptr, op_end, &size); |
- op_ptr = read_uleb128 (op_ptr, op_end, &offset); |
+ op_ptr = safe_read_uleb128 (op_ptr, op_end, &size); |
+ op_ptr = safe_read_uleb128 (op_ptr, op_end, &offset); |
add_piece (ctx, size, offset); |
/* Pop off the address/regnum, and reset the location |
@@ -1335,47 +1339,57 @@ execute_stack_op (struct dwarf_expr_context *ctx, |
goto no_push; |
case DW_OP_call2: |
- result = extract_unsigned_integer (op_ptr, 2, byte_order); |
- op_ptr += 2; |
- ctx->funcs->dwarf_call (ctx, result); |
+ { |
+ cu_offset offset; |
+ |
+ offset.cu_off = extract_unsigned_integer (op_ptr, 2, byte_order); |
+ op_ptr += 2; |
+ ctx->funcs->dwarf_call (ctx, offset); |
+ } |
goto no_push; |
case DW_OP_call4: |
- result = extract_unsigned_integer (op_ptr, 4, byte_order); |
- op_ptr += 4; |
- ctx->funcs->dwarf_call (ctx, result); |
+ { |
+ cu_offset offset; |
+ |
+ offset.cu_off = extract_unsigned_integer (op_ptr, 4, byte_order); |
+ op_ptr += 4; |
+ ctx->funcs->dwarf_call (ctx, offset); |
+ } |
goto no_push; |
case DW_OP_GNU_entry_value: |
{ |
- ULONGEST len; |
- int dwarf_reg; |
+ uint64_t len; |
CORE_ADDR deref_size; |
+ union call_site_parameter_u kind_u; |
- op_ptr = read_uleb128 (op_ptr, op_end, &len); |
+ op_ptr = safe_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) |
+ kind_u.dwarf_reg = dwarf_block_to_dwarf_reg (op_ptr, op_ptr + len); |
+ if (kind_u.dwarf_reg != -1) |
{ |
op_ptr += len; |
- ctx->funcs->push_dwarf_reg_entry_value (ctx, dwarf_reg, |
- 0 /* unused */, |
+ ctx->funcs->push_dwarf_reg_entry_value (ctx, |
+ CALL_SITE_PARAMETER_DWARF_REG, |
+ kind_u, |
-1 /* deref_size */); |
goto no_push; |
} |
- dwarf_reg = dwarf_block_to_dwarf_reg_deref (op_ptr, op_ptr + len, |
- &deref_size); |
- if (dwarf_reg != -1) |
+ kind_u.dwarf_reg = dwarf_block_to_dwarf_reg_deref (op_ptr, |
+ op_ptr + len, |
+ &deref_size); |
+ if (kind_u.dwarf_reg != -1) |
{ |
if (deref_size == -1) |
deref_size = ctx->addr_size; |
op_ptr += len; |
- ctx->funcs->push_dwarf_reg_entry_value (ctx, dwarf_reg, |
- 0 /* unused */, |
- deref_size); |
+ ctx->funcs->push_dwarf_reg_entry_value (ctx, |
+ CALL_SITE_PARAMETER_DWARF_REG, |
+ kind_u, deref_size); |
goto no_push; |
} |
@@ -1384,14 +1398,29 @@ execute_stack_op (struct dwarf_expr_context *ctx, |
"or for DW_OP_breg*(0)+DW_OP_deref*")); |
} |
+ case DW_OP_GNU_parameter_ref: |
+ { |
+ union call_site_parameter_u kind_u; |
+ |
+ kind_u.param_offset.cu_off = extract_unsigned_integer (op_ptr, 4, |
+ byte_order); |
+ op_ptr += 4; |
+ ctx->funcs->push_dwarf_reg_entry_value (ctx, |
+ CALL_SITE_PARAMETER_PARAM_OFFSET, |
+ kind_u, |
+ -1 /* deref_size */); |
+ } |
+ goto no_push; |
+ |
case DW_OP_GNU_const_type: |
{ |
- ULONGEST type_die; |
+ cu_offset type_die; |
int n; |
const gdb_byte *data; |
struct type *type; |
- op_ptr = read_uleb128 (op_ptr, op_end, &type_die); |
+ op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset); |
+ type_die.cu_off = uoffset; |
n = *op_ptr++; |
data = op_ptr; |
op_ptr += n; |
@@ -1403,11 +1432,12 @@ execute_stack_op (struct dwarf_expr_context *ctx, |
case DW_OP_GNU_regval_type: |
{ |
- ULONGEST type_die; |
+ cu_offset type_die; |
struct type *type; |
- op_ptr = read_uleb128 (op_ptr, op_end, ®); |
- op_ptr = read_uleb128 (op_ptr, op_end, &type_die); |
+ op_ptr = safe_read_uleb128 (op_ptr, op_end, ®); |
+ op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset); |
+ type_die.cu_off = uoffset; |
type = dwarf_get_base_type (ctx, type_die, 0); |
result = (ctx->funcs->read_reg) (ctx->baton, reg); |
@@ -1420,12 +1450,13 @@ execute_stack_op (struct dwarf_expr_context *ctx, |
case DW_OP_GNU_convert: |
case DW_OP_GNU_reinterpret: |
{ |
- ULONGEST type_die; |
+ cu_offset type_die; |
struct type *type; |
- op_ptr = read_uleb128 (op_ptr, op_end, &type_die); |
+ op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset); |
+ type_die.cu_off = uoffset; |
- if (type_die == 0) |
+ if (type_die.cu_off == 0) |
type = address_type; |
else |
type = dwarf_get_base_type (ctx, type_die, 0); |
@@ -1506,7 +1537,7 @@ ctx_no_get_tls_address (void *baton, CORE_ADDR offset) |
/* Stub dwarf_expr_context_funcs.dwarf_call implementation. */ |
void |
-ctx_no_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset) |
+ctx_no_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset) |
{ |
error (_("%s is invalid in this context"), "DW_OP_call*"); |
} |
@@ -1514,7 +1545,7 @@ ctx_no_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset) |
/* Stub dwarf_expr_context_funcs.get_base_type implementation. */ |
struct type * |
-ctx_no_get_base_type (struct dwarf_expr_context *ctx, size_t die) |
+ctx_no_get_base_type (struct dwarf_expr_context *ctx, cu_offset die) |
{ |
error (_("Support for typed DWARF is not supported in this context")); |
} |
@@ -1524,13 +1555,25 @@ ctx_no_get_base_type (struct dwarf_expr_context *ctx, size_t die) |
void |
ctx_no_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx, |
- int dwarf_reg, CORE_ADDR fb_offset, |
+ enum call_site_parameter_kind kind, |
+ union call_site_parameter_u kind_u, |
int deref_size) |
{ |
internal_error (__FILE__, __LINE__, |
_("Support for DW_OP_GNU_entry_value is unimplemented")); |
} |
+/* Stub dwarf_expr_context_funcs.get_addr_index implementation. */ |
+ |
+CORE_ADDR |
+ctx_no_get_addr_index (void *baton, unsigned int index) |
+{ |
+ error (_("%s is invalid in this context"), "DW_OP_GNU_addr_index"); |
+} |
+ |
+/* Provide a prototype to silence -Wmissing-prototypes. */ |
+extern initialize_file_ftype _initialize_dwarf2expr; |
+ |
void |
_initialize_dwarf2expr (void) |
{ |