summaryrefslogtreecommitdiffstats
path: root/lldb/source/Expression
diff options
context:
space:
mode:
authorSean Callanan <scallanan@apple.com>2013-04-05 02:22:57 +0000
committerSean Callanan <scallanan@apple.com>2013-04-05 02:22:57 +0000
commit5a1af4e63a068efed4ab3218a63d2147404cc0fc (patch)
tree2efca166de2c880075a495d354beb12d7bcec8bc /lldb/source/Expression
parent2f91004b64d360e80f244ab0a5e35f975c4e3c76 (diff)
downloadbcm5719-llvm-5a1af4e63a068efed4ab3218a63d2147404cc0fc.tar.gz
bcm5719-llvm-5a1af4e63a068efed4ab3218a63d2147404cc0fc.zip
Factored out memory access into the target process
from IRExecutionUnit into a superclass called IRMemoryMap. IRMemoryMap handles all reading and writing, ensuring that areas are kept track of and memory is properly cached (and deleted). Also fixed several cases where we would simply leak binary data in the target process over time. Now the expression objects explicitly own their IRExecutionUnit and delete it when they go away. This is why I had to modify ClangUserExpression, ClangUtilityFunction, and ClangFunction. As a side effect of this, I am removing the JIT mutex for an IRMemoryMap. If it turns out that we need this mutex, I'll add it in then, but right now it's just adding complexity. This is part of a more general project to make expressions fully reusable. The next step is to make materialization and dematerialization use the IRMemoryMap API rather than writing and reading directly from the process's memory. This will allow the IR interpreter to use the same data, but in the host's memory, without having to use a different set of pointers. llvm-svn: 178832
Diffstat (limited to 'lldb/source/Expression')
-rw-r--r--lldb/source/Expression/ClangExpressionParser.cpp5
-rw-r--r--lldb/source/Expression/ClangFunction.cpp1
-rw-r--r--lldb/source/Expression/ClangUserExpression.cpp1
-rw-r--r--lldb/source/Expression/ClangUtilityFunction.cpp3
-rw-r--r--lldb/source/Expression/IRExecutionUnit.cpp536
-rw-r--r--lldb/source/Expression/IRMemoryMap.cpp410
6 files changed, 642 insertions, 314 deletions
diff --git a/lldb/source/Expression/ClangExpressionParser.cpp b/lldb/source/Expression/ClangExpressionParser.cpp
index 32daaa92861..61e24101491 100644
--- a/lldb/source/Expression/ClangExpressionParser.cpp
+++ b/lldb/source/Expression/ClangExpressionParser.cpp
@@ -461,7 +461,8 @@ static bool FindFunctionInModule (ConstString &mangled_name,
Error
ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
- lldb::addr_t &func_end,
+ lldb::addr_t &func_end,
+ std::auto_ptr<IRExecutionUnit> &execution_unit_ap,
ExecutionContext &exe_ctx,
bool &evaluated_statically,
lldb::ClangExpressionVariableSP &const_result,
@@ -593,6 +594,8 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
}
m_execution_unit->GetRunnableInfo(err, func_addr, func_end);
+
+ execution_unit_ap = m_execution_unit;
return err;
}
diff --git a/lldb/source/Expression/ClangFunction.cpp b/lldb/source/Expression/ClangFunction.cpp
index f8db5c9c798..74fb0c0e806 100644
--- a/lldb/source/Expression/ClangFunction.cpp
+++ b/lldb/source/Expression/ClangFunction.cpp
@@ -266,6 +266,7 @@ ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors)
Error jit_error (m_parser->PrepareForExecution (m_jit_start_addr,
m_jit_end_addr,
+ m_execution_unit_ap,
exe_ctx,
evaluated_statically,
const_result,
diff --git a/lldb/source/Expression/ClangUserExpression.cpp b/lldb/source/Expression/ClangUserExpression.cpp
index cff35c35e7a..b0acfa04f23 100644
--- a/lldb/source/Expression/ClangUserExpression.cpp
+++ b/lldb/source/Expression/ClangUserExpression.cpp
@@ -463,6 +463,7 @@ ClangUserExpression::Parse (Stream &error_stream,
Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
m_jit_end_addr,
+ m_execution_unit_ap,
exe_ctx,
m_evaluated_statically,
m_const_result,
diff --git a/lldb/source/Expression/ClangUtilityFunction.cpp b/lldb/source/Expression/ClangUtilityFunction.cpp
index af33340bd16..61b0702dfd3 100644
--- a/lldb/source/Expression/ClangUtilityFunction.cpp
+++ b/lldb/source/Expression/ClangUtilityFunction.cpp
@@ -130,7 +130,8 @@ ClangUtilityFunction::Install (Stream &error_stream,
bool evaluated_statically = false; // should stay that way
Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
- m_jit_end_addr,
+ m_jit_end_addr,
+ m_execution_unit_ap,
exe_ctx,
evaluated_statically,
const_result,
diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp
index 25fb157040c..dba361bd525 100644
--- a/lldb/source/Expression/IRExecutionUnit.cpp
+++ b/lldb/source/Expression/IRExecutionUnit.cpp
@@ -1,4 +1,4 @@
-//===-- IRExecutionUnit.cpp ------------------------------*- C++ -*-===//
+//===-- IRExecutionUnit.cpp -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -29,7 +29,7 @@ IRExecutionUnit::IRExecutionUnit (std::auto_ptr<llvm::Module> &module_ap,
ConstString &name,
lldb::ProcessSP process_sp,
std::vector<std::string> &cpu_features) :
- m_process_wp(process_sp),
+ IRMemoryMap(process_sp),
m_module_ap(module_ap),
m_module(m_module_ap.get()),
m_cpu_features(cpu_features),
@@ -45,89 +45,55 @@ IRExecutionUnit::WriteNow (const uint8_t *bytes,
size_t size,
Error &error)
{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- auto iter = m_allocations.insert(m_allocations.end(), Allocation());
-
- Allocation &allocation(*iter);
-
- allocation.m_size = size;
- allocation.m_alignment = 8;
- allocation.m_data.reset(new DataBufferHeap(bytes, size));
- allocation.m_local_start = (uintptr_t)allocation.m_data->GetBytes();
- allocation.m_section_id = Allocation::eSectionIDNone;
-
- lldb_private::Error err;
-
- size_t allocation_size = (allocation.m_size ? allocation.m_size : 1) + allocation.m_alignment - 1;
-
- if (allocation_size == 0)
- allocation_size = 1;
-
- lldb::ProcessSP process_sp = m_process_wp.lock();
-
- if (!process_sp)
- {
- err.SetErrorToGenericError();
- err.SetErrorString("Couldn't find the process");
- return LLDB_INVALID_ADDRESS;
- }
-
- allocation.m_remote_allocation = process_sp->AllocateMemory(allocation_size,
- (lldb::ePermissionsReadable | lldb::ePermissionsWritable),
- err);
+ lldb::addr_t allocation_process_addr = Malloc (size,
+ 8,
+ lldb::ePermissionsWritable | lldb::ePermissionsReadable,
+ eAllocationPolicyMirror,
+ error);
- if (!err.Success())
+ if (!error.Success())
return LLDB_INVALID_ADDRESS;
- process_sp->WriteMemory(allocation.m_remote_allocation, bytes, size, err);
+ WriteMemory(allocation_process_addr, bytes, size, error);
- if (!err.Success())
+ if (!error.Success())
{
- process_sp->DeallocateMemory(allocation.m_remote_allocation);
- allocation.m_remote_allocation = LLDB_INVALID_ADDRESS;
+ Error err;
+ Free (allocation_process_addr, err);
+
return LLDB_INVALID_ADDRESS;
}
- uint64_t mask = allocation.m_alignment - 1;
-
- allocation.m_remote_start = (allocation.m_remote_allocation + mask) & (~mask);
-
- allocation.m_allocated = true;
-
- if (log)
+ if (Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
{
- log->Printf("IRExecutionUnit::WriteNow() wrote to 0x%llx", allocation.m_remote_start);
- allocation.dump(log);
- }
+ DataBufferHeap my_buffer(size, 0);
+ Error err;
+ ReadMemory(my_buffer.GetBytes(), allocation_process_addr, size, err);
- return allocation.m_remote_start;
+ if (err.Success())
+ {
+ DataExtractor my_extractor(my_buffer.GetBytes(), my_buffer.GetByteSize(), lldb::eByteOrderBig, 8);
+
+ StreamString ss;
+
+ my_extractor.Dump(&ss, 0, lldb::eFormatBytesWithASCII, 1, my_buffer.GetByteSize(), 32, allocation_process_addr, 0, 0);
+
+ log->PutCString(ss.GetData());
+ }
+ }
+
+ return allocation_process_addr;
}
void
IRExecutionUnit::FreeNow (lldb::addr_t allocation)
{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
if (allocation == LLDB_INVALID_ADDRESS)
return;
- lldb::ProcessSP process_sp = m_process_wp.lock();
-
- if (!process_sp)
- return;
+ Error err;
- for (auto ai = m_allocations.begin(), ae = m_allocations.end();
- ai != ae;
- ++ai)
- {
- if (ai->m_remote_allocation == allocation)
- {
- m_allocations.erase(ai);
- log->Printf("IRExecutionUnit::FreeNow() freed 0x%llx", allocation);
- return;
- }
- }
+ Free(allocation, err);
}
Error
@@ -271,7 +237,7 @@ IRExecutionUnit::GetRunnableInfo(Error &error,
lldb::addr_t &func_addr,
lldb::addr_t &func_end)
{
- lldb::ProcessSP process_sp(m_process_wp.lock());
+ lldb::ProcessSP process_sp(GetProcessWP().lock());
func_addr = LLDB_INVALID_ADDRESS;
func_end = LLDB_INVALID_ADDRESS;
@@ -289,159 +255,147 @@ IRExecutionUnit::GetRunnableInfo(Error &error,
func_end = m_function_end_load_addr;
return;
- }; // someone else may have gotten the mutex first
+ };
+
+ m_did_jit = true;
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ std::string error_string;
+ if (log)
{
- Mutex::Locker jit_mutex_locker(m_jit_mutex);
-
- if (m_did_jit)
- {
- func_addr = m_function_load_addr;
- func_end = m_function_end_load_addr;
-
- return;
- }; // someone else may have gotten the mutex first
+ std::string s;
+ llvm::raw_string_ostream oss(s);
- m_did_jit = true;
+ m_module->print(oss, NULL);
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ oss.flush();
- std::string error_string;
-
- if (log)
- {
- std::string s;
- llvm::raw_string_ostream oss(s);
-
- m_module->print(oss, NULL);
-
- oss.flush();
+ log->Printf ("Module being sent to JIT: \n%s", s.c_str());
+ }
+
+ llvm::Triple triple(m_module->getTargetTriple());
+ llvm::Function *function = m_module->getFunction (m_name.AsCString());
+ llvm::Reloc::Model relocModel;
+ llvm::CodeModel::Model codeModel;
+
+ if (triple.isOSBinFormatELF())
+ {
+ relocModel = llvm::Reloc::Static;
+ // This will be small for 32-bit and large for 64-bit.
+ codeModel = llvm::CodeModel::JITDefault;
+ }
+ else
+ {
+ relocModel = llvm::Reloc::PIC_;
+ codeModel = llvm::CodeModel::Small;
+ }
+
+ m_module_ap->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError, &error);
+
+ llvm::EngineBuilder builder(m_module_ap.get());
+
+ builder.setEngineKind(llvm::EngineKind::JIT)
+ .setErrorStr(&error_string)
+ .setRelocationModel(relocModel)
+ .setJITMemoryManager(new MemoryManager(*this))
+ .setOptLevel(llvm::CodeGenOpt::Less)
+ .setAllocateGVsWithCode(true)
+ .setCodeModel(codeModel)
+ .setUseMCJIT(true);
+
+ llvm::StringRef mArch;
+ llvm::StringRef mCPU;
+ llvm::SmallVector<std::string, 0> mAttrs;
+
+ for (std::string &feature : m_cpu_features)
+ mAttrs.push_back(feature);
+
+ llvm::TargetMachine *target_machine = builder.selectTarget(triple,
+ mArch,
+ mCPU,
+ mAttrs);
+
+ m_execution_engine_ap.reset(builder.create(target_machine));
+
+ if (!m_execution_engine_ap.get())
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str());
+ return;
+ }
+ else
+ {
+ m_module_ap.release(); // ownership was transferred
+ }
+
+ m_execution_engine_ap->DisableLazyCompilation();
+
+ // We don't actually need the function pointer here, this just forces it to get resolved.
+
+ void *fun_ptr = m_execution_engine_ap->getPointerToFunction(function);
+
+ if (!error.Success())
+ {
+ // We got an error through our callback!
+ return;
+ }
+
+ if (!function)
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat("Couldn't find '%s' in the JITted module", m_name.AsCString());
+ return;
+ }
+
+ if (!fun_ptr)
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", m_name.AsCString());
+ return;
+ }
+
+ m_jitted_functions.push_back (JittedFunction(m_name.AsCString(), (lldb::addr_t)fun_ptr));
+
+ CommitAllocations(process_sp);
+ ReportAllocations(*m_execution_engine_ap);
+ WriteData(process_sp);
- log->Printf ("Module being sent to JIT: \n%s", s.c_str());
- }
-
- llvm::Triple triple(m_module->getTargetTriple());
- llvm::Function *function = m_module->getFunction (m_name.AsCString());
- llvm::Reloc::Model relocModel;
- llvm::CodeModel::Model codeModel;
+ for (JittedFunction &jitted_function : m_jitted_functions)
+ {
+ jitted_function.m_remote_addr = GetRemoteAddressForLocal (jitted_function.m_local_addr);
- if (triple.isOSBinFormatELF())
+ if (!jitted_function.m_name.compare(m_name.AsCString()))
{
- relocModel = llvm::Reloc::Static;
- // This will be small for 32-bit and large for 64-bit.
- codeModel = llvm::CodeModel::JITDefault;
+ AddrRange func_range = GetRemoteRangeForLocal(jitted_function.m_local_addr);
+ m_function_end_load_addr = func_range.first + func_range.second;
+ m_function_load_addr = jitted_function.m_remote_addr;
}
- else
- {
- relocModel = llvm::Reloc::PIC_;
- codeModel = llvm::CodeModel::Small;
- }
-
- m_module_ap->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError, &error);
-
- llvm::EngineBuilder builder(m_module_ap.get());
-
- builder.setEngineKind(llvm::EngineKind::JIT)
- .setErrorStr(&error_string)
- .setRelocationModel(relocModel)
- .setJITMemoryManager(new MemoryManager(*this))
- .setOptLevel(llvm::CodeGenOpt::Less)
- .setAllocateGVsWithCode(true)
- .setCodeModel(codeModel)
- .setUseMCJIT(true);
-
- llvm::StringRef mArch;
- llvm::StringRef mCPU;
- llvm::SmallVector<std::string, 0> mAttrs;
-
- for (std::string &feature : m_cpu_features)
- mAttrs.push_back(feature);
+ }
+
+ if (log)
+ {
+ log->Printf("Code can be run in the target.");
- llvm::TargetMachine *target_machine = builder.selectTarget(triple,
- mArch,
- mCPU,
- mAttrs);
+ StreamString disassembly_stream;
- m_execution_engine_ap.reset(builder.create(target_machine));
+ Error err = DisassembleFunction(disassembly_stream, process_sp);
- if (!m_execution_engine_ap.get())
+ if (!err.Success())
{
- error.SetErrorToGenericError();
- error.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str());
- return;
+ log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
}
else
{
- m_module_ap.release(); // ownership was transferred
- }
-
- m_execution_engine_ap->DisableLazyCompilation();
-
- // We don't actually need the function pointer here, this just forces it to get resolved.
-
- void *fun_ptr = m_execution_engine_ap->getPointerToFunction(function);
-
- if (!error.Success())
- {
- // We got an error through our callback!
- return;
- }
-
- if (!function)
- {
- error.SetErrorToGenericError();
- error.SetErrorStringWithFormat("Couldn't find '%s' in the JITted module", m_name.AsCString());
- return;
+ log->Printf("Function disassembly:\n%s", disassembly_stream.GetData());
}
-
- if (!fun_ptr)
- {
- error.SetErrorToGenericError();
- error.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", m_name.AsCString());
- return;
- }
-
- m_jitted_functions.push_back (JittedFunction(m_name.AsCString(), (lldb::addr_t)fun_ptr));
-
- CommitAllocations(process_sp);
- ReportAllocations(*m_execution_engine_ap);
- WriteData(process_sp);
-
- for (JittedFunction &jitted_function : m_jitted_functions)
- {
- jitted_function.m_remote_addr = GetRemoteAddressForLocal (jitted_function.m_local_addr);
-
- if (!jitted_function.m_name.compare(m_name.AsCString()))
- {
- AddrRange func_range = GetRemoteRangeForLocal(jitted_function.m_local_addr);
- m_function_end_load_addr = func_range.first + func_range.second;
- m_function_load_addr = jitted_function.m_remote_addr;
- }
- }
-
- if (log)
- {
- log->Printf("Code can be run in the target.");
-
- StreamString disassembly_stream;
-
- Error err = DisassembleFunction(disassembly_stream, process_sp);
-
- if (!err.Success())
- {
- log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
- }
- else
- {
- log->Printf("Function disassembly:\n%s", disassembly_stream.GetData());
- }
- }
-
- func_addr = m_function_load_addr;
- func_end = m_function_end_load_addr;
-
- return;
}
+
+ func_addr = m_function_load_addr;
+ func_end = m_function_end_load_addr;
+
+ return;
}
IRExecutionUnit::~IRExecutionUnit ()
@@ -482,20 +436,16 @@ IRExecutionUnit::MemoryManager::allocateStub(const llvm::GlobalValue* F,
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
uint8_t *return_value = m_default_mm_ap->allocateStub(F, StubSize, Alignment);
-
- auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
-
- Allocation &allocation(*iter);
-
- allocation.m_size = StubSize;
- allocation.m_alignment = Alignment;
- allocation.m_local_start = (uintptr_t)return_value;
+
+ m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ StubSize,
+ Alignment));
if (log)
{
log->Printf("IRExecutionUnit::allocateStub (F=%p, StubSize=%u, Alignment=%u) = %p",
F, StubSize, Alignment, return_value);
- allocation.dump(log);
}
return return_value;
@@ -516,19 +466,15 @@ IRExecutionUnit::MemoryManager::allocateSpace(intptr_t Size, unsigned Alignment)
uint8_t *return_value = m_default_mm_ap->allocateSpace(Size, Alignment);
- auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
-
- Allocation &allocation(*iter);
-
- allocation.m_size = Size;
- allocation.m_alignment = Alignment;
- allocation.m_local_start = (uintptr_t)return_value;
+ m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ Size,
+ Alignment));
if (log)
{
log->Printf("IRExecutionUnit::allocateSpace(Size=%" PRIu64 ", Alignment=%u) = %p",
(uint64_t)Size, Alignment, return_value);
- allocation.dump(log);
}
return return_value;
@@ -543,21 +489,16 @@ IRExecutionUnit::MemoryManager::allocateCodeSection(uintptr_t Size,
uint8_t *return_value = m_default_mm_ap->allocateCodeSection(Size, Alignment, SectionID);
- auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
-
- Allocation &allocation(*iter);
-
- allocation.m_size = Size;
- allocation.m_alignment = Alignment;
- allocation.m_local_start = (uintptr_t)return_value;
- allocation.m_section_id = SectionID;
- allocation.m_executable = true;
+ m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable | lldb::ePermissionsExecutable,
+ Size,
+ Alignment,
+ SectionID));
if (log)
{
log->Printf("IRExecutionUnit::allocateCodeSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p",
(uint64_t)Size, Alignment, SectionID, return_value);
- allocation.dump(log);
}
return return_value;
@@ -573,20 +514,15 @@ IRExecutionUnit::MemoryManager::allocateDataSection(uintptr_t Size,
uint8_t *return_value = m_default_mm_ap->allocateDataSection(Size, Alignment, SectionID, IsReadOnly);
- auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
-
- Allocation &allocation(*iter);
-
- allocation.m_size = Size;
- allocation.m_alignment = Alignment;
- allocation.m_local_start = (uintptr_t)return_value;
- allocation.m_section_id = SectionID;
-
+ m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ Size,
+ Alignment,
+ SectionID));
if (log)
{
log->Printf("IRExecutionUnit::allocateDataSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p",
(uint64_t)Size, Alignment, SectionID, return_value);
- allocation.dump(log);
}
return return_value;
@@ -600,19 +536,15 @@ IRExecutionUnit::MemoryManager::allocateGlobal(uintptr_t Size,
uint8_t *return_value = m_default_mm_ap->allocateGlobal(Size, Alignment);
- auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
-
- Allocation &allocation(*iter);
-
- allocation.m_size = Size;
- allocation.m_alignment = Alignment;
- allocation.m_local_start = (uintptr_t)return_value;
+ m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ Size,
+ Alignment));
if (log)
{
log->Printf("IRExecutionUnit::allocateGlobal(Size=0x%" PRIx64 ", Alignment=%u) = %p",
(uint64_t)Size, Alignment, return_value);
- allocation.dump(log);
}
return return_value;
@@ -649,11 +581,16 @@ IRExecutionUnit::MemoryManager::deallocateExceptionTable(void *ET)
lldb::addr_t
IRExecutionUnit::GetRemoteAddressForLocal (lldb::addr_t local_address)
{
- for (Allocation &allocation : m_allocations)
+ for (AllocationRecord &record : m_records)
{
- if (local_address >= allocation.m_local_start &&
- local_address < allocation.m_local_start + allocation.m_size)
- return allocation.m_remote_start + (local_address - allocation.m_local_start);
+ if (local_address >= record.m_host_address &&
+ local_address < record.m_host_address + record.m_size)
+ {
+ if (record.m_process_address == LLDB_INVALID_ADDRESS)
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ return record.m_process_address + (local_address - record.m_host_address);
}
return LLDB_INVALID_ADDRESS;
@@ -662,11 +599,16 @@ IRExecutionUnit::GetRemoteAddressForLocal (lldb::addr_t local_address)
IRExecutionUnit::AddrRange
IRExecutionUnit::GetRemoteRangeForLocal (lldb::addr_t local_address)
{
- for (Allocation &allocation : m_allocations)
+ for (AllocationRecord &record : m_records)
{
- if (local_address >= allocation.m_local_start &&
- local_address < allocation.m_local_start + allocation.m_size)
- return AddrRange(allocation.m_remote_start, allocation.m_size);
+ if (local_address >= record.m_host_address &&
+ local_address < record.m_host_address + record.m_size)
+ {
+ if (record.m_process_address == LLDB_INVALID_ADDRESS)
+ return AddrRange(0, 0);
+
+ return AddrRange(record.m_process_address, record.m_size);
+ }
}
return AddrRange (0, 0);
@@ -675,53 +617,38 @@ IRExecutionUnit::GetRemoteRangeForLocal (lldb::addr_t local_address)
bool
IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp)
{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
bool ret = true;
- for (Allocation &allocation : m_allocations)
+ lldb_private::Error err;
+
+ for (AllocationRecord &record : m_records)
{
- if (allocation.m_allocated)
+ if (record.m_process_address != LLDB_INVALID_ADDRESS)
continue;
- lldb_private::Error err;
-
- size_t allocation_size = (allocation.m_size ? allocation.m_size : 1) + allocation.m_alignment - 1;
-
- if (allocation_size == 0)
- allocation_size = 1;
-
- allocation.m_remote_allocation = process_sp->AllocateMemory(
- allocation_size,
- allocation.m_executable ? (lldb::ePermissionsReadable | lldb::ePermissionsExecutable)
- : (lldb::ePermissionsReadable | lldb::ePermissionsWritable),
- err);
-
- uint64_t mask = allocation.m_alignment - 1;
- allocation.m_remote_start = (allocation.m_remote_allocation + mask) & (~mask);
+ record.m_process_address = Malloc(record.m_size,
+ record.m_alignment,
+ record.m_permissions,
+ eAllocationPolicyProcessOnly,
+ err);
if (!err.Success())
{
ret = false;
break;
}
-
- allocation.m_allocated = true;
-
- if (log)
- {
- log->Printf("IRExecutionUnit::CommitAllocations() committed an allocation");
- allocation.dump(log);
- }
}
if (!ret)
{
- for (Allocation &allocation : m_allocations)
+ for (AllocationRecord &record : m_records)
{
- if (allocation.m_allocated)
- process_sp->DeallocateMemory(allocation.m_remote_start);
+ if (record.m_process_address != LLDB_INVALID_ADDRESS)
+ {
+ Free(record.m_process_address, err);
+ record.m_process_address = LLDB_INVALID_ADDRESS;
+ }
}
}
@@ -731,16 +658,17 @@ IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp)
void
IRExecutionUnit::ReportAllocations (llvm::ExecutionEngine &engine)
{
- for (Allocation &allocation : m_allocations)
+ for (AllocationRecord &record : m_records)
{
- if (!allocation.m_allocated)
+ if (record.m_process_address == LLDB_INVALID_ADDRESS)
continue;
- if (allocation.m_section_id == Allocation::eSectionIDNone)
+ if (record.m_section_id == eSectionIDInvalid)
continue;
- engine.mapSectionAddress((void*)allocation.m_local_start, allocation.m_remote_start);
+ engine.mapSectionAddress((void*)record.m_host_address, record.m_process_address);
}
+
// Trigger re-application of relocations.
engine.finalizeObject();
}
@@ -748,45 +676,29 @@ IRExecutionUnit::ReportAllocations (llvm::ExecutionEngine &engine)
bool
IRExecutionUnit::WriteData (lldb::ProcessSP &process_sp)
{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- for (Allocation &allocation : m_allocations)
+ for (AllocationRecord &record : m_records)
{
- if (!allocation.m_allocated)
+ if (record.m_process_address == LLDB_INVALID_ADDRESS)
return false;
- if (allocation.m_local_start == LLDB_INVALID_ADDRESS)
- continue;
-
lldb_private::Error err;
-
- if (process_sp->WriteMemory(allocation.m_remote_start,
- (void*)allocation.m_local_start,
- allocation.m_size,
- err) != allocation.m_size ||
- !err.Success())
- return false;
-
- if (log)
- {
- log->Printf("IRExecutionUnit::CommitAllocations() wrote an allocation");
- allocation.dump(log);
- }
+
+ WriteMemory (record.m_process_address, (uint8_t*)record.m_host_address, record.m_size, err);
}
return true;
}
void
-IRExecutionUnit::Allocation::dump (Log *log)
+IRExecutionUnit::AllocationRecord::dump (Log *log)
{
if (!log)
return;
log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d)",
- (unsigned long long)m_local_start,
+ (unsigned long long)m_host_address,
(unsigned long long)m_size,
- (unsigned long long)m_remote_start,
+ (unsigned long long)m_process_address,
(unsigned)m_alignment,
(unsigned)m_section_id);
}
diff --git a/lldb/source/Expression/IRMemoryMap.cpp b/lldb/source/Expression/IRMemoryMap.cpp
new file mode 100644
index 00000000000..aea57b25ae1
--- /dev/null
+++ b/lldb/source/Expression/IRMemoryMap.cpp
@@ -0,0 +1,410 @@
+//===-- IRMemoryMap.cpp -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Expression/IRMemoryMap.h"
+#include "lldb/Target/Process.h"
+
+using namespace lldb_private;
+
+IRMemoryMap::IRMemoryMap (lldb::ProcessSP process_sp) :
+ m_process_wp(process_sp)
+{
+}
+
+IRMemoryMap::~IRMemoryMap ()
+{
+ lldb::ProcessSP process_sp = m_process_wp.lock();
+
+ if (process_sp)
+ {
+ for (AllocationMap::value_type &allocation : m_allocations)
+ {
+ if (allocation.second.m_policy == eAllocationPolicyMirror ||
+ allocation.second.m_policy == eAllocationPolicyHostOnly)
+ process_sp->DeallocateMemory(allocation.second.m_process_alloc);
+
+ if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
+ {
+ log->Printf("IRMemoryMap::~IRMemoryMap deallocated [0x%llx..0x%llx)",
+ (uint64_t)allocation.second.m_process_start,
+ (uint64_t)allocation.second.m_process_start + (uint64_t)allocation.second.m_size);
+ }
+ }
+ }
+}
+
+lldb::addr_t
+IRMemoryMap::FindSpace (size_t size)
+{
+ // Yup, this is just plain O(n) insertion. We'll use a range tree if we
+ // start caring.
+
+ lldb::addr_t remote_address = 0x1000; // skip first page of memory
+
+ for (AllocationMap::value_type &allocation : m_allocations)
+ {
+ if (remote_address < allocation.second.m_process_start &&
+ remote_address + size <= allocation.second.m_process_start)
+ return remote_address;
+
+ remote_address = allocation.second.m_process_start = allocation.second.m_size;
+ }
+
+ if (remote_address + size < remote_address)
+ return LLDB_INVALID_ADDRESS; // massively unlikely
+
+ return remote_address;
+}
+
+bool
+IRMemoryMap::ContainsHostOnlyAllocations ()
+{
+ for (AllocationMap::value_type &allocation : m_allocations)
+ {
+ if (allocation.second.m_policy == eAllocationPolicyHostOnly)
+ return true;
+ }
+
+ return false;
+}
+
+IRMemoryMap::AllocationMap::iterator
+IRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size)
+{
+ AllocationMap::iterator iter = m_allocations.lower_bound (addr);
+
+ if (iter == m_allocations.end())
+ return iter;
+
+ if (iter->first > addr)
+ {
+ if (iter == m_allocations.begin())
+ return m_allocations.end();
+ iter--;
+ }
+
+ if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
+ return iter;
+
+ return m_allocations.end();
+}
+
+lldb::addr_t
+IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error)
+{
+ lldb::ProcessSP process_sp;
+ lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS;
+ lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS;
+
+ size_t allocation_size = (size ? size : 1) + alignment - 1;
+
+ switch (policy)
+ {
+ default:
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't malloc: invalid allocation policy");
+ return LLDB_INVALID_ADDRESS;
+ case eAllocationPolicyHostOnly:
+ allocation_address = FindSpace(allocation_size);
+ if (allocation_address == LLDB_INVALID_ADDRESS)
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't malloc: address space is full");
+ return LLDB_INVALID_ADDRESS;
+ }
+ break;
+ case eAllocationPolicyMirror:
+ if (ContainsHostOnlyAllocations())
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't malloc: host-only allocations are polluting the address space");
+ return LLDB_INVALID_ADDRESS;
+ }
+ process_sp = m_process_wp.lock();
+ if (process_sp)
+ {
+ allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
+ if (!error.Success())
+ return LLDB_INVALID_ADDRESS;
+ }
+ else
+ {
+ allocation_address = FindSpace(allocation_size);
+ if (allocation_address == LLDB_INVALID_ADDRESS)
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't malloc: address space is full");
+ return LLDB_INVALID_ADDRESS;
+ }
+ }
+ break;
+ case eAllocationPolicyProcessOnly:
+ if (ContainsHostOnlyAllocations())
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't malloc: host-only allocations are polluting the address space");
+ return LLDB_INVALID_ADDRESS;
+ }
+ process_sp = m_process_wp.lock();
+ if (process_sp)
+ {
+ allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
+ if (!error.Success())
+ return LLDB_INVALID_ADDRESS;
+ }
+ else
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't malloc: process doesn't exist, and this memory must be in the process");
+ return LLDB_INVALID_ADDRESS;
+ }
+ break;
+ }
+
+
+ lldb::addr_t mask = alignment - 1;
+ aligned_address = (allocation_address + mask) & (~mask);
+
+ Allocation &allocation(m_allocations[aligned_address]);
+
+ allocation.m_process_alloc = allocation_address;
+ allocation.m_process_start = aligned_address;
+ allocation.m_size = size;
+ allocation.m_permissions = permissions;
+ allocation.m_alignment = alignment;
+ allocation.m_policy = policy;
+
+ switch (policy)
+ {
+ default:
+ assert (0 && "We cannot reach this!");
+ case eAllocationPolicyHostOnly:
+ allocation.m_data.reset(new DataBufferHeap(size, 0));
+ break;
+ case eAllocationPolicyProcessOnly:
+ break;
+ case eAllocationPolicyMirror:
+ allocation.m_data.reset(new DataBufferHeap(size, 0));
+ break;
+ }
+
+ if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
+ {
+ const char * policy_string;
+
+ switch (policy)
+ {
+ default:
+ policy_string = "<invalid policy>";
+ break;
+ case eAllocationPolicyHostOnly:
+ policy_string = "eAllocationPolicyHostOnly";
+ break;
+ case eAllocationPolicyProcessOnly:
+ policy_string = "eAllocationPolicyProcessOnly";
+ break;
+ case eAllocationPolicyMirror:
+ policy_string = "eAllocationPolicyMirror";
+ break;
+ }
+
+ log->Printf("IRMemoryMap::Malloc (%llu, 0x%llx, 0x%llx, %s) -> 0x%llx",
+ (uint64_t)size,
+ (uint64_t)alignment,
+ (uint64_t)permissions,
+ policy_string,
+ aligned_address);
+ }
+
+ return aligned_address;
+}
+
+void
+IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
+{
+ AllocationMap::iterator iter = m_allocations.find(process_address);
+
+ if (iter == m_allocations.end())
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't free: allocation doesn't exist");
+ return;
+ }
+
+ Allocation &allocation = iter->second;
+
+ switch (allocation.m_policy)
+ {
+ default:
+ case eAllocationPolicyHostOnly:
+ break;
+ case eAllocationPolicyMirror:
+ case eAllocationPolicyProcessOnly:
+ lldb::ProcessSP process_sp = m_process_wp.lock();
+ if (process_sp)
+ process_sp->DeallocateMemory(allocation.m_process_alloc);
+ }
+
+ if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
+ {
+ log->Printf("IRMemoryMap::Free (0x%llx) freed [0x%llx..0x%llx)",
+ (uint64_t)process_address,
+ iter->second.m_process_start,
+ iter->second.m_process_start + iter->second.m_size);
+ }
+
+ m_allocations.erase(iter);
+}
+
+void
+IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error)
+{
+ AllocationMap::iterator iter = FindAllocation(process_address, size);
+
+ if (iter == m_allocations.end())
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't write: no allocation contains the target range");
+ return;
+ }
+
+ Allocation &allocation = iter->second;
+
+ uint64_t offset = process_address - allocation.m_process_start;
+
+ lldb::ProcessSP process_sp;
+
+ switch (allocation.m_policy)
+ {
+ default:
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't write: invalid allocation policy");
+ return;
+ case eAllocationPolicyHostOnly:
+ if (!allocation.m_data)
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't write: data buffer is empty");
+ return;
+ }
+ ::memcpy (allocation.m_data->GetBytes() + offset, bytes, size);
+ break;
+ case eAllocationPolicyMirror:
+ if (!allocation.m_data)
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't write: data buffer is empty");
+ return;
+ }
+ ::memcpy (allocation.m_data->GetBytes() + offset, bytes, size);
+ process_sp = m_process_wp.lock();
+ if (process_sp)
+ {
+ process_sp->WriteMemory(process_address, bytes, size, error);
+ if (!error.Success())
+ return;
+ }
+ break;
+ case eAllocationPolicyProcessOnly:
+ process_sp = m_process_wp.lock();
+ if (process_sp)
+ {
+ process_sp->WriteMemory(process_address, bytes, size, error);
+ if (!error.Success())
+ return;
+ }
+ break;
+ }
+
+ if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
+ {
+ log->Printf("IRMemoryMap::WriteMemory (0x%llx, 0x%llx, 0x%lld) went to [0x%llx..0x%llx)",
+ (uint64_t)process_address,
+ (uint64_t)bytes,
+ (uint64_t)size,
+ (uint64_t)allocation.m_process_start,
+ (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
+ }
+}
+
+void
+IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error)
+{
+ AllocationMap::iterator iter = FindAllocation(process_address, size);
+
+ if (iter == m_allocations.end())
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't read: no allocation contains the target range");
+ return;
+ }
+
+ Allocation &allocation = iter->second;
+
+ uint64_t offset = process_address - allocation.m_process_start;
+
+ lldb::ProcessSP process_sp;
+
+ switch (allocation.m_policy)
+ {
+ default:
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't read: invalid allocation policy");
+ return;
+ case eAllocationPolicyHostOnly:
+ if (!allocation.m_data)
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't read: data buffer is empty");
+ return;
+ }
+ ::memcpy (bytes, allocation.m_data->GetBytes() + offset, size);
+ break;
+ case eAllocationPolicyMirror:
+ process_sp = m_process_wp.lock();
+ if (process_sp)
+ {
+ process_sp->ReadMemory(process_address, bytes, size, error);
+ if (!error.Success())
+ return;
+ }
+ else
+ {
+ if (!allocation.m_data)
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't read: data buffer is empty");
+ return;
+ }
+ ::memcpy (bytes, allocation.m_data->GetBytes() + offset, size);
+ }
+ break;
+ case eAllocationPolicyProcessOnly:
+ process_sp = m_process_wp.lock();
+ if (process_sp)
+ {
+ process_sp->ReadMemory(process_address, bytes, size, error);
+ if (!error.Success())
+ return;
+ }
+ break;
+ }
+
+ if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
+ {
+ log->Printf("IRMemoryMap::ReadMemory (0x%llx, 0x%llx, 0x%lld) came from [0x%llx..0x%llx)",
+ (uint64_t)process_address,
+ (uint64_t)bytes,
+ (uint64_t)size,
+ (uint64_t)allocation.m_process_start,
+ (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
+ }
+}
OpenPOWER on IntegriCloud