[Lldb-commits] [lldb] 8be139f - [lldb] Add settings for expression evaluation memory allocations.

Anton Korobeynikov via lldb-commits lldb-commits at lists.llvm.org
Tue May 2 11:02:59 PDT 2023


Author: Ilya Kuklin
Date: 2023-05-02T11:02:44-07:00
New Revision: 8be139fc1251b99316d65403bde9c2326b12da20

URL: https://github.com/llvm/llvm-project/commit/8be139fc1251b99316d65403bde9c2326b12da20
DIFF: https://github.com/llvm/llvm-project/commit/8be139fc1251b99316d65403bde9c2326b12da20.diff

LOG: [lldb] Add settings for expression evaluation memory allocations.

Expression evaluation allocates memory for storing intermediate data during evaluation. For it to work properly it has to be allocated within target's available address space, for example within first 0xFFFF bytes for the 16-bit MSP430. The memory for such targets can be very tightly packed, but not all targets support GetMemoryRegionInfo API to pick an unused region, like MSP430 with MSPDebug GDB server.

These settings allow the programmer to manually pick precisely where and how much memory to allocate for expression evaluation in order not to overlap with existing data in process memory.

Reviewed By: bulbazord

Differential Revision: https://reviews.llvm.org/D149262

Added: 
    lldb/test/API/commands/expression/memory-allocation/Makefile
    lldb/test/API/commands/expression/memory-allocation/TestMemoryAllocSettings.py
    lldb/test/API/commands/expression/memory-allocation/main.cpp

Modified: 
    lldb/include/lldb/Target/ABI.h
    lldb/include/lldb/Target/Target.h
    lldb/source/Expression/IRMemoryMap.cpp
    lldb/source/Expression/LLVMUserExpression.cpp
    lldb/source/Plugins/ABI/MSP430/ABISysV_msp430.h
    lldb/source/Target/Target.cpp
    lldb/source/Target/TargetProperties.td

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Target/ABI.h b/lldb/include/lldb/Target/ABI.h
index f0753172d3e71..f600e29c7c4b0 100644
--- a/lldb/include/lldb/Target/ABI.h
+++ b/lldb/include/lldb/Target/ABI.h
@@ -147,6 +147,8 @@ class ABI : public PluginInterface {
 
   virtual bool GetPointerReturnRegister(const char *&name) { return false; }
 
+  virtual uint64_t GetStackFrameSize() { return 512 * 1024; }
+
   static lldb::ABISP FindPlugin(lldb::ProcessSP process_sp, const ArchSpec &arch);
 
 protected:

diff  --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index b557dd26a3acc..d15f0705630ce 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -204,6 +204,12 @@ class TargetProperties : public Properties {
 
   uint64_t GetExprErrorLimit() const;
 
+  uint64_t GetExprAllocAddress() const;
+
+  uint64_t GetExprAllocSize() const;
+
+  uint64_t GetExprAllocAlign() const;
+
   bool GetUseHexImmediates() const;
 
   bool GetUseFastStepping() const;

diff  --git a/lldb/source/Expression/IRMemoryMap.cpp b/lldb/source/Expression/IRMemoryMap.cpp
index 951444db86a87..de631370bb048 100644
--- a/lldb/source/Expression/IRMemoryMap.cpp
+++ b/lldb/source/Expression/IRMemoryMap.cpp
@@ -92,26 +92,26 @@ lldb::addr_t IRMemoryMap::FindSpace(size_t size) {
     ret = llvm::alignTo(addr + alloc_size, 4096);
   }
 
+  uint64_t end_of_memory;
+  switch (GetAddressByteSize()) {
+  case 2:
+    end_of_memory = 0xffffull;
+    break;
+  case 4:
+    end_of_memory = 0xffffffffull;
+    break;
+  case 8:
+    end_of_memory = 0xffffffffffffffffull;
+    break;
+  default:
+    lldbassert(false && "Invalid address size.");
+    return LLDB_INVALID_ADDRESS;
+  }
+
   // Now, if it's possible to use the GetMemoryRegionInfo API to detect mapped
   // regions, walk forward through memory until a region is found that has
   // adequate space for our allocation.
   if (process_is_alive) {
-    uint64_t end_of_memory;
-    switch (process_sp->GetAddressByteSize()) {
-    case 2:
-      end_of_memory = 0xffffull;
-      break;
-    case 4:
-      end_of_memory = 0xffffffffull;
-      break;
-    case 8:
-      end_of_memory = 0xffffffffffffffffull;
-      break;
-    default:
-      lldbassert(false && "Invalid address size.");
-      return LLDB_INVALID_ADDRESS;
-    }
-
     MemoryRegionInfo region_info;
     Status err = process_sp->GetMemoryRegionInfo(ret, region_info);
     if (err.Success()) {
@@ -147,29 +147,40 @@ lldb::addr_t IRMemoryMap::FindSpace(size_t size) {
   // to the end of the allocations we've already reported, or use a 'sensible'
   // default if this is our first allocation.
   if (m_allocations.empty()) {
-    uint32_t address_byte_size = GetAddressByteSize();
-    if (address_byte_size != UINT32_MAX) {
-      switch (address_byte_size) {
-      case 2:
-        ret = 0x8000ull;
-        break;
-      case 4:
-        ret = 0xee000000ull;
-        break;
-      case 8:
-        ret = 0xdead0fff00000000ull;
-        break;
-      default:
-        lldbassert(false && "Invalid address size.");
+    uint64_t alloc_address = target_sp->GetExprAllocAddress();
+    if (alloc_address > 0) {
+      if (alloc_address >= end_of_memory) {
+        lldbassert(0 && "The allocation address for expression evaluation must "
+                        "be within process address space");
         return LLDB_INVALID_ADDRESS;
       }
+      ret = alloc_address;
+    } else {
+      uint32_t address_byte_size = GetAddressByteSize();
+      if (address_byte_size != UINT32_MAX) {
+        switch (address_byte_size) {
+        case 2:
+          ret = 0x8000ull;
+          break;
+        case 4:
+          ret = 0xee000000ull;
+          break;
+        case 8:
+          ret = 0xdead0fff00000000ull;
+          break;
+        default:
+          lldbassert(false && "Invalid address size.");
+          return LLDB_INVALID_ADDRESS;
+        }
+      }
     }
   } else {
     auto back = m_allocations.rbegin();
     lldb::addr_t addr = back->first;
     size_t alloc_size = back->second.m_size;
-    auto arch = target_sp->GetArchitecture().GetTriple().getArch();
-    auto align = arch == llvm::Triple::msp430 ? 512 : 4096;
+    uint64_t align = target_sp->GetExprAllocAlign();
+    if (align == 0)
+      align = 4096;
     ret = llvm::alignTo(addr + alloc_size, align);
   }
 

diff  --git a/lldb/source/Expression/LLVMUserExpression.cpp b/lldb/source/Expression/LLVMUserExpression.cpp
index af63a1629a647..9d01bfcb72200 100644
--- a/lldb/source/Expression/LLVMUserExpression.cpp
+++ b/lldb/source/Expression/LLVMUserExpression.cpp
@@ -23,6 +23,7 @@
 #include "lldb/Symbol/SymbolVendor.h"
 #include "lldb/Symbol/Type.h"
 #include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/ABI.h"
 #include "lldb/Target/ExecutionContext.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/StackFrame.h"
@@ -34,6 +35,7 @@
 #include "lldb/Utility/Log.h"
 #include "lldb/Utility/StreamString.h"
 
+using namespace lldb;
 using namespace lldb_private;
 
 char LLVMUserExpression::ID;
@@ -333,9 +335,14 @@ bool LLVMUserExpression::PrepareToExecuteJITExpression(
     if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS) {
       Status alloc_error;
 
-      auto arch = target->GetArchitecture().GetTriple().getArch();
-      const size_t stack_frame_size =
-          arch == llvm::Triple::msp430 ? 512 : 512 * 1024;
+      size_t stack_frame_size = target->GetExprAllocSize();
+      if (stack_frame_size == 0) {
+        ABISP abi_sp;
+        if (process && (abi_sp = process->GetABI()))
+          stack_frame_size = abi_sp->GetStackFrameSize();
+        else
+          stack_frame_size = 512 * 1024;
+      }
 
       const bool zero_memory = false;
 

diff  --git a/lldb/source/Plugins/ABI/MSP430/ABISysV_msp430.h b/lldb/source/Plugins/ABI/MSP430/ABISysV_msp430.h
index 91f48a8416112..8ef39e7aa1bb7 100644
--- a/lldb/source/Plugins/ABI/MSP430/ABISysV_msp430.h
+++ b/lldb/source/Plugins/ABI/MSP430/ABISysV_msp430.h
@@ -55,6 +55,8 @@ class ABISysV_msp430 : public lldb_private::RegInfoBasedABI {
   const lldb_private::RegisterInfo *
   GetRegisterInfoArray(uint32_t &count) override;
 
+  uint64_t GetStackFrameSize() override { return 512; }
+
   //------------------------------------------------------------------
   // Static Functions
   //------------------------------------------------------------------

diff  --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 033224c41ed2c..9d4581d4ffd4c 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -4586,6 +4586,24 @@ uint64_t TargetProperties::GetExprErrorLimit() const {
       g_target_properties[idx].default_uint_value);
 }
 
+uint64_t TargetProperties::GetExprAllocAddress() const {
+  const uint32_t idx = ePropertyExprAllocAddress;
+  return m_collection_sp->GetPropertyAtIndexAsUInt64(
+      nullptr, idx, g_target_properties[idx].default_uint_value);
+}
+
+uint64_t TargetProperties::GetExprAllocSize() const {
+  const uint32_t idx = ePropertyExprAllocSize;
+  return m_collection_sp->GetPropertyAtIndexAsUInt64(
+      nullptr, idx, g_target_properties[idx].default_uint_value);
+}
+
+uint64_t TargetProperties::GetExprAllocAlign() const {
+  const uint32_t idx = ePropertyExprAllocAlign;
+  return m_collection_sp->GetPropertyAtIndexAsUInt64(
+      nullptr, idx, g_target_properties[idx].default_uint_value);
+}
+
 bool TargetProperties::GetBreakpointsConsultPlatformAvoidList() {
   const uint32_t idx = ePropertyBreakpointUseAvoidList;
   return m_collection_sp->GetPropertyAtIndexAsBoolean(idx).value_or(

diff  --git a/lldb/source/Target/TargetProperties.td b/lldb/source/Target/TargetProperties.td
index 51bfd28914af9..e8350cb9e2799 100644
--- a/lldb/source/Target/TargetProperties.td
+++ b/lldb/source/Target/TargetProperties.td
@@ -24,6 +24,15 @@ let Definition = "target" in {
     DefaultUnsignedValue<5>,
     Desc<"The maximum amount of errors to emit while parsing an expression. "
          "A value of 0 means to always continue parsing if possible.">;
+  def ExprAllocAddress: Property<"expr-alloc-address", "UInt64">,
+    DefaultUnsignedValue<0>,
+    Desc<"Start address within the process address space of memory allocation for expression evaluation.">;
+  def ExprAllocSize: Property<"expr-alloc-size", "UInt64">,
+    DefaultUnsignedValue<0>,
+    Desc<"Amount of memory in bytes to allocate for expression evaluation.">;
+  def ExprAllocAlign: Property<"expr-alloc-align", "UInt64">,
+    DefaultUnsignedValue<0>,
+    Desc<"Alignment for each memory allocation for expression evaluation.">;
   def PreferDynamic: Property<"prefer-dynamic-value", "Enum">,
     DefaultEnumValue<"eDynamicDontRunTarget">,
     EnumValues<"OptionEnumValues(g_dynamic_value_types)">,

diff  --git a/lldb/test/API/commands/expression/memory-allocation/Makefile b/lldb/test/API/commands/expression/memory-allocation/Makefile
new file mode 100644
index 0000000000000..99998b20bcb05
--- /dev/null
+++ b/lldb/test/API/commands/expression/memory-allocation/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules

diff  --git a/lldb/test/API/commands/expression/memory-allocation/TestMemoryAllocSettings.py b/lldb/test/API/commands/expression/memory-allocation/TestMemoryAllocSettings.py
new file mode 100644
index 0000000000000..3dc8dc16495c9
--- /dev/null
+++ b/lldb/test/API/commands/expression/memory-allocation/TestMemoryAllocSettings.py
@@ -0,0 +1,35 @@
+"""
+Test changing setting for expression memory allocation.
+"""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestMemoryAllocSettings(TestBase):
+
+    def test(self):
+        """Test changing settings for expression memory allocation."""
+        self.build()
+        target = self.createTestTarget()
+
+        self.log_file = self.getBuildArtifact("log-expr.txt")
+
+        self.runCmd("settings set target.expr-alloc-address 0xdead0000")
+        self.runCmd("settings set target.expr-alloc-size 10000")
+        self.runCmd("settings set target.expr-alloc-align 0x1000")
+
+        self.runCmd("log enable lldb expr -f " + self.log_file)
+        self.runCmd("expression -- int foo; &foo")
+
+        self.assertTrue(os.path.isfile(self.log_file))
+        with open(self.log_file, 'r') as f:
+            log = f.read()
+
+        alloc0 = re.search('^.*IRMemoryMap::Malloc.+?0xdead0000.*$', log, re.MULTILINE)
+        # Malloc adds additional bytes to allocation size, hence 10007
+        alloc1 = re.search('^.*IRMemoryMap::Malloc\s*?\(10007.+?0xdead1000.*$', log, re.MULTILINE)
+        self.assertTrue(alloc0, "Couldn't find an allocation at a given address.")
+        self.assertTrue(alloc1, "Couldn't find an allocation of a given size at a given address.")
+

diff  --git a/lldb/test/API/commands/expression/memory-allocation/main.cpp b/lldb/test/API/commands/expression/memory-allocation/main.cpp
new file mode 100644
index 0000000000000..4cce7f667ff72
--- /dev/null
+++ b/lldb/test/API/commands/expression/memory-allocation/main.cpp
@@ -0,0 +1,3 @@
+int main() {
+  return 0;
+}


        


More information about the lldb-commits mailing list