https://github.com/rchamala updated https://github.com/llvm/llvm-project/pull/120834
>From 126ba755d58aa74c6d0c5727ec08593cfcfb57ee Mon Sep 17 00:00:00 2001 From: Rahul Reddy Chamala <racha...@fb.com> Date: Fri, 20 Dec 2024 15:55:36 -0800 Subject: [PATCH] [lldb][ResolveSourceFileCallback] Implement API, Python interface Summary: RFC https://discourse.llvm.org/t/rfc-python-callback-for-target-get-module/71580 Use SWIG for the resolve source file callback the same as other Python callbacks. TestResolveSourceFileCallback.py verifies the functionalities. Test Plan: Added shell tests for validation ``` ./llvm-lit -sv TestResolveSourceFileCallback.py ``` Differential Revision: https://phabricator.intern.facebook.com/D67541203 --- lldb/bindings/python/python-typemaps.swig | 44 ++++ lldb/bindings/python/python-wrapper.swig | 49 ++++- lldb/include/lldb/API/SBDefines.h | 5 + lldb/include/lldb/API/SBPlatform.h | 3 + lldb/source/API/SBPlatform.cpp | 37 ++++ .../TestResolveSourceFileCallback.py | 196 ++++++++++++++++++ lldb/test/API/python_api/sbplatform/test.exe | Bin 0 -> 21704 bytes .../API/python_api/sbplatform/test_new.cpp | 15 ++ 8 files changed, 347 insertions(+), 2 deletions(-) create mode 100644 lldb/test/API/python_api/sbplatform/TestResolveSourceFileCallback.py create mode 100755 lldb/test/API/python_api/sbplatform/test.exe create mode 100644 lldb/test/API/python_api/sbplatform/test_new.cpp diff --git a/lldb/bindings/python/python-typemaps.swig b/lldb/bindings/python/python-typemaps.swig index f8c33e15c03e66..84d26986104d31 100644 --- a/lldb/bindings/python/python-typemaps.swig +++ b/lldb/bindings/python/python-typemaps.swig @@ -713,3 +713,47 @@ template <> bool SetNumberFromPyObject<double>(double &number, PyObject *obj) { $1 = $input == Py_None; $1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input)); } + +// For lldb::SBPlatformResolveSourceFileCallback +%typemap(in) (lldb::SBPlatformResolveSourceFileCallback callback, void *callback_baton) { + if (!($input == Py_None || + PyCallable_Check(reinterpret_cast<PyObject *>($input)))) { + PyErr_SetString(PyExc_TypeError, "Need a callable object or None!"); + SWIG_fail; + } + + if ($input == Py_None) { + $1 = nullptr; + $2 = nullptr; + } else { + PythonCallable callable = Retain<PythonCallable>($input); + if (!callable.IsValid()) { + PyErr_SetString(PyExc_TypeError, "Need a valid callable object"); + SWIG_fail; + } + + llvm::Expected<PythonCallable::ArgInfo> arg_info = callable.GetArgInfo(); + if (!arg_info) { + PyErr_SetString(PyExc_TypeError, + ("Could not get arguments: " + + llvm::toString(arg_info.takeError())).c_str()); + SWIG_fail; + } + + if (arg_info.get().max_positional_args != 3) { + PyErr_SetString(PyExc_TypeError, "Expected 3 argument callable object"); + SWIG_fail; + } + + Py_INCREF($input); + + $1 = LLDBSwigPythonCallResolveSourceFileCallback; + $2 = $input; + } +} + +%typemap(typecheck) (lldb::SBPlatformResolveSourceFileCallback callback, + void *callback_baton) { + $1 = $input == Py_None; + $1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input)); +} diff --git a/lldb/bindings/python/python-wrapper.swig b/lldb/bindings/python/python-wrapper.swig index b72a462d04643b..fb0b0368914fbf 100644 --- a/lldb/bindings/python/python-wrapper.swig +++ b/lldb/bindings/python/python-wrapper.swig @@ -727,7 +727,7 @@ lldb_private::python::SWIGBridge::LLDBSwigPythonHandleOptionArgumentCompletionFo dict_sp->AddBooleanItem("no-completion", true); return dict_sp; } - + // Convert the return dictionary to a DictionarySP. StructuredData::ObjectSP result_obj_sp = result.CreateStructuredObject(); @@ -753,7 +753,7 @@ bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallParsedCommandObject( auto pfunc = self.ResolveName<PythonCallable>("__call__"); if (!pfunc.IsAllocated()) { - cmd_retobj.AppendError("Could not find '__call__' method in implementation class"); + cmd_retobj.AppendError("Could not find '__call__' method in implementation class"); return false; } @@ -1095,4 +1095,49 @@ static SBError LLDBSwigPythonCallLocateModuleCallback( return *sb_error_ptr; } + +static SBError LLDBSwigPythonCallResolveSourceFileCallback( + void *callback_baton, + const lldb::ModuleSP &module_sp, + const SBFileSpec &original_source_file_spec_sb, + SBFileSpec &resolved_source_file_spec_sb) { + SWIG_Python_Thread_Block swig_thread_block; + + PyErr_Cleaner py_err_cleaner(true); + + PythonObject module_sb_arg = SWIGBridge::ToSWIGWrapper(module_sp); + PythonObject original_source_file_spec_arg = SWIGBridge::ToSWIGWrapper( + std::make_unique<SBFileSpec>(original_source_file_spec_sb)); + PythonObject resolved_source_file_spec_arg = SWIGBridge::ToSWIGWrapper( + std::make_unique<SBFileSpec>(resolved_source_file_spec_sb)); + + PythonCallable callable = + Retain<PythonCallable>(reinterpret_cast<PyObject *>(callback_baton)); + if (!callable.IsValid()) { + return SBError("The callback callable is not valid."); + } + + PythonObject result = callable(module_sb_arg, original_source_file_spec_arg, + resolved_source_file_spec_arg); + + if (!result.IsAllocated()) + return SBError("No result."); + lldb::SBError *sb_error_ptr = nullptr; + if (SWIG_ConvertPtr(result.get(), (void **)&sb_error_ptr, + SWIGTYPE_p_lldb__SBError, 0) == -1) { + return SBError("Result is not SBError."); + } + + if (sb_error_ptr->Success()) { + lldb::SBFileSpec *sb_resolved_source_file_spec_ptr = nullptr; + if (SWIG_ConvertPtr(resolved_source_file_spec_arg.get(), + (void **)&sb_resolved_source_file_spec_ptr, + SWIGTYPE_p_lldb__SBFileSpec, 0) == -1) + return SBError("resolved_source_file_spec is not SBFileSpec."); + + resolved_source_file_spec_sb = *sb_resolved_source_file_spec_ptr; + } + + return *sb_error_ptr; +} %} diff --git a/lldb/include/lldb/API/SBDefines.h b/lldb/include/lldb/API/SBDefines.h index 159a9ba799b181..fa676ed799bbeb 100644 --- a/lldb/include/lldb/API/SBDefines.h +++ b/lldb/include/lldb/API/SBDefines.h @@ -146,6 +146,11 @@ typedef void (*SBDebuggerDestroyCallback)(lldb::user_id_t debugger_id, typedef lldb::SBError (*SBPlatformLocateModuleCallback)( void *baton, const lldb::SBModuleSpec &module_spec, lldb::SBFileSpec &module_file_spec, lldb::SBFileSpec &symbol_file_spec); + +typedef lldb::SBError (*SBPlatformResolveSourceFileCallback)( + void *baton, const lldb::ModuleSP &module_sp, + const lldb::SBFileSpec &original_source_file_spec, + lldb::SBFileSpec &resolved_source_file_spec); } #endif // LLDB_API_SBDEFINES_H diff --git a/lldb/include/lldb/API/SBPlatform.h b/lldb/include/lldb/API/SBPlatform.h index d63d2ed1eaba62..37ab2ef0441cf5 100644 --- a/lldb/include/lldb/API/SBPlatform.h +++ b/lldb/include/lldb/API/SBPlatform.h @@ -190,6 +190,9 @@ class LLDB_API SBPlatform { SBError SetLocateModuleCallback(lldb::SBPlatformLocateModuleCallback callback, void *callback_baton); + SBError SetResolveSourceFileCallback( + lldb::SBPlatformResolveSourceFileCallback callback, void *callback_baton); + protected: friend class SBDebugger; friend class SBTarget; diff --git a/lldb/source/API/SBPlatform.cpp b/lldb/source/API/SBPlatform.cpp index 394268b77aa21f..f0fd0a3418fa56 100644 --- a/lldb/source/API/SBPlatform.cpp +++ b/lldb/source/API/SBPlatform.cpp @@ -732,3 +732,40 @@ SBError SBPlatform::SetLocateModuleCallback( }); return SBError(); } + +SBError SBPlatform::SetResolveSourceFileCallback( + lldb::SBPlatformResolveSourceFileCallback callback, void *callback_baton) { + LLDB_INSTRUMENT_VA(this, callback, callback_baton); + PlatformSP platform_sp(GetSP()); + if (!platform_sp) { + return SBError("invalid platform"); + } + + if (!callback) { + // Clear the callback. + platform_sp->SetResolveSourceFileCallback(nullptr); + return SBError(); + } + + // Platform.h does not accept lldb::SBPlatform ResolveSourceFileCallback + // directly because of the SBFileSpec dependency. Use a lambda to + // convert FileSpec <--> SBFileSpec for the callback arguments. + platform_sp->SetResolveSourceFileCallback( + [callback, callback_baton](const lldb::ModuleSP &module_sp, + const FileSpec &original_source_file_spec, + FileSpec &resolved_source_file_spec) { + SBFileSpec original_source_file_spec_sb(original_source_file_spec); + SBFileSpec resolved_source_file_spec_sb; + + SBError error = + callback(callback_baton, module_sp, original_source_file_spec_sb, + resolved_source_file_spec_sb); + + if (error.Success()) { + resolved_source_file_spec = resolved_source_file_spec_sb.ref(); + } + + return error.ref().Clone(); + }); + return SBError(); +} diff --git a/lldb/test/API/python_api/sbplatform/TestResolveSourceFileCallback.py b/lldb/test/API/python_api/sbplatform/TestResolveSourceFileCallback.py new file mode 100644 index 00000000000000..78bf4e47145ca7 --- /dev/null +++ b/lldb/test/API/python_api/sbplatform/TestResolveSourceFileCallback.py @@ -0,0 +1,196 @@ +""" +Test resolve source file callback functionality +""" + +import os +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from pathlib import Path + +import lldb + +SOURCE_ORIGINAL_FILE = "test.cpp" # File does not exist +SOURCE_NEW_FILE = "test_new.cpp" # File exists +SOURCE_NEW_NON_EXISTENT_FILE = "non-existent-file" +EXE_NAME = "test.exe" + + +class ResolveSourceFileCallbackTestCase(TestBase): + def setUp(self): + TestBase.setUp(self) + + # Set the input directory + self.input_dir = (Path(self.getSourceDir())).resolve() + + # Set executable to test.exe and ensure it exists + exe_path = (self.input_dir / EXE_NAME).resolve() + self.assertTrue(exe_path.exists()) + exe_path_str = str(exe_path) + + # Create target + self.target = self.dbg.CreateTarget(exe_path_str) + self.assertTrue(self.target) + + # Create platform + self.platform = self.target.GetPlatform() + + # Launch the process once, stop at breakpoint "sum" function and get the frame + self.frame = self.get_frame_for_paused_process("sum", exe_path_str) + + # Set the original source file spec + source_file_path = os.path.join(self.input_dir, SOURCE_ORIGINAL_FILE) + self.original_source_file_spec = lldb.SBFileSpec(source_file_path) + + # Set the new source file spec + new_source_file_path = os.path.join(self.input_dir, SOURCE_NEW_FILE) + self.new_source_file_spec = lldb.SBFileSpec(new_source_file_path) + + def get_frame_for_paused_process(self, function_name, exe) -> lldb.SBFrame: + # Launch the process, stop at breakpoint on function name and get the frame + + # Set breakpoint + breakpoint = self.target.BreakpointCreateByName(function_name, exe) + self.assertTrue( + breakpoint and breakpoint.GetNumLocations() == 1, VALID_BREAKPOINT + ) + + # Now launch the process, and do not stop at entry point. + process = self.target.LaunchSimple( + None, None, self.get_process_working_directory() + ) + self.assertTrue(process, PROCESS_IS_VALID) + + # Get the stopped thread + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue( + thread.IsValid(), "There should be a thread stopped due to breakpoint" + ) + + # Get the frame + frame0 = thread.GetFrameAtIndex(0) + self.assertTrue(frame0.IsValid(), "There should be a valid frame") + + return frame0 + + def get_source_file_for_frame(self) -> lldb.SBFileSpec: + line_entry = self.frame.GetLineEntry() + self.assertTrue(line_entry.IsValid(), "There should be a valid line entry") + + return line_entry.GetFileSpec() + + def test_set_non_callable(self): + # The callback should be callable. + non_callable = "a" + + with self.assertRaises(TypeError, msg="Need a callable object or None!"): + self.platform.SetResolveSourceFileCallback(non_callable) + + def test_set_wrong_args(self): + # The callback should accept 3 argument. + def test_args2(a, b): + pass + + with self.assertRaises(TypeError, msg="Expected 3 argument callable object"): + self.platform.SetResolveSourceFileCallback(test_args2) + + def test_default(self): + # The default behavior is to locate the source file with LLDB implementation + # and frame.GetLineEntry should return the original file spec. + resolved_source_file_spec = self.get_source_file_for_frame() + + # Check if the source file spec is resolved to the original file spec + self.assertEqual(resolved_source_file_spec, self.original_source_file_spec) + self.assertFalse(self.original_source_file_spec.Exists()) + + def test_set_none(self): + # SetResolveSourceFileCallback should succeed to clear the callback with None + # and frame.GetLineEntry will return the original file spec. + self.assertTrue(self.platform.SetResolveSourceFileCallback(None).Success()) + + resolved_source_file_spec = self.get_source_file_for_frame() + + # Check if the source file spec is resolved to the original file spec + self.assertEqual(resolved_source_file_spec, self.original_source_file_spec) + self.assertFalse(resolved_source_file_spec.Exists()) + + def test_return_original_file_on_error(self): + # The callback fails, frame.GetLineEntry should return the original file spec. + + # Resolve Source File Callback + def test_source_file_callback( + module_sp: lldb.SBModule, + original_file_spec: lldb.SBFileSpec, + resolved_file_spec: lldb.SBFileSpec, + ): + return lldb.SBError("Resolve Source File Callback failed") + + self.assertTrue( + self.platform.SetResolveSourceFileCallback( + test_source_file_callback + ).Success() + ) + + resolved_source_file_spec = self.get_source_file_for_frame() + + # Check if the source file spec is resolved to the original file spec + self.assertEqual(resolved_source_file_spec, self.original_source_file_spec) + self.assertFalse(resolved_source_file_spec.Exists()) + + def test_return_orignal_file_with_new_nonexistent_file(self): + # The callback should return a valid SBFileSpec but the file does not exist. + # frame.GetLineEntry should return the original file spec. + + # Resolve Source File Callback + def test_source_file_callback( + module_sp: lldb.SBModule, + original_file_spec: lldb.SBFileSpec, + resolved_file_spec: lldb.SBFileSpec, + ): + resolved_file_spec.SetDirectory(str(self.input_dir)) + resolved_file_spec.SetFilename(SOURCE_NEW_NON_EXISTENT_FILE) + + return lldb.SBError() + + # SetResolveSourceFileCallback should succeed and frame.GetLineEntry will return the original file spec + self.assertTrue( + self.platform.SetResolveSourceFileCallback( + test_source_file_callback + ).Success() + ) + + # Get resolved source file spec from frame0 + resolved_source_file_spec = self.get_source_file_for_frame() + + # Check if the source file spec is resolved to the original file spec + self.assertEqual(resolved_source_file_spec, self.original_source_file_spec) + self.assertFalse(resolved_source_file_spec.Exists()) + + def test_return_new_existent_file(self): + # The callback should return a valid SBFileSpec and file exists. + # frame.GetLineEntry should return the new file spec. + + # Resolve Source File Callback + def test_source_file_callback( + module_sp: lldb.SBModule, + original_file_spec: lldb.SBFileSpec, + resolved_file_spec: lldb.SBFileSpec, + ): + resolved_file_spec.SetDirectory(str(self.input_dir)) + resolved_file_spec.SetFilename(SOURCE_NEW_FILE) + + return lldb.SBError() + + # SetResolveSourceFileCallback should succeed and frame.GetLineEntry will return the new file spec from callback + self.assertTrue( + self.platform.SetResolveSourceFileCallback( + test_source_file_callback + ).Success() + ) + + # Get resolved source file spec from frame0 + resolved_source_file_spec = self.get_source_file_for_frame() + + # Check if the source file spec is resolved to the file set in callback + self.assertEqual(resolved_source_file_spec, self.new_source_file_spec) + self.assertFalse(self.original_source_file_spec.Exists()) + self.assertTrue(resolved_source_file_spec.Exists()) diff --git a/lldb/test/API/python_api/sbplatform/test.exe b/lldb/test/API/python_api/sbplatform/test.exe new file mode 100755 index 0000000000000000000000000000000000000000..ee23081015ce7944535bc76b8a17861d80c74cc0 GIT binary patch literal 21704 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 literal 0 HcmV?d00001 diff --git a/lldb/test/API/python_api/sbplatform/test_new.cpp b/lldb/test/API/python_api/sbplatform/test_new.cpp new file mode 100644 index 00000000000000..e9ffc97618f5d1 --- /dev/null +++ b/lldb/test/API/python_api/sbplatform/test_new.cpp @@ -0,0 +1,15 @@ +#include <iostream> + +int sum(int a, int b) { + return a + b; // Find the line number of function sum here. +} + +int main() { + + int a = 2; + int b = 3; + int c = sum(a, b); + + std::cout << "c is " << c << std::endl; + return 0; +} _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits