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":0x00000000000006e4, + "rbx":0x00000001040b6060, + "rcx":0x00000001040b2e00, + "rdx":0x00000001040b2ba8, + "rdi":0x000000000000002a, + "rsi":0x00000001040b2b98, + "rbp":0x00000001040b2a20, + "rsp":0x00000001040b2a20, + "r8":0x00000000003e131e, + "r9":0xffffffff00000000, + "r10":0x0000000000000000, + "r11":0x0000000000000246, + "r12":0x000000010007c3a0, + "r13":0x00000001040b2b18, + "r14":0x0000000100003f90, + "r15":0x00000001040b2b88, + "rip":0x0000000100003f61, + "rflags":0x0000000000000206, + "cs":0x000000000000002b, + "fs":0x0000000000000000, + "gs":0x0000000000000000, + } + def __init__(self, target): super().__init__(target) @@ -73,8 +123,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("{}Q".format(len(self.registers)), *self.registers.values()) def __lldb_init_module(debugger, dict): diff --git a/lldb/examples/python/scripted_process/scripted_process.py b/lldb/examples/python/scripted_process/scripted_process.py --- a/lldb/examples/python/scripted_process/scripted_process.py +++ b/lldb/examples/python/scripted_process/scripted_process.py @@ -16,6 +16,10 @@ THE METHODS EXPOSED MIGHT CHANGE IN THE FUTURE. """ + memory_regions = None + stack_memory_dump = None + loaded_images = None + @abstractmethod def __init__(self, target, args): """ Construct a scripted process. @@ -91,7 +95,6 @@ """ pass - @abstractmethod def get_loaded_images(self): """ Get the list of loaded images for the scripted process. @@ -110,7 +113,7 @@ an `lldb.SBFileSpec` and a load address. None if the list is empty. """ - pass + return self.loaded_images def get_process_id(self): """ Get the scripted process identifier. 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; 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; + llvm::Optional GetOpaqueTypeFromSBMemoryRegionInfo( + const lldb::SBMemoryRegionInfo &mem_region) const; + protected: Debugger &m_debugger; lldb::ScriptLanguage m_script_lang; diff --git a/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h b/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h --- a/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h +++ b/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h @@ -12,6 +12,7 @@ #include "lldb/Core/StructuredDataImpl.h" #include "lldb/Interpreter/ScriptInterpreter.h" #include "lldb/Interpreter/ScriptedInterface.h" +#include "lldb/Target/MemoryRegionInfo.h" #include "lldb/lldb-private.h" @@ -34,9 +35,10 @@ virtual Status Stop() { return Status("ScriptedProcess did not stop"); } - virtual lldb::MemoryRegionInfoSP - GetMemoryRegionContainingAddress(lldb::addr_t address) { - return nullptr; + virtual llvm::Optional + GetMemoryRegionContainingAddress(lldb::addr_t address, Status &error) { + error.SetErrorString("ScriptedProcess have no memory region."); + return {}; } virtual StructuredData::DictionarySP GetThreadWithID(lldb::tid_t tid) { 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 @@ -22,6 +22,24 @@ 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_up->SetName(name); + m_opaque_up->GetRange().SetRangeBase(begin); + m_opaque_up->GetRange().SetRangeEnd(end); + m_opaque_up->SetLLDBPermissions(permissions); + m_opaque_up->SetMapped(mapped ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); + m_opaque_up->SetIsStackMemory(stack_memory ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); +} + SBMemoryRegionInfo::SBMemoryRegionInfo(const MemoryRegionInfo *lldb_object_ptr) : m_opaque_up(new MemoryRegionInfo()) { if (lldb_object_ptr) @@ -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,14 @@ return Status(); } +llvm::Optional +ScriptInterpreter::GetOpaqueTypeFromSBMemoryRegionInfo( + const lldb::SBMemoryRegionInfo &mem_region) const { + if (!mem_region.m_opaque_up) + return llvm::None; + return *mem_region.m_opaque_up.get(); +} + 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 @@ -239,7 +239,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( @@ -258,24 +258,34 @@ Status ScriptedProcess::GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo ®ion) { - // TODO: Implement - return Status(); + CheckInterpreterAndScriptObject(); + + Status error; + if (auto region_or_err = + GetInterface().GetMemoryRegionContainingAddress(load_addr, error)) + region = *region_or_err; + + return error; } Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos ®ion_list) { CheckInterpreterAndScriptObject(); + Status error; lldb::addr_t address = 0; - lldb::MemoryRegionInfoSP mem_region_sp = nullptr; - while ((mem_region_sp = - GetInterface().GetMemoryRegionContainingAddress(address))) { - auto range = mem_region_sp->GetRange(); + while (auto region_or_err = + GetInterface().GetMemoryRegionContainingAddress(address, error)) { + if (error.Fail()) + break; + + MemoryRegionInfo &mem_region = *region_or_err; + auto range = mem_region.GetRange(); address += range.GetRangeBase() + range.GetByteSize(); - region_list.push_back(*mem_region_sp.get()); + region_list.push_back(mem_region); } - return {}; + return error; } void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); } 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.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h @@ -35,8 +35,9 @@ Status Stop() override; - lldb::MemoryRegionInfoSP - GetMemoryRegionContainingAddress(lldb::addr_t address) override; + llvm::Optional + GetMemoryRegionContainingAddress(lldb::addr_t address, + Status &error) override; StructuredData::DictionarySP GetThreadWithID(lldb::tid_t tid) override; 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 @@ -82,11 +82,18 @@ return GetStatusFromMethod("stop"); } -lldb::MemoryRegionInfoSP +llvm::Optional ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress( - lldb::addr_t address) { - // TODO: Implement - return {}; + lldb::addr_t address, Status &error) { + auto mem_region = Dispatch>( + "get_memory_region_containing_address", error, address); + + if (error.Fail()) { + return ErrorWithMessage(__PRETTY_FUNCTION__, + error.AsCString(), error); + } + + return mem_region; } 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 @@ -140,6 +140,11 @@ ScriptedPythonInterface::ExtractValueFromPythonObject( python::PythonObject &p, Status &error); +template <> +llvm::Optional +ScriptedPythonInterface::ExtractValueFromPythonObject< + llvm::Optional>(python::PythonObject &p, Status &error); + } // namespace lldb_private #endif // LLDB_ENABLE_PYTHON diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp @@ -63,11 +63,30 @@ LLDBSWIGPython_CastPyObjectToSBData(p.get())); if (!sb_data) { - error.SetErrorString("Couldn't cast lldb::SBError to lldb::Status."); + error.SetErrorString( + "Couldn't cast lldb::SBData to lldb::DataExtractorSP."); return nullptr; } return m_interpreter.GetDataExtractorFromSBData(*sb_data); } +template <> +llvm::Optional +ScriptedPythonInterface::ExtractValueFromPythonObject< + llvm::Optional>(python::PythonObject &p, Status &error) { + + lldb::SBMemoryRegionInfo *sb_mem_reg_info = + reinterpret_cast( + LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(p.get())); + + if (!sb_mem_reg_info) { + error.SetErrorString( + "Couldn't cast lldb::SBMemoryRegionInfo to lldb::MemoryRegionInfoSP."); + return {}; + } + + return m_interpreter.GetOpaqueTypeFromSBMemoryRegionInfo(*sb_mem_reg_info); +} + #endif diff --git a/lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py b/lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py --- a/lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py +++ b/lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py @@ -43,41 +43,35 @@ self.expect('script dir(ScriptedProcess)', substrs=["launch"]) - def test_launch_scripted_process_sbapi(self): + def test_scripted_process_and_scripted_thread(self): """Test that we can launch an lldb scripted process using the SBAPI, - check its process ID and read string from memory.""" + check its process ID, read string from memory, check scripted thread + id, name stop reason and register context. + """ self.build() target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) self.assertTrue(target, VALID_TARGET) - scripted_process_example_relpath = ['..','..','..','..','examples','python','scripted_process','my_scripted_process.py'] + scripted_process_example_relpath = 'dummy_scripted_process.py' os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1' self.runCmd("command script import " + os.path.join(self.getSourceDir(), - *scripted_process_example_relpath)) + scripted_process_example_relpath)) launch_info = lldb.SBLaunchInfo(None) launch_info.SetProcessPluginName("ScriptedProcess") - launch_info.SetScriptedProcessClassName("my_scripted_process.MyScriptedProcess") + launch_info.SetScriptedProcessClassName("dummy_scripted_process.DummyScriptedProcess") error = lldb.SBError() process = target.Launch(launch_info, error) self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID) self.assertEqual(process.GetProcessID(), 42) - hello_world = "Hello, world!" - memory_read = process.ReadCStringFromMemory(0x50000000000, - len(hello_world) + 1, # NULL byte - error) - - self.assertTrue(error.Success(), "Failed to read memory from scripted process.") - self.assertEqual(hello_world, memory_read) - self.assertEqual(process.GetNumThreads(), 1) thread = process.GetSelectedThread() self.assertTrue(thread, "Invalid thread.") self.assertEqual(thread.GetThreadID(), 0x19) - self.assertEqual(thread.GetName(), "MyScriptedThread.thread-1") + self.assertEqual(thread.GetName(), "DummyScriptedThread.thread-1") self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal) self.assertGreater(thread.GetNumFrames(), 0) @@ -94,13 +88,21 @@ for idx, reg in enumerate(registers, start=1): self.assertEqual(idx, int(reg.value, 16)) - def test_launch_scripted_process_cli(self): + def test_launch_scripted_process_stack_frames(self): """Test that we can launch an lldb scripted process from the command line, check its process ID and read string from memory.""" self.build() target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) self.assertTrue(target, VALID_TARGET) + for module in target.modules: + if 'a.out' in module.GetFileSpec().GetFilename(): + main_module = module + + self.assertTrue(main_module, "Invalid main module.") + error = target.SetModuleLoadAddress(main_module, 0) + self.assertTrue(error.Success(), "Reloading main module at offset 0 failed.") + scripted_process_example_relpath = ['..','..','..','..','examples','python','scripted_process','my_scripted_process.py'] self.runCmd("command script import " + os.path.join(self.getSourceDir(), *scripted_process_example_relpath)) @@ -108,12 +110,21 @@ process = target.GetProcess() self.assertTrue(process, PROCESS_IS_VALID) self.assertEqual(process.GetProcessID(), 42) + self.assertEqual(process.GetNumThreads(), 1) error = lldb.SBError() hello_world = "Hello, world!" memory_read = process.ReadCStringFromMemory(0x50000000000, len(hello_world) + 1, # NULL byte error) + thread = process.GetSelectedThread() + self.assertTrue(thread, "Invalid thread.") + self.assertEqual(thread.GetThreadID(), 0x19) + self.assertEqual(thread.GetName(), "MyScriptedThread.thread-1") - self.assertTrue(error.Success(), "Failed to read memory from scripted process.") - self.assertEqual(hello_world, memory_read) + self.assertEqual(thread.GetNumFrames(), 4) + frame = thread.GetSelectedFrame() + self.assertTrue(frame, "Invalid frame.") + self.assertEqual(frame.GetFunctionName(), "bar") + self.assertEqual(int(frame.FindValue("i", lldb.eValueTypeVariableArgument).GetValue()), 42) + self.assertEqual(int(frame.FindValue("j", lldb.eValueTypeVariableLocal).GetValue()), 42 * 42) diff --git a/lldb/examples/python/scripted_process/my_scripted_process.py b/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py copy from lldb/examples/python/scripted_process/my_scripted_process.py copy to lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py --- a/lldb/examples/python/scripted_process/my_scripted_process.py +++ b/lldb/test/API/functionalities/scripted_process/dummy_scripted_process.py @@ -1,4 +1,4 @@ -import os,struct,signal +import os,struct, signal from typing import Any, Dict @@ -6,12 +6,12 @@ from lldb.plugins.scripted_process import ScriptedProcess from lldb.plugins.scripted_process import ScriptedThread -class MyScriptedProcess(ScriptedProcess): +class DummyScriptedProcess(ScriptedProcess): def __init__(self, target: lldb.SBTarget, args : lldb.SBStructuredData): super().__init__(target, args) def get_memory_region_containing_address(self, addr: int) -> lldb.SBMemoryRegionInfo: - return self.memory_regions[0] + return None def get_thread_with_id(self, tid: int): return {} @@ -39,10 +39,10 @@ return True def get_scripted_thread_plugin(self): - return MyScriptedThread.__module__ + "." + MyScriptedThread.__name__ + return DummyScriptedThread.__module__ + "." + DummyScriptedThread.__name__ -class MyScriptedThread(ScriptedThread): +class DummyScriptedThread(ScriptedThread): def __init__(self, target): super().__init__(target) @@ -50,7 +50,10 @@ return 0x19 def get_name(self) -> str: - return MyScriptedThread.__name__ + ".thread-1" + return DummyScriptedThread.__name__ + ".thread-1" + + def get_state(self) -> int: + return lldb.eStateStopped def get_stop_reason(self) -> Dict[str, Any]: return { "type": lldb.eStopReasonSignal, "data": { @@ -81,7 +84,7 @@ if not 'SKIP_SCRIPTED_PROCESS_LAUNCH' in os.environ: debugger.HandleCommand( "process launch -C %s.%s" % (__name__, - MyScriptedProcess.__name__)) + DummyScriptedProcess.__name__)) else: print("Name of the class that will manage the scripted process: '%s.%s'" - % (__name__, MyScriptedProcess.__name__)) \ No newline at end of file + % (__name__, DummyScriptedProcess.__name__)) \ No newline at end of file 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; + return j; // break here } + +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;