mirror of
https://github.com/zebrajr/pytorch.git
synced 2025-12-07 12:21:27 +01:00
Summary: Pull Request resolved: https://github.com/pytorch/pytorch/pull/58117 Previously it was not possible to load C extension modules with deploy because extension modules need to link against the Python.h API functions. Since each libtorchdeploy_interpreter.so had its own copy of these functions, it is not possible to tell dlopen to resolve symbols in a loaded SO from one of these libraries without exposing its symbols globally. This patch adds a custom ELF loader which does the custom loading of attaching c extension libraries to the Python API that loaded the shared library. Simple use of numpy and regex modules appears to work. This diff has some limitations: * 64-bit Linux only. OSX and windows use different formats for shared libraries. 32-bit ELF files are not supported. * debug info is not immediately availiable to debuggers. A script for lldb is provided which can be loaded so that lldb knows about the libraries as they are loaded. * shared libraries can directly use the Python API, but libraries they depend on (via DT_NEEDED entries in their dynamic segment) may not use Python. In the future, we can try to detect whether a sub library uses the Python API and load it with our customer loader. * TLS initialization and library initialization may occur in a different order than what would happen with dlopen, potentially leading to some issues running destructors in TLS segments. Use of this C++ features is relatively rare. Test Plan: Imported from OSS Reviewed By: suo Differential Revision: D28435305 Pulled By: zdevito fbshipit-source-id: 10f046053dd1d250e3c73f2cce8eb945eeba31b6
35 lines
1.3 KiB
Python
35 lines
1.3 KiB
Python
import lldb # type: ignore[import]
|
|
# load into lldb instance with:
|
|
# command script import tools/lldb/deploy_debugger.py
|
|
|
|
target = lldb.debugger.GetSelectedTarget()
|
|
bp = target.BreakpointCreateByRegex("__deploy_register_code")
|
|
bp.SetScriptCallbackBody("""\
|
|
process = frame.thread.GetProcess()
|
|
target = process.target
|
|
symbol_addr = frame.module.FindSymbol("__deploy_module_info").GetStartAddress()
|
|
info_addr = symbol_addr.GetLoadAddress(target)
|
|
e = lldb.SBError()
|
|
ptr_size = 8
|
|
str_addr = process.ReadPointerFromMemory(info_addr, e)
|
|
file_addr = process.ReadPointerFromMemory(info_addr + ptr_size, e)
|
|
file_size = process.ReadPointerFromMemory(info_addr + 2*ptr_size, e)
|
|
load_bias = process.ReadPointerFromMemory(info_addr + 3*ptr_size, e)
|
|
name = process.ReadCStringFromMemory(str_addr, 512, e)
|
|
r = process.ReadMemory(file_addr, file_size, e)
|
|
from tempfile import NamedTemporaryFile
|
|
from pathlib import Path
|
|
stem = Path(name).stem
|
|
with NamedTemporaryFile(prefix=stem, suffix='.so', delete=False) as tf:
|
|
tf.write(r)
|
|
print("torch_deploy registering debug inforation for ", tf.name)
|
|
cmd1 = f"target modules add {tf.name}"
|
|
# print(cmd1)
|
|
lldb.debugger.HandleCommand(cmd1)
|
|
cmd2 = f"target modules load -f {tf.name} -s {hex(load_bias)}"
|
|
# print(cmd2)
|
|
lldb.debugger.HandleCommand(cmd2)
|
|
|
|
return False
|
|
""")
|