blob: edfaa3eb634023ab6a919dd8deb5d360b8aa84b2 [file] [log] [blame]
Jianliang Shenabf00412021-11-12 10:58:52 +08001# -----------------------------------------------------------------------------
2# Copyright (c) 2021, Arm Limited. All rights reserved.
3#
4# SPDX-License-Identifier: BSD-3-Clause
5#
6# -----------------------------------------------------------------------------
7
8import sqlite3
9import argparse
10import os
11import glob
12import curses
13import curses.textpad
14
15line1 = "─" * 128
16line2 = "-" * 128
17none_databse = "Cannot find database file! Please use this command to create \
18databse:\n\n\tpython3 code_size_analyze.py -i <map file path>\n"
19cmd_file="Enter the file name:"
20cmd_func="Enter the function name:"
21cmd_data="Enter the data name:"
22
23class UI(object):
24 UP, DOWN = -1, 1
25
26 def __init__(self):
27 """
28 Initialize variables.
29 """
30 self.con = sqlite3.connect("data.db")
31 self.cur = self.con.cursor()
32
33 # Window variables
34 self.window = None
35 self.width = 0
36 self.height = 0
37
38 # Page variables
39 self.items = []
40
41 # Menu variables
42 self.menu_depth = 0
43 self.detail = 0
44 self.section_detail = 0
45
46 # Internal variables
47 self.file_name = ""
48 self.function_name = ""
49 self.data_name = ""
50 self.section_name = ""
51 self.library_name = ""
52 self.obj_file = ""
53
54 def init_curses(self):
55 """
56 Setup the curses
57 """
58 self.window = curses.initscr()
59 self.window.keypad(True)
60
61 curses.noecho()
62 curses.cbreak()
63 curses.curs_set(False)
64
65 curses.start_color()
66 curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLACK)
67 curses.init_pair(2, curses.COLOR_BLACK, curses.COLOR_WHITE)
68
69 self.current = curses.color_pair(2)
70 self.height, self.width = self.window.getmaxyx()
71
72 self.max_lines = curses.LINES - 1
73 self.top = 0
74
75 self.bottom = len(self.items)
76 self.current = 0
77 self.current_x = 0
78 self.page = self.bottom // self.max_lines
79
80 def run(self):
81 """
82 Continue running the TUI until get interrupted
83 """
84 # Create window.
85 self.init_curses()
86 try:
87 self.draw_page()
88 self.input_stream() # Get keys input
89 except KeyboardInterrupt:
90 pass
91 finally:
92 curses.endwin()
93
94 def input_stream(self):
95 """
96 Waiting an input and run a proper method according to type of input
97 """
98 while True:
99 self.display()
100
101 ch = self.window.getch()
102 if ch == curses.KEY_UP:
103 self.scroll(self.UP)
104 elif ch == curses.KEY_DOWN:
105 self.scroll(self.DOWN)
106 elif ch == curses.KEY_LEFT:
107 self.current_x = max(self.current_x - 1, 0)
108 elif ch == curses.KEY_RIGHT:
109 self.current_x = self.current_x + 1
110 # If press 'q' or 'Q', escape this page
111 elif ch == ord('q') or ch == ord('Q'):
112 if self.menu_depth == 0:
113 break
114 self.menu_depth = max(self.menu_depth - 1, 0)
115 self.draw_page()
116 # If press ENTER, get into next page if it exists
117 elif ch == 10:
118 self.get_menu_choose()
119 self.menu_depth = self.menu_depth + 1
120 self.draw_page()
121 # If press ':', get target name form input line
122 elif ch == 58:
123 if self.menu_depth == 1:
124 # Search functions or data
125 if self.detail == 3:
126 self.draw_function_page(self.get_input_line_msg(cmd_func))
127 if self.detail == 4:
128 self.draw_data_page(self.get_input_line_msg(cmd_data))
129 # If press 's' or 'S', save to file
130 elif ch == ord('s') or ch == ord('S'):
131 self.save_file(self.get_input_line_msg(cmd_file))
132
133 def get_input_line_msg(self, cmd):
134 """
135 Get message from input line.
136 """
137 self.window.addstr(self.height - 1, 0,
138 cmd,
139 curses.color_pair(2))
140 self.input_line = curses.newwin(1,
141 curses.COLS - 2 - len(cmd),
142 curses.LINES-1,
143 len(cmd) + 1)
144 self.input_box = curses.textpad.Textbox(self.input_line)
145 self.window.refresh()
146 self.input_box.edit()
147 ret = self.input_box.gather()[:len(self.input_box.gather())-1]
148 self.display()
149 self.input_line.clear()
150 return ret
151
152 def save_file(self, output_file_name):
153 """
154 Save to files
155 """
156 fo = open(output_file_name + '.txt', "w")
157 for s in self.items:
158 fo.write(s + '\n')
159 fo.close()
160
161 def scroll(self, direction):
162 """
163 Scrolling the window when pressing up/down arrow keys
164 """
165 next_line = self.current + direction
166 if (direction == self.UP) and (self.top > 0 and self.current == 0):
167 self.top += direction
168 return
169 if (direction == self.DOWN) and (next_line == self.max_lines) and \
170 (self.top + self.max_lines < self.bottom):
171 self.top += direction
172 return
173 if (direction == self.UP) and (self.top > 0 or self.current > 0):
174 self.current = next_line
175 return
176 if (direction == self.DOWN) and (next_line < self.max_lines) and \
177 (self.top + next_line < self.bottom):
178 self.current = next_line
179 return
180
181 def paging(self, direction):
182 """
183 Paging the window when pressing left/right arrow keys
184 """
185 current_page = (self.top + self.current) // self.max_lines
186 next_page = current_page + direction
187 if next_page == self.page:
188 self.current = min(self.current, self.bottom % self.max_lines - 1)
189 if (direction == self.UP) and (current_page > 0):
190 self.top = max(0, self.top - self.max_lines)
191 return
192 if (direction == self.DOWN) and (current_page < self.page):
193 self.top += self.max_lines
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 +
202 self.max_lines]):
203 if idx == self.current:
204 self.window.addstr(idx, 0,
205 item[self.current_x:self.current_x +
206 self.width],
207 curses.color_pair(2))
208 else:
209 self.window.addstr(idx, 0,
210 item[self.current_x:self.current_x +
211 self.width],
212 curses.color_pair(1))
213 self.window.refresh()
214
215 def draw_page(self):
216 """
217 Draw different page with menu_depth, detail and section_detail.
218 """
219 if self.menu_depth == 0:
220 self.draw_file_page()
221 elif self.menu_depth == 1:
222 if self.detail == 1:
223 self.draw_summary_page()
224 if self.detail == 2:
225 self.draw_section_page()
226 if self.detail == 3:
227 self.draw_function_page("")
228 if self.detail == 4:
229 self.draw_data_page("")
230 if self.detail == 5:
231 self.draw_library_page()
232 if self.detail == 6:
233 self.draw_obj_page()
234 elif self.menu_depth == 2:
235 if self.detail == 2:
236 self.draw_section_detail_page()
237 if self.detail == 3:
238 self.draw_function_detail_page()
239 if self.detail == 4:
240 self.draw_data_detail_page()
241 if self.detail == 5:
242 self.draw_library_detail_page()
243 if self.detail == 6:
244 self.draw_obj_detail_page()
245 # Draw section detail menu, here self.detail is 2
246 elif self.menu_depth == 3 and self.detail == 2:
247 if self.section_detail == 1:
248 self.draw_section_lib()
249 if self.section_detail == 2:
250 self.draw_section_func()
251 if self.section_detail == 3:
252 self.draw_section_data()
253 # Only section detail menu can move to menu depth 5, here function
254 # detail and data detail are also supported.
255 elif self.menu_depth == 4:
256 if self.section_detail == 2:
257 self.draw_function_detail_page()
258 if self.section_detail == 3:
259 self.draw_data_detail_page()
260
261 # Refresh page variables
262 self.bottom = len(self.items)
263 self.current = 0
264 self.current_x = 0
265 self.top = 0
266 self.page = self.bottom // self.max_lines
267
268 def get_menu_choose(self):
269 """
270 Get options from menus or specific objects like function, data, library
271 or object files.
272 """
273
274 """
275 First page, menu_depth = 1
276 =============================
277 Current file: tfm_s.axf
278 1. Summary Info -->
279 2. Section Module -->
280 3. Function detail -->
281 4. Data detail -->
282 5. Library Summary -->
283 6. Object files Summary -->
284 =============================
285 It will change the self.detail's value in range 1 - 6
286 """
287 if self.menu_depth == 0:
288 if self.current + self.top > 0:
289 self.detail = self.current
290 else:
291 # Except first line
292 self.menu_depth = self.menu_depth - 1
293 if self.menu_depth == 1:
294 if self.current + self.top > 0:
295 # Get section name which will be used to draw its detail page in
296 # draw_page() function.
297 if self.detail == 2:
298 self.section_name = \
299 self.items[self.top + self.current].split()[0]
300 # Get function name and its object file to avoid same name
301 # situation. Function name will be used to draw its detail page
302 # in draw_page() function.
303 elif self.detail == 3:
304 self.function_name = \
305 self.items[self.top + self.current].split()[0]
306 self.obj_file = \
307 self.items[self.top + self.current].split()[4]
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 elif self.detail == 4:
312 self.data_name = \
313 self.items[self.top + self.current].split()[0]
314 self.obj_file = \
315 self.items[self.top + self.current].split()[5]
316 # Get library name which will be used to draw its detail page in
317 # draw_page() function.
318 elif self.detail == 5:
319 self.library_name = \
320 self.items[self.top + self.current].split()[0]
321 # Get object file name which will be used to draw its detail
322 # page in draw_page() function.
323 elif self.detail == 6:
324 self.obj_file = \
325 self.items[self.top + self.current].split()[0]
326 else:
327 # Other invalid choose will not change menu depth.
328 self.menu_depth = self.menu_depth - 1
329 else:
330 # Except first line
331 self.menu_depth = self.menu_depth - 1
332 """
333 Section detail page, menu_depth = 1
334 =============================
335 Name :TFM_UNPRIV_CODE Size :155544
336 1. Summary -->
337 2. Function -->
338 3. Data -->
339 =============================
340 It will change the self.section_detail's value in range 1 - 3
341 """
342 if self.menu_depth == 2:
343 if self.current + self.top > 0:
344 if self.detail == 2:
345 self.section_detail = self.current
346 else:
347 # Only section page's detail can change menu depth.
348 self.menu_depth = self.menu_depth - 1
349 else:
350 # Except first line
351 self.menu_depth = self.menu_depth - 1
352 if self.menu_depth == 3:
353 if self.current + self.top > 0:
354 # Get function name and its object file to avoid same name
355 # situation. Function name will be used to draw its detail page
356 # in draw_page() function.
357 if self.section_detail == 2:
358 self.function_name = \
359 self.items[self.top + self.current].split()[0]
360 self.obj_file = \
361 self.items[self.top + self.current].split()[4]
362 # Get data name and its object file name to avoid same name
363 # situation. Data name will be used to draw its detail page in
364 # draw_page() function.
365 elif self.section_detail == 3:
366 self.data_name = \
367 self.items[self.top + self.current].split()[0]
368 self.obj_file = \
369 self.items[self.top + self.current].split()[5]
370 else:
371 # Other invalid choose will not change menu depth.
372 self.menu_depth = self.menu_depth - 1
373 else:
374 # Except first line
375 self.menu_depth = self.menu_depth - 1
376 if self.menu_depth == 4:
377 # Max menu depth.
378 self.menu_depth = self.menu_depth - 1
379
380 def draw_file_page(self):
381 self.items = ["Code Size Analysis Tool for Map File",
382 "1. Summary Info -->",
383 "2. Section Module -->",
384 "3. Function detail -->",
385 "4. Data detail -->",
386 "5. Library Summary -->",
387 "6. Object files Summary -->"]
388
389 def draw_summary_page(self):
390 """
391 Get summary info from database and save into self.items.
392 """
393 cursor = self.cur.execute("select * from Summary")
394 for row in cursor:
395 self.items = ["Code size\t: {:<8}\t{:<4.2f}\tKB".
396 format(row[0], row[0]/1024),
397 "RO data\t\t: {:<8}\t{:<4.2f}\tKB".
398 format(row[1], row[1]/1024),
399 "RW data\t\t: {:<8}\t{:<4.2f}\tKB".
400 format(row[2], row[2]/1024),
401 "ZI data\t\t: {:<8}\t{:<4.2f}\tKB".
402 format(row[3], row[3]/1024),
403 "Flash size\t: {:<8}\t{:<4.2f}\tKB = Code + RO + RW".
404 format(row[4], row[4]/1024),
405 "RAM size\t: {:<8}\t{:<4.2f}\tKB = RW + ZI".
406 format(row[5], row[5]/1024)]
407 break
408
409 def draw_section_page(self):
410 """
411 Get section info from database and save into self.items.
412 """
413 self.items = ["{:<50}{:<16}{:<16}{:<16}".
414 format("Name", "Size", "Address", "PAD size")]
415
416 cursor = self.cur.execute("select * from Section ORDER BY size DESC")
417 for row in cursor:
418 self.items.append("{:<50}{:<16}{:<16}{:<16}".
419 format(row[0], row[1], row[2], row[3]))
420
421 def draw_section_detail_page(self):
422 """
423 Section detail page with a menu.
424 """
425 cursor = self.cur.execute("select * from Section WHERE name = '{}'".
426 format(self.section_name))
427 for row in cursor:
428 self.items = ["Name :{}\t\tSize :{}".
429 format(self.section_name, row[1]),
430 "1. Summary -->",
431 "2. Function -->",
432 "3. Data -->"]
433 break
434
435 def draw_section_lib(self):
436 lib_dict, obj_dict = {}, {}
437 lib_list, obj_list = [], []
438 exsit_no_lib_obj = False
439 tmp_list = []
440 colums_name = "{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".format(
441 "Name", "Flash", "RAM", "Code", "RO data", "RW data", "ZI data", "Total")
442 count = 0
443
444 """
445 Get detail information with functions and data from tables in database
446 with a dictionary in python.
447 """
448 cursor = self.cur.execute("select * from Function WHERE section = '{}' ORDER BY lib_file DESC".
449 format(self.section_name))
450 for row in cursor:
451 lib_name = row[5]
452 if lib_name in lib_dict.keys():
453 lib_dict[lib_name]['Code'] += row[2]
454 else:
455 lib_dict[lib_name] = {'RO': 0, 'RW': 0,
456 'Code': row[2], 'ZI': 0}
457
458 obj_name = row[4]
459 if obj_name in obj_dict.keys():
460 obj_dict[obj_name]['Code'] += row[2]
461 else:
462 obj_dict[obj_name] = {'RO': 0, 'RW': 0,
463 'Code': row[2], 'Lib': lib_name, 'ZI': 0}
464
465 cursor = self.cur.execute("select * from Data WHERE section = '{}' ORDER BY lib_file DESC".
466 format(self.section_name))
467 for row in cursor:
468 lib_name = row[6]
469 if lib_name in lib_dict.keys():
470 lib_dict[lib_name][row[4]] += row[2]
471 else:
472 lib_dict[lib_name] = {'RO': 0, 'RW': 0, 'Code': 0, 'ZI': 0}
473 lib_dict[lib_name][row[4]] = row[2]
474
475 obj_name = row[5]
476 if obj_name in obj_dict.keys():
477 obj_dict[obj_name][row[4]] += row[2]
478 else:
479 obj_dict[obj_name] = {'RO': 0, 'RW': 0,
480 'Code': 0, 'Lib': lib_name, 'ZI': 0}
481 obj_dict[obj_name][row[4]] = row[2]
482
483 """
484 Transform the dictionary to a dictionary list in python and sort the
485 elements with total size.
486 """
487 for s in lib_dict.keys():
488 lib_list.append({'Name': s,
489 'RO': lib_dict[s]['RO'],
490 'RW': lib_dict[s]['RW'],
491 'Code': lib_dict[s]['Code'],
492 'ZI': lib_dict[s]['ZI']})
493 lib_list = sorted(lib_list,
494 key=lambda i: i['RO'] +
495 i['Code'] + i['RW'] + i['ZI'],
496 reverse=True)
497 for s in obj_dict.keys():
498 obj_list.append({'Name': s,
499 'RO': obj_dict[s]['RO'],
500 'RW': obj_dict[s]['RW'],
501 'Code': obj_dict[s]['Code'],
502 'Lib': obj_dict[s]['Lib'],
503 'ZI': obj_dict[s]['ZI']})
504 obj_list = sorted(obj_list,
505 key=lambda i: i['RO'] +
506 i['Code'] + i['RW'] + i['ZI'],
507 reverse=True)
508
509 def sum_data(data_list):
510 """
511 Calculate the sum of libraries or object files, and implement total
512 data line. It will be added into self.items.
513 """
514 ret = {'RO': 0, 'RW': 0, 'Code': 0, 'ZI': 0,
515 'Flash': 0, 'Ram': 0, 'Total': 0}
516 if len(data_list) > 0:
517 for s in data_list:
518 ret['Code'] += s['Code']
519 ret['RO'] += s['RO']
520 ret['RW'] += s['RW']
521 ret['ZI'] += s['ZI']
522 ret['Flash'] += s['Code'] + s['RO'] + s['RW']
523 ret['Ram'] += s['RW'] + s['ZI']
524 ret['Total'] = ret['Flash'] + ret['ZI']
525 self.items.append(line2)
526 self.items.append("{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
527 format("Summary",
528 ret['Flash'],
529 ret['Ram'],
530 ret['Code'],
531 ret['RO'],
532 ret['RW'],
533 ret['ZI'],
534 ret['Total']))
535 self.items.append(line1)
536 return ret
537
538 def insert_column_line(title):
539 """
540 Quickly insert column line.
541 """
542 self.items.append(title)
543 self.items.append(line2)
544 self.items.append(colums_name)
545 self.items.append(line2)
546
547 def quick_insert_data_line(s):
548 """
549 Quickly insert a single data line.
550 """
551 self.items.append("{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
552 format(s['Name'],
553 s['Code'] + s['RO'] + s['RW'],
554 s['RW'] + s['ZI'],
555 s['Code'],
556 s['RO'],
557 s['RW'],
558 s['ZI'],
559 s['Code'] + s['RO'] + s['RW'] + s['ZI']))
560 """
561 Dump library information.
562 """
563 self.items = [line1]
564 insert_column_line("\t\t\t\t\t\t\tSection libraries")
565 for s in lib_list:
566 if s['Name'].find(".o") > 0:
567 exsit_no_lib_obj = True
568 else:
569 tmp_list.append(s)
570 quick_insert_data_line(s)
571 sum_data(tmp_list)
572
573 """
574 Dump object file information.
575 """
576 insert_column_line("\t\t\t\t\t\t\tSection object files")
577 for s in obj_list:
578 quick_insert_data_line(s)
579 ret = sum_data(obj_list)
580 total_flash_size, total_ram_size = ret['Flash'], ret['Ram']
581
582 """
583 Dump NOT-IN-LIBRARY object file information.
584 """
585 if exsit_no_lib_obj:
586 insert_column_line(
587 "\t\t\t\t\t\t\tSection NOT-IN-LIBRARY object files")
588 tmp_list = []
589 for s in lib_list:
590 if s['Name'].find(".o") > 0:
591 tmp_list.append(s)
592 quick_insert_data_line(s)
593 sum_data(tmp_list)
594
595 """
596 Insert the summary information at the top of this page.
597 """
598 cursor = self.cur.execute(
599 "select * from Section WHERE name = '{}'".format(self.section_name))
600 for row in cursor:
601 self.items.insert(0, "Section Name :{}\tTotal Size :{}\tFlash : {}\tRAM : {:<6}\tPad size = {}".
602 format(self.section_name, row[1], total_flash_size, total_ram_size, row[3]))
603 break
604 self.items.insert(0, line2)
605 self.items.insert(0, "\t\t\t\t\t\t\tSection information")
606 self.items.insert(0, line1)
607
608 """
609 Dump detail information of the section.
610 """
611 index = 4 * ' '
612 self.items.append("\t\t\t\t\t\t\tDetail information")
613 self.items.append(line2)
614 for s in lib_list:
615 self.items.append("{} Code Size = {} RO Data = {} RW Data = {} ZI Data = {}".
616 format(s['Name'], s['Code'], s['RO'], s['RW'], s['ZI']))
617 for t in obj_list:
618 if t['Lib'] == s['Name']:
619 self.items.append(index + "{} Code Size = {} RO Data = {} RW Data = {} ZI Data = {}".format(
620 t['Name'], t['Code'], t['RO'], t['RW'], t['ZI']))
621 count = 0
622 cursor = self.cur.execute("select * from Function WHERE section = '{}' and lib_file = '{}' and obj_file = '{}' ORDER BY size DESC".
623 format(self.section_name,
624 s['Name'],
625 t['Name']))
626 for row in cursor:
627 if row and count == 0:
628 self.items.append(index * 2 + "Code size = {}".
629 format(t['Code']))
630 count = count + 1
631 self.items.append(index * 3 + "{:<6} {} ".
632 format(row[2], row[0]))
633
634 def get_certain_data(type_name, s, t):
635 count = 0
636 cursor = self.cur.execute("select * from Data WHERE section = '{}' and lib_file = '{}' and obj_file = '{}' and type = '{}' ORDER BY size DESC".
637 format(self.section_name,
638 s['Name'],
639 t['Name'],
640 type_name))
641 for row in cursor:
642 if row and count == 0:
643 self.items.append(index * 2 + "{} Data = {}".
644 format(type_name, t[type_name]))
645 count = count + 1
646 self.items.append(index * 3 + "{:<6} {}".
647 format(row[2], row[0]))
648
649 get_certain_data('RO', s, t)
650 get_certain_data('RW', s, t)
651 get_certain_data('ZI', s, t)
652 self.items.append(line2)
653
654 def draw_section_func(self):
655 self.items = ["{:<50}{:<32}{:<10}{:<16}{:<40}{:<40}".
656 format("Name",
657 "Section",
658 "Size",
659 "Address",
660 "Object File",
661 "Library")]
662 cursor = self.cur.execute("select * from Function WHERE section = '{}' ORDER BY size DESC".
663 format(self.section_name))
664 for row in cursor:
665 self.items.append("{:<50}{:<32}{:<10}{:<16}{:<40}{:<40}".
666 format(row[0], row[1], row[2], row[3], row[4], row[5]))
667
668 def draw_section_data(self):
669 self.items = ["{:<50}{:<32}{:<10}{:<16}{:<16}{:<40}{:<40}".
670 format("Name",
671 "Section",
672 "Size",
673 "Address",
674 "Type",
675 "Object File",
676 "Library")]
677
678 cursor = self.cur.execute("select * from Data WHERE section = '{}' ORDER BY size DESC".
679 format(self.section_name))
680 for row in cursor:
681 data_name = row[0]
682 if len(data_name) >= 50:
683 data_name = data_name[:40] + "-->"
684 self.items.append("{:<50}{:<32}{:<10}{:<16}{:<16}{:<40}{:<40}".
685 format(data_name, row[1], row[2], row[3], row[4], row[5], row[6]))
686
687 def quick_append(self):
688 self.items.append(line1)
689
690 self.items.append("{:<50}{:<32}{:<10}{:<16}{:<40}".
691 format("Name",
692 "Section",
693 "Size",
694 "Type",
695 "Object File"))
696 self.items.append(line2)
697
698 def quick_append_data(self, cursor):
699 flag = False
700 for row in cursor:
701 if not flag:
702 self.quick_append()
703 data_name = row[0]
704 if len(data_name) >= 50:
705 data_name = data_name[:40] + "-->"
706 self.items.append("{:<50}{:<32}{:<10}{:<16}{:<40}".
707 format(data_name, row[1], row[2], row[4], row[5]))
708 flag = True
709
710 def draw_library_page(self):
711 self.items = ["{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
712 format("Name",
713 "Flash size",
714 "RAM size",
715 "Code",
716 "RO data",
717 "RW data",
718 "ZI data",
719 "Inc. data",
720 "Debug")]
721
722 cursor = self.cur.execute(
723 "select * from Library ORDER BY flashsize DESC")
724 for row in cursor:
725 self.items.append("{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
726 format(row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8]))
727
728 def draw_library_detail_page(self):
729 flag = False
730 """
731 Draw title.
732 """
733 self.items = [line1, "{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
734 format("Name",
735 "Flash size",
736 "RAM size",
737 "Code",
738 "RO data",
739 "RW data",
740 "ZI data",
741 "Inc. data"),
742 line2]
743
744 cursor = self.cur.execute("select * from Library WHERE name = '{}'".
745 format(self.library_name))
746 for row in cursor:
747 self.items.append("{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
748 format(row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7]))
749 break
750
751 """
752 Draw object files.
753 """
754 self.items.append(line1)
755 self.items.append("{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
756 format("Name",
757 "Flash size",
758 "RAM size",
759 "Code",
760 "RO data",
761 "RW data",
762 "ZI data",
763 "Inc. data"))
764 self.items.append(line2)
765
766 cursor = self.cur.execute("select * from Object WHERE library = '{}' ORDER BY flashsize DESC".
767 format(self.library_name))
768 for row in cursor:
769 self.items.append("{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
770 format(row[0], row[2], row[3], row[4], row[5], row[6], row[7], row[8]))
771
772 """
773 Draw functions.
774 """
775 cursor = self.cur.execute("select * from Function WHERE lib_file = '{}' ORDER BY size DESC".
776 format(self.library_name))
777 for row in cursor:
778 if not flag:
779 self.quick_append()
780 self.items.append("{:<50}{:<32}{:<10}{:<16}{:<40}".
781 format(row[0], row[1], row[2], "Code", row[4]))
782 flag = True
783
784 """
785 Draw RO data.
786 """
787 cursor = self.cur.execute("select * from Data WHERE type = 'RO' and lib_file = '{}' ORDER BY size DESC".
788 format(self.library_name))
789 self.quick_append_data(cursor)
790
791 """
792 Draw RW data.
793 """
794 cursor = self.cur.execute("select * from Data WHERE type = 'RW' and lib_file = '{}' ORDER BY size DESC".
795 format(self.library_name))
796 self.quick_append_data(cursor)
797
798 """
799 Draw ZI data.
800 """
801 cursor = self.cur.execute("select * from Data WHERE type = 'ZI' and lib_file = '{}' ORDER BY size DESC".
802 format(self.library_name))
803 self.quick_append_data(cursor)
804 self.items.append(line1)
805
806 def draw_obj_page(self):
807 self.items = ["{:<50}{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
808 format("Name",
809 "Library",
810 "Flash size",
811 "RAM size",
812 "Code",
813 "RO data",
814 "RW data",
815 "ZI data",
816 "Inc. data",
817 "Debug")]
818 cursor = self.cur.execute(
819 "select * from Object WHERE library = 'no library' ORDER BY flashsize DESC")
820 for row in cursor:
821 self.items.append("{:<50}{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
822 format(row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8], row[9]))
823 cursor = self.cur.execute(
824 "select * from Object WHERE library != 'no library' ORDER BY flashsize DESC")
825 for row in cursor:
826 self.items.append("{:<50}{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
827 format(row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8], row[9]))
828
829 def draw_obj_detail_page(self):
830 flag = False
831 self.items = [line1,
832 "{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
833 format("Name",
834 "Flash size",
835 "RAM size",
836 "Code",
837 "RO data",
838 "RW data",
839 "ZI data",
840 "Inc. data"),
841 line2]
842
843 cursor = self.cur.execute("select * from Object WHERE name = '{}'".
844 format(self.obj_file))
845 for row in cursor:
846 self.items.append("{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
847 format(row[0], row[2], row[3], row[4], row[5], row[6], row[7], row[8]))
848 break
849
850 cursor = self.cur.execute("select * from Function WHERE obj_file = '{}' ORDER BY size DESC".
851 format(self.obj_file))
852 for row in cursor:
853 if not flag:
854 self.quick_append()
855 self.items.append("{:<50}{:<32}{:<10}{:<16}{:<40}".
856 format(row[0], row[1], row[2], "Code", row[4]))
857 flag = True
858
859 cursor = self.cur.execute("select * from Data WHERE type = 'RO' and obj_file = '{}' ORDER BY size DESC".
860 format(self.obj_file))
861 self.quick_append_data(cursor)
862
863 cursor = self.cur.execute("select * from Data WHERE type = 'RW' and obj_file = '{}' ORDER BY size DESC".
864 format(self.obj_file))
865 self.quick_append_data(cursor)
866
867 cursor = self.cur.execute("select * from Data WHERE type = 'ZI' and obj_file = '{}' ORDER BY size DESC".
868 format(self.obj_file))
869 self.quick_append_data(cursor)
870 self.items.append(line1)
871
872 def draw_function_page(self, search_func):
873 self.items = []
874 self.items.append("{:<50}{:<50}{:<10}{:<16}{:<40}{:<40}".
875 format("Name",
876 "Section",
877 "Size",
878 "Address",
879 "Object File",
880 "Library"))
881 if search_func:
882 cursor = self.cur.execute("select * from Function WHERE name LIKE '%{}%'".
883 format(search_func))
884 else:
885 cursor = self.cur.execute(
886 "select * from Function ORDER BY size DESC")
887 for row in cursor:
888 self.items.append("{:<50}{:<50}{:<10}{:<16}{:<40}{:<40}".
889 format(row[0], row[1], row[2], row[3], row[4], row[5]))
890
891 def draw_function_detail_page(self):
892 if self.obj_file:
893 cursor = self.cur.execute("select * from Function WHERE name = '{}' and obj_file = '{}'".
894 format(self.function_name, self.obj_file))
895 else:
896 cursor = self.cur.execute("select * from Function WHERE name = '{}'".
897 format(self.function_name))
898 for row in cursor:
899 self.items = ["=================================================",
900 "Name\t\t\t: {}".format(row[0]),
901 "Symbol type\t\t: Function",
902 "Section\t\t\t: {}".format(row[1]),
903 "Size\t\t\t: {}".format(row[2]),
904 "Base address\t\t: {}".format(row[3]),
905 "Object file\t\t: {}".format(row[4]),
906 "Library\t\t\t: {}".format(row[5]),
907 "================================================="]
908 self.items.append("Called symbol:")
909 content = row[6].split('|')
910 for s in content:
911 self.items.append("\t"+s)
912 self.items.append("Dst symbol:")
913 content = row[7].split('|')
914 for s in content:
915 self.items.append("\t"+s)
916
917 def draw_data_page(self, search_data):
918 self.items = ["{:<50}{:<50}{:<10}{:<16}{:<16}{:<40}{:<40}".
919 format("Name",
920 "Section",
921 "Size",
922 "Address",
923 "Type",
924 "Object File",
925 "Library")]
926 if search_data:
927 cursor = self.cur.execute("select * from Data WHERE name LIKE '%{}%'".
928 format(search_data))
929 else:
930 cursor = self.cur.execute("select * from Data ORDER BY size DESC")
931 for row in cursor:
932 data_name = row[0]
933 if len(data_name) >= 50:
934 data_name = data_name[:40] + "-->"
935 self.items.append("{:<50}{:<50}{:<10}{:<16}{:<16}{:<40}{:<40}".
936 format(data_name, row[1], row[2], row[3], row[4], row[5], row[6]))
937
938 def draw_data_detail_page(self):
939 if self.obj_file:
940 cursor = self.cur.execute("select * from Data WHERE name = '{}' and obj_file = '{}'".
941 format(self.data_name, self.obj_file))
942 else:
943 cursor = self.cur.execute("select * from Data WHERE name = '{}'".
944 format(self.data_name))
945
946
947 for row in cursor:
948 self.items = ["=================================================",
949 "Name\t\t\t: {}".format(row[0]),
950 "Symbol type\t\t: {}".format(row[4]),
951 "Section\t\t\t: {}".format(row[1]),
952 "Size\t\t\t: {}".format(row[2]),
953 "Base address\t\t: {}".format(row[3]),
954 "Object file\t\t: {}".format(row[5]),
955 "Library\t\t\t: {}".format(row[6]),
956 "================================================="]
957 self.items.append("Called symbol:")
958 content = row[7].split('|')
959 for s in content:
960 self.items.append("\t"+s)
961 self.items.append("Dst symbol:")
962 content = row[8].split('|')
963 for s in content:
964 self.items.append("\t"+s)
965
966def collect_summary():
967 """
968 Program Size: Code=181622 RO-data=26226 RW-data=3128 ZI-data=79364
969 """
970 cur.execute('''create table Summary
971 (Code INT NOT NULL,
972 RO_data INT NOT NULL,
973 RW_data INT NOT NULL,
974 ZI_data INT NOT NULL,
975 Flash INT NOT NULL,
976 RAM INT NOT NULL
977 );''')
978 code_size = ro_data = rw_data = zi_data = flash_size = ram_size = 0
979 if gnuarm:
980 for s in gnuarm_info:
981 if s[3] == "text":
982 code_size += s[1]
983 if s[3] == "rodata":
984 ro_data += s[1]
985 if s[3] == "data":
986 rw_data += s[1]
987 if s[3] == "bss":
988 zi_data += s[1]
989 elif armcc:
990 for line in open(file_path, "r"):
991 if line.find("gram Size: Code=") > 0:
992 content = line.split()
993 code_size = int(content[2].split('=')[1])
994 ro_data = int(content[3].split('=')[1])
995 rw_data = int(content[4].split('=')[1])
996 zi_data = int(content[5].split('=')[1])
997 flash_size = code_size + ro_data + rw_data
998 ram_size = rw_data + zi_data
999 cur.execute("insert into Summary values (?,?,?,?,?,?)",
1000 (code_size, ro_data, rw_data, zi_data, flash_size, ram_size))
1001
1002def collect_section():
1003 cur.execute('''create table Section
1004 (name TEXT NOT NULL,
1005 size INT NOT NULL,
1006 address TEXT NOT NULL,
1007 pad_size INT NOT NULL
1008 );''')
1009 cur.execute('''create table Function
1010 (name TEXT NOT NULL,
1011 section TEXT NOT NULL,
1012 size INT NOT NULL,
1013 base_addr TEXT NOT NULL,
1014 obj_file TEXT NOT_NULL,
1015 lib_file TEXT NOT_NULL,
1016 called_symbol STRING NOT_NULL,
1017 dst_symbol STRING NOT_NULL
1018 );''')
1019 cur.execute('''create table Data
1020 (name TEXT NOT NULL,
1021 section TEXT NOT NULL,
1022 size INT NOT NULL,
1023 base_addr TEXT NOT NULL,
1024 type TEXT NOT NULL,
1025 obj_file TEXT NOT_NULL,
1026 lib_file TEXT NOT_NULL,
1027 called_symbol TEXT NOT_NULL,
1028 dst_symbol TEXT NOT_NULL
1029 );''')
1030 if gnuarm:
1031 for s in gnuarm_info:
1032 if s[3] == "text":
1033 cur.execute("insert into Function values (?, ?, ?, ?, ?, ?, ?, ?)",
1034 (s[0], "Unknown", s[1], s[2], s[4], s[5], "", ""))
1035 if s[3] == "rodata":
1036 cur.execute("insert into Data values (?, ?, ?, ?, ?, ?, ?, ?, ?)",
1037 (s[0], "Unknown", s[1], s[2], "RO", s[4], s[5], "", ""))
1038 if s[3] == "data":
1039 cur.execute("insert into Data values (?, ?, ?, ?, ?, ?, ?, ?, ?)",
1040 (s[0], "Unknown", s[1], s[2], "RW", s[4], s[5], "", ""))
1041 if s[3] == "bss":
1042 cur.execute("insert into Data values (?, ?, ?, ?, ?, ?, ?, ?, ?)",
1043 (s[0], "Unknown", s[1], s[2], "ZI", s[4], s[5], "", ""))
1044 elif armcc:
1045 """
1046 Execution Region TFM_UNPRIV_CODE (Base: 0x10085360, Size: 0x000327e0, Max: 0xffffffff, ABSOLUTE)
1047
1048 Base Addr Size Type Attr Idx E Section Name Object
1049
1050 0x10085360 0x00000008 Code RO 3759 * !!!main c_w.l(__main.o)
1051 0x10085368 0x00000034 Code RO 4234 !!!scatter c_w.l(__scatter.o)
1052 0x1008539c 0x0000005a Code RO 4232 !!dczerorl2 c_w.l(__dczerorl2.o)
1053 """
1054 line_idx, line_start = 0, 0
1055 section_name = ""
1056 section_addr = ""
1057 section_size = 0
1058 section_pad_size = 0
1059 for line in open(file_path, "r"):
1060 line_idx += 1
1061
1062 if line.find("Execution Region") > 0:
1063 if len(section_name) > 0:
1064 cur.execute("insert into Section values (?, ?, ?, ?)",
1065 (section_name, section_size, section_addr, section_pad_size))
1066 line_start = line_idx + 1
1067
1068 content = line.split()
1069 if len(content) >= 10:
1070 section_name = content[2]
1071 section_addr = content[4][:-1]
1072 section_size = int(content[6][:-1], 16)
1073 section_pad_size = 0
1074 if line.find("PAD\n") > 0 and line_idx > line_start and line_start > 0:
1075 section_pad_size += int(line.split()[1], 16)
1076 if line.find(" Code ") > 0:
1077 content = line.split()
1078 if len(content) >= 7:
1079 if line.find(" * ") > 0:
1080 content.remove("*")
1081 func_name = content[5].strip().split('.')[-1]
1082 dst_symbol, called_symbol = "", ""
1083 if content[6].find('(') > 0:
1084 object_file = content[6][content[6].find(
1085 '(') + 1: -1]
1086 lib_file = content[6][:content[6].find(
1087 '(')]
1088 else:
1089 object_file = lib_file = content[6]
1090 for line in open(file_path, "r"):
1091 if line.find(func_name) > 0:
1092 if line.find("refers to {}({}".format(object_file, content[5].strip())) > 0 or line.find("refers (Special) to {}({}".format(object_file, content[5].strip())) > 0:
1093 dst_symbol = dst_symbol + get_dst(line, func_name)
1094 elif line.find("{}({}) refers to".format(object_file, content[5].strip())) > 0 or \
1095 line.find('{}({}) refers (Special) to'.format(object_file, content[5].strip())) > 0:
1096 called_symbol = called_symbol + \
1097 get_src(line, func_name)
1098 cur.execute("insert into Function values (?, ?, ?, ?, ?, ?, ?, ?)",
1099 (func_name,
1100 section_name,
1101 int(content[1].strip(), 16),
1102 content[0].strip(),
1103 object_file,
1104 lib_file,
1105 called_symbol,
1106 dst_symbol))
1107 if line.find(" Data ") > 0 or line.find(" Zero ") > 0:
1108 content = line.split()
1109 if len(content) == 7:
1110 dst_symbol, called_symbol = "", ""
1111 if content[2] == "Zero":
1112 data_type = "ZI"
1113 else:
1114 data_type = content[3]
1115 data_name = content[5].strip()
1116 if content[6].find('(') > 0:
1117 object_file = content[6][content[6].find(
1118 '(') + 1: -1]
1119 lib_file = content[6][:content[6].find(
1120 '(')]
1121 else:
1122 object_file = lib_file = content[6]
1123 for line in open(file_path, "r"):
1124 if line.find(data_name) > 0:
1125 if line.find("refers to {}({}".format(object_file, data_name)) > 0 or line.find("refers (Special) to {}({}".format(object_file, data_name)) > 0:
1126 dst_symbol = dst_symbol + get_dst(line, data_name)
1127 elif line.find("{}({}) refers to".format(object_file, data_name)) > 0 or \
1128 line.find('{}({}) refers (Special) to'.format(object_file, data_name)) > 0:
1129 called_symbol = called_symbol + \
1130 get_src(line, data_name)
1131 cur.execute("insert into Data values (?, ?, ?, ?, ?, ?, ?, ?, ?)",
1132 (data_name,
1133 section_name,
1134 int(content[1].strip(), 16),
1135 content[0].strip(),
1136 data_type,
1137 object_file,
1138 lib_file,
1139 called_symbol,
1140 dst_symbol))
1141
1142def format_info(content):
1143 if content:
1144 object_file = content[0:content.find('(')]
1145 target = content[content.find('(') + 1:content.find(')')]
1146 return "{:<50}".format(object_file) + ' : ' + target + '|'
1147
1148def get_dst(line, target):
1149 ret = ""
1150 content = []
1151 if line.find('refers to') > 0:
1152 content = line.split('refers to')
1153 if line.find('refers (Special) to') > 0:
1154 content = line.split('refers (Special) to')
1155 if content and content[1].find(target) > 0:
1156 ret = format_info(content[0].strip())
1157 return ret
1158
1159def get_src(line, target):
1160 ret = ""
1161 content = []
1162 if line.find('refers to') > 0:
1163 content = line.split('refers to')
1164 if line.find('refers (Special) to') > 0:
1165 content = line.split('refers (Special) to')
1166 if content and content[0].find(target) > 0:
1167 ret = format_info(content[1].strip())
1168 return ret
1169
1170def collect_set(index):
1171 name_list = []
1172 detail_list = []
1173 for s in gnuarm_info:
1174 if s[index] not in name_list:
1175 name_list.append(s[index])
1176 if s[3] == "text":
1177 detail_list.append({'name': s[index], 'Code':s[1],'ZI':0, 'RO':0,'RW':0})
1178 if s[3] == "rodata":
1179 detail_list.append({'name': s[index], 'Code':0,'ZI':0, 'RO':s[1],'RW':0})
1180 if s[3] == "data":
1181 detail_list.append({'name': s[index], 'Code':0,'ZI':0, 'RO':0,'RW':s[1]})
1182 if s[3] == "bss":
1183 detail_list.append({'name': s[index], 'Code':0,'ZI':s[1], 'RO':0,'RW':0})
1184 else:
1185 for t in detail_list:
1186 if t['name'] == s[index]:
1187 if s[3] == "text":
1188 t['Code'] += s[1]
1189 if s[3] == "rodata":
1190 t['RO'] += s[1]
1191 if s[3] == "data":
1192 t['RW'] += s[1]
1193 if s[3] == "bss":
1194 t['ZI'] += s[1]
1195 return detail_list
1196
1197def collect_library():
1198 cur.execute('''create table Library
1199 (name TEXT NOT NULL,
1200 flashsize INT NOT NULL,
1201 ramsize INT NOT NULL,
1202 code INT NOT NULL,
1203 rodata INT NOT NULL,
1204 rwdata INT NOT NULL,
1205 zidata INT NOT NULL,
1206 incdata INT NOT_NULL,
1207 Debug INT NOT NULL
1208 );''')
1209 if gnuarm:
1210 lib_detail_list = collect_set(5)
1211 for s in lib_detail_list:
1212 cur.execute("insert into Library values (?, ?, ?, ?, ?, ?, ?, ?, ?)",
1213 (s['name'],
1214 s['Code']+ s['RO'] + s['RW'],
1215 s['RW'] + s['ZI'],
1216 s['Code'],
1217 s['RO'],
1218 s['RW'],
1219 s['ZI'],
1220 0, 0))
1221
1222 elif armcc:
1223 """
1224 Code (inc. data) RO Data RW Data ZI Data Debug Library Name
1225
1226 1520 0 0 0 1152 284 libtfm_app_rot_partition_core_test_2.a
1227 300 48 0 0 1032 64 libtfm_app_rot_partition_flih_test.a
1228 462 0 0 0 772 40 libtfm_app_rot_partition_ipc_client.a
1229 4364 6 20 28 6729 1312 libtfm_app_rot_partition_ps.a
1230 """
1231 line_idx, line_start = 0, 0
1232 for line in open(file_path, "r"):
1233 line_idx += 1
1234 if line.find("Code (inc. data) RO Data RW Data ZI Data Debug Library Name") > 0:
1235 line_start = line_idx + 1
1236 if line_idx > line_start and line_start > 0:
1237 content = line.split()
1238 if len(content) == 7:
1239 cur.execute("insert into Library values (?, ?, ?, ?, ?, ?, ?, ?, ?)",
1240 (content[6],
1241 int(content[0]) + int(content[2]) + int(content[3]),
1242 int(content[3]) + int(content[4]),
1243 content[0],
1244 content[2],
1245 content[3],
1246 content[4],
1247 content[1],
1248 content[5]))
1249 else:
1250 break
1251
1252def collect_obj():
1253 cur.execute('''create table Object
1254 (name TEXT NOT NULL,
1255 library TEXT NOT NULL,
1256 flashsize INT NOT NULL,
1257 ramsize INT NOT NULL,
1258 code INT NOT NULL,
1259 rodata INT NOT NULL,
1260 rwdata INT NOT NULL,
1261 zidata INT NOT NULL,
1262 incdata INT NOT_NULL,
1263 Debug INT NOT NULL
1264 );''')
1265 if gnuarm:
1266 obj_lib = ""
1267 obj_detail_list = collect_set(4)
1268 for s in obj_detail_list:
1269 for t in gnuarm_info:
1270 if t[4] == s['name']:
1271 obj_lib = t[5]
1272 break
1273 cur.execute("insert into Object values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
1274 (s['name'],
1275 obj_lib,
1276 s['Code']+ s['RO'] + s['RW'],
1277 s['RW'] + s['ZI'],
1278 s['Code'],
1279 s['RO'],
1280 s['RW'],
1281 s['ZI'],
1282 0, 0))
1283 elif armcc:
1284 """
1285 Code (inc. data) RO Data RW Data ZI Data Debug Object Name
1286
1287 0 0 48 0 328 0 load_info_idle_sp.o
1288 0 0 48 0 72 0 load_info_ns_agent.o
1289 0 0 83 0 92 0 load_info_tfm_crypto.o
1290
1291 Code (inc. data) RO Data RW Data ZI Data Debug Library Member Name
1292
1293 90 0 0 0 0 0 __dczerorl2.o
1294 8 0 0 0 0 68 __main.o
1295 0 0 0 0 0 0 __rtentry.o
1296 """
1297 line_idx, line_start = 0, 0
1298 for line in open(file_path, "r"):
1299 line_idx += 1
1300 if line.find("Code (inc. data) RO Data RW Data ZI Data Debug Object Name") > 0:
1301 line_start = line_idx + 1
1302 if line_idx > line_start and line_start > 0:
1303 content = line.split()
1304 if len(content) == 7:
1305 cur.execute("insert into Object values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
1306 (content[6],
1307 "no library",
1308 int(content[0]) + int(content[2]) + int(content[3]),
1309 int(content[3]) + int(content[4]),
1310 content[0],
1311 content[2],
1312 content[3],
1313 content[4],
1314 content[1],
1315 content[5]))
1316 else:
1317 break
1318 line_idx, line_start = 0, 0
1319 for line in open(file_path, "r"):
1320 line_idx += 1
1321 if line.find("Code (inc. data) RO Data RW Data ZI Data Debug Library Member Name") > 0:
1322 line_start = line_idx + 1
1323 if line_idx > line_start and line_start > 0:
1324 content = line.split()
1325 if len(content) == 7:
1326 obj_name = content[6]
1327 library_file = ""
1328 for line in open(file_path, "r"):
1329 if line.find(obj_name) > 0:
1330 ch_r = line[line.find(obj_name) + len(obj_name)]
1331 ch_l = line[line.find(obj_name) - 1]
1332 if ch_l == '(' and ch_r == ')':
1333 library_file = line.split(
1334 )[6][:line.split()[6].find('(')]
1335 if len(library_file) == 0:
1336 library_file = "no library"
1337 cur.execute("insert into Object values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
1338 (content[6],
1339 library_file,
1340 int(content[0]) + int(content[2]) +
1341 int(content[3]),
1342 int(content[3]) + int(content[4]),
1343 content[0],
1344 content[2],
1345 content[3],
1346 content[4],
1347 content[1],
1348 content[5]))
1349 else:
1350 break
1351
1352def get_info_from_gnuarm_map():
1353 """
1354 Collect information from GNUARM map file.
1355 """
1356 text = os.popen('cat ' + file_path).read()
1357 text = text[text.find('Linker script and memory map\n'):]
1358
1359 for type in ["text", "data", "bss", "rodata"]:
1360 values = []
1361 i = 0
1362 key_type = '.' + type + '.'
1363 i_max = text.rfind(key_type) + text[text.rfind(key_type):].find(')') + 2
1364 while (i < i_max) & (text[i:].find(key_type) != -1):
1365 temp = ''
1366 i = len(text[:i]) + text[i:].find(key_type)
1367 while (text[i-2] != '.' or text[i-1] != 'o' ) or (text[i] != '\n' and text[i] != ')'):
1368 temp = temp + text[i]
1369 i += 1
1370 if(i >= i_max):
1371 break
1372 temp = temp.replace('\n', ' ').replace('\t', ' ')
1373 if (temp.find('0x') >= 0):
1374 values.append(temp)
1375 i += 1
1376
1377 """
1378 Get detail data from lines.
1379 """
1380 for line in values:
1381 sym = line[line.find(key_type):line.find("0x")].replace('\n', '').replace('\t', '').replace(' ', '').replace(key_type, '')
1382 addr = "0x" + line.split()[1][-10:]
1383 pos = line.find("0x", line.find('0x') + 1)
1384 if (pos == -1):
1385 continue
1386 line = line[pos:]
1387 size = int(line.split(' ')[0], 16)
1388 lib = line[line.rfind('/') + 1:line.rfind('.o') + 2]
1389 obj = lib[lib.find("(") + 1:lib.rfind('.o')]
1390 if lib.find('(') > 0:
1391 lib = lib[:lib.find("(")]
1392 else:
1393 lib = "no library"
1394 gnuarm_info.append([sym, size, addr, type, obj + ".o", lib])
1395
1396 """
1397 Read some common symbols from GNUARM map file. These symbols are bss data.
1398 """
1399 text = os.popen('cat ' + file_path).read()
1400 text = text[text.find("Allocating common symbols") + len("Allocating common symbols"):text.find("Discarded input sections")]
1401 common_symbol_list = text.split()[4:]
1402 for i in range(int(len(common_symbol_list) / 3)):
1403 common_symbol = common_symbol_list[3 * i]
1404 for line in open(file_path, "r"):
1405 if line.find(common_symbol) > 0 and line.find("0x0000") > 0:
1406 addr = "0x" + line.split()[0][-10:]
1407 common_symbol_size = int(common_symbol_list[3 * i + 1], 16)
1408 temp = common_symbol_list[3 * i + 2]
1409 lib = temp[temp.rfind('/') + 1:temp.rfind('.o') + 2]
1410 obj = lib[lib.find("(") + 1:lib.rfind('.o')]
1411 if lib.find('(') > 0:
1412 lib = lib[:lib.find("(")]
1413 else:
1414 lib = "no library"
1415 gnuarm_info.append([common_symbol, common_symbol_size, addr, "bss", obj + ".o", lib])
1416
1417def main(args):
1418 output = ""
1419 if args.map_file_input:
1420 if args.gnuarm_compiler and args.armclang_compiler:
1421 print("Error: Need \'--gnuarm\' or \'--armcc\'")
1422 if args.gnuarm_compiler or args.armclang_compiler:
1423 global cur, file_path, gnuarm_info, gnuarm, armcc
1424 gnuarm = armcc = False
1425 for infile in glob.glob(os.path.join(os.getcwd(), '*.db')):
1426 os.remove(infile)
1427 file_path = args.map_file_input
1428 con = sqlite3.connect("data.db")
1429 cur = con.cursor()
1430 if args.gnuarm_compiler:
1431 gnuarm_info = []
1432 gnuarm = True
1433 get_info_from_gnuarm_map()
1434 else:
1435 armcc = True
1436 collect_summary()
1437 collect_section()
1438 collect_library()
1439 collect_obj()
1440 con.commit()
1441 con.close()
1442 else:
1443 print("Error: Need \'--gnuarm\' or \'--armcc\'")
1444
1445 if args.ui_show:
1446 if os.path.exists('data.db'):
1447 ui = UI()
1448 ui.run()
1449 ui.con.close()
1450 else:
1451 print(none_databse)
1452
1453 if args.all:
1454 if os.path.exists('data.db'):
1455 ui = UI()
1456 ui.draw_summary_page()
1457 output = ui.items
1458 else:
1459 print(none_databse)
1460
1461 if args.list_function:
1462 if os.path.exists('data.db'):
1463 ui = UI()
1464 ui.draw_function_page("")
1465 output = ui.items
1466 else:
1467 print(none_databse)
1468
1469 if args.function_name:
1470 if os.path.exists('data.db'):
1471 ui = UI()
1472 ui.draw_function_page(args.function_name)
1473 output = ui.items
1474 else:
1475 print(none_databse)
1476
1477 if args.dump_function_name:
1478 if os.path.exists('data.db'):
1479 ui = UI()
1480 ui.function_name = args.dump_function_name
1481 ui.draw_function_detail_page()
1482 output = ui.items
1483 else:
1484 print(none_databse)
1485
1486 if args.list_data:
1487 if os.path.exists('data.db'):
1488 ui = UI()
1489 ui.draw_data_page("")
1490 output = ui.items
1491 else:
1492 print(none_databse)
1493
1494 if args.data_name:
1495 if os.path.exists('data.db'):
1496 ui = UI()
1497 ui.draw_data_page(args.data_name)
1498 output = ui.items
1499 else:
1500 print(none_databse)
1501
1502 if args.dump_data_name:
1503 if os.path.exists('data.db'):
1504 ui = UI()
1505 ui.data_name = args.dump_data_name
1506 ui.draw_data_detail_page()
1507 output = ui.items
1508 else:
1509 print(none_databse)
1510
1511 if args.list_obj:
1512 if os.path.exists('data.db'):
1513 ui = UI()
1514 ui.draw_obj_page()
1515 output = ui.items
1516 else:
1517 print(none_databse)
1518
1519 if args.obj_name:
1520 if os.path.exists('data.db'):
1521 ui = UI()
1522 ui.obj_file = args.obj_name
1523 ui.draw_obj_detail_page()
1524 output = ui.items
1525 else:
1526 print(none_databse)
1527
1528 if args.list_library:
1529 if os.path.exists('data.db'):
1530 ui = UI()
1531 ui.draw_library_page()
1532 output = ui.items
1533 else:
1534 print(none_databse)
1535
1536 if args.library_name:
1537 if os.path.exists('data.db'):
1538 ui = UI()
1539 ui.library_name = args.library_name
1540 ui.draw_library_detail_page()
1541 output = ui.items
1542 else:
1543 print(none_databse)
1544 if args.list_section:
1545 if os.path.exists('data.db'):
1546 ui = UI()
1547 ui.draw_section_page()
1548 output = ui.items
1549 else:
1550 print(none_databse)
1551
1552 if args.section_name:
1553 if os.path.exists('data.db'):
1554 ui = UI()
1555 ui.section_name = args.section_name
1556 ui.draw_section_lib()
1557 output = ui.items
1558 else:
1559 print(none_databse)
1560
1561 if output:
1562 for s in output:
1563 print(s)
1564
1565def parse_args():
1566 """
1567 """
1568
1569 parser = argparse.ArgumentParser()
1570
1571 parser.add_argument('-i', '--input',
1572 dest='map_file_input',
1573 help='map file path <path>/tfm_s.map')
1574 parser.add_argument('-u', '--ui',
1575 dest='ui_show',
1576 action='store_true',
1577 help='show UI')
1578
1579 parser.add_argument('--gnuarm',
1580 dest='gnuarm_compiler',
1581 action='store_true',
1582 help='gnuarm map file input')
1583
1584 parser.add_argument('--armcc',
1585 dest='armclang_compiler',
1586 action='store_true',
1587 help='armclang map file input')
1588
1589 parser.add_argument('-a', '--all',
1590 dest='all',
1591 action='store_true',
1592 help='show total')
1593
1594 parser.add_argument('-f', '--list_function',
1595 dest='list_function',
1596 action='store_true',
1597 help='list function')
1598 parser.add_argument('--search_func',
1599 dest='function_name',
1600 help='search function')
1601 parser.add_argument('--dump_function',
1602 dest='dump_function_name',
1603 help='dump function')
1604
1605 parser.add_argument('-d', '--list_data',
1606 dest='list_data',
1607 action='store_true',
1608 help='list data')
1609 parser.add_argument('--search_data',
1610 dest='data_name',
1611 help='search data')
1612 parser.add_argument('--dump_data',
1613 dest='dump_data_name',
1614 help='dump data')
1615
1616 parser.add_argument('-o', '--list_obj',
1617 dest='list_obj',
1618 action='store_true',
1619 help='list object file')
1620 parser.add_argument('--dump_obj',
1621 dest='obj_name',
1622 help='dump object file')
1623
1624 parser.add_argument('-l', '--list_library',
1625 dest='list_library',
1626 action='store_true',
1627 help='list library')
1628 parser.add_argument('--dump_library',
1629 dest='library_name',
1630 help='dump library')
1631
1632 parser.add_argument('-s', '--list_section',
1633 dest='list_section',
1634 action='store_true',
1635 help='list section')
1636 parser.add_argument('--dump_section',
1637 dest='section_name',
1638 help='dump section')
1639 args = parser.parse_args()
1640 return args
1641
1642
1643if __name__ == '__main__':
1644 main(parse_args())
1645 exit(0)