diff --git a/lldb/bindings/interface/SBMemoryRegionInfo.i b/lldb/bindings/interface/SBMemoryRegionInfo.i --- a/lldb/bindings/interface/SBMemoryRegionInfo.i +++ b/lldb/bindings/interface/SBMemoryRegionInfo.i @@ -20,6 +20,9 @@ SBMemoryRegionInfo (const lldb::SBMemoryRegionInfo &rhs); + SBMemoryRegionInfo::SBMemoryRegionInfo(const char *name, lldb::addr_t begin, + lldb::addr_t end, uint32_t permissions, bool mapped, bool stack_memory); + ~SBMemoryRegionInfo (); void diff --git a/lldb/bindings/interface/SBMemoryRegionInfoList.i b/lldb/bindings/interface/SBMemoryRegionInfoList.i --- a/lldb/bindings/interface/SBMemoryRegionInfoList.i +++ b/lldb/bindings/interface/SBMemoryRegionInfoList.i @@ -24,6 +24,9 @@ uint32_t GetSize () const; + bool + GetMemoryRegionContainingAddress (lldb::addr_t addr, SBMemoryRegionInfo ®ion_info); + bool GetMemoryRegionAtIndex (uint32_t idx, SBMemoryRegionInfo ®ion_info); diff --git a/lldb/bindings/python/python-wrapper.swig b/lldb/bindings/python/python-wrapper.swig --- a/lldb/bindings/python/python-wrapper.swig +++ b/lldb/bindings/python/python-wrapper.swig @@ -974,6 +974,22 @@ return sb_ptr; } +SWIGEXPORT void* +LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo +( + PyObject* data +) +{ + lldb::SBMemoryRegionInfo* sb_ptr = NULL; + + int valid_cast = SWIG_ConvertPtr(data, (void**)&sb_ptr, SWIGTYPE_p_lldb__SBMemoryRegionInfo, 0); + + if (valid_cast == -1) + return NULL; + + return sb_ptr; +} + SWIGEXPORT bool LLDBSwigPythonCallCommand ( diff --git a/lldb/examples/python/scripted_process/main.stack-dump b/lldb/examples/python/scripted_process/main.stack-dump new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@ lldb.SBMemoryRegionInfo: - return self.memory_regions[0] + for region in self.memory_regions: + if region.GetRegionBase() <= addr < region.GetRegionEnd(): + return region + return None def get_thread_with_id(self, tid: int): return {} @@ -20,10 +31,25 @@ return {} def read_memory_at_address(self, addr: int, size: int) -> lldb.SBData: - data = lldb.SBData().CreateDataFromCString( + data = lldb.SBData() + + with open(self.stack_memory_dump, 'rb') as f: + stack_mem = f.read(-1) + if not stack_mem: + return data + + mem_region = self.get_memory_region_containing_address(addr) + + if not mem_region or addr + size > mem_region.GetRegionEnd(): + return data + + offset = addr - mem_region.GetRegionBase() + shrunk_stack_mem = stack_mem[offset:offset + size] + + error = lldb.SBError() + data.SetData(error, shrunk_stack_mem, self.target.GetByteOrder(), - self.target.GetCodeByteSize(), - "Hello, world!") + self.target.GetAddressByteSize()) return data def get_loaded_images(self): @@ -43,6 +69,30 @@ class MyScriptedThread(ScriptedThread): + registers = { + "rax":0x0000000100070010, + "rbx":0x00000001040b6060, + "rcx":0x00000001040b2dd0, + "rdx":0x00000001040b2b78, + "rdi":0x000000000000002a, + "rsi":0x00000001040b2b68, + "rbp":0x00000001040b29f0, + "rsp":0x00000001040b29f0, + "r8":0x000000000038054b, + "r9":0xffffffff00000000, + "r10":0x0000000000000000, + "r11":0x0000000000000246, + "r12":0x000000010007c3a0, + "r13":0x00000001040b2ae8, + "r14":0x0000000100003f90, + "r15":0x00000001040b2b58, + "rip":0x0000000100003f57, + "rflags":0x0000000000000206, + "cs":0x000000000000002b, + "fs":0x0000000000000000, + "gs":0x0000000000000000, + } + def __init__(self, target): super().__init__(target) @@ -76,8 +126,7 @@ return self.frame_zero[0:0] def get_register_context(self) -> str: - return struct.pack( - '21Q', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21) + return struct.pack(f"{len(self.registers)}Q", *self.registers.values()) def __lldb_init_module(debugger, dict): diff --git a/lldb/include/lldb/API/SBMemoryRegionInfo.h b/lldb/include/lldb/API/SBMemoryRegionInfo.h --- a/lldb/include/lldb/API/SBMemoryRegionInfo.h +++ b/lldb/include/lldb/API/SBMemoryRegionInfo.h @@ -20,6 +20,10 @@ SBMemoryRegionInfo(const lldb::SBMemoryRegionInfo &rhs); + SBMemoryRegionInfo(const char *name, lldb::addr_t begin, lldb::addr_t end, + uint32_t permissions, bool mapped, + bool stack_memory = false); + ~SBMemoryRegionInfo(); const lldb::SBMemoryRegionInfo & @@ -117,6 +121,8 @@ friend class SBProcess; friend class SBMemoryRegionInfoList; + friend class lldb_private::ScriptInterpreter; + lldb_private::MemoryRegionInfo &ref(); const lldb_private::MemoryRegionInfo &ref() const; @@ -124,7 +130,7 @@ // Unused. SBMemoryRegionInfo(const lldb_private::MemoryRegionInfo *lldb_object_ptr); - lldb::MemoryRegionInfoUP m_opaque_up; + lldb::MemoryRegionInfoSP m_opaque_sp; }; } // namespace lldb diff --git a/lldb/include/lldb/API/SBMemoryRegionInfoList.h b/lldb/include/lldb/API/SBMemoryRegionInfoList.h --- a/lldb/include/lldb/API/SBMemoryRegionInfoList.h +++ b/lldb/include/lldb/API/SBMemoryRegionInfoList.h @@ -27,6 +27,9 @@ uint32_t GetSize() const; + bool GetMemoryRegionContainingAddress(lldb::addr_t addr, + SBMemoryRegionInfo ®ion_info); + bool GetMemoryRegionAtIndex(uint32_t idx, SBMemoryRegionInfo ®ion_info); void Append(lldb::SBMemoryRegionInfo ®ion); diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h --- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h +++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h @@ -11,6 +11,7 @@ #include "lldb/API/SBData.h" #include "lldb/API/SBError.h" +#include "lldb/API/SBMemoryRegionInfo.h" #include "lldb/Breakpoint/BreakpointOptions.h" #include "lldb/Core/Communication.h" #include "lldb/Core/PluginInterface.h" @@ -564,6 +565,9 @@ Status GetStatusFromSBError(const lldb::SBError &error) const; + lldb::MemoryRegionInfoSP GetOpaquePtrFromSBMemoryRegionInfo( + const lldb::SBMemoryRegionInfo &mem_region) const; + protected: Debugger &m_debugger; lldb::ScriptLanguage m_script_lang; diff --git a/lldb/source/API/SBMemoryRegionInfo.cpp b/lldb/source/API/SBMemoryRegionInfo.cpp --- a/lldb/source/API/SBMemoryRegionInfo.cpp +++ b/lldb/source/API/SBMemoryRegionInfo.cpp @@ -18,21 +18,39 @@ using namespace lldb; using namespace lldb_private; -SBMemoryRegionInfo::SBMemoryRegionInfo() : m_opaque_up(new MemoryRegionInfo()) { +SBMemoryRegionInfo::SBMemoryRegionInfo() : m_opaque_sp(new MemoryRegionInfo()) { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBMemoryRegionInfo); } +SBMemoryRegionInfo::SBMemoryRegionInfo(const char *name, lldb::addr_t begin, + lldb::addr_t end, uint32_t permissions, + bool mapped, bool stack_memory) + : SBMemoryRegionInfo() { + LLDB_RECORD_CONSTRUCTOR( + SBMemoryRegionInfo, + (const char *, lldb::addr_t, lldb::addr_t, uint32_t, bool, bool), name, + begin, end, permissions, mapped, stack_memory); + m_opaque_sp->SetName(name); + m_opaque_sp->GetRange().SetRangeBase(begin); + m_opaque_sp->GetRange().SetRangeEnd(end); + m_opaque_sp->SetLLDBPermissions(permissions); + m_opaque_sp->SetMapped(mapped ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); + m_opaque_sp->SetIsStackMemory(stack_memory ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); +} + SBMemoryRegionInfo::SBMemoryRegionInfo(const MemoryRegionInfo *lldb_object_ptr) - : m_opaque_up(new MemoryRegionInfo()) { + : m_opaque_sp(new MemoryRegionInfo()) { if (lldb_object_ptr) ref() = *lldb_object_ptr; } SBMemoryRegionInfo::SBMemoryRegionInfo(const SBMemoryRegionInfo &rhs) - : m_opaque_up() { + : m_opaque_sp() { LLDB_RECORD_CONSTRUCTOR(SBMemoryRegionInfo, (const lldb::SBMemoryRegionInfo &), rhs); - m_opaque_up = clone(rhs.m_opaque_up); + m_opaque_sp = clone(rhs.m_opaque_sp); } const SBMemoryRegionInfo &SBMemoryRegionInfo:: @@ -42,7 +60,7 @@ SBMemoryRegionInfo, operator=,(const lldb::SBMemoryRegionInfo &), rhs); if (this != &rhs) - m_opaque_up = clone(rhs.m_opaque_up); + m_opaque_sp = clone(rhs.m_opaque_sp); return LLDB_RECORD_RESULT(*this); } @@ -51,7 +69,7 @@ void SBMemoryRegionInfo::Clear() { LLDB_RECORD_METHOD_NO_ARGS(void, SBMemoryRegionInfo, Clear); - m_opaque_up->Clear(); + m_opaque_sp->Clear(); } bool SBMemoryRegionInfo::operator==(const SBMemoryRegionInfo &rhs) const { @@ -70,56 +88,56 @@ return ref() != rhs.ref(); } -MemoryRegionInfo &SBMemoryRegionInfo::ref() { return *m_opaque_up; } +MemoryRegionInfo &SBMemoryRegionInfo::ref() { return *m_opaque_sp; } -const MemoryRegionInfo &SBMemoryRegionInfo::ref() const { return *m_opaque_up; } +const MemoryRegionInfo &SBMemoryRegionInfo::ref() const { return *m_opaque_sp; } lldb::addr_t SBMemoryRegionInfo::GetRegionBase() { LLDB_RECORD_METHOD_NO_ARGS(lldb::addr_t, SBMemoryRegionInfo, GetRegionBase); - return m_opaque_up->GetRange().GetRangeBase(); + return m_opaque_sp->GetRange().GetRangeBase(); } lldb::addr_t SBMemoryRegionInfo::GetRegionEnd() { LLDB_RECORD_METHOD_NO_ARGS(lldb::addr_t, SBMemoryRegionInfo, GetRegionEnd); - return m_opaque_up->GetRange().GetRangeEnd(); + return m_opaque_sp->GetRange().GetRangeEnd(); } bool SBMemoryRegionInfo::IsReadable() { LLDB_RECORD_METHOD_NO_ARGS(bool, SBMemoryRegionInfo, IsReadable); - return m_opaque_up->GetReadable() == MemoryRegionInfo::eYes; + return m_opaque_sp->GetReadable() == MemoryRegionInfo::eYes; } bool SBMemoryRegionInfo::IsWritable() { LLDB_RECORD_METHOD_NO_ARGS(bool, SBMemoryRegionInfo, IsWritable); - return m_opaque_up->GetWritable() == MemoryRegionInfo::eYes; + return m_opaque_sp->GetWritable() == MemoryRegionInfo::eYes; } bool SBMemoryRegionInfo::IsExecutable() { LLDB_RECORD_METHOD_NO_ARGS(bool, SBMemoryRegionInfo, IsExecutable); - return m_opaque_up->GetExecutable() == MemoryRegionInfo::eYes; + return m_opaque_sp->GetExecutable() == MemoryRegionInfo::eYes; } bool SBMemoryRegionInfo::IsMapped() { LLDB_RECORD_METHOD_NO_ARGS(bool, SBMemoryRegionInfo, IsMapped); - return m_opaque_up->GetMapped() == MemoryRegionInfo::eYes; + return m_opaque_sp->GetMapped() == MemoryRegionInfo::eYes; } const char *SBMemoryRegionInfo::GetName() { LLDB_RECORD_METHOD_NO_ARGS(const char *, SBMemoryRegionInfo, GetName); - return m_opaque_up->GetName().AsCString(); + return m_opaque_sp->GetName().AsCString(); } bool SBMemoryRegionInfo::HasDirtyMemoryPageList() { LLDB_RECORD_METHOD_NO_ARGS(bool, SBMemoryRegionInfo, HasDirtyMemoryPageList); - return m_opaque_up->GetDirtyPageList().hasValue(); + return m_opaque_sp->GetDirtyPageList().hasValue(); } uint32_t SBMemoryRegionInfo::GetNumDirtyPages() { @@ -127,7 +145,7 @@ uint32_t num_dirty_pages = 0; llvm::Optional> dirty_page_list = - m_opaque_up->GetDirtyPageList(); + m_opaque_sp->GetDirtyPageList(); if (dirty_page_list.hasValue()) num_dirty_pages = dirty_page_list.getValue().size(); @@ -140,7 +158,7 @@ addr_t dirty_page_addr = LLDB_INVALID_ADDRESS; const llvm::Optional> &dirty_page_list = - m_opaque_up->GetDirtyPageList(); + m_opaque_sp->GetDirtyPageList(); if (dirty_page_list.hasValue() && idx < dirty_page_list.getValue().size()) dirty_page_addr = dirty_page_list.getValue()[idx]; @@ -150,7 +168,7 @@ int SBMemoryRegionInfo::GetPageSize() { LLDB_RECORD_METHOD_NO_ARGS(int, SBMemoryRegionInfo, GetPageSize); - return m_opaque_up->GetPageSize(); + return m_opaque_sp->GetPageSize(); } bool SBMemoryRegionInfo::GetDescription(SBStream &description) { @@ -158,13 +176,13 @@ (lldb::SBStream &), description); Stream &strm = description.ref(); - const addr_t load_addr = m_opaque_up->GetRange().base; + const addr_t load_addr = m_opaque_sp->GetRange().base; strm.Printf("[0x%16.16" PRIx64 "-0x%16.16" PRIx64 " ", load_addr, - load_addr + m_opaque_up->GetRange().size); - strm.Printf(m_opaque_up->GetReadable() ? "R" : "-"); - strm.Printf(m_opaque_up->GetWritable() ? "W" : "-"); - strm.Printf(m_opaque_up->GetExecutable() ? "X" : "-"); + load_addr + m_opaque_sp->GetRange().size); + strm.Printf(m_opaque_sp->GetReadable() ? "R" : "-"); + strm.Printf(m_opaque_sp->GetWritable() ? "W" : "-"); + strm.Printf(m_opaque_sp->GetExecutable() ? "X" : "-"); strm.Printf("]"); return true; @@ -178,6 +196,9 @@ LLDB_REGISTER_CONSTRUCTOR(SBMemoryRegionInfo, ()); LLDB_REGISTER_CONSTRUCTOR(SBMemoryRegionInfo, (const lldb::SBMemoryRegionInfo &)); + LLDB_REGISTER_CONSTRUCTOR( + SBMemoryRegionInfo, + (const char *, lldb::addr_t, lldb::addr_t, uint32_t, bool, bool)); LLDB_REGISTER_METHOD( const lldb::SBMemoryRegionInfo &, SBMemoryRegionInfo, operator=,(const lldb::SBMemoryRegionInfo &)); diff --git a/lldb/source/API/SBMemoryRegionInfoList.cpp b/lldb/source/API/SBMemoryRegionInfoList.cpp --- a/lldb/source/API/SBMemoryRegionInfoList.cpp +++ b/lldb/source/API/SBMemoryRegionInfoList.cpp @@ -48,6 +48,17 @@ void Clear() { m_regions.clear(); } + bool GetMemoryRegionContainingAddress(lldb::addr_t addr, + MemoryRegionInfo ®ion_info) { + for (auto ®ion : m_regions) { + if (region.GetRange().Contains(addr)) { + region_info = region; + return true; + } + } + return false; + } + bool GetMemoryRegionInfoAtIndex(size_t index, MemoryRegionInfo ®ion_info) { if (index >= GetSize()) @@ -103,6 +114,15 @@ return m_opaque_up->GetSize(); } +bool SBMemoryRegionInfoList::GetMemoryRegionContainingAddress( + lldb::addr_t addr, SBMemoryRegionInfo ®ion_info) { + LLDB_RECORD_METHOD( + bool, SBMemoryRegionInfoList, GetMemoryRegionContainingAddress, + (lldb::addr_t, lldb::SBMemoryRegionInfo &), addr, region_info); + + return m_opaque_up->GetMemoryRegionContainingAddress(addr, region_info.ref()); +} + bool SBMemoryRegionInfoList::GetMemoryRegionAtIndex( uint32_t idx, SBMemoryRegionInfo ®ion_info) { LLDB_RECORD_METHOD(bool, SBMemoryRegionInfoList, GetMemoryRegionAtIndex, @@ -153,6 +173,9 @@ SBMemoryRegionInfoList, operator=,( const lldb::SBMemoryRegionInfoList &)); LLDB_REGISTER_METHOD_CONST(uint32_t, SBMemoryRegionInfoList, GetSize, ()); + LLDB_REGISTER_METHOD(bool, SBMemoryRegionInfoList, + GetMemoryRegionContainingAddress, + (lldb::addr_t, lldb::SBMemoryRegionInfo &)); LLDB_REGISTER_METHOD(bool, SBMemoryRegionInfoList, GetMemoryRegionAtIndex, (uint32_t, lldb::SBMemoryRegionInfo &)); LLDB_REGISTER_METHOD(void, SBMemoryRegionInfoList, Clear, ()); diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp b/lldb/source/Interpreter/ScriptInterpreter.cpp --- a/lldb/source/Interpreter/ScriptInterpreter.cpp +++ b/lldb/source/Interpreter/ScriptInterpreter.cpp @@ -83,6 +83,11 @@ return Status(); } +lldb::MemoryRegionInfoSP ScriptInterpreter::GetOpaquePtrFromSBMemoryRegionInfo( + const lldb::SBMemoryRegionInfo &mem_region) const { + return mem_region.m_opaque_sp; +} + lldb::ScriptLanguage ScriptInterpreter::StringToLanguage(const llvm::StringRef &language) { if (language.equals_insensitive(LanguageToString(eScriptLanguageNone))) diff --git a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp --- a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp +++ b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp @@ -248,7 +248,7 @@ lldb::DataExtractorSP data_extractor_sp = GetInterface().ReadMemoryAtAddress(addr, size, error); - if (!data_extractor_sp || error.Fail()) + if (!data_extractor_sp || !data_extractor_sp->GetByteSize() || error.Fail()) return 0; offset_t bytes_copied = data_extractor_sp->CopyByteOrderedData( diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h --- a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h @@ -53,6 +53,7 @@ extern "C" void *LLDBSWIGPython_CastPyObjectToSBData(void *data); extern "C" void *LLDBSWIGPython_CastPyObjectToSBError(void *data); extern "C" void *LLDBSWIGPython_CastPyObjectToSBValue(void *data); +extern "C" void *LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(void *data); } // namespace lldb_private diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp @@ -95,8 +95,24 @@ lldb::MemoryRegionInfoSP ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress( lldb::addr_t address) { - // TODO: Implement - return {}; + auto error_with_message = [](llvm::StringRef message) { + LLDB_LOGF(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS), + "ScriptedProcess::%s ERROR = %s", __FUNCTION__, message.data()); + return lldb::MemoryRegionInfoSP(); + }; + + Status error; + lldb::MemoryRegionInfoSP mem_region_sp = Dispatch( + "get_memory_region_containing_address", error, address); + + if (!mem_region_sp || error.Fail()) { + return error_with_message(llvm::Twine("Null or invalid object (" + + llvm::Twine(error.AsCString()) + + llvm::Twine(").")) + .str()); + } + + return mem_region_sp; } StructuredData::DictionarySP diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h @@ -71,6 +71,23 @@ return m_interpreter.GetDataExtractorFromSBData(*sb_data); } + template <> + lldb::MemoryRegionInfoSP + ExtractValueFromPythonObject( + python::PythonObject &p, Status &error) { + lldb::SBMemoryRegionInfo *sb_mem_region = + reinterpret_cast( + LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(p.get())); + + if (!sb_mem_region) { + error.SetErrorString("Couldn't cast lldb::SBMemoryRegionInfo to " + "lldb::MemoryRegionInfoSP."); + return nullptr; + } + + return m_interpreter.GetOpaquePtrFromSBMemoryRegionInfo(*sb_mem_region); + } + template T Dispatch(llvm::StringRef method_name, Status &error, Args... args) { using namespace python; diff --git a/lldb/test/API/functionalities/scripted_process/main.c b/lldb/test/API/functionalities/scripted_process/main.c --- a/lldb/test/API/functionalities/scripted_process/main.c +++ b/lldb/test/API/functionalities/scripted_process/main.c @@ -1,5 +1,8 @@ -#include - -int main() { - return 0; // break here +int bar(int i) { + int j = i * i; // break here + return j; } + +int foo(int i) { return bar(i); } + +int main() { return foo(42); } diff --git a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp --- a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp +++ b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp @@ -166,6 +166,10 @@ return nullptr; } +extern "C" void *LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(void *data) { + return nullptr; +} + extern lldb::ValueObjectSP LLDBSWIGPython_GetValueObjectSPFromSBValue(void *data) { return nullptr;