jasonmolenda created this revision.
jasonmolenda added reviewers: JDevlieghere, jingham.
jasonmolenda added a project: LLDB.
Herald added a subscriber: Michael137.
Herald added a project: All.
jasonmolenda requested review of this revision.
Herald added a subscriber: lldb-commits.

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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D137682

Files:
  lldb/source/Expression/DWARFExpression.cpp
  lldb/source/Expression/IRMemoryMap.cpp
  lldb/test/API/lang/c/high-mem-global/Makefile
  lldb/test/API/lang/c/high-mem-global/TestHighMemGlobal.py
  lldb/test/API/lang/c/high-mem-global/main.c

Index: lldb/test/API/lang/c/high-mem-global/main.c
===================================================================
--- /dev/null
+++ lldb/test/API/lang/c/high-mem-global/main.c
@@ -0,0 +1,9 @@
+
+struct mystruct {
+  int c, d, e;
+} global = {1, 2, 3};
+
+int main ()
+{
+  return global.c; // break here
+}
Index: lldb/test/API/lang/c/high-mem-global/TestHighMemGlobal.py
===================================================================
--- /dev/null
+++ lldb/test/API/lang/c/high-mem-global/TestHighMemGlobal.py
@@ -0,0 +1,52 @@
+"""Look that lldb can display a global loaded in high memory at an addressable address."""
+
+
+import lldb
+from lldbsuite.test.lldbtest import *
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.decorators import *
+
+class TestHighMemGlobal(TestBase):
+
+    NO_DEBUG_INFO_TESTCASE = True
+
+    @skipUnlessDarwin  # hardcoding of __DATA segment name
+    def test_command_line(self):
+        """Test that we can display a global variable loaded in high memory."""
+        self.build()
+
+        exe = self.getBuildArtifact("a.out")
+        err = lldb.SBError()
+
+        target = self.dbg.CreateTarget(exe, '', '', False, err)
+        self.assertTrue(target.IsValid())
+        module = target.GetModuleAtIndex(0)
+        self.assertTrue(module.IsValid())
+        data_segment = module.FindSection("__DATA")
+        self.assertTrue(data_segment.IsValid())
+        err.Clear()
+
+        self.expect("p global.c", substrs=[' = 1'])
+
+        err = target.SetSectionLoadAddress(data_segment, 0xffffffff00000000)
+        self.assertTrue(err.Success())
+        self.expect("p global.c", substrs=[' = 1'])
+
+        err = target.SetSectionLoadAddress(data_segment, 0x0000088100004000)
+        self.assertTrue(err.Success())
+        self.expect("p global.c", substrs=[' = 1'])
+
+        # This is an address in IRMemoryMap::FindSpace where it has an 
+        # lldb-side buffer of memory that's used in IR interpreters when
+        # memory cannot be allocated in the inferior / functions cannot
+        # be jitted.
+        err = target.SetSectionLoadAddress(data_segment, 0xdead0fff00000000)
+        self.assertTrue(err.Success())
+
+        # The global variable `global` is now overlayed by this 
+        # IRMemoryMap special buffer, and now we cannot see the variable.
+        # If the IRInterpreter some day is able to distinguish between
+        # an addr_t in its IRMemoryMap local buffer versus inferior process
+        # memory, this test would no longer pass.
+        self.runCmd("p int $tmp = global.c")
+        self.expect("p $tmp != 1", substrs=[' = true'])
Index: lldb/test/API/lang/c/high-mem-global/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/lang/c/high-mem-global/Makefile
@@ -0,0 +1,3 @@
+C_SOURCES := main.c
+
+include Makefile.rules
Index: lldb/source/Expression/IRMemoryMap.cpp
===================================================================
--- lldb/source/Expression/IRMemoryMap.cpp
+++ lldb/source/Expression/IRMemoryMap.cpp
@@ -143,7 +143,7 @@
     if (address_byte_size != UINT32_MAX) {
       switch (address_byte_size) {
       case 8:
-        ret = 0xffffffff00000000ull;
+        ret = 0xdead0fff00000000ull;
         break;
       case 4:
         ret = 0xee000000ull;
Index: lldb/source/Expression/DWARFExpression.cpp
===================================================================
--- lldb/source/Expression/DWARFExpression.cpp
+++ lldb/source/Expression/DWARFExpression.cpp
@@ -917,9 +917,8 @@
         stack.back().SetValueType(Value::ValueType::FileAddress);
         // Convert the file address to a load address, so subsequent
         // DWARF operators can operate on it.
-        if (frame)
-          stack.back().ConvertToLoadAddress(module_sp.get(),
-                                            frame->CalculateTarget().get());
+        if (target)
+          stack.back().ConvertToLoadAddress(module_sp.get(), target);
       }
       break;
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to