[lldb-dev] DW_OP_deref handling
Davide Italiano via lldb-dev
lldb-dev at lists.llvm.org
Thu Oct 11 12:32:00 PDT 2018
On Thu, Oct 11, 2018 at 11:16 AM Greg Clayton <clayborg at gmail.com> wrote:
>
> The issue is DW_OP_deref dereferences a pointer and pushes it onto the stack. The code currently, for a load address that is on top of the stack does:
>
> Value::ValueType value_type = stack.back().GetValueType();
> switch (value_type) {
> case Value::eValueTypeLoadAddress:
> if (exe_ctx) {
> if (process) {
> lldb::addr_t pointer_addr = stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
> Status error;
> lldb::addr_t pointer_value = process->ReadPointerFromMemory(pointer_addr, error);
> if (pointer_value != LLDB_INVALID_ADDRESS) {
> stack.back().GetScalar() = pointer_value;
> stack.back().ClearContext();
> } else {
> return false;
> }
>
> Here we just use "stack.back()" to access the item at the top of the expression value stack. The top value has a Value::ValueType of Value::eValueTypeLoadAddress. We don't reset this value to be Value::eValueTypeScalar, but we probably should and that will probably fix this issue.
>
> DWARF5 finally added the ability to track what each value means on the expression stack. Prior to DWARF 5, we had no idea what each entry on the expression value stack was (file address, load address (Value::eValueTypeLoadAddress), plain value (Value::eValueTypeScalar). We have tracked this info for a while now, but the DWARF5 spec is much more specific on how things should be treated. From the spec:
>
> DW_OP_deref
>
> The DW_OP_deref operation pops the top stack entry and treats it as an address. The popped value must have an integral type. The value retrieved from that address is pushed, and has the generic type. The size of the data retrieved from the dereferenced address is the size of an address on the target machine.
>
> No the "The value retrieved from that address is pushed, and has the generic type." statement. In LLDB this means the value's ValueType should be set to Value::eValueTypeScalar.
>
> So try modifying the code with stack.back().SetValueType(Value::eValueTypeScalar) after the stack.back().ClearContext():
>
> if (pointer_value != LLDB_INVALID_ADDRESS) {
> stack.back().GetScalar() = pointer_value;
> stack.back().ClearContext();
> stack.back().SetValueType(Value::eValueTypeScalar);
> } else {
> return false;
> }
>
> That might fix things.
>
> The way the expression ends up right now we end up with an expression stack saying that the value is a load address which means we must read the value from memory in order to find it. This would be the right thing to do if your location expression was:
>
> 0x000000da: TAG_variable [9]
> AT_location( fbreg -16 )
> AT_name( "x" )
> AT_decl_file(...)
> AT_decl_line( 4 )
> AT_type( {0x00000204} ( $sxD ) )
>
> Note I removed the "deref" from the location expression. In this case the variable would need to be read from memory. If the value was to be in a register, then the location would be:
>
> 0x000000da: TAG_variable [9]
> AT_location( reg16 )
> AT_name( "x" )
> AT_decl_file(...)
> AT_decl_line( 4 )
> AT_type( {0x00000204} ( $sxD ) )
>
> Then the value would be in register 16 itself (not dereferenced).
>
> Hope this all makes sense. If you have any questions let me know.
>
Thanks. I tend to agree this is the right thing to do, but it happens
to break many tests in the debugger.
Failing Tests (26):
lldb-Suite :: functionalities/unwind/sigtramp/TestSigtrampUnwind.py
lldb-Suite :: lang/c/blocks/TestBlocks.py
lldb-Suite :: lang/swift/address_of/TestSwiftAddressOf.py
lldb-Suite ::
lang/swift/expression/class_constrained_protocol/TestClassConstrainedProtocol.py
lldb-Suite ::
lang/swift/expression/exclusivity_suppression/TestExclusivitySuppression.py
lldb-Suite ::
lang/swift/expression/optional_amibiguity/TestOptionalAmbiguity.py
lldb-Suite :: lang/swift/expression/scopes/TestExpressionScopes.py
lldb-Suite :: lang/swift/expression/weak_self/TestWeakSelf.py
lldb-Suite ::
lang/swift/foundation_value_types/data/TestSwiftFoundationTypeData.py
lldb-Suite ::
lang/swift/foundation_value_types/date/TestSwiftFoundationTypeDate.py
lldb-Suite ::
lang/swift/foundation_value_types/indexpath/TestSwiftFoundationTypeIndexPath.py
lldb-Suite ::
lang/swift/foundation_value_types/measurement/TestSwiftFoundationTypeMeasurement.py
lldb-Suite ::
lang/swift/foundation_value_types/notification/TestSwiftFoundationTypeNotification.py
lldb-Suite ::
lang/swift/foundation_value_types/url/TestSwiftFoundationTypeURL.py
lldb-Suite ::
lang/swift/foundation_value_types/uuid/TestSwiftFoundationTypeUUID.py
lldb-Suite :: lang/swift/generic_tuple/TestSwiftGenericTuple.py
lldb-Suite :: lang/swift/po/sys_types/TestSwiftPOSysTypes.py
lldb-Suite :: lang/swift/resilience/TestResilience.py
lldb-Suite ::
lang/swift/variables/generic_struct_debug_info/generic_flatmap/TestSwiftGenericStructDebugInfoGenericFlatMap.py
lldb-Suite :: lang/swift/variables/inout/TestInOutVariables.py
lldb-Suite :: lang/swift/variables/protocol/TestSwiftProtocolTypes.py
lldb-Suite ::
lang/swift/variables/uninitialized/TestSwiftUninitializedVariable.py
lldb-Suite :: types/TestFloatTypes.py
lldb-Suite :: types/TestFloatTypesExpr.py
lldb-Suite :: types/TestIntegerTypes.py
lldb-Suite :: types/TestIntegerTypesExpr.py
Expected Passes : 1488
Unsupported Tests : 27
Unexpected Failures: 26
My guess here is that there are even more hacks to work around this
ambiguity of interpretation. The good thing is that many of the
failure are in the swift support, so I can probably navigate through
them relatively quickly. I'll analyze them one by one and maybe
consult you in case there's something that doesn't make se use here.
(There are several C/C++ failure here, but I'll think about those
later) :)
--
Davide
More information about the lldb-dev
mailing list