Page MenuHomePhabricator

Support dereferencing a DWARF scalar stack value
ClosedPublic

Authored by aprantl on Feb 11 2021, 2:03 PM.

Details

Summary

Swift async functions receive function arguments inside a heap-allocated data structure, similar to how ObjC block captures or C++ coroutine arguments are implement. In DWARF they are described relative to an entry value that produces a pointer into that heap object. At typical location looks like

DW_OP_entry_value [ DW_OP_reg14 ] DW_OP_deref DW_OP_plus_uconst 32 DW_OP_deref

This allows the unwinder (which has special ABI knowledge to restore the contents of r14) to push the base address onto the stack thus allowing the deref/offset operations to continue. The result of the entry value is a scalar, because DW_OP_reg14 is a register location — as it should be since we want to restore the pointer value contained in r14 at the beginning of the function and not the historical memory contents it was pointing to. The entry value should restore the address, which is still valid, not the contents at function entry.

To make this work, we need to allow LLDB to dereference Scalar stack results like load addresses, which is what this patch does. Unfortunately it is difficult to test this in isolation, since the DWARFExpression unit test doesn't have a process. Are there any situations where we shouldn't allow Scalars to be dereferences? Could they ever hold a File- or Hostaddress? I don't think so.

Diff Detail

Event Timeline

aprantl created this revision.Feb 11 2021, 2:03 PM
vsk added a comment.Feb 11 2021, 4:17 PM

The logic change seems reasonable to me. Any chance we can provide a mock memory in the DwarfExpression unit test, or check in assembly for a program that uses such an entry value expression?

I think this makes sense. From a DWARF perspective this is sound, all the standard says is that the popped value must have an integral type.

aprantl updated this revision to Diff 323488.Feb 12 2021, 3:10 PM

That took me a little to get right, but here you go! Mock process.

aprantl updated this revision to Diff 323489.Feb 12 2021, 3:16 PM

There's actually no reason to fill a second memory buffer. Replaced all of DoReadMemory with a single for loop.

vsk accepted this revision.Feb 12 2021, 4:09 PM

Thanks, lgtm.

lldb/unittests/Expression/DWARFExpressionTest.cpp
347

Neat, so lit4 is the address and the read pulls out [4, 5, 6, 7].

This revision is now accepted and ready to land.Feb 12 2021, 4:09 PM
aprantl added inline comments.Feb 12 2021, 4:10 PM
lldb/unittests/Expression/DWARFExpressionTest.cpp
347

Yeah that's the lowest sensible address without dereferencing a nullptr :-)

This revision was automatically updated to reflect the committed changes.
Herald added a project: Restricted Project. · View Herald TranscriptFeb 12 2021, 4:12 PM