+2018-03-06 Mark Wielaard <mark@klomp.org>
+
+ * dwarf.h: Add DW_OP_implicit_pointer, DW_OP_addrx, DW_OP_constx,
+ DW_OP_entry_value, DW_OP_const_type, DW_OP_regval_type,
+ DW_OP_deref_type, DW_OP_xderef_type, DW_OP_convert and
+ DW_OP_reinterpret.
+ * dwarf_getlocation.c (__libdw_intern_expression): Handle
+ DW_OP_convert, DW_OP_reinterpret, DW_OP_addrx, DW_OP_constx,
+ DW_OP_regval_type, DW_OP_entry_value, DW_OP_implicit_pointer,
+ DW_OP_deref_type, DW_OP_xderef_type and DW_OP_const_type.
+ * dwarf_getlocation_attr.c (dwarf_getlocation_attr): Handle
+ DW_OP_entry_value, DW_OP_const_type and DW_OP_implicit_pointer.
+ * dwarf_getlocation_die.c (dwarf_getlocation_die): Handle
+ DW_OP_implicit_pointer, DW_OP_convert, DW_OP_reinterpret,
+ DW_OP_const_type, DW_OP_regval_type, DW_OP_deref_type and
+ DW_OP_xderef_type.
+ * dwarf_getlocation_implicit_pointer.c
+ (dwarf_getlocation_implicit_pointer): Handle DW_OP_implicit_pointer.
+
2018-03-01 Mark Wielaard <mark@klomp.org>
* dwarf.h: Add DW_AT_GNU_locviews and DW_AT_GNU_entry_view.
DW_OP_implicit_value = 0x9e, /* DW_FORM_block follows opcode. */
DW_OP_stack_value = 0x9f, /* No operands, special like DW_OP_piece. */
+ DW_OP_implicit_pointer = 0xa0,
+ DW_OP_addrx = 0xa1,
+ DW_OP_constx = 0xa2,
+ DW_OP_entry_value = 0xa3,
+ DW_OP_const_type = 0xa4,
+ DW_OP_regval_type = 0xa5,
+ DW_OP_deref_type = 0xa6,
+ DW_OP_xderef_type = 0xa7,
+ DW_OP_convert = 0xa8,
+ DW_OP_reinterpret = 0xa9,
+
/* GNU extensions. */
DW_OP_GNU_push_tls_address = 0xe0,
DW_OP_GNU_uninit = 0xf0,
/* Return location expression list.
- Copyright (C) 2000-2010, 2013-2015 Red Hat, Inc.
+ Copyright (C) 2000-2010, 2013-2015, 2017 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2000.
case DW_OP_plus_uconst:
case DW_OP_regx:
case DW_OP_piece:
+ case DW_OP_convert:
case DW_OP_GNU_convert:
+ case DW_OP_reinterpret:
case DW_OP_GNU_reinterpret:
+ case DW_OP_addrx:
+ case DW_OP_constx:
get_uleb128 (newloc->number, data, end_data);
break;
break;
case DW_OP_bit_piece:
+ case DW_OP_regval_type:
case DW_OP_GNU_regval_type:
get_uleb128 (newloc->number, data, end_data);
if (unlikely (data >= end_data))
break;
case DW_OP_implicit_value:
+ case DW_OP_entry_value:
case DW_OP_GNU_entry_value:
/* This cannot be used in a CFI expression. */
if (unlikely (dbg == NULL))
data += newloc->number; /* Skip the block. */
break;
+ case DW_OP_implicit_pointer:
case DW_OP_GNU_implicit_pointer:
/* DW_FORM_ref_addr, depends on offset size of CU. */
if (dbg == NULL || __libdw_read_offset_inc (dbg, sec_index, &data,
get_uleb128 (newloc->number2, data, end_data); /* Byte offset. */
break;
+ case DW_OP_deref_type:
case DW_OP_GNU_deref_type:
+ case DW_OP_xderef_type:
if (unlikely (data + 1 >= end_data))
goto invalid;
newloc->number = *data++;
get_uleb128 (newloc->number2, data, end_data);
break;
+ case DW_OP_const_type:
case DW_OP_GNU_const_type:
{
size_t size;
/* Return DWARF attribute associated with a location expression op.
- Copyright (C) 2013, 2014 Red Hat, Inc.
+ Copyright (C) 2013, 2014, 2017 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
result->cu = attr_form_cu (attr);
break;
+ case DW_OP_entry_value:
case DW_OP_GNU_entry_value:
result->code = DW_AT_location;
result->form = DW_FORM_exprloc;
result->cu = attr_form_cu (attr);
break;
+ case DW_OP_const_type:
case DW_OP_GNU_const_type:
result->code = DW_AT_const_value;
result->form = DW_FORM_block1;
}
break;
+ case DW_OP_implicit_pointer:
case DW_OP_GNU_implicit_pointer:
case DW_OP_GNU_variable_value:
{
/* Return DIE associated with a location expression op.
- Copyright (C) 2013 Red Hat, Inc.
+ Copyright (C) 2013, 2017 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
Dwarf_Off dieoff;
switch (op->atom)
{
+ case DW_OP_implicit_pointer:
case DW_OP_GNU_implicit_pointer:
case DW_OP_call_ref:
case DW_OP_GNU_variable_value:
break;
case DW_OP_GNU_parameter_ref:
+ case DW_OP_convert:
case DW_OP_GNU_convert:
+ case DW_OP_reinterpret:
case DW_OP_GNU_reinterpret:
+ case DW_OP_const_type:
case DW_OP_GNU_const_type:
case DW_OP_call2:
case DW_OP_call4:
dieoff = attr->cu->start + op->number;
break;
+ case DW_OP_regval_type:
case DW_OP_GNU_regval_type:
+ case DW_OP_deref_type:
case DW_OP_GNU_deref_type:
dieoff = attr->cu->start + op->number2;
break;
+ case DW_OP_xderef_type:
+ dieoff = op->number2;
+ break;
+
default:
__libdw_seterrno (DWARF_E_INVALID_ACCESS);
return -1;
/* Return associated attribute for DW_OP_GNU_implicit_pointer.
- Copyright (C) 2010 Red Hat, Inc.
+ Copyright (C) 2010, 2017 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
if (attr == NULL)
return -1;
- if (unlikely (op->atom != DW_OP_GNU_implicit_pointer))
+ if (unlikely (op->atom != DW_OP_implicit_pointer
+ && op->atom != DW_OP_GNU_implicit_pointer))
{
__libdw_seterrno (DWARF_E_INVALID_ACCESS);
return -1;
+2018-03-06 Mark Wielaard <mark@klomp.org>
+
+ * readelf.c (print_ops): Handle DW_OP_addrx, DW_OP_constx,
+ DW_OP_implicit_pointer, DW_OP_entry_value, DW_OP_const_type,
+ DW_OP_regval_type, DW_OP_deref_type, DW_OP_xderef_type,
+ DW_OP_convert, DW_OP_reinterpret.
+
2018-03-01 Mark Wielaard <mark@klomp.org>
* readelf.c (struct listptr): Add attr field.
case DW_OP_piece:
case DW_OP_regx:
case DW_OP_plus_uconst:
- case DW_OP_constu:;
+ case DW_OP_constu:
+ case DW_OP_addrx:
+ case DW_OP_constx:;
const unsigned char *start = data;
uint64_t uleb;
NEED (1);
offset += 1 + (data - start);
break;
+ case DW_OP_implicit_pointer:
case DW_OP_GNU_implicit_pointer:
/* DIE offset operand. */
start = data;
offset += 1 + (data - start);
break;
+ case DW_OP_entry_value:
case DW_OP_GNU_entry_value:
/* Size plus expression block. */
start = data;
offset += 1 + (data - start);
break;
+ case DW_OP_const_type:
case DW_OP_GNU_const_type:
/* uleb128 CU relative DW_TAG_base_type DIE offset, 1-byte
unsigned size plus block. */
offset += 1 + (data - start);
break;
+ case DW_OP_regval_type:
case DW_OP_GNU_regval_type:
/* uleb128 register number, uleb128 CU relative
DW_TAG_base_type DIE offset. */
offset += 1 + (data - start);
break;
+ case DW_OP_deref_type:
case DW_OP_GNU_deref_type:
/* 1-byte unsigned size of value, uleb128 CU relative
DW_TAG_base_type DIE offset. */
offset += 1 + (data - start);
break;
+ case DW_OP_xderef_type:
+ /* 1-byte unsigned size of value, uleb128 base_type DIE offset. */
+ start = data;
+ NEED (1);
+ usize = *(uint8_t *) data++;
+ NEED (1);
+ get_uleb128 (uleb, data, data + len);
+ printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
+ indent, "", (uintmax_t) offset,
+ op_name, usize, uleb);
+ CONSUME (data - start);
+ offset += 1 + (data - start);
+ break;
+
+ case DW_OP_convert:
case DW_OP_GNU_convert:
+ case DW_OP_reinterpret:
case DW_OP_GNU_reinterpret:
/* uleb128 CU relative offset to DW_TAG_base_type, or zero
for conversion to untyped. */
+2018-03-06 Mark Wielaard <mark@klomp.org>
+
+ * varlocs.c (print_expr): Handle DW_OP_implicit_pointer,
+ DW_OP_entry_value, DW_OP_convert, DW_OP_reinterpret,
+ DW_OP_regval_type, DW_OP_deref_type, DW_OP_xderef_type and
+ DW_OP_const_type.
+
2018-02-16 Mark Wielaard <mark@klomp.org>
* backtrace-subr.sh (check_native_core): Check if there is any core,
/* Test program for dwarf location functions.
- Copyright (C) 2013, 2015 Red Hat, Inc.
+ Copyright (C) 2013, 2015, 2017 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
}
break;
+ case DW_OP_implicit_pointer:
case DW_OP_GNU_implicit_pointer:
/* Special, DIE offset, signed offset. Referenced DIE has a
location or const_value attribute. */
}
break;
+ case DW_OP_entry_value:
case DW_OP_GNU_entry_value:
/* Special, unsigned size plus expression block. All registers
inside the block should be interpreted as they had on
}
break;
+ case DW_OP_convert:
case DW_OP_GNU_convert:
+ case DW_OP_reinterpret:
case DW_OP_GNU_reinterpret:
/* Special, unsigned CU relative DIE offset pointing to a
DW_TAG_base_type. Pops a value, converts or reinterprets the
}
break;
+ case DW_OP_regval_type:
case DW_OP_GNU_regval_type:
/* Special, unsigned register number plus unsigned CU relative
DIE offset pointing to a DW_TAG_base_type. */
}
break;
+ case DW_OP_deref_type:
case DW_OP_GNU_deref_type:
/* Special, unsigned size plus unsigned CU relative DIE offset
- pointing to a DW_TAG_base_type. */
+ pointing to a DW_TAG_base_type. */
{
Dwarf_Die type;
if (dwarf_getlocation_die (attr, expr, &type) != 0)
}
break;
+ case DW_OP_xderef_type:
+ /* Special, unsigned size plus unsigned DIE offset
+ pointing to a DW_TAG_base_type. */
+ {
+ Dwarf_Die type;
+ if (dwarf_getlocation_die (attr, expr, &type) != 0)
+ error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
+ dwarf_errmsg (-1));
+ // XXX check size against base_type size?
+ printf ("%s(%" PRIu64 ")", opname, expr->number);
+ print_base_type (&type);
+ }
+ break;
+
+ case DW_OP_const_type:
case DW_OP_GNU_const_type:
/* Special, unsigned CU relative DIE offset pointing to a
DW_TAG_base_type, an unsigned size length plus a block with