pynuttx 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pynuttx-0.0.1/PKG-INFO +25 -0
- pynuttx-0.0.1/gdbrpc/__init__.py +43 -0
- pynuttx-0.0.1/gdbrpc/__main__.py +43 -0
- pynuttx-0.0.1/gdbrpc/cli.py +65 -0
- pynuttx-0.0.1/gdbrpc/client.py +170 -0
- pynuttx-0.0.1/gdbrpc/examples/getheaps.py +54 -0
- pynuttx-0.0.1/gdbrpc/examples/memleak.py +67 -0
- pynuttx-0.0.1/gdbrpc/server.py +285 -0
- pynuttx-0.0.1/gdbrpc/tests/stresstest.py +168 -0
- pynuttx-0.0.1/gdbrpc/utils.py +168 -0
- pynuttx-0.0.1/nxelf/__init__.py +19 -0
- pynuttx-0.0.1/nxelf/elf.py +635 -0
- pynuttx-0.0.1/nxelf/macros.py +294 -0
- pynuttx-0.0.1/nxgdb/__init__.py +86 -0
- pynuttx-0.0.1/nxgdb/autocompeletion.py +165 -0
- pynuttx-0.0.1/nxgdb/backtrace.py +259 -0
- pynuttx-0.0.1/nxgdb/circbuf.py +200 -0
- pynuttx-0.0.1/nxgdb/critmon.py +162 -0
- pynuttx-0.0.1/nxgdb/debug.py +67 -0
- pynuttx-0.0.1/nxgdb/diagnose.py +131 -0
- pynuttx-0.0.1/nxgdb/dmesg.py +90 -0
- pynuttx-0.0.1/nxgdb/elf.py +99 -0
- pynuttx-0.0.1/nxgdb/fs/__init__.py +62 -0
- pynuttx-0.0.1/nxgdb/fs/command.py +491 -0
- pynuttx-0.0.1/nxgdb/fs/fatfs.py +47 -0
- pynuttx-0.0.1/nxgdb/fs/fs.py +115 -0
- pynuttx-0.0.1/nxgdb/fs/inode.py +238 -0
- pynuttx-0.0.1/nxgdb/fs/littlefs.py +41 -0
- pynuttx-0.0.1/nxgdb/fs/lrofs.py +68 -0
- pynuttx-0.0.1/nxgdb/fs/romfs.py +68 -0
- pynuttx-0.0.1/nxgdb/fs/utils.py +42 -0
- pynuttx-0.0.1/nxgdb/fs/yaffs.py +98 -0
- pynuttx-0.0.1/nxgdb/gcore.py +144 -0
- pynuttx-0.0.1/nxgdb/gdbrpc.py +181 -0
- pynuttx-0.0.1/nxgdb/irq.py +91 -0
- pynuttx-0.0.1/nxgdb/kasan.py +202 -0
- pynuttx-0.0.1/nxgdb/libuv.py +162 -0
- pynuttx-0.0.1/nxgdb/lists.py +453 -0
- pynuttx-0.0.1/nxgdb/memcheck.py +264 -0
- pynuttx-0.0.1/nxgdb/memclassifier/default.py +179 -0
- pynuttx-0.0.1/nxgdb/memclassifier/size.py +28 -0
- pynuttx-0.0.1/nxgdb/memclassifier/utils.py +41 -0
- pynuttx-0.0.1/nxgdb/memclassify.py +410 -0
- pynuttx-0.0.1/nxgdb/memdump.py +1098 -0
- pynuttx-0.0.1/nxgdb/memleak.py +296 -0
- pynuttx-0.0.1/nxgdb/mm.py +896 -0
- pynuttx-0.0.1/nxgdb/net.py +323 -0
- pynuttx-0.0.1/nxgdb/noteram.py +180 -0
- pynuttx-0.0.1/nxgdb/notesnap.py +119 -0
- pynuttx-0.0.1/nxgdb/nxcrash/busyloop.py +84 -0
- pynuttx-0.0.1/nxgdb/nxcrash/deadlock.py +95 -0
- pynuttx-0.0.1/nxgdb/nxcrash/stackoverflow.py +91 -0
- pynuttx-0.0.1/nxgdb/nxcrash/thread.py +108 -0
- pynuttx-0.0.1/nxgdb/pginfo.py +130 -0
- pynuttx-0.0.1/nxgdb/pm.py +114 -0
- pynuttx-0.0.1/nxgdb/prefix.py +58 -0
- pynuttx-0.0.1/nxgdb/profile.py +98 -0
- pynuttx-0.0.1/nxgdb/protocols/circbuf.py +35 -0
- pynuttx-0.0.1/nxgdb/protocols/fs.py +72 -0
- pynuttx-0.0.1/nxgdb/protocols/irq.py +35 -0
- pynuttx-0.0.1/nxgdb/protocols/mm.py +122 -0
- pynuttx-0.0.1/nxgdb/protocols/thread.py +141 -0
- pynuttx-0.0.1/nxgdb/protocols/uorb.py +103 -0
- pynuttx-0.0.1/nxgdb/protocols/value.py +67 -0
- pynuttx-0.0.1/nxgdb/protocols/wdog.py +35 -0
- pynuttx-0.0.1/nxgdb/protocols/wqueue.py +63 -0
- pynuttx-0.0.1/nxgdb/quickjs.py +99 -0
- pynuttx-0.0.1/nxgdb/rpmsg.py +325 -0
- pynuttx-0.0.1/nxgdb/rpmsgtrace2pcap.py +113 -0
- pynuttx-0.0.1/nxgdb/stack.py +260 -0
- pynuttx-0.0.1/nxgdb/target.py +124 -0
- pynuttx-0.0.1/nxgdb/thread.py +682 -0
- pynuttx-0.0.1/nxgdb/tlsdump.py +153 -0
- pynuttx-0.0.1/nxgdb/tricore.py +166 -0
- pynuttx-0.0.1/nxgdb/uname.py +148 -0
- pynuttx-0.0.1/nxgdb/uorb.py +174 -0
- pynuttx-0.0.1/nxgdb/utils.py +1344 -0
- pynuttx-0.0.1/nxgdb/wdog.py +78 -0
- pynuttx-0.0.1/nxgdb/wqueue.py +194 -0
- pynuttx-0.0.1/nxgdbmcp/__init__.py +22 -0
- pynuttx-0.0.1/nxgdbmcp/__main__.py +29 -0
- pynuttx-0.0.1/nxgdbmcp/gmcp/__init__.py +24 -0
- pynuttx-0.0.1/nxgdbmcp/gmcp/context.py +25 -0
- pynuttx-0.0.1/nxgdbmcp/gmcp/main.py +83 -0
- pynuttx-0.0.1/nxgdbmcp/gmcp/session/__init__.py +26 -0
- pynuttx-0.0.1/nxgdbmcp/gmcp/session/context.py +75 -0
- pynuttx-0.0.1/nxgdbmcp/gmcp/session/gdb_session.py +66 -0
- pynuttx-0.0.1/nxgdbmcp/gmcp/tools/__init__.py +38 -0
- pynuttx-0.0.1/nxgdbmcp/gmcp/tools/command.py +41 -0
- pynuttx-0.0.1/nxgdbmcp/gmcp/tools/controlflow.py +216 -0
- pynuttx-0.0.1/nxgdbmcp/gmcp/tools/memory.py +246 -0
- pynuttx-0.0.1/nxgdbmcp/gmcp/tools/session.py +280 -0
- pynuttx-0.0.1/nxgdbmcp/gmcp/tools/shell.py +60 -0
- pynuttx-0.0.1/nxgdbmcp/gmcp/tools/utils.py +66 -0
- pynuttx-0.0.1/nxgdbmcp/gmcp/tools/value.py +113 -0
- pynuttx-0.0.1/nxgdbmcp/gmcp/utils.py +53 -0
- pynuttx-0.0.1/nxreg/__init__.py +19 -0
- pynuttx-0.0.1/nxreg/register.py +573 -0
- pynuttx-0.0.1/nxstub/__init__.py +398 -0
- pynuttx-0.0.1/nxstub/__main__.py +24 -0
- pynuttx-0.0.1/nxstub/gdbstub.py +299 -0
- pynuttx-0.0.1/nxstub/proxy.py +165 -0
- pynuttx-0.0.1/nxstub/target.py +347 -0
- pynuttx-0.0.1/nxstub/utils.py +136 -0
- pynuttx-0.0.1/nxtrace/__init__.py +19 -0
- pynuttx-0.0.1/nxtrace/etmv4_decoder.py +1944 -0
- pynuttx-0.0.1/nxtrace/general_rtt.py +346 -0
- pynuttx-0.0.1/nxtrace/perfetto_trace.py +456 -0
- pynuttx-0.0.1/nxtrace/perfetto_trace_pb2.py +2556 -0
- pynuttx-0.0.1/nxtrace/rtt.py +144 -0
- pynuttx-0.0.1/nxtrace/trace.py +907 -0
- pynuttx-0.0.1/pynuttx.egg-info/PKG-INFO +25 -0
- pynuttx-0.0.1/pynuttx.egg-info/SOURCES.txt +126 -0
- pynuttx-0.0.1/pynuttx.egg-info/dependency_links.txt +1 -0
- pynuttx-0.0.1/pynuttx.egg-info/requires.txt +17 -0
- pynuttx-0.0.1/pynuttx.egg-info/top_level.txt +7 -0
- pynuttx-0.0.1/pyproject.toml +38 -0
- pynuttx-0.0.1/setup.cfg +4 -0
- pynuttx-0.0.1/tests/test_mock_stack.py +201 -0
- pynuttx-0.0.1/tests/test_mock_thread.py +101 -0
- pynuttx-0.0.1/tests/test_mock_utils.py +159 -0
- pynuttx-0.0.1/tests/test_runtime_dmesg.py +33 -0
- pynuttx-0.0.1/tests/test_runtime_fs.py +58 -0
- pynuttx-0.0.1/tests/test_runtime_memory.py +76 -0
- pynuttx-0.0.1/tests/test_runtime_net.py +51 -0
- pynuttx-0.0.1/tests/test_runtime_profile.py +63 -0
- pynuttx-0.0.1/tests/test_runtime_stack.py +42 -0
- pynuttx-0.0.1/tests/test_runtime_thread.py +102 -0
pynuttx-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pynuttx
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: python scirpt for NuttX
|
|
5
|
+
Classifier: Programming Language :: Python :: 3
|
|
6
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
7
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Requires-Dist: angr>=0.0.0
|
|
10
|
+
Requires-Dist: capstone>=0.0.0
|
|
11
|
+
Requires-Dist: cloudpickle>=0.0.0
|
|
12
|
+
Requires-Dist: construct>=0.0.0
|
|
13
|
+
Requires-Dist: debugpy>=0.0.0
|
|
14
|
+
Requires-Dist: lauterbach-trace32-rcl>=0.0.0
|
|
15
|
+
Requires-Dist: lief>=0.0.0
|
|
16
|
+
Requires-Dist: matplotlib>=0.0.0
|
|
17
|
+
Requires-Dist: mcp>=0.0.0
|
|
18
|
+
Requires-Dist: numpy>=0.0.0
|
|
19
|
+
Requires-Dist: pandas>=0.0.0
|
|
20
|
+
Requires-Dist: pillow>=0.0.0
|
|
21
|
+
Requires-Dist: plotly>=0.0.0
|
|
22
|
+
Requires-Dist: prettytable>=0.0.0
|
|
23
|
+
Requires-Dist: pyelftools>=0.0.0
|
|
24
|
+
Requires-Dist: pylink-square>=0.0.0
|
|
25
|
+
Requires-Dist: viztracer>=0.0.0
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
############################################################################
|
|
2
|
+
# tools/pynuttx/gdbrpc/__init__.py
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
#
|
|
6
|
+
# Licensed to the Apache Software Foundation (ASF) under one or more
|
|
7
|
+
# contributor license agreements. See the NOTICE file distributed with
|
|
8
|
+
# this work for additional information regarding copyright ownership. The
|
|
9
|
+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
10
|
+
# "License"); you may not use this file except in compliance with the
|
|
11
|
+
# License. You may obtain a copy of the License at
|
|
12
|
+
#
|
|
13
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
14
|
+
#
|
|
15
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
16
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
17
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
18
|
+
# License for the specific language governing permissions and limitations
|
|
19
|
+
# under the License.
|
|
20
|
+
#
|
|
21
|
+
############################################################################
|
|
22
|
+
|
|
23
|
+
import importlib.util
|
|
24
|
+
|
|
25
|
+
__all__ = [
|
|
26
|
+
"Client",
|
|
27
|
+
"ClientCLI",
|
|
28
|
+
"PostRequest",
|
|
29
|
+
"Request",
|
|
30
|
+
"Response",
|
|
31
|
+
"PacketStatus",
|
|
32
|
+
"Server",
|
|
33
|
+
"ShellExec",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
# Client must be imported first because ClientCLI depends on it
|
|
37
|
+
from .client import Client
|
|
38
|
+
from .utils import PacketStatus, PostRequest, Request, Response, ShellExec
|
|
39
|
+
|
|
40
|
+
if importlib.util.find_spec("gdb") is not None:
|
|
41
|
+
from .server import Server # noqa: F401
|
|
42
|
+
|
|
43
|
+
from .cli import ClientCLI
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
############################################################################
|
|
3
|
+
# tools/pynuttx/gdbrpc/__main__.py
|
|
4
|
+
#
|
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
6
|
+
#
|
|
7
|
+
# Licensed to the Apache Software Foundation (ASF) under one or more
|
|
8
|
+
# contributor license agreements. See the NOTICE file distributed with
|
|
9
|
+
# this work for additional information regarding copyright ownership. The
|
|
10
|
+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
11
|
+
# "License"); you may not use this file except in compliance with the
|
|
12
|
+
# License. You may obtain a copy of the License at
|
|
13
|
+
#
|
|
14
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
15
|
+
#
|
|
16
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
17
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
18
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
19
|
+
# License for the specific language governing permissions and limitations
|
|
20
|
+
# under the License.
|
|
21
|
+
#
|
|
22
|
+
############################################################################
|
|
23
|
+
|
|
24
|
+
import argparse
|
|
25
|
+
import os
|
|
26
|
+
import sys
|
|
27
|
+
|
|
28
|
+
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
29
|
+
parent_dir = os.path.dirname(current_dir)
|
|
30
|
+
if parent_dir not in sys.path:
|
|
31
|
+
sys.path.insert(0, parent_dir)
|
|
32
|
+
|
|
33
|
+
if __name__ == "__main__":
|
|
34
|
+
import gdbrpc
|
|
35
|
+
|
|
36
|
+
parser = argparse.ArgumentParser(description="GDB Socket Client")
|
|
37
|
+
parser.add_argument("--host", default="localhost", help="Server host")
|
|
38
|
+
parser.add_argument("--port", type=int, default=20819, help="Server port")
|
|
39
|
+
|
|
40
|
+
args = parser.parse_args()
|
|
41
|
+
|
|
42
|
+
client = gdbrpc.ClientCLI(args.host, args.port)
|
|
43
|
+
client.start()
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
############################################################################
|
|
2
|
+
# tools/pynuttx/gdbrpc/cli.py
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
#
|
|
6
|
+
# Licensed to the Apache Software Foundation (ASF) under one or more
|
|
7
|
+
# contributor license agreements. See the NOTICE file distributed with
|
|
8
|
+
# this work for additional information regarding copyright ownership. The
|
|
9
|
+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
10
|
+
# "License"); you may not use this file except in compliance with the
|
|
11
|
+
# License. You may obtain a copy of the License at
|
|
12
|
+
#
|
|
13
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
14
|
+
#
|
|
15
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
16
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
17
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
18
|
+
# License for the specific language governing permissions and limitations
|
|
19
|
+
# under the License.
|
|
20
|
+
#
|
|
21
|
+
############################################################################
|
|
22
|
+
|
|
23
|
+
import logging
|
|
24
|
+
|
|
25
|
+
from gdbrpc.client import Client
|
|
26
|
+
from gdbrpc.utils import ShellExec
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class ClientCLI(Client):
|
|
30
|
+
def __init__(self, host, port):
|
|
31
|
+
super().__init__(host, port, logLevel=logging.WARNING)
|
|
32
|
+
|
|
33
|
+
def _show_command_help(self):
|
|
34
|
+
print("Welcome to the GDB Remote Protocol Client")
|
|
35
|
+
print("Type `exit` or `quit` to disconnect.")
|
|
36
|
+
print("Type `help` to show this help message.")
|
|
37
|
+
print("If you need `interrupt` command to stop the target, use Ctrl+C.")
|
|
38
|
+
|
|
39
|
+
def _loop(self):
|
|
40
|
+
print("gdb> ", end="", flush=True)
|
|
41
|
+
while True:
|
|
42
|
+
try:
|
|
43
|
+
command = input().strip()
|
|
44
|
+
if not command:
|
|
45
|
+
continue
|
|
46
|
+
if command.lower() in ("exit", "quit"):
|
|
47
|
+
self.disconnect()
|
|
48
|
+
break
|
|
49
|
+
if command.lower() == "help":
|
|
50
|
+
self._show_command_help()
|
|
51
|
+
print("gdb> ", end="", flush=True)
|
|
52
|
+
continue
|
|
53
|
+
print(self.call(ShellExec(command)))
|
|
54
|
+
print("gdb> ", end="", flush=True)
|
|
55
|
+
except KeyboardInterrupt:
|
|
56
|
+
print("")
|
|
57
|
+
self.call(ShellExec("interrupt"))
|
|
58
|
+
print("gdb> ", end="", flush=True)
|
|
59
|
+
except EOFError:
|
|
60
|
+
self.disconnect()
|
|
61
|
+
|
|
62
|
+
def start(self):
|
|
63
|
+
assert self.connect()
|
|
64
|
+
self._show_command_help()
|
|
65
|
+
self._loop()
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
############################################################################
|
|
2
|
+
# tools/pynuttx/gdbrpc/client.py
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
#
|
|
6
|
+
# Licensed to the Apache Software Foundation (ASF) under one or more
|
|
7
|
+
# contributor license agreements. See the NOTICE file distributed with
|
|
8
|
+
# this work for additional information regarding copyright ownership. The
|
|
9
|
+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
10
|
+
# "License"); you may not use this file except in compliance with the
|
|
11
|
+
# License. You may obtain a copy of the License at
|
|
12
|
+
#
|
|
13
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
14
|
+
#
|
|
15
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
16
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
17
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
18
|
+
# License for the specific language governing permissions and limitations
|
|
19
|
+
# under the License.
|
|
20
|
+
#
|
|
21
|
+
############################################################################
|
|
22
|
+
|
|
23
|
+
import logging
|
|
24
|
+
import os
|
|
25
|
+
import queue
|
|
26
|
+
import socket
|
|
27
|
+
import sys
|
|
28
|
+
import threading
|
|
29
|
+
from datetime import datetime
|
|
30
|
+
from typing import Dict, Optional, Tuple
|
|
31
|
+
|
|
32
|
+
import cloudpickle as pickle
|
|
33
|
+
from gdbrpc.utils import (
|
|
34
|
+
DEFAULT_TIMEOUT,
|
|
35
|
+
PacketStatus,
|
|
36
|
+
PostRequest,
|
|
37
|
+
Request,
|
|
38
|
+
Response,
|
|
39
|
+
socket_recv,
|
|
40
|
+
socket_send,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class Client:
|
|
45
|
+
def __init__(self, host="localhost", port=20819, logLevel=logging.INFO):
|
|
46
|
+
self._host = host
|
|
47
|
+
self._port = port
|
|
48
|
+
self._socket: socket.socket
|
|
49
|
+
self._connected = False
|
|
50
|
+
self._response = queue.Queue()
|
|
51
|
+
self._pending_requests: Dict[int, PostRequest] = {}
|
|
52
|
+
|
|
53
|
+
self._logger = logging.getLogger(__name__)
|
|
54
|
+
if not self._logger.hasHandlers():
|
|
55
|
+
self._logger.setLevel(logLevel)
|
|
56
|
+
timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
|
|
57
|
+
pid = os.getpid()
|
|
58
|
+
handler = logging.FileHandler(f"gdbrpc_client-{timestamp}-pid{pid}.log")
|
|
59
|
+
formatter = logging.Formatter("%(asctime)s gdbrpc_client: %(message)s")
|
|
60
|
+
handler.setFormatter(formatter)
|
|
61
|
+
self._logger.addHandler(handler)
|
|
62
|
+
|
|
63
|
+
def connect(self):
|
|
64
|
+
try:
|
|
65
|
+
self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
66
|
+
self._socket.connect((self._host, self._port))
|
|
67
|
+
self._connected = True
|
|
68
|
+
logging.info(f"Connected to GDB server at {self._host}:{self._port}")
|
|
69
|
+
|
|
70
|
+
threading.Thread(
|
|
71
|
+
target=self._listen_responses, daemon=True, args=(self._socket,)
|
|
72
|
+
).start()
|
|
73
|
+
|
|
74
|
+
return True
|
|
75
|
+
except Exception as e:
|
|
76
|
+
logging.error(f"Failed to connect {self._host}:{self._port}: {e}")
|
|
77
|
+
return False
|
|
78
|
+
|
|
79
|
+
def _listen_responses(self, socket: socket.socket):
|
|
80
|
+
try:
|
|
81
|
+
while self._connected:
|
|
82
|
+
data: Tuple[Response, PacketStatus] = pickle.loads(
|
|
83
|
+
socket_recv(socket, self._logger)
|
|
84
|
+
)
|
|
85
|
+
response, status = data
|
|
86
|
+
self._logger.debug(
|
|
87
|
+
f"Received response for request ID {response.tag}, current queue: {self._pending_requests}"
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
if status == PacketStatus.PYTHON_VERSION_MISMATCH:
|
|
91
|
+
response.payload += f"\nclient python version: {sys.version}"
|
|
92
|
+
self._response.put(response.payload)
|
|
93
|
+
elif (
|
|
94
|
+
status == PacketStatus.HAS_CALLBACK
|
|
95
|
+
and response.tag in self._pending_requests
|
|
96
|
+
):
|
|
97
|
+
self._logger.debug(f"Handling callback for request ID {status}")
|
|
98
|
+
callback = self._pending_requests.get(response.tag)
|
|
99
|
+
|
|
100
|
+
assert isinstance(callback, PostRequest)
|
|
101
|
+
|
|
102
|
+
try:
|
|
103
|
+
callback(response.payload)
|
|
104
|
+
except Exception as e:
|
|
105
|
+
self._logger.error(
|
|
106
|
+
f"Error in callback {callback}, which raised an exception: {e}"
|
|
107
|
+
)
|
|
108
|
+
finally:
|
|
109
|
+
callback.finish.set()
|
|
110
|
+
else:
|
|
111
|
+
self._response.put(response)
|
|
112
|
+
self._logger.debug(
|
|
113
|
+
f"Response for request ID {response.tag} put into response queue"
|
|
114
|
+
)
|
|
115
|
+
self._logger.info(
|
|
116
|
+
f"Received data: {response.payload}. from {self._host}:{self._port}"
|
|
117
|
+
)
|
|
118
|
+
except ConnectionError:
|
|
119
|
+
self._logger.info("Connection closed by server")
|
|
120
|
+
self.disconnect()
|
|
121
|
+
except Exception as e:
|
|
122
|
+
self._logger.error(f"Error receiving data: {e}")
|
|
123
|
+
self.disconnect()
|
|
124
|
+
|
|
125
|
+
def disconnect(self):
|
|
126
|
+
self._connected = False
|
|
127
|
+
self._logger.info("Disconnecting...")
|
|
128
|
+
if self._socket:
|
|
129
|
+
try:
|
|
130
|
+
self._socket.close()
|
|
131
|
+
self._logger.info("Socket closed successfully.")
|
|
132
|
+
except Exception as e:
|
|
133
|
+
self._logger.error(f"Error closing socket: {e}")
|
|
134
|
+
self._logger.info("Disconnected")
|
|
135
|
+
|
|
136
|
+
def no_pending_requests(self) -> bool:
|
|
137
|
+
return len(self._pending_requests) == 0
|
|
138
|
+
|
|
139
|
+
def call(
|
|
140
|
+
self,
|
|
141
|
+
request: Request,
|
|
142
|
+
post_request: Optional[PostRequest] = None,
|
|
143
|
+
timeout: float = DEFAULT_TIMEOUT,
|
|
144
|
+
):
|
|
145
|
+
if not self._connected:
|
|
146
|
+
raise ConnectionError("Not connected to server")
|
|
147
|
+
if not isinstance(request, Request):
|
|
148
|
+
raise TypeError("request must be a Request instance")
|
|
149
|
+
if post_request is not None and not isinstance(post_request, PostRequest):
|
|
150
|
+
raise TypeError("post_request must be a PostRequest instance or None")
|
|
151
|
+
|
|
152
|
+
if post_request is not None:
|
|
153
|
+
self._logger.debug(f"Registering callback for request ID {request.tag}")
|
|
154
|
+
self._pending_requests[request.tag] = post_request
|
|
155
|
+
payload = (request, PacketStatus.HAS_CALLBACK)
|
|
156
|
+
else:
|
|
157
|
+
self._logger.debug(f"No callback for request ID {request.tag}")
|
|
158
|
+
payload = (request, PacketStatus.NO_CALLBACK)
|
|
159
|
+
|
|
160
|
+
self._logger.debug(f"Sending request: {request} to {self._host}:{self._port}")
|
|
161
|
+
|
|
162
|
+
socket_send(self._socket, pickle.dumps(payload), self._logger)
|
|
163
|
+
|
|
164
|
+
try:
|
|
165
|
+
rs = self._response.get(timeout=timeout)
|
|
166
|
+
except queue.Empty:
|
|
167
|
+
self._logger.error("Request timed out")
|
|
168
|
+
raise TimeoutError("Request timed out")
|
|
169
|
+
|
|
170
|
+
return rs.payload
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
############################################################################
|
|
3
|
+
# tools/pynuttx/gdbrpc/examples/getheaps.py
|
|
4
|
+
#
|
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
6
|
+
#
|
|
7
|
+
# Licensed to the Apache Software Foundation (ASF) under one or more
|
|
8
|
+
# contributor license agreements. See the NOTICE file distributed with
|
|
9
|
+
# this work for additional information regarding copyright ownership. The
|
|
10
|
+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
11
|
+
# "License"); you may not use this file except in compliance with the
|
|
12
|
+
# License. You may obtain a copy of the License at
|
|
13
|
+
#
|
|
14
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
15
|
+
#
|
|
16
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
17
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
18
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
19
|
+
# License for the specific language governing permissions and limitations
|
|
20
|
+
# under the License.
|
|
21
|
+
#
|
|
22
|
+
############################################################################
|
|
23
|
+
|
|
24
|
+
import os
|
|
25
|
+
import queue
|
|
26
|
+
import sys
|
|
27
|
+
|
|
28
|
+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../..")))
|
|
29
|
+
|
|
30
|
+
import gdbrpc # noqa: E402
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class Func(gdbrpc.Request):
|
|
34
|
+
def __init__(self):
|
|
35
|
+
super().__init__()
|
|
36
|
+
|
|
37
|
+
def __call__(self, q: queue.Queue):
|
|
38
|
+
import nxgdb
|
|
39
|
+
|
|
40
|
+
heaps = nxgdb.mm.get_heaps()
|
|
41
|
+
for heap in heaps:
|
|
42
|
+
print(heap)
|
|
43
|
+
q.put(list(map(str, heaps)))
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
if __name__ == "__main__":
|
|
47
|
+
|
|
48
|
+
client = gdbrpc.Client()
|
|
49
|
+
|
|
50
|
+
assert client.connect()
|
|
51
|
+
|
|
52
|
+
print(client.call(Func(), timeout=10))
|
|
53
|
+
|
|
54
|
+
client.disconnect()
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
############################################################################
|
|
3
|
+
# tools/pynuttx/gdbrpc/examples/memleak.py
|
|
4
|
+
#
|
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
6
|
+
#
|
|
7
|
+
# Licensed to the Apache Software Foundation (ASF) under one or more
|
|
8
|
+
# contributor license agreements. See the NOTICE file distributed with
|
|
9
|
+
# this work for additional information regarding copyright ownership. The
|
|
10
|
+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
11
|
+
# "License"); you may not use this file except in compliance with the
|
|
12
|
+
# License. You may obtain a copy of the License at
|
|
13
|
+
#
|
|
14
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
15
|
+
#
|
|
16
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
17
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
18
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
19
|
+
# License for the specific language governing permissions and limitations
|
|
20
|
+
# under the License.
|
|
21
|
+
#
|
|
22
|
+
############################################################################
|
|
23
|
+
|
|
24
|
+
import logging
|
|
25
|
+
import os
|
|
26
|
+
import queue
|
|
27
|
+
import sys
|
|
28
|
+
|
|
29
|
+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../..")))
|
|
30
|
+
|
|
31
|
+
import gdbrpc # noqa: E402
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class FetchResult(gdbrpc.PostRequest):
|
|
35
|
+
def __init__(self):
|
|
36
|
+
super().__init__()
|
|
37
|
+
|
|
38
|
+
def __call__(self, result):
|
|
39
|
+
print(result)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class MemLeak(gdbrpc.Request):
|
|
43
|
+
def __init__(self):
|
|
44
|
+
super().__init__()
|
|
45
|
+
|
|
46
|
+
def __call__(self, q: queue.Queue):
|
|
47
|
+
import gdb
|
|
48
|
+
|
|
49
|
+
q.put(gdb.execute("memleak", to_string=True))
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
if __name__ == "__main__":
|
|
53
|
+
|
|
54
|
+
client = gdbrpc.Client(logLevel=logging.DEBUG)
|
|
55
|
+
|
|
56
|
+
assert client.connect()
|
|
57
|
+
|
|
58
|
+
bt = FetchResult()
|
|
59
|
+
client.call(MemLeak(), bt)
|
|
60
|
+
|
|
61
|
+
print("Waiting for async call to complete...")
|
|
62
|
+
|
|
63
|
+
bt.finish.wait()
|
|
64
|
+
|
|
65
|
+
print("Async call completed.")
|
|
66
|
+
|
|
67
|
+
client.disconnect()
|