kuilpd created this revision.
kuilpd added reviewers: asl, bulbazord, DavidSpickett.
kuilpd added projects: LLDB, All.
Herald added subscribers: Michael137, JDevlieghere, arichardson.
kuilpd requested review of this revision.
Herald added a subscriber: lldb-commits.

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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D149262

Files:
  lldb/include/lldb/Target/Target.h
  lldb/source/Expression/IRMemoryMap.cpp
  lldb/source/Expression/LLVMUserExpression.cpp
  lldb/source/Target/Target.cpp
  lldb/source/Target/TargetProperties.td

Index: lldb/source/Target/TargetProperties.td
===================================================================
--- lldb/source/Target/TargetProperties.td
+++ lldb/source/Target/TargetProperties.td
@@ -24,6 +24,15 @@
     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)">,
Index: lldb/source/Target/Target.cpp
===================================================================
--- lldb/source/Target/Target.cpp
+++ lldb/source/Target/Target.cpp
@@ -4587,6 +4587,24 @@
       nullptr, idx, 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(
Index: lldb/source/Expression/LLVMUserExpression.cpp
===================================================================
--- lldb/source/Expression/LLVMUserExpression.cpp
+++ lldb/source/Expression/LLVMUserExpression.cpp
@@ -334,8 +334,9 @@
       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)
+        stack_frame_size = arch == llvm::Triple::msp430 ? 512 : 512 * 1024;
 
       const bool zero_memory = false;
 
Index: lldb/source/Expression/IRMemoryMap.cpp
===================================================================
--- lldb/source/Expression/IRMemoryMap.cpp
+++ lldb/source/Expression/IRMemoryMap.cpp
@@ -92,26 +92,26 @@
     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,41 @@
   // 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 = arch == llvm::Triple::msp430 ? 512 : 4096;
     ret = llvm::alignTo(addr + alloc_size, align);
   }
 
Index: lldb/include/lldb/Target/Target.h
===================================================================
--- lldb/include/lldb/Target/Target.h
+++ lldb/include/lldb/Target/Target.h
@@ -204,6 +204,12 @@
 
   uint64_t GetExprErrorLimit() const;
 
+  uint64_t GetExprAllocAddress() const;
+
+  uint64_t GetExprAllocSize() const;
+
+  uint64_t GetExprAllocAlign() const;
+
   bool GetUseHexImmediates() const;
 
   bool GetUseFastStepping() const;
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to