libdw: Add new DWARF5 Dwarf expression operations.

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 and OP_reinterpret are implemented like their
pre-DWARF5 GNU variants.

DW_OP_xderef_type is implemented as a (non-CU relative) variant of
DW_OP_deref_type.

DW_OP_addrx and DW_OP_constx are recognized but not interpreted yet.

Signed-off-by: Mark Wielaard <mark@klomp.org>
This commit is contained in:
Mark Wielaard
2017-11-15 12:13:38 +01:00
parent 06263dda99
commit 86fbef9bca
10 changed files with 120 additions and 8 deletions
+19
View File
@@ -1,3 +1,22 @@
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.
+11
View File
@@ -567,6 +567,17 @@ enum
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,
+11 -1
View File
@@ -1,5 +1,5 @@
/* 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.
@@ -452,8 +452,12 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
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;
@@ -471,6 +475,7 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
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))
@@ -479,6 +484,7 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
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))
@@ -492,6 +498,7 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
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,
@@ -504,13 +511,16 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
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;
+4 -1
View File
@@ -1,5 +1,5 @@
/* 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
@@ -67,6 +67,7 @@ dwarf_getlocation_attr (Dwarf_Attribute *attr, const Dwarf_Op *op, Dwarf_Attribu
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;
@@ -74,6 +75,7 @@ dwarf_getlocation_attr (Dwarf_Attribute *attr, const Dwarf_Op *op, Dwarf_Attribu
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;
@@ -96,6 +98,7 @@ dwarf_getlocation_attr (Dwarf_Attribute *attr, const Dwarf_Op *op, Dwarf_Attribu
}
break;
case DW_OP_implicit_pointer:
case DW_OP_GNU_implicit_pointer:
case DW_OP_GNU_variable_value:
{
+11 -1
View File
@@ -1,5 +1,5 @@
/* 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
@@ -43,6 +43,7 @@ dwarf_getlocation_die (Dwarf_Attribute *attr, const Dwarf_Op *op,
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:
@@ -50,19 +51,28 @@ dwarf_getlocation_die (Dwarf_Attribute *attr, const Dwarf_Op *op,
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;
+3 -2
View File
@@ -1,5 +1,5 @@
/* 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
@@ -55,7 +55,8 @@ dwarf_getlocation_implicit_pointer (Dwarf_Attribute *attr, const Dwarf_Op *op,
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;
+7
View File
@@ -1,3 +1,10 @@
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.
+24 -1
View File
@@ -4295,7 +4295,9 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
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);
@@ -4388,6 +4390,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
offset += 1 + (data - start);
break;
case DW_OP_implicit_pointer:
case DW_OP_GNU_implicit_pointer:
/* DIE offset operand. */
start = data;
@@ -4410,6 +4413,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
offset += 1 + (data - start);
break;
case DW_OP_entry_value:
case DW_OP_GNU_entry_value:
/* Size plus expression block. */
start = data;
@@ -4425,6 +4429,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
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. */
@@ -4444,6 +4449,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
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. */
@@ -4460,6 +4466,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
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. */
@@ -4477,7 +4484,23 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
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. */
+7
View File
@@ -1,3 +1,10 @@
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,
+23 -2
View File
@@ -1,5 +1,5 @@
/* 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
@@ -411,6 +411,7 @@ print_expr (Dwarf_Attribute *attr, Dwarf_Op *expr, Dwarf_Addr addr)
}
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. */
@@ -504,6 +505,7 @@ print_expr (Dwarf_Attribute *attr, Dwarf_Op *expr, Dwarf_Addr addr)
}
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
@@ -546,7 +548,9 @@ print_expr (Dwarf_Attribute *attr, Dwarf_Op *expr, Dwarf_Addr addr)
}
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
@@ -571,6 +575,7 @@ print_expr (Dwarf_Attribute *attr, Dwarf_Op *expr, Dwarf_Addr addr)
}
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. */
@@ -586,9 +591,10 @@ print_expr (Dwarf_Attribute *attr, Dwarf_Op *expr, Dwarf_Addr addr)
}
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)
@@ -601,6 +607,21 @@ print_expr (Dwarf_Attribute *attr, Dwarf_Op *expr, Dwarf_Addr addr)
}
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