mirror of
https://github.com/apache/nuttx.git
synced 2026-05-21 21:34:07 +08:00
tools/gdb: add pyproject.toml to build as a package
Now the GDB tool can be built with python -m build . to generate a package. Signed-off-by: xuxingliang <xuxingliang@xiaomi.com>
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
dist/
|
||||
nuttxgdb.egg-info/
|
||||
@@ -0,0 +1,35 @@
|
||||
############################################################################
|
||||
# tools/gdb/gdbinit.py
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
import sys
|
||||
from os import path
|
||||
|
||||
here = path.dirname(path.abspath(__file__))
|
||||
|
||||
if __name__ == "__main__":
|
||||
if here not in sys.path:
|
||||
sys.path.insert(0, here)
|
||||
|
||||
if "nuttxgdb" in sys.modules:
|
||||
del sys.modules["nuttxgdb"]
|
||||
|
||||
import nuttxgdb # noqa: F401
|
||||
@@ -1,5 +1,5 @@
|
||||
############################################################################
|
||||
# tools/gdb/__init__.py
|
||||
# tools/gdb/nuttxgdb/__init__.py
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@@ -20,19 +20,17 @@
|
||||
#
|
||||
############################################################################
|
||||
|
||||
import glob
|
||||
import os
|
||||
import sys
|
||||
import importlib
|
||||
from os import listdir, path
|
||||
|
||||
import gdb
|
||||
|
||||
python_dir = os.path.abspath(__file__)
|
||||
python_dir = os.path.dirname(python_dir)
|
||||
here = path.dirname(path.abspath(__file__))
|
||||
|
||||
sys.path.insert(1, python_dir)
|
||||
# Search the python dir for all .py files, and source each
|
||||
py_files = glob.glob(f"{python_dir}/*.py")
|
||||
py_files.remove(os.path.abspath(__file__))
|
||||
# Scan dir to get all modules available
|
||||
modules = [
|
||||
path.splitext(path.basename(f))[0] for f in listdir(here) if f.endswith(".py")
|
||||
]
|
||||
|
||||
|
||||
def register_commands(event):
|
||||
@@ -41,20 +39,29 @@ def register_commands(event):
|
||||
|
||||
register_commands.registered = True
|
||||
|
||||
gdb.write("Registering NuttX GDB commands...\n")
|
||||
gdb.write(f"Registering NuttX GDB commands from {here}\n")
|
||||
gdb.execute("set pagination off")
|
||||
gdb.write("set pagination off\n")
|
||||
gdb.execute("set python print-stack full")
|
||||
gdb.write("set python print-stack full\n")
|
||||
for py_file in py_files:
|
||||
gdb.execute(f"source {py_file}")
|
||||
gdb.write(f"source {py_file}\n")
|
||||
|
||||
utils = __import__("utils")
|
||||
utils.check_version()
|
||||
gdb.execute('handle SIGUSR1 "nostop" "pass" "noprint"')
|
||||
gdb.write('"handle SIGUSR1 "nostop" "pass" "noprint"\n')
|
||||
|
||||
# Register all modules
|
||||
for m in modules:
|
||||
if m == "__init__":
|
||||
continue
|
||||
|
||||
module = importlib.import_module(f"{__package__}.{m}")
|
||||
|
||||
# Get all classes inherited from gdb.Command
|
||||
for c in module.__dict__.values():
|
||||
if isinstance(c, type) and issubclass(c, gdb.Command):
|
||||
c()
|
||||
|
||||
utils = importlib.import_module(f"{__package__}.utils")
|
||||
utils.check_version()
|
||||
|
||||
|
||||
if len(gdb.objfiles()) == 0:
|
||||
gdb.events.new_objfile.connect(register_commands)
|
||||
@@ -1,5 +1,7 @@
|
||||
############################################################################
|
||||
# tools/gdb/dmesg.py
|
||||
# tools/gdb/nuttxgdb/dmesg.py
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
@@ -19,14 +21,16 @@
|
||||
############################################################################
|
||||
|
||||
import gdb
|
||||
import utils
|
||||
|
||||
from . import utils
|
||||
|
||||
CONFIG_RAMLOG_SYSLOG = utils.get_symbol_value("CONFIG_RAMLOG_SYSLOG")
|
||||
|
||||
|
||||
class Dmesg(gdb.Command):
|
||||
def __init__(self):
|
||||
super().__init__("dmesg", gdb.COMMAND_USER)
|
||||
if CONFIG_RAMLOG_SYSLOG:
|
||||
super().__init__("dmesg", gdb.COMMAND_USER)
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
sysdev = utils.gdb_eval_or_none("g_sysdev")
|
||||
@@ -43,7 +47,3 @@ class Dmesg(gdb.Command):
|
||||
clean_data = bytes(buf).replace(b"\x00", "␀".encode("utf-8"))
|
||||
gdb.write(clean_data.decode("utf-8"))
|
||||
gdb.write("\n")
|
||||
|
||||
|
||||
if CONFIG_RAMLOG_SYSLOG:
|
||||
Dmesg()
|
||||
@@ -1,5 +1,7 @@
|
||||
############################################################################
|
||||
# tools/gdb/fs.py
|
||||
# tools/gdb/nuttxgdb/fs.py
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
@@ -22,7 +24,8 @@ import argparse
|
||||
import enum
|
||||
|
||||
import gdb
|
||||
import utils
|
||||
|
||||
from . import utils
|
||||
|
||||
FSNODEFLAG_TYPE_MASK = utils.get_symbol_value("FSNODEFLAG_TYPE_MASK")
|
||||
|
||||
@@ -220,7 +223,8 @@ class Fdinfo(gdb.Command):
|
||||
|
||||
class Mount(gdb.Command):
|
||||
def __init__(self):
|
||||
super().__init__("mount", gdb.COMMAND_USER)
|
||||
if not utils.get_symbol_value("CONFIG_DISABLE_MOUNTPOINT"):
|
||||
super().__init__("mount", gdb.COMMAND_USER)
|
||||
|
||||
def mountpt_filter(self, node, path):
|
||||
if inode_gettype(node) == InodeType.MOUNTPT:
|
||||
@@ -339,7 +343,8 @@ class InfoShmfs(gdb.Command):
|
||||
"""Show share memory usage"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("info shm", gdb.COMMAND_USER)
|
||||
if CONFIG_FS_SHMFS:
|
||||
super().__init__("info shm", gdb.COMMAND_USER)
|
||||
|
||||
def shm_filter(self, node, path):
|
||||
if inode_gettype(node) != InodeType.SHM:
|
||||
@@ -352,14 +357,3 @@ class InfoShmfs(gdb.Command):
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
foreach_inode(self.shm_filter)
|
||||
|
||||
|
||||
Fdinfo()
|
||||
|
||||
if not utils.get_symbol_value("CONFIG_DISABLE_MOUNTPOINT"):
|
||||
Mount()
|
||||
|
||||
ForeachInode()
|
||||
|
||||
if CONFIG_FS_SHMFS:
|
||||
InfoShmfs()
|
||||
@@ -1,5 +1,5 @@
|
||||
############################################################################
|
||||
# tools/gdb/gcore.py
|
||||
# tools/gdb/nuttxgdb/gcore.py
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@@ -25,7 +25,8 @@ import os
|
||||
import shutil
|
||||
|
||||
import gdb
|
||||
import utils
|
||||
|
||||
from . import utils
|
||||
|
||||
|
||||
def create_file_with_size(filename, size):
|
||||
@@ -133,6 +134,3 @@ class NXGcore(gdb.Command):
|
||||
tmpfile.close()
|
||||
|
||||
print(f"Please run gdbserver.py to parse {corefile}")
|
||||
|
||||
|
||||
NXGcore()
|
||||
@@ -1,5 +1,5 @@
|
||||
############################################################################
|
||||
# tools/gdb/lists.py
|
||||
# tools/gdb/nuttxgdb/lists.py
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@@ -23,7 +23,8 @@
|
||||
import argparse
|
||||
|
||||
import gdb
|
||||
import utils
|
||||
|
||||
from . import utils
|
||||
|
||||
list_node_type = utils.lookup_type("struct list_node")
|
||||
sq_queue_type = utils.lookup_type("sq_queue_t")
|
||||
@@ -1,5 +1,5 @@
|
||||
############################################################################
|
||||
# tools/gdb/macros.py
|
||||
# tools/gdb/nuttxgdb/macros.py
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@@ -1,5 +1,5 @@
|
||||
############################################################################
|
||||
# tools/gdb/memdump.py
|
||||
# tools/gdb/nuttxgdb/memdump.py
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@@ -25,9 +25,10 @@ import bisect
|
||||
import time
|
||||
|
||||
import gdb
|
||||
import utils
|
||||
from lists import NxSQueue
|
||||
from utils import get_long_type, get_symbol_value, lookup_type, read_ulong
|
||||
|
||||
from . import utils
|
||||
from .lists import NxSQueue
|
||||
from .utils import get_long_type, get_symbol_value, lookup_type, read_ulong
|
||||
|
||||
MM_ALLOC_BIT = 0x1
|
||||
MM_PREVFREE_BIT = 0x2
|
||||
@@ -1014,9 +1015,3 @@ class Memfrag(gdb.Command):
|
||||
f"heap size: {heapsize}, free size: {freesize}, uordblks:"
|
||||
f"{info.__len__()} largest block: {info[0]['size']} \n"
|
||||
)
|
||||
|
||||
|
||||
Memfrag()
|
||||
Memdump()
|
||||
Memleak()
|
||||
Memmap()
|
||||
@@ -1,5 +1,7 @@
|
||||
############################################################################
|
||||
# tools/gdb/net.py
|
||||
# tools/gdb/nuttxgdb/net.py
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
@@ -19,8 +21,9 @@
|
||||
############################################################################
|
||||
|
||||
import gdb
|
||||
import utils
|
||||
from lists import NxDQueue, NxSQueue
|
||||
|
||||
from . import utils
|
||||
from .lists import NxDQueue, NxSQueue
|
||||
|
||||
socket = utils.import_check(
|
||||
"socket", errmsg="No socket module found, please try gdb-multiarch instead.\n"
|
||||
@@ -108,7 +111,8 @@ class NetStats(gdb.Command):
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("netstats", gdb.COMMAND_USER)
|
||||
if utils.get_symbol_value("CONFIG_NET") and socket:
|
||||
super().__init__("netstats", gdb.COMMAND_USER)
|
||||
|
||||
def iob_stats(self):
|
||||
try:
|
||||
@@ -242,7 +246,3 @@ class NetStats(gdb.Command):
|
||||
if utils.get_symbol_value("CONFIG_NET_UDP") and "udp" in args:
|
||||
self.udp_stats()
|
||||
gdb.write("\n")
|
||||
|
||||
|
||||
if utils.get_symbol_value("CONFIG_NET") and socket:
|
||||
NetStats()
|
||||
@@ -1,5 +1,5 @@
|
||||
############################################################################
|
||||
# tools/gdb/stack.py
|
||||
# tools/gdb/nuttxgdb/stack.py
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@@ -23,7 +23,8 @@
|
||||
import traceback
|
||||
|
||||
import gdb
|
||||
import utils
|
||||
|
||||
from . import utils
|
||||
|
||||
STACK_COLORATION_PATTERN = utils.get_symbol_value(
|
||||
"STACK_COLOR", locspec="up_create_stack"
|
||||
@@ -217,6 +218,3 @@ class StackUsage(gdb.Command):
|
||||
continue
|
||||
|
||||
self.format_print(pid, stack)
|
||||
|
||||
|
||||
StackUsage()
|
||||
@@ -1,5 +1,5 @@
|
||||
############################################################################
|
||||
# tools/gdb/thread.py
|
||||
# tools/gdb/nuttxgdb/thread.py
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@@ -25,12 +25,20 @@ import re
|
||||
from enum import Enum, auto
|
||||
|
||||
import gdb
|
||||
import utils
|
||||
from stack import Stack
|
||||
|
||||
from . import utils
|
||||
from .stack import Stack
|
||||
|
||||
UINT16_MAX = 0xFFFF
|
||||
SEM_TYPE_MUTEX = 4
|
||||
TSTATE_TASK_RUNNING = utils.get_symbol_value("TSTATE_TASK_RUNNING")
|
||||
CONFIG_SMP_NCPUS = utils.get_symbol_value("CONFIG_SMP_NCPUS") or 1
|
||||
|
||||
|
||||
def is_thread_command_supported():
|
||||
# Check if the native thread command is available by compare the number of threads.
|
||||
# It should have at least CONFIG_SMP_NCPUS of idle threads.
|
||||
return len(gdb.selected_inferior().threads()) > CONFIG_SMP_NCPUS
|
||||
|
||||
|
||||
class Registers:
|
||||
@@ -207,6 +215,8 @@ class Nxinfothreads(gdb.Command):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("info nxthreads", gdb.COMMAND_USER)
|
||||
if not is_thread_command_supported():
|
||||
gdb.execute("define info threads\n info nxthreads \n end\n")
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
npidhash = gdb.parse_and_eval("g_npidhash")
|
||||
@@ -298,6 +308,8 @@ class Nxthread(gdb.Command):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("nxthread", gdb.COMMAND_USER)
|
||||
if not is_thread_command_supported():
|
||||
gdb.execute("define thread\n nxthread \n end\n")
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
npidhash = gdb.parse_and_eval("g_npidhash")
|
||||
@@ -375,6 +387,11 @@ class Nxcontinue(gdb.Command):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("nxcontinue", gdb.COMMAND_USER)
|
||||
if not is_thread_command_supported():
|
||||
gdb.execute("define c\n nxcontinue \n end\n")
|
||||
gdb.write(
|
||||
"\n\x1b[31;1m if use thread command, please don't use 'continue', use 'c' instead !!!\x1b[m\n"
|
||||
)
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
g_registers.restore()
|
||||
@@ -386,6 +403,11 @@ class Nxstep(gdb.Command):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("nxstep", gdb.COMMAND_USER)
|
||||
if not is_thread_command_supported():
|
||||
gdb.execute("define s\n nxstep \n end\n")
|
||||
gdb.write(
|
||||
"\x1b[31;1m if use thread command, please don't use 'step', use 's' instead !!!\x1b[m\n"
|
||||
)
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
g_registers.restore()
|
||||
@@ -637,36 +659,3 @@ class DeadLock(gdb.Command):
|
||||
gdb.write("No deadlock detected.")
|
||||
|
||||
gdb.write("\n")
|
||||
|
||||
|
||||
def register_commands():
|
||||
DeadLock()
|
||||
SetRegs()
|
||||
Ps()
|
||||
Nxcontinue()
|
||||
Nxinfothreads()
|
||||
Nxstep()
|
||||
Nxthread()
|
||||
|
||||
# Use custom command for thread if current target does not support it.
|
||||
# The recognized threads count is less than or equal to the number of CPUs in this case.
|
||||
# For coredump and gdb-stub, use native thread commands.
|
||||
ncpus = utils.get_symbol_value("CONFIG_SMP_NCPUS") or 1
|
||||
nthreads = len(gdb.selected_inferior().threads())
|
||||
if nthreads <= ncpus:
|
||||
# Native threads command is not available, override the threads command
|
||||
gdb.execute("define info threads\n info nxthreads \n end\n")
|
||||
gdb.execute("define thread\n nxthread \n end\n")
|
||||
|
||||
# We can't use a user command to rename continue it will recursion
|
||||
gdb.execute("define c\n nxcontinue \n end\n")
|
||||
gdb.execute("define s\n nxstep \n end\n")
|
||||
gdb.write(
|
||||
"\n\x1b[31;1m if use thread command, please don't use 'continue', use 'c' instead !!!\x1b[m\n"
|
||||
)
|
||||
gdb.write(
|
||||
"\x1b[31;1m if use thread command, please don't use 'step', use 's' instead !!!\x1b[m\n"
|
||||
)
|
||||
|
||||
|
||||
register_commands()
|
||||
@@ -1,5 +1,5 @@
|
||||
############################################################################
|
||||
# tools/gdb/utils.py
|
||||
# tools/gdb/nuttxgdb/utils.py
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@@ -25,7 +25,8 @@ import shlex
|
||||
from typing import List, Tuple, Union
|
||||
|
||||
import gdb
|
||||
from macros import fetch_macro_info, try_expand
|
||||
|
||||
from .macros import fetch_macro_info, try_expand
|
||||
|
||||
g_symbol_cache = {}
|
||||
g_type_cache = {}
|
||||
@@ -293,90 +294,6 @@ def parse_arg(arg: str) -> Union[gdb.Value, int]:
|
||||
return None
|
||||
|
||||
|
||||
class Hexdump(gdb.Command):
|
||||
"""hexdump address/symbol <size>"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("hexdump", gdb.COMMAND_USER)
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
args = shlex.split(args)
|
||||
if not args or len(args) < 1:
|
||||
gdb.write("Usage: hexdump address/symbol <size>\n")
|
||||
return
|
||||
|
||||
address = parse_arg(args[0])
|
||||
size = parse_arg(args[1]) if len(args) > 1 else None
|
||||
if not size:
|
||||
size = address.type.sizeof if isinstance(address, gdb.Value) else 128
|
||||
|
||||
print(f"Dumping {size} bytes from {hex(address)}")
|
||||
hexdump(address, size)
|
||||
|
||||
|
||||
Hexdump()
|
||||
|
||||
|
||||
class Addr2Line(gdb.Command):
|
||||
"""Convert addresses or expressions
|
||||
|
||||
Usage: addr2line address1 address2 expression1
|
||||
Example: addr2line 0x1234 0x5678
|
||||
addr2line "0x1234 + pointer->abc" &var var->field function_name var
|
||||
addr2line $pc $r1 "$r2 + var"
|
||||
addr2line [24/08/29 20:51:02] [CPU1] [209] [ap] sched_dumpstack: backtrace| 0: 0x402cd484 0x4028357e
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("addr2line", gdb.COMMAND_USER)
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
if not args:
|
||||
gdb.write(Addr2Line.__doc__ + "\n")
|
||||
return
|
||||
|
||||
addresses = []
|
||||
for arg in shlex.split(args):
|
||||
v = parse_arg(arg)
|
||||
if not v:
|
||||
gdb.write(f'Ignore "{arg}"\n')
|
||||
continue
|
||||
|
||||
addresses.append(v)
|
||||
|
||||
backtraces = backtrace(addresses)
|
||||
formatter = "{:<20} {:<32} {}\n"
|
||||
gdb.write(formatter.format("Address", "Symbol", "Source"))
|
||||
for addr, func, source in backtraces:
|
||||
gdb.write(formatter.format(hex(addr), func, source))
|
||||
|
||||
|
||||
Addr2Line()
|
||||
|
||||
|
||||
class Profile(gdb.Command):
|
||||
"""Profile a gdb command
|
||||
|
||||
Usage: profile <gdb command>
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.cProfile = import_check(
|
||||
"cProfile", errmsg="cProfile module not found, try gdb-multiarch.\n"
|
||||
)
|
||||
if not self.cProfile:
|
||||
return
|
||||
|
||||
super().__init__("profile", gdb.COMMAND_USER)
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
|
||||
self.cProfile.run(f"gdb.execute('{args}')", sort="cumulative")
|
||||
|
||||
|
||||
Profile()
|
||||
|
||||
|
||||
def nitems(array):
|
||||
array_type = array.type
|
||||
element_type = array_type.target()
|
||||
@@ -681,3 +598,86 @@ def check_version():
|
||||
|
||||
switch_inferior(1) # Switch back
|
||||
suppress_cli_notifications(state)
|
||||
|
||||
|
||||
class Hexdump(gdb.Command):
|
||||
"""hexdump address/symbol <size>"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("hexdump", gdb.COMMAND_USER)
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
argv = args.split(" ")
|
||||
address = 0
|
||||
size = 0
|
||||
if argv[0] == "":
|
||||
gdb.write("Usage: hexdump address/symbol <size>\n")
|
||||
return
|
||||
|
||||
if is_decimal(argv[0]) or is_hexadecimal(argv[0]):
|
||||
address = int(argv[0], 0)
|
||||
size = int(argv[1], 0)
|
||||
else:
|
||||
var = gdb.parse_and_eval(f"{argv[0]}")
|
||||
address = int(var.address)
|
||||
size = int(var.type.sizeof)
|
||||
gdb.write(f"{argv[0]} {hex(address)} {int(size)}\n")
|
||||
|
||||
hexdump(address, size)
|
||||
|
||||
|
||||
class Addr2Line(gdb.Command):
|
||||
"""Convert addresses or expressions
|
||||
|
||||
Usage: addr2line address1 address2 expression1
|
||||
Example: addr2line 0x1234 0x5678
|
||||
addr2line "0x1234 + pointer->abc" &var var->field function_name var
|
||||
addr2line $pc $r1 "$r2 + var"
|
||||
addr2line [24/08/29 20:51:02] [CPU1] [209] [ap] sched_dumpstack: backtrace| 0: 0x402cd484 0x4028357e
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("addr2line", gdb.COMMAND_USER)
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
if not args:
|
||||
gdb.write(Addr2Line.__doc__ + "\n")
|
||||
return
|
||||
|
||||
addresses = []
|
||||
for arg in shlex.split(args):
|
||||
if is_decimal(arg):
|
||||
addresses.append(int(arg))
|
||||
elif is_hexadecimal(arg):
|
||||
addresses.append(int(arg, 16))
|
||||
else:
|
||||
try:
|
||||
var = gdb.parse_and_eval(f"{arg}")
|
||||
addresses.append(var)
|
||||
except gdb.error as e:
|
||||
gdb.write(f"Ignore {arg}: {e}\n")
|
||||
|
||||
backtraces = backtrace(addresses)
|
||||
formatter = "{:<20} {:<32} {}\n"
|
||||
gdb.write(formatter.format("Address", "Symbol", "Source"))
|
||||
for addr, func, source in backtraces:
|
||||
gdb.write(formatter.format(hex(addr), func, source))
|
||||
|
||||
|
||||
class Profile(gdb.Command):
|
||||
"""Profile a gdb command
|
||||
|
||||
Usage: profile <gdb command>
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.cProfile = import_check(
|
||||
"cProfile", errmsg="cProfile module not found, try gdb-multiarch.\n"
|
||||
)
|
||||
if not self.cProfile:
|
||||
return
|
||||
|
||||
super().__init__("profile", gdb.COMMAND_USER)
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
self.cProfile.run(f"gdb.execute('{args}')", sort="cumulative")
|
||||
@@ -0,0 +1,22 @@
|
||||
[build-system]
|
||||
requires = ["setuptools>=61", "wheel"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
version = "0.0.1"
|
||||
name = 'nuttxgdb'
|
||||
description = 'NuttX RTOS GDB extensions'
|
||||
readme = "README.md"
|
||||
license = { file = 'LICENSE' }
|
||||
classifiers = [
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: Apache Software License",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3",
|
||||
]
|
||||
|
||||
dependencies = ["matplotlib", "numpy", "pyelftools"]
|
||||
requires-python = ">=3.8"
|
||||
|
||||
[tool.setuptools.package-dir]
|
||||
nuttxgdb = "nuttxgdb"
|
||||
Reference in New Issue
Block a user