@embedder/embedder 1.1.1 → 2.0.6
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.
- package/assets/_commonjsHelpers-C1uRMj_j.js +1 -0
- package/assets/cli-Ccqv_iE9.js +865 -0
- package/assets/devtools-B4JKPJyU.js +1 -0
- package/assets/index-B3hJUcJE.js +1 -0
- package/assets/index-BSFXqd02.js +1 -0
- package/assets/index-DjlgDVzW.js +1 -0
- package/cli.js +2 -0
- package/package.json +15 -96
- package/LICENSE +0 -36
- package/bundle/embedder.js +0 -618
- package/bundle/gdb-debugger-python/gdb_bridge.py +0 -392
- package/bundle/gdb-debugger-python/requirements.txt +0 -1
- package/bundle/postinstall-for-users.js +0 -515
- package/bundle/repomap-bridge.js +0 -6
- package/bundle/repomap-python/importance.py +0 -58
- package/bundle/repomap-python/queries/tree-sitter-language-pack/README.md +0 -9
- package/bundle/repomap-python/queries/tree-sitter-language-pack/arduino-tags.scm +0 -5
- package/bundle/repomap-python/queries/tree-sitter-language-pack/c-tags.scm +0 -9
- package/bundle/repomap-python/queries/tree-sitter-language-pack/chatito-tags.scm +0 -16
- package/bundle/repomap-python/queries/tree-sitter-language-pack/commonlisp-tags.scm +0 -122
- package/bundle/repomap-python/queries/tree-sitter-language-pack/cpp-tags.scm +0 -15
- package/bundle/repomap-python/queries/tree-sitter-language-pack/csharp-tags.scm +0 -26
- package/bundle/repomap-python/queries/tree-sitter-language-pack/d-tags.scm +0 -26
- package/bundle/repomap-python/queries/tree-sitter-language-pack/dart-tags.scm +0 -92
- package/bundle/repomap-python/queries/tree-sitter-language-pack/elisp-tags.scm +0 -5
- package/bundle/repomap-python/queries/tree-sitter-language-pack/elixir-tags.scm +0 -54
- package/bundle/repomap-python/queries/tree-sitter-language-pack/elm-tags.scm +0 -19
- package/bundle/repomap-python/queries/tree-sitter-language-pack/gleam-tags.scm +0 -41
- package/bundle/repomap-python/queries/tree-sitter-language-pack/go-tags.scm +0 -42
- package/bundle/repomap-python/queries/tree-sitter-language-pack/java-tags.scm +0 -20
- package/bundle/repomap-python/queries/tree-sitter-language-pack/javascript-tags.scm +0 -88
- package/bundle/repomap-python/queries/tree-sitter-language-pack/lua-tags.scm +0 -34
- package/bundle/repomap-python/queries/tree-sitter-language-pack/ocaml-tags.scm +0 -115
- package/bundle/repomap-python/queries/tree-sitter-language-pack/ocaml_interface-tags.scm +0 -98
- package/bundle/repomap-python/queries/tree-sitter-language-pack/pony-tags.scm +0 -39
- package/bundle/repomap-python/queries/tree-sitter-language-pack/properties-tags.scm +0 -5
- package/bundle/repomap-python/queries/tree-sitter-language-pack/python-tags.scm +0 -14
- package/bundle/repomap-python/queries/tree-sitter-language-pack/r-tags.scm +0 -21
- package/bundle/repomap-python/queries/tree-sitter-language-pack/racket-tags.scm +0 -12
- package/bundle/repomap-python/queries/tree-sitter-language-pack/ruby-tags.scm +0 -64
- package/bundle/repomap-python/queries/tree-sitter-language-pack/rust-tags.scm +0 -60
- package/bundle/repomap-python/queries/tree-sitter-language-pack/solidity-tags.scm +0 -43
- package/bundle/repomap-python/queries/tree-sitter-language-pack/swift-tags.scm +0 -51
- package/bundle/repomap-python/queries/tree-sitter-language-pack/udev-tags.scm +0 -20
- package/bundle/repomap-python/queries/tree-sitter-languages/README.md +0 -24
- package/bundle/repomap-python/queries/tree-sitter-languages/c-tags.scm +0 -9
- package/bundle/repomap-python/queries/tree-sitter-languages/c_sharp-tags.scm +0 -46
- package/bundle/repomap-python/queries/tree-sitter-languages/cpp-tags.scm +0 -15
- package/bundle/repomap-python/queries/tree-sitter-languages/dart-tags.scm +0 -91
- package/bundle/repomap-python/queries/tree-sitter-languages/elisp-tags.scm +0 -8
- package/bundle/repomap-python/queries/tree-sitter-languages/elixir-tags.scm +0 -54
- package/bundle/repomap-python/queries/tree-sitter-languages/elm-tags.scm +0 -19
- package/bundle/repomap-python/queries/tree-sitter-languages/go-tags.scm +0 -30
- package/bundle/repomap-python/queries/tree-sitter-languages/hcl-tags.scm +0 -77
- package/bundle/repomap-python/queries/tree-sitter-languages/java-tags.scm +0 -20
- package/bundle/repomap-python/queries/tree-sitter-languages/javascript-tags.scm +0 -88
- package/bundle/repomap-python/queries/tree-sitter-languages/kotlin-tags.scm +0 -27
- package/bundle/repomap-python/queries/tree-sitter-languages/ocaml-tags.scm +0 -115
- package/bundle/repomap-python/queries/tree-sitter-languages/ocaml_interface-tags.scm +0 -98
- package/bundle/repomap-python/queries/tree-sitter-languages/php-tags.scm +0 -26
- package/bundle/repomap-python/queries/tree-sitter-languages/python-tags.scm +0 -12
- package/bundle/repomap-python/queries/tree-sitter-languages/ql-tags.scm +0 -26
- package/bundle/repomap-python/queries/tree-sitter-languages/ruby-tags.scm +0 -64
- package/bundle/repomap-python/queries/tree-sitter-languages/rust-tags.scm +0 -60
- package/bundle/repomap-python/queries/tree-sitter-languages/scala-tags.scm +0 -65
- package/bundle/repomap-python/queries/tree-sitter-languages/typescript-tags.scm +0 -41
- package/bundle/repomap-python/repomap.py +0 -229
- package/bundle/repomap-python/repomap_bridge.py +0 -234
- package/bundle/repomap-python/repomap_class.py +0 -637
- package/bundle/repomap-python/repomap_server.py +0 -561
- package/bundle/repomap-python/requirements.txt +0 -7
- package/bundle/repomap-python/scm.py +0 -59
- package/bundle/repomap-python/utils.py +0 -58
- package/bundle/sandbox-macos-permissive-closed.sb +0 -26
- package/bundle/sandbox-macos-permissive-open.sb +0 -19
- package/bundle/sandbox-macos-permissive-proxied.sb +0 -31
- package/bundle/sandbox-macos-restrictive-closed.sb +0 -87
- package/bundle/sandbox-macos-restrictive-open.sb +0 -90
- package/bundle/sandbox-macos-restrictive-proxied.sb +0 -92
- package/postinstall.js +0 -42
|
@@ -1,392 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Enhanced GDB Bridge for Embedder CLI Debugger with Embedded System Support
|
|
4
|
-
Supports both local debugging and remote debugging for embedded targets.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import argparse
|
|
8
|
-
import json
|
|
9
|
-
import sys
|
|
10
|
-
import os
|
|
11
|
-
import signal
|
|
12
|
-
import threading
|
|
13
|
-
import time
|
|
14
|
-
from typing import Dict, Any, Optional
|
|
15
|
-
import pygdbmi
|
|
16
|
-
from pygdbmi.gdbcontroller import GdbController
|
|
17
|
-
|
|
18
|
-
class EmbeddedGDBBridge:
|
|
19
|
-
def __init__(self, executable: str, working_dir: Optional[str] = None,
|
|
20
|
-
remote_mode: bool = False, host: str = 'localhost',
|
|
21
|
-
port: int = 3333, gdb_command: str = 'gdb'):
|
|
22
|
-
self.executable = executable
|
|
23
|
-
self.working_dir = working_dir
|
|
24
|
-
self.remote_mode = remote_mode
|
|
25
|
-
self.host = host
|
|
26
|
-
self.port = port
|
|
27
|
-
self.gdb_command = gdb_command
|
|
28
|
-
self.gdb_controller: Optional[GdbController] = None
|
|
29
|
-
self.running = True
|
|
30
|
-
self.log_file_path = os.path.join(os.getcwd(), 'log.txt')
|
|
31
|
-
|
|
32
|
-
# Initialize stderr logging
|
|
33
|
-
self._init_stderr_logging()
|
|
34
|
-
|
|
35
|
-
def _init_stderr_logging(self):
|
|
36
|
-
"""Initialize stderr logging to log.txt file"""
|
|
37
|
-
try:
|
|
38
|
-
log_header = f"\n[{time.strftime('%Y-%m-%dT%H:%M:%S')}] Python GDB Bridge Starting\n"
|
|
39
|
-
with open(self.log_file_path, 'a') as log_file:
|
|
40
|
-
log_file.write(log_header)
|
|
41
|
-
except Exception as e:
|
|
42
|
-
print(f"[WARNING] Failed to initialize stderr log file: {e}", file=sys.stderr)
|
|
43
|
-
|
|
44
|
-
def _log_to_file(self, message: str, level: str = "INFO"):
|
|
45
|
-
"""Log a message to the stderr log file"""
|
|
46
|
-
try:
|
|
47
|
-
timestamp = time.strftime('%Y-%m-%dT%H:%M:%S')
|
|
48
|
-
log_entry = f"[{timestamp}] [Python Bridge {level}] {message}\n"
|
|
49
|
-
with open(self.log_file_path, 'a') as log_file:
|
|
50
|
-
log_file.write(log_entry)
|
|
51
|
-
except Exception as e:
|
|
52
|
-
print(f"[WARNING] Failed to write to log file: {e}", file=sys.stderr)
|
|
53
|
-
|
|
54
|
-
def initialize(self):
|
|
55
|
-
"""Initialize GDB controller and set up debugging session"""
|
|
56
|
-
try:
|
|
57
|
-
self._log_to_file("Starting GDB bridge initialization")
|
|
58
|
-
|
|
59
|
-
# Create GDB controller with appropriate command
|
|
60
|
-
gdb_path = self.gdb_command.split()[0] if ' ' in self.gdb_command else self.gdb_command
|
|
61
|
-
|
|
62
|
-
# Debug: Print what we're trying to execute
|
|
63
|
-
debug_msg = f"gdb_command: '{self.gdb_command}' (type: {type(self.gdb_command)}, len: {len(self.gdb_command)})"
|
|
64
|
-
print(f"[DEBUG] {debug_msg}", file=sys.stderr, flush=True)
|
|
65
|
-
self._log_to_file(debug_msg, "DEBUG")
|
|
66
|
-
|
|
67
|
-
debug_msg = f"gdb_path: '{gdb_path}' (type: {type(gdb_path)}, len: {len(gdb_path)})"
|
|
68
|
-
print(f"[DEBUG] {debug_msg}", file=sys.stderr, flush=True)
|
|
69
|
-
self._log_to_file(debug_msg, "DEBUG")
|
|
70
|
-
|
|
71
|
-
# Try different ways to pass the command to handle potential compatibility issues
|
|
72
|
-
try:
|
|
73
|
-
# Always request an MI interpreter if the caller forgot; pygdbmi
|
|
74
|
-
# expects structured output. We detect a missing flag crudely
|
|
75
|
-
# and append '--interpreter=mi2'.
|
|
76
|
-
cmd_parts = gdb_path.split()
|
|
77
|
-
if '--interpreter' not in ' '.join(cmd_parts):
|
|
78
|
-
cmd_parts += ['--interpreter=mi2']
|
|
79
|
-
|
|
80
|
-
debug_msg = f"Attempting to create GdbController with command={cmd_parts}"
|
|
81
|
-
print(f"[DEBUG] {debug_msg}", file=sys.stderr, flush=True)
|
|
82
|
-
self._log_to_file(debug_msg, "DEBUG")
|
|
83
|
-
# Give GDB a more generous timeout for large ELF symbol tables
|
|
84
|
-
self.gdb_controller = GdbController(command=cmd_parts)
|
|
85
|
-
except Exception as e1:
|
|
86
|
-
error_msg = f"Failed with command='{gdb_path}': {e1}"
|
|
87
|
-
print(f"[DEBUG] {error_msg}", file=sys.stderr, flush=True)
|
|
88
|
-
self._log_to_file(error_msg, "ERROR")
|
|
89
|
-
try:
|
|
90
|
-
cmd_parts = gdb_path.split()
|
|
91
|
-
if '--interpreter' not in ' '.join(cmd_parts):
|
|
92
|
-
cmd_parts += ['--interpreter=mi2']
|
|
93
|
-
|
|
94
|
-
debug_msg = f"Attempting to create GdbController with command={cmd_parts}"
|
|
95
|
-
print(f"[DEBUG] {debug_msg}", file=sys.stderr, flush=True)
|
|
96
|
-
self._log_to_file(debug_msg, "DEBUG")
|
|
97
|
-
self.gdb_controller = GdbController(command=cmd_parts)
|
|
98
|
-
except Exception as e2:
|
|
99
|
-
error_msg = f"Failed with command=['{gdb_path}']: {e2}"
|
|
100
|
-
print(f"[DEBUG] {error_msg}", file=sys.stderr, flush=True)
|
|
101
|
-
self._log_to_file(error_msg, "ERROR")
|
|
102
|
-
try:
|
|
103
|
-
debug_msg = "Attempting to create GdbController with default constructor"
|
|
104
|
-
print(f"[DEBUG] {debug_msg}", file=sys.stderr, flush=True)
|
|
105
|
-
self._log_to_file(debug_msg, "DEBUG")
|
|
106
|
-
self.gdb_controller = GdbController()
|
|
107
|
-
except Exception as e3:
|
|
108
|
-
error_msg = f"Failed with default constructor: {e3}"
|
|
109
|
-
print(f"[DEBUG] {error_msg}", file=sys.stderr, flush=True)
|
|
110
|
-
self._log_to_file(error_msg, "ERROR")
|
|
111
|
-
|
|
112
|
-
# Provide helpful error message for embedded debugging
|
|
113
|
-
error_msg = f"Failed to initialize GDB with command '{gdb_path}'. "
|
|
114
|
-
if gdb_path == 'gdb':
|
|
115
|
-
error_msg += "For embedded debugging, you may need to:\n"
|
|
116
|
-
error_msg += "1. Create an EMBEDDER.md file in your project root with embedded debugging configuration\n"
|
|
117
|
-
error_msg += "2. Install GDB for your target architecture (e.g., arm-none-eabi-gdb)\n"
|
|
118
|
-
error_msg += "3. Ensure the GDB executable is in your PATH"
|
|
119
|
-
|
|
120
|
-
self._log_to_file(error_msg, "ERROR")
|
|
121
|
-
raise Exception(error_msg)
|
|
122
|
-
|
|
123
|
-
self._log_to_file("✅ GDB controller created successfully")
|
|
124
|
-
print(f"[DEBUG] ✅ GDB controller created successfully", file=sys.stderr, flush=True)
|
|
125
|
-
|
|
126
|
-
# Check if executable file exists before loading
|
|
127
|
-
if not os.path.exists(self.executable):
|
|
128
|
-
error_msg = f"Executable file not found: {self.executable}"
|
|
129
|
-
self._log_to_file(error_msg, "ERROR")
|
|
130
|
-
print(f"[ERROR] {error_msg}", file=sys.stderr, flush=True)
|
|
131
|
-
raise Exception(error_msg)
|
|
132
|
-
|
|
133
|
-
# Get file size for logging
|
|
134
|
-
file_size = os.path.getsize(self.executable)
|
|
135
|
-
self._log_to_file(f"Executable file exists, size: {file_size} bytes")
|
|
136
|
-
print(f"[DEBUG] Executable file exists, size: {file_size} bytes", file=sys.stderr, flush=True)
|
|
137
|
-
|
|
138
|
-
# Load executable with enhanced error handling
|
|
139
|
-
try:
|
|
140
|
-
self._log_to_file(f"Loading executable: {self.executable}")
|
|
141
|
-
print(f"[DEBUG] Loading executable: {self.executable}", file=sys.stderr, flush=True)
|
|
142
|
-
|
|
143
|
-
load_cmd = f'-file-exec-and-symbols {self.executable}'
|
|
144
|
-
self._log_to_file(f"Executing GDB command: {load_cmd}")
|
|
145
|
-
print(f"[DEBUG] Executing GDB command: {load_cmd}", file=sys.stderr, flush=True)
|
|
146
|
-
|
|
147
|
-
response = self.gdb_controller.write(load_cmd, timeout_sec=30) # Increased timeout
|
|
148
|
-
self._log_to_file(f"✅ Executable load response received, length: {len(response) if response else 0}")
|
|
149
|
-
print(f"[DEBUG] ✅ Executable load response received", file=sys.stderr, flush=True)
|
|
150
|
-
|
|
151
|
-
self._send_response('gdb_response', response)
|
|
152
|
-
|
|
153
|
-
# Check if load was successful
|
|
154
|
-
if response and isinstance(response, list):
|
|
155
|
-
error_responses = [r for r in response if r.get('message') == 'error']
|
|
156
|
-
if error_responses:
|
|
157
|
-
error_msg = f"Failed to load executable: {error_responses}"
|
|
158
|
-
self._log_to_file(error_msg, "ERROR")
|
|
159
|
-
print(f"[ERROR] {error_msg}", file=sys.stderr, flush=True)
|
|
160
|
-
raise Exception(error_msg)
|
|
161
|
-
|
|
162
|
-
except Exception as e:
|
|
163
|
-
error_msg = f"Failed to load executable: {str(e)}"
|
|
164
|
-
self._log_to_file(error_msg, "ERROR")
|
|
165
|
-
print(f"[ERROR] {error_msg}", file=sys.stderr, flush=True)
|
|
166
|
-
raise Exception(error_msg)
|
|
167
|
-
|
|
168
|
-
if self.remote_mode:
|
|
169
|
-
try:
|
|
170
|
-
# Connect to remote target (embedded system)
|
|
171
|
-
target_cmd = f'-target-select remote {self.host}:{self.port}'
|
|
172
|
-
self._log_to_file(f"Connecting to remote target: {target_cmd}")
|
|
173
|
-
print(f"[DEBUG] Connecting to remote target: {target_cmd}", file=sys.stderr, flush=True)
|
|
174
|
-
|
|
175
|
-
response = self.gdb_controller.write(target_cmd, timeout_sec=15)
|
|
176
|
-
self._log_to_file(f"✅ Remote target connection response received")
|
|
177
|
-
print(f"[DEBUG] ✅ Remote target connection response received", file=sys.stderr, flush=True)
|
|
178
|
-
|
|
179
|
-
self._send_response('gdb_response', response)
|
|
180
|
-
|
|
181
|
-
# Check if connection was successful
|
|
182
|
-
if response and isinstance(response, list):
|
|
183
|
-
error_responses = [r for r in response if r.get('message') == 'error']
|
|
184
|
-
if error_responses:
|
|
185
|
-
error_msg = f"Failed to connect to remote target: {error_responses}"
|
|
186
|
-
self._log_to_file(error_msg, "ERROR")
|
|
187
|
-
print(f"[ERROR] {error_msg}", file=sys.stderr, flush=True)
|
|
188
|
-
raise Exception(error_msg)
|
|
189
|
-
|
|
190
|
-
# Program is no longer loaded automatically. This will be handled by the client.
|
|
191
|
-
|
|
192
|
-
# Send remote connection event
|
|
193
|
-
self._send_event('remote_connected', {
|
|
194
|
-
'host': self.host,
|
|
195
|
-
'port': self.port,
|
|
196
|
-
'executable': self.executable
|
|
197
|
-
})
|
|
198
|
-
|
|
199
|
-
except Exception as e:
|
|
200
|
-
error_msg = f"Failed during remote target setup: {str(e)}"
|
|
201
|
-
self._log_to_file(error_msg, "ERROR")
|
|
202
|
-
print(f"[ERROR] {error_msg}", file=sys.stderr, flush=True)
|
|
203
|
-
raise Exception(error_msg)
|
|
204
|
-
|
|
205
|
-
# Send initialization complete event
|
|
206
|
-
self._send_event('initialized', {
|
|
207
|
-
'mode': 'remote' if self.remote_mode else 'local',
|
|
208
|
-
'executable': self.executable,
|
|
209
|
-
'working_dir': self.working_dir,
|
|
210
|
-
'gdb_command': self.gdb_command,
|
|
211
|
-
'timestamp': str(time.time())
|
|
212
|
-
})
|
|
213
|
-
|
|
214
|
-
success_msg = f"GDB client fully initialized in {'remote' if self.remote_mode else 'local'} mode"
|
|
215
|
-
print(f"[GDB-Bridge] ✅ {success_msg}", file=sys.stderr, flush=True)
|
|
216
|
-
self._log_to_file(success_msg, "SUCCESS")
|
|
217
|
-
|
|
218
|
-
except Exception as e:
|
|
219
|
-
error_msg = f"Failed to initialize GDB: {str(e)}"
|
|
220
|
-
self._log_to_file(error_msg, "ERROR")
|
|
221
|
-
print(f"[GDB-Bridge] ❌ {error_msg}", file=sys.stderr, flush=True)
|
|
222
|
-
self._send_error(error_msg)
|
|
223
|
-
sys.exit(1)
|
|
224
|
-
|
|
225
|
-
def _send_response(self, type: str, response: Dict[str, Any]):
|
|
226
|
-
"""Helper to send a response to stdout."""
|
|
227
|
-
output = {
|
|
228
|
-
'type': type,
|
|
229
|
-
'payload': response
|
|
230
|
-
}
|
|
231
|
-
print(json.dumps(output), flush=True)
|
|
232
|
-
|
|
233
|
-
def _send_event(self, event_type: str, payload: Dict[str, Any]):
|
|
234
|
-
"""Helper to send an event to stdout."""
|
|
235
|
-
output = {
|
|
236
|
-
'type': 'event',
|
|
237
|
-
'event': event_type,
|
|
238
|
-
'payload': payload
|
|
239
|
-
}
|
|
240
|
-
print(json.dumps(output), flush=True)
|
|
241
|
-
|
|
242
|
-
def _send_error(self, message: str):
|
|
243
|
-
"""Helper to send an error response to stdout."""
|
|
244
|
-
output = {
|
|
245
|
-
'type': 'error',
|
|
246
|
-
'payload': {'message': message}
|
|
247
|
-
}
|
|
248
|
-
print(json.dumps(output), flush=True)
|
|
249
|
-
|
|
250
|
-
def send_command(self, command: str) -> dict:
|
|
251
|
-
"""Send a raw GDB/MI command to GDB."""
|
|
252
|
-
try:
|
|
253
|
-
if not self.gdb_controller:
|
|
254
|
-
error_msg = 'GDB not initialized'
|
|
255
|
-
self._log_to_file(error_msg, "ERROR")
|
|
256
|
-
return {'success': False, 'error': error_msg}
|
|
257
|
-
|
|
258
|
-
# Ensure command ends with newline
|
|
259
|
-
if not command.endswith('\n'):
|
|
260
|
-
command += '\n'
|
|
261
|
-
|
|
262
|
-
self._log_to_file(f"Sending GDB command: {command.strip()}", "DEBUG")
|
|
263
|
-
|
|
264
|
-
# Reduced timeout to 8 seconds to work better with TypeScript 15-second timeout
|
|
265
|
-
try:
|
|
266
|
-
response = self.gdb_controller.write(command, timeout_sec=8)
|
|
267
|
-
self._send_response('gdb_response', response)
|
|
268
|
-
return {'success': True}
|
|
269
|
-
except Exception as timeout_error:
|
|
270
|
-
# Handle timeout more gracefully
|
|
271
|
-
if 'timeout' in str(timeout_error).lower():
|
|
272
|
-
error_msg = f"Command failed: Did not get response from gdb after 8 seconds"
|
|
273
|
-
self._log_to_file(error_msg, "ERROR")
|
|
274
|
-
self._send_error(error_msg)
|
|
275
|
-
return {'success': False, 'error': error_msg}
|
|
276
|
-
else:
|
|
277
|
-
raise timeout_error
|
|
278
|
-
|
|
279
|
-
except Exception as e:
|
|
280
|
-
error_msg = f"Failed to send command '{command.strip()}': {str(e)}"
|
|
281
|
-
self._log_to_file(error_msg, "ERROR")
|
|
282
|
-
return {'success': False, 'error': str(e)}
|
|
283
|
-
|
|
284
|
-
def cleanup(self) -> dict:
|
|
285
|
-
"""Clean up GDB session and resources."""
|
|
286
|
-
try:
|
|
287
|
-
self._log_to_file("Starting GDB bridge cleanup")
|
|
288
|
-
|
|
289
|
-
# Signal the reader thread to stop
|
|
290
|
-
self.running = False
|
|
291
|
-
|
|
292
|
-
# Try to send exit command to GDB first
|
|
293
|
-
if self.gdb_controller:
|
|
294
|
-
try:
|
|
295
|
-
self._log_to_file("Sending exit command to GDB", "DEBUG")
|
|
296
|
-
self.gdb_controller.write('-gdb-exit\n', timeout_sec=5)
|
|
297
|
-
except Exception as e:
|
|
298
|
-
self._log_to_file(f"Failed to send exit command: {e}", "WARNING")
|
|
299
|
-
pass # GDB might already be gone
|
|
300
|
-
|
|
301
|
-
# Wait for reader thread to finish
|
|
302
|
-
# In this case, the reader thread is the GDB controller itself,
|
|
303
|
-
# so we just wait for the process to exit.
|
|
304
|
-
if self.gdb_controller:
|
|
305
|
-
self._log_to_file("Waiting for GDB process to exit", "DEBUG")
|
|
306
|
-
self.gdb_controller.wait(timeout=2)
|
|
307
|
-
|
|
308
|
-
# Terminate GDB process
|
|
309
|
-
if self.gdb_controller:
|
|
310
|
-
try:
|
|
311
|
-
self._log_to_file("Terminating GDB process", "DEBUG")
|
|
312
|
-
self.gdb_controller.terminate()
|
|
313
|
-
self.gdb_controller.wait(timeout=3)
|
|
314
|
-
except Exception as e:
|
|
315
|
-
self._log_to_file(f"Failed to terminate GDB process: {e}", "WARNING")
|
|
316
|
-
pass
|
|
317
|
-
|
|
318
|
-
self._log_to_file("GDB bridge cleanup completed successfully", "SUCCESS")
|
|
319
|
-
return {'success': True}
|
|
320
|
-
|
|
321
|
-
except Exception as e:
|
|
322
|
-
error_msg = f"Failed to cleanup GDB bridge: {str(e)}"
|
|
323
|
-
self._log_to_file(error_msg, "ERROR")
|
|
324
|
-
return {'success': False, 'error': str(e)}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
def main():
|
|
328
|
-
parser = argparse.ArgumentParser(description='Enhanced GDB Bridge for Embedder CLI Debugger')
|
|
329
|
-
parser.add_argument('executable', help='Path to executable to debug')
|
|
330
|
-
parser.add_argument('--working-dir', help='Working directory for GDB session')
|
|
331
|
-
parser.add_argument('--remote', '--remote-mode', action='store_true', help='Enable remote debugging mode')
|
|
332
|
-
parser.add_argument('--host', default='localhost', help='Host for remote debugging (e.g., 192.168.1.100)')
|
|
333
|
-
parser.add_argument('--port', type=int, default=3333, help='Port for remote debugging')
|
|
334
|
-
parser.add_argument('--gdb-command', default='gdb', help='Command to run GDB (e.g., gdb, arm-none-eabi-gdb)')
|
|
335
|
-
|
|
336
|
-
args = parser.parse_args()
|
|
337
|
-
|
|
338
|
-
bridge = EmbeddedGDBBridge(args.executable, args.working_dir, args.remote, args.host, args.port, args.gdb_command)
|
|
339
|
-
|
|
340
|
-
# Initialize GDB
|
|
341
|
-
try:
|
|
342
|
-
bridge.initialize()
|
|
343
|
-
except Exception as e:
|
|
344
|
-
bridge._send_error(f"Failed to initialize bridge: {str(e)}")
|
|
345
|
-
sys.exit(1)
|
|
346
|
-
|
|
347
|
-
# Command processing loop
|
|
348
|
-
try:
|
|
349
|
-
bridge._log_to_file("Starting command processing loop")
|
|
350
|
-
for line in sys.stdin:
|
|
351
|
-
try:
|
|
352
|
-
command_data = json.loads(line.strip())
|
|
353
|
-
|
|
354
|
-
if command_data.get('action') == 'send_command':
|
|
355
|
-
raw_command = command_data.get('command', '')
|
|
356
|
-
response = bridge.send_command(raw_command)
|
|
357
|
-
if not response.get('success'):
|
|
358
|
-
error_msg = f"Command failed: {response.get('error', 'Unknown error')}"
|
|
359
|
-
bridge._log_to_file(error_msg, "ERROR")
|
|
360
|
-
bridge._send_error(error_msg)
|
|
361
|
-
|
|
362
|
-
elif command_data.get('action') == 'cleanup':
|
|
363
|
-
bridge._log_to_file("Received cleanup command")
|
|
364
|
-
bridge.cleanup()
|
|
365
|
-
break
|
|
366
|
-
|
|
367
|
-
else:
|
|
368
|
-
error_msg = f"Unknown action: {command_data.get('action')}"
|
|
369
|
-
bridge._log_to_file(error_msg, "ERROR")
|
|
370
|
-
bridge._send_error(error_msg)
|
|
371
|
-
|
|
372
|
-
except json.JSONDecodeError as e:
|
|
373
|
-
error_msg = f"Invalid JSON command: {str(e)}"
|
|
374
|
-
bridge._log_to_file(error_msg, "ERROR")
|
|
375
|
-
bridge._send_error(error_msg)
|
|
376
|
-
except Exception as e:
|
|
377
|
-
error_msg = f"Command processing error: {str(e)}"
|
|
378
|
-
bridge._log_to_file(error_msg, "ERROR")
|
|
379
|
-
bridge._send_error(error_msg)
|
|
380
|
-
|
|
381
|
-
except KeyboardInterrupt:
|
|
382
|
-
bridge._log_to_file("Received keyboard interrupt, cleaning up", "WARNING")
|
|
383
|
-
bridge.cleanup()
|
|
384
|
-
except Exception as e:
|
|
385
|
-
error_msg = f"Main loop error: {str(e)}"
|
|
386
|
-
bridge._log_to_file(error_msg, "ERROR")
|
|
387
|
-
bridge._send_error(error_msg)
|
|
388
|
-
bridge.cleanup()
|
|
389
|
-
sys.exit(1)
|
|
390
|
-
|
|
391
|
-
if __name__ == '__main__':
|
|
392
|
-
main()
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
pygdbmi>=0.10.0
|