mirror of
https://github.com/intel/llvm.git
synced 2026-01-30 22:53:05 +08:00
[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
This commit is contained in:
committed by
Kazuki Sakamoto
parent
1a4bc114ec
commit
f03dbdb70a
338
lldb/test/API/python_api/sbplatform/TestLocateModuleCallback.py
Normal file
338
lldb/test/API/python_api/sbplatform/TestLocateModuleCallback.py
Normal file
@@ -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,
|
||||
)
|
||||
Reference in New Issue
Block a user