mirror of
https://github.com/openharmony/third_party_elfutils.git
synced 2026-07-19 19:43:34 -04:00
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:
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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. */
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user