memory_analyzer/gdb_commands.py (31 lines of code) (raw):
#!/usr/bin/env python3
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
"""Module containing all of the custom GDB commands to be used for memory analysis.
This is equivalent to a GDB command file, and can only be called from a GDB process."""
import os
import sys
import gdb
TEMPLATES_PATH = os.getenv("MEMORY_ANALYZER_TEMPLATES_PATH")
def lock_GIL(func):
def wrapper(*args):
out = gdb.execute("call (void*) PyGILState_Ensure()", to_string=True)
gil_value = next((x for x in out.split() if x.startswith("$")), "$1")
print("GIL", gil_value)
func(*args)
call = "call (void) PyGILState_Release(" + gil_value + ")"
gdb.execute(call)
return wrapper
class FileCommand(gdb.Command):
def __init__(self):
super(FileCommand, self).__init__("file_command", gdb.COMMAND_NONE)
@lock_GIL
def invoke(self, filename, from_tty):
cmd_string = "with open('{filename}') as f: exec(f.read())".format(
filename=filename
)
gdb.execute(
'call (void) PyRun_SimpleString("{cmd_str}")'.format(cmd_str=cmd_string)
)
FileCommand()
pid = gdb.selected_inferior().pid
gdb.execute(
"file_command {TEMPLATES_PATH}/rendered_template-{pid}.py.out".format(
TEMPLATES_PATH=TEMPLATES_PATH, pid=pid
)
)