aboutsummaryrefslogtreecommitdiff
path: root/lldb/test/API/python_api
diff options
context:
space:
mode:
authorKazuki Sakamoto <sakamoto@splhack.org>2023-06-23 21:28:04 -0700
committerKazuki Sakamoto <kaz@meta.com>2023-07-12 11:33:51 -0700
commitf03dbdb70aed74ed64c1a42a85e47e3f86315ae7 (patch)
treebcb2d540a09d488a2943f349dbc15eaa365c823e /lldb/test/API/python_api
parent1a4bc114ec8a80550259b5b3b1c7ab0d5c5fa4da (diff)
downloadllvm-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.py338
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,
+ )