diff options
| author | Kazuki Sakamoto <sakamoto@splhack.org> | 2023-06-23 21:28:04 -0700 |
|---|---|---|
| committer | Kazuki Sakamoto <kaz@meta.com> | 2023-07-12 11:33:51 -0700 |
| commit | f03dbdb70aed74ed64c1a42a85e47e3f86315ae7 (patch) | |
| tree | bcb2d540a09d488a2943f349dbc15eaa365c823e /lldb/test/API/python_api | |
| parent | 1a4bc114ec8a80550259b5b3b1c7ab0d5c5fa4da (diff) | |
| download | llvm-f03dbdb70aed74ed64c1a42a85e47e3f86315ae7.zip llvm-f03dbdb70aed74ed64c1a42a85e47e3f86315ae7.tar.gz llvm-f03dbdb70aed74ed64c1a42a85e47e3f86315ae7.tar.bz2 | |
[lldb][LocateModuleCallback] Implement API, Python interface
RFC https://discourse.llvm.org/t/rfc-python-callback-for-target-get-module/71580
Use SWIG for the locate module callback the same as other Python callbacks.
TestLocateModuleCallback.py verifies the functionalities.
Differential Revision: https://reviews.llvm.org/D153735
Diffstat (limited to 'lldb/test/API/python_api')
| -rw-r--r-- | lldb/test/API/python_api/sbplatform/TestLocateModuleCallback.py | 338 |
1 files changed, 338 insertions, 0 deletions
diff --git a/lldb/test/API/python_api/sbplatform/TestLocateModuleCallback.py b/lldb/test/API/python_api/sbplatform/TestLocateModuleCallback.py new file mode 100644 index 0000000..672795f --- /dev/null +++ b/lldb/test/API/python_api/sbplatform/TestLocateModuleCallback.py @@ -0,0 +1,338 @@ +""" +Test platform locate module callback functionality +""" + +import ctypes +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from pathlib import Path + +import lldb + +UNITTESTS_TARGET_INPUTS_PATH = "../../../../unittests/Target/Inputs" +MODULE_PLATFORM_PATH = "/system/lib64/AndroidModule.so" +MODULE_TRIPLE = "aarch64-none-linux" +MODULE_RESOLVED_TRIPLE = "aarch64--linux-android" +MODULE_UUID = "80008338-82A0-51E5-5922-C905D23890DA-BDDEFECC" +MODULE_FUNCTION = "boom" +MODULE_HIDDEN_FUNCTION = "boom_hidden" +MODULE_FILE = "AndroidModule.so" +MODULE_NON_EXISTENT_FILE = "non-existent-file" +SYMBOL_FILE = "AndroidModule.unstripped.so" +BREAKPAD_SYMBOL_FILE = "AndroidModule.so.sym" +SYMBOL_STRIPPED = "stripped" +SYMBOL_UNSTRIPPED = "unstripped" + + +class LocateModuleCallbackTestCase(TestBase): + def setUp(self): + TestBase.setUp(self) + self.platform = self.dbg.GetSelectedPlatform() + self.target = self.dbg.CreateTarget("") + self.assertTrue(self.target) + + self.input_dir = ( + Path(self.getSourceDir()) / UNITTESTS_TARGET_INPUTS_PATH + ).resolve() + self.assertTrue(self.input_dir.is_dir()) + + def check_module_spec(self, module_spec: lldb.SBModuleSpec): + self.assertEqual( + MODULE_UUID.replace("-", ""), + ctypes.string_at( + int(module_spec.GetUUIDBytes()), + module_spec.GetUUIDLength(), + ) + .hex() + .upper(), + ) + + self.assertEqual(MODULE_TRIPLE, module_spec.GetTriple()) + + self.assertEqual(MODULE_PLATFORM_PATH, module_spec.GetFileSpec().fullpath) + + def check_module(self, module: lldb.SBModule, symbol_file: str, symbol_kind: str): + self.assertTrue(module.IsValid()) + + self.assertEqual( + MODULE_UUID, + module.GetUUIDString(), + ) + + self.assertEqual(MODULE_RESOLVED_TRIPLE, module.GetTriple()) + + self.assertEqual(MODULE_PLATFORM_PATH, module.GetPlatformFileSpec().fullpath) + + self.assertEqual( + str(self.input_dir / MODULE_FILE), + module.GetFileSpec().fullpath, + ) + + self.assertEqual( + str(self.input_dir / symbol_file), + module.GetSymbolFileSpec().fullpath, + ) + + sc_list = module.FindFunctions(MODULE_FUNCTION, lldb.eSymbolTypeCode) + self.assertEqual(1, sc_list.GetSize()) + sc_list = module.FindFunctions(MODULE_HIDDEN_FUNCTION, lldb.eSymbolTypeCode) + self.assertEqual(0 if symbol_kind == SYMBOL_STRIPPED else 1, sc_list.GetSize()) + + 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.SetLocateModuleCallback(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.SetLocateModuleCallback(test_args2) + + def test_default(self): + # The default behavior is to locate the module with LLDB implementation + # and AddModule should fail. + module = self.target.AddModule( + MODULE_PLATFORM_PATH, + MODULE_TRIPLE, + MODULE_UUID, + ) + + self.assertFalse(module) + + def test_set_none(self): + # SetLocateModuleCallback should succeed to clear the callback with None. + # and AddModule should fail. + self.assertTrue(self.platform.SetLocateModuleCallback(None).Success()) + + module = self.target.AddModule( + MODULE_PLATFORM_PATH, + MODULE_TRIPLE, + MODULE_UUID, + ) + + self.assertFalse(module) + + def test_return_error(self): + # The callback fails, AddModule should fail. + def test_locate_module( + module_spec: lldb.SBModuleSpec, + module_file_spec: lldb.SBFileSpec, + symbol_file_spec: lldb.SBFileSpec, + ): + self.check_module_spec(module_spec) + return lldb.SBError("locate module callback failed") + + self.assertTrue( + self.platform.SetLocateModuleCallback(test_locate_module).Success() + ) + + module = self.target.AddModule( + MODULE_PLATFORM_PATH, + MODULE_TRIPLE, + MODULE_UUID, + ) + + self.assertFalse(module) + + def test_return_no_files(self): + # The callback succeeds but not return any files, AddModule should fail. + def test_locate_module( + module_spec: lldb.SBModuleSpec, + module_file_spec: lldb.SBFileSpec, + symbol_file_spec: lldb.SBFileSpec, + ): + self.check_module_spec(module_spec) + return lldb.SBError() + + self.assertTrue( + self.platform.SetLocateModuleCallback(test_locate_module).Success() + ) + + module = self.target.AddModule( + MODULE_PLATFORM_PATH, + MODULE_TRIPLE, + MODULE_UUID, + ) + + self.assertFalse(module) + + def test_return_non_existent_module(self): + # The callback returns non-existent module file, AddModule should fail. + def test_locate_module( + module_spec: lldb.SBModuleSpec, + module_file_spec: lldb.SBFileSpec, + symbol_file_spec: lldb.SBFileSpec, + ): + self.check_module_spec(module_spec) + + module_file_spec.SetDirectory(str(self.input_dir)) + module_file_spec.SetFilename(MODULE_NON_EXISTENT_FILE) + + return lldb.SBError() + + self.assertTrue( + self.platform.SetLocateModuleCallback(test_locate_module).Success() + ) + + module = self.target.AddModule( + MODULE_PLATFORM_PATH, + MODULE_TRIPLE, + MODULE_UUID, + ) + + self.assertFalse(module) + + def test_return_module_with_non_existent_symbol(self): + # The callback returns a module and non-existent symbol file, + # AddModule should fail. + def test_locate_module( + module_spec: lldb.SBModuleSpec, + module_file_spec: lldb.SBFileSpec, + symbol_file_spec: lldb.SBFileSpec, + ): + self.check_module_spec(module_spec) + + module_file_spec.SetDirectory(str(self.input_dir)) + module_file_spec.SetFilename(MODULE_FILE) + + symbol_file_spec.SetDirectory(str(self.input_dir)) + symbol_file_spec.SetFilename(MODULE_NON_EXISTENT_FILE) + + return lldb.SBError() + + self.assertTrue( + self.platform.SetLocateModuleCallback(test_locate_module).Success() + ) + + module = self.target.AddModule( + MODULE_PLATFORM_PATH, + MODULE_TRIPLE, + MODULE_UUID, + ) + + self.assertFalse(module) + + def test_return_non_existent_symbol(self): + # The callback returns non-existent symbol file, AddModule should fail. + def test_locate_module( + module_spec: lldb.SBModuleSpec, + module_file_spec: lldb.SBFileSpec, + symbol_file_spec: lldb.SBFileSpec, + ): + self.check_module_spec(module_spec) + + symbol_file_spec.SetDirectory(str(self.input_dir)) + symbol_file_spec.SetFilename(MODULE_NON_EXISTENT_FILE) + + return lldb.SBError() + + self.assertTrue( + self.platform.SetLocateModuleCallback(test_locate_module).Success() + ) + + module = self.target.AddModule( + MODULE_PLATFORM_PATH, + MODULE_TRIPLE, + MODULE_UUID, + ) + + self.assertFalse(module) + + def test_return_module(self): + # The callback returns the module file, AddModule should succeed. + def test_locate_module( + module_spec: lldb.SBModuleSpec, + module_file_spec: lldb.SBFileSpec, + symbol_file_spec: lldb.SBFileSpec, + ): + self.check_module_spec(module_spec) + + module_file_spec.SetDirectory(str(self.input_dir)) + module_file_spec.SetFilename(MODULE_FILE) + + return lldb.SBError() + + self.assertTrue( + self.platform.SetLocateModuleCallback(test_locate_module).Success() + ) + + module = self.target.AddModule( + MODULE_PLATFORM_PATH, + MODULE_TRIPLE, + MODULE_UUID, + ) + + self.check_module( + module=module, symbol_file=MODULE_FILE, symbol_kind=SYMBOL_STRIPPED + ) + + def test_return_module_with_symbol(self): + # The callback returns the module file and the symbol file, + # AddModule should succeed. + def test_locate_module( + module_spec: lldb.SBModuleSpec, + module_file_spec: lldb.SBFileSpec, + symbol_file_spec: lldb.SBFileSpec, + ): + self.check_module_spec(module_spec) + + module_file_spec.SetDirectory(str(self.input_dir)) + module_file_spec.SetFilename(MODULE_FILE) + + symbol_file_spec.SetDirectory(str(self.input_dir)) + symbol_file_spec.SetFilename(SYMBOL_FILE) + + return lldb.SBError() + + self.assertTrue( + self.platform.SetLocateModuleCallback(test_locate_module).Success() + ) + + module = self.target.AddModule( + MODULE_PLATFORM_PATH, + MODULE_TRIPLE, + MODULE_UUID, + ) + + self.check_module( + module=module, symbol_file=SYMBOL_FILE, symbol_kind=SYMBOL_UNSTRIPPED + ) + + def test_return_module_with_breakpad_symbol(self): + # The callback returns the module file and the breakpad symbol file, + # AddModule should succeed. + def test_locate_module( + module_spec: lldb.SBModuleSpec, + module_file_spec: lldb.SBFileSpec, + symbol_file_spec: lldb.SBFileSpec, + ): + self.check_module_spec(module_spec) + + module_file_spec.SetDirectory(str(self.input_dir)) + module_file_spec.SetFilename(MODULE_FILE) + + symbol_file_spec.SetDirectory(str(self.input_dir)) + symbol_file_spec.SetFilename(BREAKPAD_SYMBOL_FILE) + + return lldb.SBError() + + self.assertTrue( + self.platform.SetLocateModuleCallback(test_locate_module).Success() + ) + + module = self.target.AddModule( + MODULE_PLATFORM_PATH, + MODULE_TRIPLE, + MODULE_UUID, + ) + + self.check_module( + module=module, + symbol_file=BREAKPAD_SYMBOL_FILE, + symbol_kind=SYMBOL_UNSTRIPPED, + ) |
