7
7
import gdb
8
8
9
9
10
+ class bcolors :
11
+ HEADER = "\033 [95m"
12
+ OKBLUE = "\033 [94m"
13
+ OKCYAN = "\033 [96m"
14
+ OKGREEN = "\033 [92m"
15
+ WARNING = "\033 [93m"
16
+ FAIL = "\033 [91m"
17
+ ENDC = "\033 [0m"
18
+ BOLD = "\033 [1m"
19
+ UNDERLINE = "\033 [4m"
20
+
21
+
22
+ LOG_PREFIX = "[FURI]"
23
+
24
+
25
+ def error (line ):
26
+ print (f"{ bcolors .FAIL } { LOG_PREFIX } { line } { bcolors .ENDC } " )
27
+
28
+
29
+ def warning (line ):
30
+ print (f"{ bcolors .WARNING } { LOG_PREFIX } { line } { bcolors .ENDC } " )
31
+
32
+
33
+ def info (line ):
34
+ print (f"{ bcolors .OKGREEN } { LOG_PREFIX } { line } { bcolors .ENDC } " )
35
+
36
+
10
37
def get_file_crc32 (filename ):
11
38
with open (filename , "rb" ) as f :
12
39
return zlib .crc32 (f .read ())
@@ -39,20 +66,20 @@ def get_original_elf_path(self) -> str:
39
66
def is_debug_available (self ) -> bool :
40
67
have_debug_info = bool (self .debug_link_elf and self .debug_link_crc )
41
68
if not have_debug_info :
42
- print ("No debug info available for this app" )
69
+ warning ("No debug info available for this app" )
43
70
return False
44
71
debug_elf_path = self .get_original_elf_path ()
45
72
debug_elf_crc32 = get_file_crc32 (debug_elf_path )
46
73
if self .debug_link_crc != debug_elf_crc32 :
47
- print (
74
+ warning (
48
75
f"Debug info ({ debug_elf_path } ) CRC mismatch: { self .debug_link_crc :08x} != { debug_elf_crc32 :08x} , rebuild app"
49
76
)
50
77
return False
51
78
return True
52
79
53
80
def get_gdb_load_command (self ) -> str :
54
81
load_path = self .get_original_elf_path ()
55
- print (f"Loading debug information from { load_path } " )
82
+ info (f"Loading debug information from { load_path } " )
56
83
load_command = (
57
84
f"add-symbol-file -readnow { load_path } 0x{ self .text_address :08x} "
58
85
)
@@ -121,12 +148,12 @@ def invoke(self, arg, from_tty):
121
148
AppState .DEBUG_ELF_ROOT = arg
122
149
try :
123
150
global helper
124
- print (f"Set '{ arg } ' as debug info lookup path for Flipper external apps" )
151
+ info (f"Set '{ arg } ' as debug info lookup path for Flipper external apps" )
125
152
helper .attach_to_fw ()
126
153
gdb .events .stop .connect (helper .handle_stop )
127
154
gdb .events .gdb_exiting .connect (helper .handle_exit )
128
155
except gdb .error as e :
129
- print (f"Support for Flipper external apps debug is not available: { e } " )
156
+ error (f"Support for Flipper external apps debug is not available: { e } " )
130
157
131
158
132
159
class FlipperAppStateHelper :
@@ -148,13 +175,29 @@ def _exec_gdb_command(self, command: str) -> bool:
148
175
gdb .execute (command )
149
176
return True
150
177
except gdb .error as e :
151
- print (f"Failed to execute GDB command '{ command } ': { e } " )
178
+ error (f"Failed to execute GDB command '{ command } ': { e } " )
152
179
return False
153
180
181
+ def _get_crash_message (self ):
182
+ message = self .app_check_message .value ()
183
+ if message == 1 :
184
+ return "furi_assert failed"
185
+ elif message == 2 :
186
+ return "furi_check failed"
187
+ else :
188
+ return message
189
+
154
190
def _sync_apps (self ) -> None :
191
+ crash_message = self ._get_crash_message ()
192
+ if crash_message :
193
+ crash_message = f"! System crashed: { crash_message } !"
194
+ error ("!" * len (crash_message ))
195
+ error (crash_message )
196
+ error ("!" * len (crash_message ))
197
+
155
198
self .set_debug_mode (True )
156
199
if not (app_list := self .app_list_ptr .value ()):
157
- print ("Reset app loader state" )
200
+ info ("Reset app loader state" )
158
201
for app in self ._current_apps :
159
202
self ._exec_gdb_command (app .get_gdb_unload_command ())
160
203
self ._current_apps = []
@@ -167,22 +210,23 @@ def _sync_apps(self) -> None:
167
210
168
211
for app in self ._current_apps .copy ():
169
212
if app .entry_address not in loaded_apps :
170
- print (f"Application { app .name } is no longer loaded" )
213
+ warning (f"Application { app .name } is no longer loaded" )
171
214
if not self ._exec_gdb_command (app .get_gdb_unload_command ()):
172
- print (f"Failed to unload debug info for { app .name } " )
215
+ error (f"Failed to unload debug info for { app .name } " )
173
216
self ._current_apps .remove (app )
174
217
175
218
for entry_point , app in loaded_apps .items ():
176
219
if entry_point not in set (app .entry_address for app in self ._current_apps ):
177
220
new_app_state = AppState .from_gdb (app )
178
- print (f"New application loaded. Adding debug info" )
221
+ warning (f"New application loaded. Adding debug info" )
179
222
if self ._exec_gdb_command (new_app_state .get_gdb_load_command ()):
180
223
self ._current_apps .append (new_app_state )
181
224
else :
182
- print (f"Failed to load debug info for { new_app_state } " )
225
+ error (f"Failed to load debug info for { new_app_state } " )
183
226
184
227
def attach_to_fw (self ) -> None :
185
- print ("Attaching to Flipper firmware" )
228
+ info ("Attaching to Flipper firmware" )
229
+ self .app_check_message = gdb .lookup_global_symbol ("__furi_check_message" )
186
230
self .app_list_ptr = gdb .lookup_global_symbol (
187
231
"flipper_application_loaded_app_list"
188
232
)
@@ -200,10 +244,10 @@ def set_debug_mode(self, mode: bool) -> None:
200
244
try :
201
245
gdb .execute (f"set variable furi_hal_debug_gdb_session_active = { int (mode )} " )
202
246
except gdb .error as e :
203
- print (f"Failed to set debug mode: { e } " )
247
+ error (f"Failed to set debug mode: { e } " )
204
248
205
249
206
250
# Init additional 'fap-set-debug-elf-root' command and set up hooks
207
251
SetFapDebugElfRoot ()
208
252
helper = FlipperAppStateHelper ()
209
- print ("Support for Flipper external apps debug is loaded" )
253
+ info ("Support for Flipper external apps debug is loaded" )
0 commit comments