blob: 6b5a704fa71600235ffe3bec53e93b6a5fd94014 [file] [log] [blame]
Jianliang Shen9b4ba112022-01-19 14:57:04 +08001# ------------------------------------------------------------------------------
2# Copyright (c) 2022, Arm Limited. All rights reserved.
3#
4# SPDX-License-Identifier: BSD-3-Clause
5#
6# ------------------------------------------------------------------------------
7
8import sqlite3
9import curses
10import curses.textpad
11
12class UI(object):
13 """
14 Class UI is used to show the data in the terminal with library curses. It
15 contains two main diffrent functions, one is to control the UI and show the
16 message in the terminal, the other is to search the information and then
17 transform it into a string varible called items[]. This can be showed or
18 exported as a plaintext. These functions to fill items[] are PUBLIC.
19
20 - Methods:
21 - UI().run() - Run the UI in terminal.
22 - UI.draw_<symbol>_page() - Get the information of specific symbol
Jianliang Shen28cce572022-05-02 21:44:03 +080023 - UI.open_db() - Open database.
Jianliang Shen9b4ba112022-01-19 14:57:04 +080024
25 - Variables:
26 - UI().items - The result searched from database.
27 - UI().armcc - ARMCLANG option.
28 - UI().gnuarm - GNUARM option.
29 - UI().con - Database handler.
30 - UI().function_name - Specific function name.
31 - UI().data_name - Specific data name.
32 - UI().section_name - Specific section name.
33 - UI().library_name - Specific library name.
34 - UI().obj_file - Specific object file name.
Jianliang Shen28cce572022-05-02 21:44:03 +080035 - UI().db_file - Database file.
36 - UI().sort - Database list order: size, name and so on.
37 - UI().order - Database sort order: DESC and ASC.
Jianliang Shen9b4ba112022-01-19 14:57:04 +080038 """
39
40 def __init__(self):
41 """
42 Initialize variables.
43 """
44 self.function_name = ""
45 self.data_name = ""
46 self.section_name = ""
47 self.library_name = ""
48 self.obj_file = ""
49 self.gnuarm = False
50 self.armcc = False
51 self.items = []
Jianliang Shen28cce572022-05-02 21:44:03 +080052 self.db_file = ""
53 self.sort = "size"
54 self.order = "DESC"
Jianliang Shen9b4ba112022-01-19 14:57:04 +080055
Jianliang Shen9b4ba112022-01-19 14:57:04 +080056 self.__window = None
57 self.__width = 0
58 self.__height = 0
59 self.__menu_depth = 0
60 self.__detail = 0
61 self.__section_detail = 0
62 self.__UP = -1
63 self.__DOWN = 1
64 self.__line1 = "─" * 128
65 self.__line2 = "-" * 128
66 self.__cmd_file="Enter the file name:"
67 self.__cmd_func="Enter the function name:"
68 self.__cmd_data="Enter the data name:"
69
Jianliang Shen28cce572022-05-02 21:44:03 +080070 def open_db(self):
71 self.con = sqlite3.connect(self.db_file)
72 self.__cur = self.con.cursor()
73 cursor = self.__cur.execute("select * from Compiler")
74 for row in cursor:
75 compiler = row[1]
76 if compiler == 1:
77 self.gnuarm = True
78 elif compiler == 0:
79 self.armcc = True
80
Jianliang Shen9b4ba112022-01-19 14:57:04 +080081 def __init_curses(self):
82 """
83 Setup the curses
84 """
85 self.__window = curses.initscr()
86 self.__window.keypad(True)
87
88 curses.noecho()
89 curses.cbreak()
90 curses.curs_set(False)
91
92 curses.start_color()
93 curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLACK)
94 curses.init_pair(2, curses.COLOR_BLACK, curses.COLOR_WHITE)
95
96 self.__current = curses.color_pair(2)
97 self.__height, self.__width = self.__window.getmaxyx()
98
99 self.__max_lines = curses.LINES - 1
100 self.__top = 0
101
102 self.__bottom = len(self.items)
103 self.__current = 0
104 self.__current_x = 0
105
106 def __input_stream(self):
107 """
108 Waiting an input and run a proper method according to type of input
109 """
110 while True:
111 self.__display()
112
113 ch = self.__window.getch()
114 if ch == curses.KEY_UP:
115 self.__scroll(self.__UP)
116 elif ch == curses.KEY_DOWN:
117 self.__scroll(self.__DOWN)
118 elif ch == curses.KEY_LEFT:
119 self.__current_x = max(self.__current_x - 1, 0)
120 elif ch == curses.KEY_RIGHT:
121 self.__current_x = self.__current_x + 1
122 elif ch == ord('q') or ch == ord('Q'):
123 """
124 If press 'q' or 'Q', escape this page
125 """
126 if self.__menu_depth == 0:
127 break
128 self.__menu_depth = max(self.__menu_depth - 1, 0)
129 self.__draw_page()
130 elif ch == 10:
131 """
132 If press ENTER, get into next page if it exists
133 """
134 self.__get_menu_choose()
135 self.__menu_depth = self.__menu_depth + 1
136 self.__draw_page()
137 elif ch == 58:
138 """
139 If press ':', get target name form input line to search
140 functions or data
141 """
142 if self.__menu_depth == 1:
143 if self.__detail == 3:
144 self.draw_function_page(self.__get_input_line_msg(self.__cmd_func))
145 if self.__detail == 4:
146 self.draw_data_page(self.__get_input_line_msg(self.__cmd_data))
147 elif ch == ord('s') or ch == ord('S'):
148 """
149 If press 's' or 'S', save to file
150 """
151 self.__save_file(self.__get_input_line_msg(self.__cmd_file))
152
153 def __get_input_line_msg(self, cmd):
154 """
155 Get message from input line.
156 """
157 self.__window.addstr(self.__height - 1, 0, cmd, curses.color_pair(2))
158 self.input_line = curses.newwin(1, curses.COLS - 2 - len(cmd), curses.LINES-1, len(cmd) + 1)
159 self.input_box = curses.textpad.Textbox(self.input_line)
160 self.__window.refresh()
161 self.input_box.edit()
162 ret = self.input_box.gather()[:len(self.input_box.gather())-1]
163 self.__display()
164 self.input_line.clear()
165 return ret
166
167 def __save_file(self, output_file_name):
168 """
169 Save to files
170 """
171 fo = open(output_file_name + '.txt', "w")
172 for s in self.items:
173 fo.write(s + '\n')
174 fo.close()
175
176 def __scroll(self, direction):
177 """
178 Scrolling the window when pressing up/down arrow keys
179 """
180 next_line = self.__current + direction
181 if (direction == self.__UP) and (self.__top > 0 and self.__current == 0):
182 self.__top += direction
183 return
184 if (direction == self.__DOWN) and (next_line == self.__max_lines) and \
185 (self.__top + self.__max_lines < self.__bottom):
186 self.__top += direction
187 return
188 if (direction == self.__UP) and (self.__top > 0 or self.__current > 0):
189 self.__current = next_line
190 return
191 if (direction == self.__DOWN) and (next_line < self.__max_lines) and \
192 (self.__top + next_line < self.__bottom):
193 self.__current = next_line
194 return
195
196 def __display(self):
197 """
198 Display the items on window
199 """
200 self.__window.erase()
201 for idx, item in enumerate(self.items[self.__top:self.__top + self.__max_lines]):
202 if idx == self.__current:
203 self.__window.addstr(idx, 0, item[self.__current_x:self.__current_x + self.__width], curses.color_pair(2))
204 else:
205 self.__window.addstr(idx, 0, item[self.__current_x:self.__current_x + self.__width], curses.color_pair(1))
206 self.__window.refresh()
207
208 def __draw_page(self):
209 """
210 Draw different page with menu_depth, detail and section_detail.
211 """
212 if self.__menu_depth == 0:
213 self.__draw_welcome_page()
214 elif self.__menu_depth == 1:
215 if self.__detail == 1:
216 self.draw_summary_page()
217 if self.__detail == 2:
218 self.draw_section_page()
219 if self.__detail == 3:
220 self.draw_function_page("")
221 if self.__detail == 4:
222 self.draw_data_page("")
223 if self.__detail == 5:
224 self.draw_library_page()
225 if self.__detail == 6:
226 self.draw_obj_page()
227 elif self.__menu_depth == 2:
228 if self.__detail == 2:
229 self.draw_section_detail_page()
230 if self.__detail == 3:
231 self.draw_function_detail_page()
232 if self.__detail == 4:
233 self.draw_data_detail_page()
234 if self.__detail == 5:
235 self.draw_library_detail_page()
236 if self.__detail == 6:
237 self.draw_obj_detail_page()
238 elif self.__menu_depth == 3 and self.__detail == 2:
239 """
240 Draw section detail menu, here self.__detail is 2
241 """
242 if self.__section_detail == 1:
243 self.draw_section_lib()
244 if self.__section_detail == 2:
245 self.draw_section_func()
246 if self.__section_detail == 3:
247 self.draw_section_data()
248 elif self.__menu_depth == 4:
249 """
250 Only section detail menu can move to menu depth 5, here function
251 detail and data detail are also supported.
252 """
253 if self.__section_detail == 2:
254 self.draw_function_detail_page()
255 if self.__section_detail == 3:
256 self.draw_data_detail_page()
257
258 self.__bottom = len(self.items)
259 self.__current = 0
260 self.__current_x = 0
261 self.__top = 0
262
263 def __get_menu_choose(self):
264 """
265 Get options from menus or specific objects like function, data, library
266 or object files.
267 """
268
269 """
270 First page, menu_depth = 1
271 =============================
272 Current file: tfm_s.axf
273 1. Summary Info -->
274 2. Section Module -->
275 3. Function detail -->
276 4. Data detail -->
277 5. Library Summary -->
278 6. Object files Summary -->
279 =============================
280 It will change the self.__detail's value in range 1 - 6
281 """
282 if self.__menu_depth == 0:
283 if self.__current + self.__top > 0:
284 self.__detail = self.__current
285 else:
286 """
287 Except first line
288 """
289 self.__menu_depth = self.__menu_depth - 1
290 if self.__menu_depth == 1:
291 if self.__current + self.__top > 0:
292 if self.__detail == 2:
293 """
294 Get section name which will be used to draw its detail page
295 in __draw_page() function.
296 """
297 self.section_name = self.items[self.__top + self.__current].split()[0]
298 elif self.__detail == 3:
299 """
300 Get function name and its object file to avoid same name
301 situation. Function name will be used to draw its detail
302 page in __draw_page() function.
303 """
304 self.function_name = self.items[self.__top + self.__current].split()[0]
305 self.obj_file = self.items[self.__top + self.__current].split()[4]
306 elif self.__detail == 4:
307 """
308 Get data name and its object file name to avoid same name
309 situation. Data name will be used to draw its detail page in
310 __draw_page() function.
311 """
312 self.data_name = self.items[self.__top + self.__current].split()[0]
313 self.obj_file = self.items[self.__top + self.__current].split()[5]
314 elif self.__detail == 5:
315 """
316 Get library name which will be used to draw its detail page
317 in __draw_page() function.
318 """
319 self.library_name = self.items[self.__top + self.__current].split()[0]
320 elif self.__detail == 6:
321 """
322 Get object file name which will be used to draw its detail
323 page in __draw_page() function.
324 """
325 self.obj_file = self.items[self.__top + self.__current].split()[0]
326 else:
327 """
328 Other invalid choose will not change menu depth.
329 """
330 self.__menu_depth = self.__menu_depth - 1
331 else:
332 """
333 Except first line
334 """
335 self.__menu_depth = self.__menu_depth - 1
336 """
337 Section detail page, menu_depth = 1
338 =============================
339 Name :TFM_UNPRIV_CODE Size :155544
340 1. Summary -->
341 2. Function -->
342 3. Data -->
343 =============================
344 It will change the self.__section_detail's value in range 1 - 3
345 """
346 if self.__menu_depth == 2:
347 if self.__current + self.__top > 0:
348 if self.__detail == 2:
349 self.__section_detail = self.__current
350 else:
351 self.__menu_depth = self.__menu_depth - 1
352 else:
353 self.__menu_depth = self.__menu_depth - 1
354 if self.__menu_depth == 3:
355 if self.__current + self.__top > 0:
356 if self.__section_detail == 2:
357 self.function_name = self.items[self.__top + self.__current].split()[0]
358 self.obj_file = self.items[self.__top + self.__current].split()[4]
359 elif self.__section_detail == 3:
360 self.data_name = self.items[self.__top + self.__current].split()[0]
361 self.obj_file = self.items[self.__top + self.__current].split()[5]
362 else:
363 self.__menu_depth = self.__menu_depth - 1
364 else:
365 self.__menu_depth = self.__menu_depth - 1
366 if self.__menu_depth == 4:
367 self.__menu_depth = self.__menu_depth - 1
368
369 def __draw_welcome_page(self):
370 self.items = ["Code Size Analysis Tool for Map File",
371 "1. Summary Info -->",
372 "2. Section Module -->",
373 "3. Function detail -->",
374 "4. Data detail -->",
375 "5. Library Summary -->",
376 "6. Object files Summary -->"]
377
378 def draw_summary_page(self):
379 """
380 Get summary info from database and save into self.items.
381 """
382 cursor = self.__cur.execute("select * from Summary")
383 if self.gnuarm:
384 for row in cursor:
385 self.items = [self.__line1,
386 "Total usage(include all symbols and \"fill or pad\"):",
387 "Flash size\t: {:<8}\t{:<4.2f}\tKB".
388 format(row[6], row[6]/1024),
389 "RAM size\t: {:<8}\t{:<4.2f}\tKB".
390 format(row[7], row[7]/1024),
391 self.__line2,
392 "These data are collected from functions, stacks or arrays sizes without \"fill or pad\" part!",
393 "Text size\t: {:<8}\t{:<4.2f}\tKB".
394 format(row[0], row[0]/1024),
395 "Read-only data\t: {:<8}\t{:<4.2f}\tKB".
396 format(row[1], row[1]/1024),
397 "Read-write data\t: {:<8}\t{:<4.2f}\tKB".
398 format(row[2], row[2]/1024),
399 "BSS data\t: {:<8}\t{:<4.2f}\tKB".
400 format(row[3], row[3]/1024),
401 self.__line2,
402 "Some other unknown type symbols locate in flash or ram:",
403 "Total unknown type symbols in flash: {:<8}\t{:<4.2f}\tKB".
404 format(row[4], row[4]/1024),
405 "Total unknown type symbols in RAM : {:<8}\t{:<4.2f}\tKB".
406 format(row[5], row[5]/1024),
407 self.__line1]
408 break
409 if self.armcc:
410 for row in cursor:
411 self.items = ["Code size\t: {:<8}\t{:<4.2f}\tKB".
412 format(row[0], row[0]/1024),
413 "RO data\t\t: {:<8}\t{:<4.2f}\tKB".
414 format(row[1], row[1]/1024),
415 "RW data\t\t: {:<8}\t{:<4.2f}\tKB".
416 format(row[2], row[2]/1024),
417 "ZI data\t\t: {:<8}\t{:<4.2f}\tKB".
418 format(row[3], row[3]/1024),
419 "Flash size\t: {:<8}\t{:<4.2f}\tKB = Code + RO + RW".
420 format(row[6], row[6]/1024),
421 "RAM size\t: {:<8}\t{:<4.2f}\tKB = RW + ZI".
422 format(row[7], row[7]/1024)]
423 break
424
425 def draw_section_page(self):
426 """
427 Get section info from database and save into self.items.
428 """
429 self.items = ["{:<50}{:<16}{:<16}{:<16}".
430 format("Name", "Size", "Address", "PAD size")]
431
Jianliang Shen28cce572022-05-02 21:44:03 +0800432 cursor = self.__cur.execute("select * from Section ORDER BY {} {}".format(self.sort, self.order))
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800433 for row in cursor:
434 self.items.append("{:<50}{:<16}{:<16}{:<16}".
435 format(row[0], row[1], row[2], row[3]))
436
437 def draw_section_detail_page(self):
438 """
439 Section detail page with a menu.
440 """
441 cursor = self.__cur.execute("select * from Section WHERE name = '{}'".
442 format(self.section_name))
443 for row in cursor:
444 self.items = ["Name :{}\t\tSize :{}".
445 format(self.section_name, row[1]),
446 "1. Summary -->",
447 "2. Function -->",
448 "3. Data -->"]
449 break
450
451 def draw_section_lib(self):
452 lib_dict, obj_dict = {}, {}
453 lib_list, obj_list = [], []
454 exsit_no_lib_obj = False
455 tmp_list = []
456 colums_name = "{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".format(
457 "Name", "Flash", "RAM", "Code", "RO data", "RW data", "ZI data", "Total")
458 count = 0
459
460 """
461 Get detail information with functions and data from tables in database
462 with a dictionary in python.
463 """
464 cursor = self.__cur.execute("select * from Function WHERE section = '{}' ORDER BY lib_file DESC".
465 format(self.section_name))
466 for row in cursor:
467 lib_name = row[5]
468 if lib_name in lib_dict.keys():
469 lib_dict[lib_name]['Code'] += row[2]
470 else:
471 lib_dict[lib_name] = {'RO': 0, 'RW': 0,
472 'Code': row[2], 'ZI': 0}
473
474 obj_name = row[4]
475 if obj_name in obj_dict.keys():
476 obj_dict[obj_name]['Code'] += row[2]
477 else:
478 obj_dict[obj_name] = {'RO': 0, 'RW': 0,
479 'Code': row[2], 'Lib': lib_name, 'ZI': 0}
480
481 cursor = self.__cur.execute("select * from Data WHERE section = '{}' ORDER BY lib_file DESC".
482 format(self.section_name))
483 for row in cursor:
484 lib_name = row[6]
485 if lib_name in lib_dict.keys():
486 lib_dict[lib_name][row[4]] += row[2]
487 else:
488 lib_dict[lib_name] = {'RO': 0, 'RW': 0, 'Code': 0, 'ZI': 0}
489 lib_dict[lib_name][row[4]] = row[2]
490
491 obj_name = row[5]
492 if obj_name in obj_dict.keys():
493 obj_dict[obj_name][row[4]] += row[2]
494 else:
495 obj_dict[obj_name] = {'RO': 0, 'RW': 0,
496 'Code': 0, 'Lib': lib_name, 'ZI': 0}
497 obj_dict[obj_name][row[4]] = row[2]
498
499 """
500 Transform the dictionary to a dictionary list in python and sort the
501 elements with total size.
502 """
503 for s in lib_dict.keys():
504 lib_list.append({'Name': s,
505 'RO': lib_dict[s]['RO'],
506 'RW': lib_dict[s]['RW'],
507 'Code': lib_dict[s]['Code'],
508 'ZI': lib_dict[s]['ZI']})
509 lib_list = sorted(lib_list,
510 key=lambda i: i['RO'] + i['Code'] + i['RW'] + i['ZI'],
511 reverse=True)
512 for s in obj_dict.keys():
513 obj_list.append({'Name': s,
514 'RO': obj_dict[s]['RO'],
515 'RW': obj_dict[s]['RW'],
516 'Code': obj_dict[s]['Code'],
517 'Lib': obj_dict[s]['Lib'],
518 'ZI': obj_dict[s]['ZI']})
519 obj_list = sorted(obj_list,
520 key=lambda i: i['RO'] + i['Code'] + i['RW'] + i['ZI'],
521 reverse=True)
522
523 def sum_data(data_list):
524 """
525 Calculate the sum of libraries or object files, and implement total
526 data line. It will be added into self.items.
527 """
528 ret = {'RO': 0, 'RW': 0, 'Code': 0, 'ZI': 0,
529 'Flash': 0, 'Ram': 0, 'Total': 0}
530 if len(data_list) > 0:
531 for s in data_list:
532 ret['Code'] += s['Code']
533 ret['RO'] += s['RO']
534 ret['RW'] += s['RW']
535 ret['ZI'] += s['ZI']
536 ret['Flash'] += s['Code'] + s['RO'] + s['RW']
537 ret['Ram'] += s['RW'] + s['ZI']
538 ret['Total'] = ret['Flash'] + ret['ZI']
539 self.items.append(self.__line2)
540 self.items.append("{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
541 format("Summary",
542 ret['Flash'],
543 ret['Ram'],
544 ret['Code'],
545 ret['RO'],
546 ret['RW'],
547 ret['ZI'],
548 ret['Total']))
549 self.items.append(self.__line1)
550 return ret
551
552 def insert_column_line(title):
553 """
554 Quickly insert column line.
555 """
556 self.items.append(title)
557 self.items.append(self.__line2)
558 self.items.append(colums_name)
559 self.items.append(self.__line2)
560
561 def quick_insert_data_line(s):
562 """
563 Quickly insert a single data line.
564 """
565 self.items.append("{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
566 format(s['Name'],
567 s['Code'] + s['RO'] + s['RW'],
568 s['RW'] + s['ZI'],
569 s['Code'],
570 s['RO'],
571 s['RW'],
572 s['ZI'],
573 s['Code'] + s['RO'] + s['RW'] + s['ZI']))
574 """
575 Dump library information.
576 """
577 self.items = [self.__line1]
Jianliang Shen28cce572022-05-02 21:44:03 +0800578 insert_column_line(" " * ((128 - len("Section libraries"))//2) + "Section libraries")
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800579 for s in lib_list:
580 if s['Name'].find(".o") > 0:
581 exsit_no_lib_obj = True
582 else:
583 tmp_list.append(s)
584 quick_insert_data_line(s)
585 sum_data(tmp_list)
586
587 """
588 Dump object file information.
589 """
Jianliang Shen28cce572022-05-02 21:44:03 +0800590 insert_column_line(" " * ((128 - len("Section object files"))//2) + "Section object files")
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800591 for s in obj_list:
592 quick_insert_data_line(s)
593 ret = sum_data(obj_list)
594 total_flash_size, total_ram_size = ret['Flash'], ret['Ram']
595
596 """
597 Dump NOT-IN-LIBRARY object file information.
598 """
599 if exsit_no_lib_obj:
Jianliang Shen28cce572022-05-02 21:44:03 +0800600 insert_column_line(" " * ((128 - len("Section NOT-IN-LIBRARY object files"))//2) +
601 "Section NOT-IN-LIBRARY object files")
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800602 tmp_list = []
603 for s in lib_list:
604 if s['Name'].find(".o") > 0:
605 tmp_list.append(s)
606 quick_insert_data_line(s)
607 sum_data(tmp_list)
608
609 """
610 Insert the summary information at the top of this page.
611 """
612 cursor = self.__cur.execute(
613 "select * from Section WHERE name = '{}'".format(self.section_name))
614 for row in cursor:
615 self.items.insert(0, "Section Name :{}\tTotal Size :{}\tFlash : {}\tRAM : {:<6}\tPad size = {}".
616 format(self.section_name, row[1], total_flash_size, total_ram_size, row[3]))
617 break
618 self.items.insert(0, self.__line2)
Jianliang Shen28cce572022-05-02 21:44:03 +0800619 self.items.insert(0, " " * ((128 - len("Section information"))//2) + "Section information")
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800620 self.items.insert(0, self.__line1)
621
622 """
623 Dump detail information of the section.
624 """
625 index = 4 * ' '
Jianliang Shen28cce572022-05-02 21:44:03 +0800626 self.items.append(" " * ((128 - len("Detail information"))//2) + "Detail information")
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800627 self.items.append(self.__line2)
628 for s in lib_list:
629 self.items.append("{} Code Size = {} RO Data = {} RW Data = {} ZI Data = {}".
630 format(s['Name'], s['Code'], s['RO'], s['RW'], s['ZI']))
631 for t in obj_list:
632 if t['Lib'] == s['Name']:
633 self.items.append(index + "{} Code Size = {} RO Data = {} RW Data = {} ZI Data = {}".format(
634 t['Name'], t['Code'], t['RO'], t['RW'], t['ZI']))
635 count = 0
Jianliang Shen28cce572022-05-02 21:44:03 +0800636 cursor = self.__cur.execute("select * from Function WHERE section = '{}' and lib_file = '{}' and obj_file = '{}' ORDER BY {} {}".
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800637 format(self.section_name,
638 s['Name'],
Jianliang Shen28cce572022-05-02 21:44:03 +0800639 t['Name'],
640 self.sort,
641 self.order))
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800642 for row in cursor:
643 if row and count == 0:
644 self.items.append(index * 2 + "Code size = {}".
645 format(t['Code']))
646 count = count + 1
647 self.items.append(index * 3 + "{:<6} {} ".
648 format(row[2], row[0]))
649
650 def get_certain_data(type_name, s, t):
651 count = 0
Jianliang Shen28cce572022-05-02 21:44:03 +0800652 cursor = self.__cur.execute("select * from Data WHERE section = '{}' and lib_file = '{}' and obj_file = '{}' and type = '{}' ORDER BY {} {}".
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800653 format(self.section_name,
654 s['Name'],
655 t['Name'],
Jianliang Shen28cce572022-05-02 21:44:03 +0800656 type_name,
657 self.sort,
658 self.order))
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800659 for row in cursor:
660 if row and count == 0:
661 self.items.append(index * 2 + "{} Data = {}".
662 format(type_name, t[type_name]))
663 count = count + 1
664 self.items.append(index * 3 + "{:<6} {}".
665 format(row[2], row[0]))
666
667 get_certain_data('RO', s, t)
668 get_certain_data('RW', s, t)
669 get_certain_data('ZI', s, t)
670 self.items.append(self.__line2)
Jianliang Shen28cce572022-05-02 21:44:03 +0800671 self.items[-1] = self.__line1
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800672
673 def draw_section_func(self):
674 self.items = ["{:<50}{:<32}{:<10}{:<16}{:<40}{:<40}".
675 format("Name",
676 "Section",
677 "Size",
678 "Address",
679 "Object File",
680 "Library")]
Jianliang Shen28cce572022-05-02 21:44:03 +0800681 cursor = self.__cur.execute("select * from Function WHERE section = '{}' ORDER BY {} {}".
682 format(self.section_name, self.sort, self.order))
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800683 for row in cursor:
684 self.items.append("{:<50}{:<32}{:<10}{:<16}{:<40}{:<40}".
685 format(row[0], row[1], row[2], row[3], row[4], row[5]))
686
687 def draw_section_data(self):
688 self.items = ["{:<50}{:<32}{:<10}{:<16}{:<16}{:<40}{:<40}".
689 format("Name",
690 "Section",
691 "Size",
692 "Address",
693 "Type",
694 "Object File",
695 "Library")]
696
Jianliang Shen28cce572022-05-02 21:44:03 +0800697 cursor = self.__cur.execute("select * from Data WHERE section = '{}' ORDER BY {} {}".
698 format(self.section_name, self.sort, self.order))
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800699 for row in cursor:
700 data_name = row[0]
701 if len(data_name) >= 50:
702 data_name = data_name[:40] + "-->"
703 self.items.append("{:<50}{:<32}{:<10}{:<16}{:<16}{:<40}{:<40}".
704 format(data_name, row[1], row[2], row[3], row[4], row[5], row[6]))
705
706 def __quick_append(self):
707 self.items.append(self.__line1)
708
709 self.items.append("{:<50}{:<32}{:<10}{:<16}{:<40}".
710 format("Name",
711 "Section",
712 "Size",
713 "Type",
714 "Object File"))
715 self.items.append(self.__line2)
716
717 def __quick_append_data(self, cursor):
718 flag = False
719 for row in cursor:
720 if not flag:
721 self.__quick_append()
722 data_name = row[0]
723 if len(data_name) >= 50:
724 data_name = data_name[:40] + "-->"
725 self.items.append("{:<50}{:<32}{:<10}{:<16}{:<40}".
726 format(data_name, row[1], row[2], row[4], row[5]))
727 flag = True
728
729 def draw_library_page(self):
730 self.items = ["{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
731 format("Name",
732 "Flash size",
733 "RAM size",
734 "Code",
735 "RO data",
736 "RW data",
737 "ZI data",
738 "Inc. data",
739 "Debug")]
740
741 cursor = self.__cur.execute(
Jianliang Shen28cce572022-05-02 21:44:03 +0800742 "select * from Library ORDER BY {} {}".format(self.sort, self.order))
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800743 for row in cursor:
744 self.items.append("{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
745 format(row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8]))
746
747 def draw_library_detail_page(self):
748 flag = False
749 """
750 Draw title.
751 """
752 self.items = [self.__line1, "{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
753 format("Name",
754 "Flash size",
755 "RAM size",
756 "Code",
757 "RO data",
758 "RW data",
759 "ZI data",
760 "Inc. data"),
761 self.__line2]
762
763 cursor = self.__cur.execute("select * from Library WHERE name = '{}'".
764 format(self.library_name))
765 for row in cursor:
766 self.items.append("{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
767 format(row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7]))
768 break
769
770 """
771 Draw object files.
772 """
773 self.items.append(self.__line1)
774 self.items.append("{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
775 format("Name",
776 "Flash size",
777 "RAM size",
778 "Code",
779 "RO data",
780 "RW data",
781 "ZI data",
782 "Inc. data"))
783 self.items.append(self.__line2)
784
Jianliang Shen28cce572022-05-02 21:44:03 +0800785 cursor = self.__cur.execute("select * from Object WHERE lib_file = '{}' ORDER BY {} {}".
786 format(self.library_name, self.sort, self.order))
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800787 for row in cursor:
788 self.items.append("{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
789 format(row[0], row[2], row[3], row[4], row[5], row[6], row[7], row[8]))
790
791 """
792 Draw functions.
793 """
Jianliang Shen28cce572022-05-02 21:44:03 +0800794 cursor = self.__cur.execute("select * from Function WHERE lib_file = '{}' ORDER BY {} {}".
795 format(self.library_name, self.sort, self.order))
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800796 for row in cursor:
797 if not flag:
798 self.__quick_append()
799 self.items.append("{:<50}{:<32}{:<10}{:<16}{:<40}".
800 format(row[0], row[1], row[2], "Code", row[4]))
801 flag = True
802
803 """
804 Draw RO data.
805 """
Jianliang Shen28cce572022-05-02 21:44:03 +0800806 cursor = self.__cur.execute("select * from Data WHERE type = 'RO' and lib_file = '{}' ORDER BY {} {}".
807 format(self.library_name, self.sort, self.order))
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800808 self.__quick_append_data(cursor)
809
810 """
811 Draw RW data.
812 """
Jianliang Shen28cce572022-05-02 21:44:03 +0800813 cursor = self.__cur.execute("select * from Data WHERE type = 'RW' and lib_file = '{}' ORDER BY {} {}".
814 format(self.library_name, self.sort, self.order))
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800815 self.__quick_append_data(cursor)
816
817 """
818 Draw ZI data.
819 """
Jianliang Shen28cce572022-05-02 21:44:03 +0800820 cursor = self.__cur.execute("select * from Data WHERE type = 'ZI' and lib_file = '{}' ORDER BY {} {}".
821 format(self.library_name, self.sort, self.order))
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800822 self.__quick_append_data(cursor)
823 self.items.append(self.__line1)
824
825 def draw_obj_page(self):
826 self.items = ["{:<50}{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
827 format("Name",
828 "Library",
829 "Flash size",
830 "RAM size",
831 "Code",
832 "RO data",
833 "RW data",
834 "ZI data",
835 "Inc. data",
836 "Debug")]
Jianliang Shen28cce572022-05-02 21:44:03 +0800837 cursor = self.__cur.execute("select * from Object WHERE lib_file = 'no library' ORDER BY {} {}".format(self.sort, self.order))
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800838 for row in cursor:
839 self.items.append("{:<50}{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
840 format(row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8], row[9]))
841 cursor = self.__cur.execute(
Jianliang Shen28cce572022-05-02 21:44:03 +0800842 "select * from Object WHERE lib_file != 'no library' ORDER BY {} {}".format(self.sort, self.order))
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800843 for row in cursor:
844 self.items.append("{:<50}{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
845 format(row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8], row[9]))
846
847 def draw_obj_detail_page(self):
848 flag = False
849 self.items = [self.__line1,
850 "{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
851 format("Name",
852 "Flash size",
853 "RAM size",
854 "Code",
855 "RO data",
856 "RW data",
857 "ZI data",
858 "Inc. data"),
859 self.__line2]
860
861 cursor = self.__cur.execute("select * from Object WHERE name = '{}'".
862 format(self.obj_file))
863 for row in cursor:
864 self.items.append("{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
865 format(row[0], row[2], row[3], row[4], row[5], row[6], row[7], row[8]))
866 break
867
Jianliang Shen28cce572022-05-02 21:44:03 +0800868 cursor = self.__cur.execute("select * from Function WHERE obj_file = '{}' ORDER BY {} {}".
869 format(self.obj_file, self.sort, self.order))
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800870 for row in cursor:
871 if not flag:
872 self.__quick_append()
873 self.items.append("{:<50}{:<32}{:<10}{:<16}{:<40}".
874 format(row[0], row[1], row[2], "Code", row[4]))
875 flag = True
876
Jianliang Shen28cce572022-05-02 21:44:03 +0800877 cursor = self.__cur.execute("select * from Data WHERE type = 'RO' and obj_file = '{}' ORDER BY {} {}".
878 format(self.obj_file, self.sort, self.order))
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800879 self.__quick_append_data(cursor)
880
Jianliang Shen28cce572022-05-02 21:44:03 +0800881 cursor = self.__cur.execute("select * from Data WHERE type = 'RW' and obj_file = '{}' ORDER BY {} {}".
882 format(self.obj_file, self.sort, self.order))
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800883 self.__quick_append_data(cursor)
884
Jianliang Shen28cce572022-05-02 21:44:03 +0800885 cursor = self.__cur.execute("select * from Data WHERE type = 'ZI' and obj_file = '{}' ORDER BY {} {}".
886 format(self.obj_file, self.sort, self.order))
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800887 self.__quick_append_data(cursor)
888 self.items.append(self.__line1)
889
890 def draw_function_page(self, search_func):
891 self.items = []
892 self.items.append("{:<50}{:<50}{:<10}{:<16}{:<40}{:<40}".
893 format("Name",
894 "Section",
895 "Size",
896 "Address",
897 "Object File",
898 "Library"))
899 if search_func:
900 cursor = self.__cur.execute("select * from Function WHERE name LIKE '%{}%'".
901 format(search_func))
902 else:
Jianliang Shen28cce572022-05-02 21:44:03 +0800903 cursor = self.__cur.execute("select * from Function ORDER BY {} {}".format(self.sort, self.order))
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800904 for row in cursor:
905 self.items.append("{:<50}{:<50}{:<10}{:<16}{:<40}{:<40}".
906 format(row[0], row[1], row[2], row[3], row[4], row[5]))
907
908 def draw_function_detail_page(self):
909 if self.obj_file:
910 cursor = self.__cur.execute("select * from Function WHERE name = '{}' and obj_file = '{}'".
911 format(self.function_name, self.obj_file))
912 else:
913 cursor = self.__cur.execute("select * from Function WHERE name = '{}'".
914 format(self.function_name))
915 for row in cursor:
916 self.items = ["=================================================",
917 "Name\t\t\t: {}".format(row[0]),
918 "Symbol type\t\t: Function",
919 "Section\t\t\t: {}".format(row[1]),
920 "Size\t\t\t: {}".format(row[2]),
921 "Base address\t\t: {}".format(row[3]),
922 "Object file\t\t: {}".format(row[4]),
923 "Library\t\t\t: {}".format(row[5]),
924 "================================================="]
925
926 def draw_data_page(self, search_data):
927 self.items = ["{:<50}{:<50}{:<10}{:<16}{:<16}{:<40}{:<40}".
928 format("Name",
929 "Section",
930 "Size",
931 "Address",
932 "Type",
933 "Object File",
934 "Library")]
935 if search_data:
936 cursor = self.__cur.execute("select * from Data WHERE name LIKE '%{}%'".
937 format(search_data))
938 else:
Jianliang Shen28cce572022-05-02 21:44:03 +0800939 cursor = self.__cur.execute("select * from Data ORDER BY {} {}".format(self.sort, self.order))
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800940 for row in cursor:
941 data_name = row[0]
942 if len(data_name) >= 50:
943 data_name = data_name[:40] + "-->"
944 self.items.append("{:<50}{:<50}{:<10}{:<16}{:<16}{:<40}{:<40}".
945 format(data_name, row[1], row[2], row[3], row[4], row[5], row[6]))
946
947 def draw_data_detail_page(self):
948 if self.obj_file:
949 cursor = self.__cur.execute("select * from Data WHERE name = '{}' and obj_file = '{}'".
950 format(self.data_name, self.obj_file))
951 else:
952 cursor = self.__cur.execute("select * from Data WHERE name = '{}'".
953 format(self.data_name))
954
955 for row in cursor:
956 self.items = ["=================================================",
957 "Name\t\t\t: {}".format(row[0]),
958 "Symbol type\t\t: {}".format(row[4]),
959 "Section\t\t\t: {}".format(row[1]),
960 "Size\t\t\t: {}".format(row[2]),
961 "Base address\t\t: {}".format(row[3]),
962 "Object file\t\t: {}".format(row[5]),
963 "Library\t\t\t: {}".format(row[6]),
964 "================================================="]
965
966 def run(self):
967 """
968 Continue running the TUI until get interrupted
969 """
Jianliang Shen28cce572022-05-02 21:44:03 +0800970 self.open_db()
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800971 self.__init_curses()
972 try:
973 self.__draw_page()
974 self.__input_stream()
975 except KeyboardInterrupt:
976 pass
977 finally:
Jianliang Shen28cce572022-05-02 21:44:03 +0800978 self.con.close()
Jianliang Shen9b4ba112022-01-19 14:57:04 +0800979 curses.endwin()