This is an archive of the discontinued LLVM Phabricator instance.

Change IRMemoryMap's last-resort magic address to an inaddressable address so it doesn't conflict
ClosedPublic

Authored by jasonmolenda on Nov 8 2022, 5:18 PM.

Details

Summary

When the IRInterpreter runs, and needs to store things in inferior memory, and it cannot allocate a memory region in the inferior, IRMemoryMap::FindSpace will create a buffer in lldb memory with a target address, and that will be used. If the target address overlaps with the address of an actual memory region in the inferior process, attempts to access the genuine memory there in IRInterpreted expressions will instead access lldb's local scratch memory. The Process may not support any way to query memory regions, so the solution Sean has picked in years past was to pick an especially unlikely address.

Obviously, we have a program that puts things at this address.

Given that 64-bit systems do not genuinely have 64 bits of address space, we can pick a better address. This patch changes the current unlikely address, 0xffffffff00000000, to 0xdead0fff00000000. Still in high memory, but because bit 62 is now 0 with this address, it cannot overlap with an actual virtual address unless there was a system alling for 62 bits of addressable address space. This is unlikely to happen soon.

I wrote a test which loads a binary into lldb, and slides the DATA segment around to different addresses, testing that the global variable in that DATA segment can still be read, as well as testing that if the DATA segment is slid to this impossible address, we get the incorrect value for the global.

This patch also fixes an incorrect way of getting the Target in DWARFExpression::Evaluate which gets a StackFrame from the ExecutionContext passed in, and uses that to get the Target, instead of simply using the Target, when calculating the load address of the address just read. This had the effect of always returning the original file address, even when I loaded the segment at different addresses, in this test where there's no running process. I looked through DWARFExpression briefly and didn't see any other code doing this.

Diff Detail

Event Timeline

jasonmolenda created this revision.Nov 8 2022, 5:18 PM
Herald added a project: Restricted Project. · View Herald TranscriptNov 8 2022, 5:18 PM
Herald added a subscriber: Michael137. · View Herald Transcript
jasonmolenda requested review of this revision.Nov 8 2022, 5:18 PM

Probably the laziest bit is at the end of the test case where I want to test that the variable isn't '1', I didn't use a substring because it's uninitialized memory could come back as '10' or something.

Update the test to check all three members of the struct can be read at the different memory addresses, and CAN'T be read when it overlaps with IRMemoryMap's special address. This final test, where we test that the values can't be accessed at this inaddressable location, is really only there to keep the test and IRMemoryMap in sync - if anyone changes how IRMemoryMap::FindSpace works with this setup, the test result changing will flag that this test needs to be revisited.

jingham accepted this revision.Nov 11 2022, 3:18 PM

Except that you explicitly want to use the expression parser here so you shouldn't use p in the test, this seems fine to me. It would be better to have a less fragile strategy for getting an unused region, but short of doing exhaustive searches which have their own problems we haven't come up with anything. So making a better hack seems worthy. Fix the p usage and this is good to go.

lldb/test/API/lang/c/high-mem-global/TestHighMemGlobal.py
29

Unless you want to test the alias, it's better to use expr rather than p in tests. We might some day change what the p alias does, and for instance if we get clever about using more static data fetching for p then your test won't test what you think it does anymore.

62

If you are really worried about false positives here, you could just use funkier values for the three members. Not sure that's really necessary, however.

This revision is now accepted and ready to land.Nov 11 2022, 3:18 PM

Update for Jim's feedback.

This revision was landed with ongoing or failed builds.Nov 14 2022, 9:54 AM
This revision was automatically updated to reflect the committed changes.