Jianliang Shen | 9b4ba11 | 2022-01-19 14:57:04 +0800 | [diff] [blame] | 1 | # ------------------------------------------------------------------------------ |
| 2 | # Copyright (c) 2022, Arm Limited. All rights reserved. |
| 3 | # |
| 4 | # SPDX-License-Identifier: BSD-3-Clause |
| 5 | # |
| 6 | # ------------------------------------------------------------------------------ |
| 7 | |
| 8 | import sqlite3 |
Jianliang Shen | 9b4ba11 | 2022-01-19 14:57:04 +0800 | [diff] [blame] | 9 | from xlsxwriter.workbook import Workbook |
| 10 | |
| 11 | class SQ(object): |
| 12 | """ |
| 13 | Class SQ is used to create a new sqlite3 database and search the information |
| 14 | of functions, data, sections, libraries, object files from map file. Then |
| 15 | store the result into the database for further usage. |
| 16 | |
| 17 | - Methods: |
| 18 | - SQ().update() - Create and update the database. |
| 19 | |
| 20 | - Variables: |
| 21 | - SQ().armcc - ARMCLANG option. |
| 22 | - SQ().gnuarm - GNUARM option. |
Jianliang Shen | 28cce57 | 2022-05-02 21:44:03 +0800 | [diff] [blame] | 23 | - SQ().map_file - The map file path which detail information comes from. |
| 24 | - SQ().db_name - The database file name to be saved. |
Jianliang Shen | 9b4ba11 | 2022-01-19 14:57:04 +0800 | [diff] [blame] | 25 | """ |
| 26 | def __init__(self): |
| 27 | """ |
| 28 | Initialize variables. |
| 29 | """ |
| 30 | self.gnuarm = False |
| 31 | self.armcc = False |
Jianliang Shen | 28cce57 | 2022-05-02 21:44:03 +0800 | [diff] [blame] | 32 | self.map_file = "" |
| 33 | self.db_name = "" |
Jianliang Shen | 9b4ba11 | 2022-01-19 14:57:04 +0800 | [diff] [blame] | 34 | |
| 35 | self.__gnuarm_info = [] |
| 36 | self.__sec_dict = {} |
Jianliang Shen | 28cce57 | 2022-05-02 21:44:03 +0800 | [diff] [blame] | 37 | self.__excel_name = "" |
Jianliang Shen | 9b4ba11 | 2022-01-19 14:57:04 +0800 | [diff] [blame] | 38 | |
| 39 | def __new(self): |
| 40 | """ |
| 41 | Create tables in a new empty database. |
| 42 | """ |
Jianliang Shen | 28cce57 | 2022-05-02 21:44:03 +0800 | [diff] [blame] | 43 | self.__con = sqlite3.connect(self.db_name) |
| 44 | self.__cur = self.__con.cursor() |
| 45 | self.__excel_name = self.db_name +'.xlsx' |
Jianliang Shen | 9b4ba11 | 2022-01-19 14:57:04 +0800 | [diff] [blame] | 46 | self.__cur.execute('''create table Summary |
| 47 | (Code INT NOT NULL, |
| 48 | RO_data INT NOT NULL, |
| 49 | RW_data INT NOT NULL, |
| 50 | ZI_data INT NOT NULL, |
| 51 | EXTRA_FLASH INT NOT NULL, |
| 52 | EXTRA_RAM INT NOT NULL, |
| 53 | Flash INT NOT NULL, |
| 54 | RAM INT NOT NULL);''') |
| 55 | self.__cur.execute('''create table Section |
| 56 | (name TEXT NOT NULL, |
| 57 | size INT NOT NULL, |
| 58 | address TEXT NOT NULL, |
| 59 | pad_size INT NOT NULL);''') |
| 60 | self.__cur.execute('''create table Function |
| 61 | (name TEXT NOT NULL, |
| 62 | section TEXT NOT NULL, |
| 63 | size INT NOT NULL, |
| 64 | base_addr TEXT NOT NULL, |
| 65 | obj_file TEXT NOT_NULL, |
| 66 | lib_file TEXT NOT_NULL);''') |
| 67 | self.__cur.execute('''create table Data |
| 68 | (name TEXT NOT NULL, |
| 69 | section TEXT NOT NULL, |
| 70 | size INT NOT NULL, |
| 71 | base_addr TEXT NOT NULL, |
| 72 | type TEXT NOT NULL, |
| 73 | obj_file TEXT NOT_NULL, |
| 74 | lib_file TEXT NOT_NULL);''') |
| 75 | self.__cur.execute('''create table Library |
| 76 | (name TEXT NOT NULL, |
Jianliang Shen | 28cce57 | 2022-05-02 21:44:03 +0800 | [diff] [blame] | 77 | size INT NOT NULL, |
Jianliang Shen | 9b4ba11 | 2022-01-19 14:57:04 +0800 | [diff] [blame] | 78 | ramsize INT NOT NULL, |
| 79 | code INT NOT NULL, |
| 80 | rodata INT NOT NULL, |
| 81 | rwdata INT NOT NULL, |
| 82 | zidata INT NOT NULL, |
| 83 | incdata INT NOT_NULL, |
| 84 | Debug INT NOT NULL);''') |
| 85 | self.__cur.execute('''create table Object |
| 86 | (name TEXT NOT NULL, |
Jianliang Shen | 28cce57 | 2022-05-02 21:44:03 +0800 | [diff] [blame] | 87 | lib_file TEXT NOT NULL, |
| 88 | size INT NOT NULL, |
Jianliang Shen | 9b4ba11 | 2022-01-19 14:57:04 +0800 | [diff] [blame] | 89 | ramsize INT NOT NULL, |
| 90 | code INT NOT NULL, |
| 91 | rodata INT NOT NULL, |
| 92 | rwdata INT NOT NULL, |
| 93 | zidata INT NOT NULL, |
| 94 | incdata INT NOT_NULL, |
| 95 | Debug INT NOT NULL);''') |
Jianliang Shen | 28cce57 | 2022-05-02 21:44:03 +0800 | [diff] [blame] | 96 | self.__cur.execute('''create table Compiler |
| 97 | (Compiler TEXT NOT NULL, |
| 98 | flag INT NOT NULL);''') |
Jianliang Shen | 9b4ba11 | 2022-01-19 14:57:04 +0800 | [diff] [blame] | 99 | if self.gnuarm: |
| 100 | self.__cur.execute('''create table Unknown |
| 101 | (name TEXT NOT NULL, |
| 102 | section TEXT NOT NULL, |
| 103 | size INT NOT NULL, |
| 104 | base_addr TEXT NOT NULL, |
| 105 | type TEXT NOT NULL, |
| 106 | obj_file TEXT NOT_NULL, |
| 107 | lib_file TEXT NOT_NULL);''') |
| 108 | |
Jianliang Shen | 28cce57 | 2022-05-02 21:44:03 +0800 | [diff] [blame] | 109 | def __collect_compiler(self): |
| 110 | if self.gnuarm: |
| 111 | self.__cur.execute("insert into Compiler values (?, ?)", ("gnuarm", 1)) |
| 112 | if self.armcc: |
| 113 | self.__cur.execute("insert into Compiler values (?, ?)", ("armcc", 0)) |
| 114 | |
Jianliang Shen | 9b4ba11 | 2022-01-19 14:57:04 +0800 | [diff] [blame] | 115 | def __collect_summary(self): |
| 116 | code_size = ro_data = rw_data = zi_data = flash_size = ram_size = extra_ram = extra_flash = 0 |
| 117 | if self.gnuarm: |
| 118 | max_ram_addr = max_flash_addr = max_addr_ram_sym_size = max_addr_flash_sym_size = 0 |
| 119 | flash_start_addr, x, ram_start_addr, y = self.__get_ram_and_flash_start_addr() |
| 120 | for s in self.__gnuarm_info: |
| 121 | if s[3] == "text": |
| 122 | code_size += s[1] |
| 123 | if s[3] == "rodata": |
| 124 | ro_data += s[1] |
| 125 | if s[3] == "data": |
| 126 | rw_data += s[1] |
| 127 | if s[3] == "bss": |
| 128 | zi_data += s[1] |
| 129 | if s[3] == "unknown_ram": |
| 130 | extra_ram += s[1] |
| 131 | if s[3] == "unknown_flash": |
| 132 | extra_flash += s[1] |
| 133 | |
| 134 | for s in self.__sec_dict.keys(): |
| 135 | if self.__sec_dict[s]['type'] == 'ram': |
| 136 | max_ram_addr = max(max_ram_addr, int(self.__sec_dict[s]['addr'], 16)) |
| 137 | max_addr_ram_sym_size = self.__sec_dict[s]['size'] |
| 138 | ram_size = max_ram_addr - ram_start_addr + max_addr_ram_sym_size |
| 139 | |
| 140 | """ |
| 141 | Some special sections like 'psp_stack' or 'heap' are pre-allocated, |
| 142 | and filled with zero. They are belonging to bss/ZI part. |
| 143 | """ |
| 144 | if self.__sec_dict[s]['size'] == self.__sec_dict[s]['fill']: |
| 145 | zi_data += self.__sec_dict[s]['size'] |
| 146 | if self.__sec_dict[s]['type'] == 'flash': |
| 147 | max_flash_addr = max(max_flash_addr, int(self.__sec_dict[s]['addr'], 16)) |
| 148 | max_addr_flash_sym_size = self.__sec_dict[s]['size'] |
| 149 | flash_size = max_flash_addr - flash_start_addr + max_addr_flash_sym_size |
| 150 | |
| 151 | """ |
| 152 | For Secure image, the TFM_DATA part is loaded from Flash. |
| 153 | """ |
Jianliang Shen | 28cce57 | 2022-05-02 21:44:03 +0800 | [diff] [blame] | 154 | for line in open(self.map_file, "r"): |
Jianliang Shen | 9b4ba11 | 2022-01-19 14:57:04 +0800 | [diff] [blame] | 155 | if line.find("load address") >= 0: |
| 156 | extra_flash_addr = int(line.split()[-1] ,16) |
| 157 | extra_flash_data = int(line.split()[-4], 16) |
| 158 | if extra_flash_addr == max_flash_addr + max_addr_flash_sym_size: |
| 159 | flash_size += extra_flash_data |
| 160 | |
| 161 | elif self.armcc: |
Jianliang Shen | 28cce57 | 2022-05-02 21:44:03 +0800 | [diff] [blame] | 162 | for line in open(self.map_file, "r"): |
Jianliang Shen | 9b4ba11 | 2022-01-19 14:57:04 +0800 | [diff] [blame] | 163 | if line.find("gram Size: Code=") > 0: |
| 164 | content = line.split() |
| 165 | code_size = int(content[2].split('=')[1]) |
| 166 | ro_data = int(content[3].split('=')[1]) |
| 167 | rw_data = int(content[4].split('=')[1]) |
| 168 | zi_data = int(content[5].split('=')[1]) |
| 169 | flash_size = code_size + ro_data + rw_data |
| 170 | ram_size = rw_data + zi_data |
| 171 | |
| 172 | self.__cur.execute("insert into Summary values (?,?,?,?,?,?,?,?)", |
| 173 | (code_size, |
| 174 | ro_data, |
| 175 | rw_data, |
| 176 | zi_data, |
| 177 | extra_flash, |
| 178 | extra_ram, |
| 179 | flash_size, |
| 180 | ram_size)) |
| 181 | |
| 182 | def __collect_section(self): |
| 183 | if self.gnuarm: |
| 184 | for s in self.__gnuarm_info: |
| 185 | if s[3] == "text": |
| 186 | self.__cur.execute("insert into Function values (?,?,?,?,?,?)", |
| 187 | (s[0], s[6], s[1], s[2], s[4], s[5])) |
| 188 | elif s[3] == "rodata": |
| 189 | self.__cur.execute("insert into Data values (?,?,?,?,?,?,?)", |
| 190 | (s[0], s[6], s[1], s[2], "RO", s[4], s[5])) |
| 191 | elif s[3] == "data": |
| 192 | self.__cur.execute("insert into Data values (?,?,?,?,?,?,?)", |
| 193 | (s[0], s[6], s[1], s[2], "RW", s[4], s[5])) |
| 194 | elif s[3] == "bss": |
| 195 | self.__cur.execute("insert into Data values (?,?,?,?,?,?,?)", |
| 196 | (s[0], s[6], s[1], s[2], "ZI", s[4], s[5])) |
| 197 | else: |
| 198 | self.__cur.execute("insert into Unknown values (?,?,?,?,?,?,?)", |
| 199 | (s[0], s[6], s[1], s[2], s[3], s[4], s[5])) |
| 200 | for s in self.__sec_dict.keys(): |
| 201 | self.__cur.execute("insert into Section values (?,?,?,?)", |
| 202 | (self.__sec_dict[s]['name'], |
| 203 | self.__sec_dict[s]['size'], |
| 204 | self.__sec_dict[s]['addr'], |
| 205 | self.__sec_dict[s]['fill'])) |
| 206 | elif self.armcc: |
| 207 | line_idx, line_start = 0, 0 |
| 208 | section_name = "" |
| 209 | section_addr = "" |
| 210 | section_size = 0 |
| 211 | section_pad_size = 0 |
Jianliang Shen | 28cce57 | 2022-05-02 21:44:03 +0800 | [diff] [blame] | 212 | for line in open(self.map_file, "r"): |
Jianliang Shen | 9b4ba11 | 2022-01-19 14:57:04 +0800 | [diff] [blame] | 213 | line_idx += 1 |
| 214 | |
| 215 | if line.find("Execution Region") > 0: |
| 216 | if len(section_name) > 0: |
| 217 | self.__cur.execute("insert into Section values (?,?,?,?)", |
| 218 | (section_name, |
| 219 | section_size, |
| 220 | section_addr, |
| 221 | section_pad_size)) |
| 222 | line_start = line_idx + 1 |
| 223 | |
| 224 | content = line.split() |
| 225 | if len(content) >= 10: |
| 226 | section_name = content[2] |
| 227 | section_addr = content[4][:-1] |
| 228 | section_size = int(content[6][:-1], 16) |
| 229 | section_pad_size = 0 |
| 230 | if line.find("PAD\n") > 0 and line_idx > line_start and line_start > 0: |
| 231 | section_pad_size += int(line.split()[1], 16) |
| 232 | if line.find(" Code ") > 0: |
| 233 | content = line.split() |
| 234 | if len(content) >= 7: |
| 235 | if line.find(" * ") > 0: |
| 236 | content.remove("*") |
| 237 | func_name = content[5].strip().split('.')[-1] |
| 238 | if content[6].find('(') > 0: |
| 239 | object_file = content[6][content[6].find('(') + 1: -1] |
| 240 | lib_file = content[6][:content[6].find('(')] |
| 241 | else: |
| 242 | object_file = lib_file = content[6] |
| 243 | self.__cur.execute("insert into Function values (?,?,?,?,?,?)", |
| 244 | (func_name, |
| 245 | section_name, |
| 246 | int(content[1].strip(), 16), |
| 247 | content[0].strip(), |
| 248 | object_file, |
| 249 | lib_file)) |
| 250 | if line.find(" Data ") > 0 or line.find(" Zero ") > 0: |
| 251 | content = line.split() |
| 252 | if len(content) == 7: |
| 253 | if content[2] == "Zero": |
| 254 | data_type = "ZI" |
| 255 | else: |
| 256 | data_type = content[3] |
| 257 | data_name = content[5].strip() |
| 258 | if content[6].find('(') > 0: |
| 259 | object_file = content[6][content[6].find('(') + 1: -1] |
| 260 | lib_file = content[6][:content[6].find('(')] |
| 261 | else: |
| 262 | object_file = lib_file = content[6] |
| 263 | self.__cur.execute("insert into Data values (?,?,?,?,?,?,?)", |
| 264 | (data_name, |
| 265 | section_name, |
| 266 | int(content[1].strip(), 16), |
| 267 | content[0].strip(), |
| 268 | data_type, |
| 269 | object_file, |
| 270 | lib_file)) |
| 271 | |
| 272 | def __collect_library(self): |
| 273 | if self.gnuarm: |
| 274 | lib_detail_list = self.__collect_set(5) |
| 275 | for s in lib_detail_list: |
| 276 | self.__cur.execute("insert into Library values (?,?,?,?,?,?,?,?,?)", |
| 277 | (s['name'], |
| 278 | s['Code']+ s['RO'] + s['RW'], |
| 279 | s['RW'] + s['ZI'], |
| 280 | s['Code'], |
| 281 | s['RO'], |
| 282 | s['RW'], |
| 283 | s['ZI'], |
| 284 | 0, 0)) |
| 285 | |
| 286 | elif self.armcc: |
| 287 | line_idx, line_start = 0, 0 |
Jianliang Shen | 28cce57 | 2022-05-02 21:44:03 +0800 | [diff] [blame] | 288 | for line in open(self.map_file, "r"): |
Jianliang Shen | 9b4ba11 | 2022-01-19 14:57:04 +0800 | [diff] [blame] | 289 | line_idx += 1 |
| 290 | if line.find("Code (inc. data) RO Data RW Data ZI Data Debug Library Name") > 0: |
| 291 | line_start = line_idx + 1 |
| 292 | if line_idx > line_start and line_start > 0: |
| 293 | content = line.split() |
| 294 | if len(content) == 7: |
| 295 | self.__cur.execute("insert into Library values (?,?,?,?,?,?,?,?,?)", |
| 296 | (content[6], |
| 297 | int(content[0]) + int(content[2]) + int(content[3]), |
| 298 | int(content[3]) + int(content[4]), |
| 299 | content[0], |
| 300 | content[2], |
| 301 | content[3], |
| 302 | content[4], |
| 303 | content[1], |
| 304 | content[5])) |
| 305 | else: |
| 306 | break |
| 307 | |
| 308 | def __collect_obj(self): |
| 309 | if self.gnuarm: |
| 310 | obj_lib = "" |
| 311 | obj_detail_list = self.__collect_set(4) |
| 312 | for s in obj_detail_list: |
| 313 | for t in self.__gnuarm_info: |
| 314 | if t[4] == s['name']: |
| 315 | obj_lib = t[5] |
| 316 | break |
| 317 | self.__cur.execute("insert into Object values (?,?,?,?,?,?,?,?,?,?)", |
| 318 | (s['name'], |
| 319 | obj_lib, |
| 320 | s['Code']+ s['RO'] + s['RW'], |
| 321 | s['RW'] + s['ZI'], |
| 322 | s['Code'], |
| 323 | s['RO'], |
| 324 | s['RW'], |
| 325 | s['ZI'], |
| 326 | 0, 0)) |
| 327 | elif self.armcc: |
| 328 | line_idx, line_start = 0, 0 |
Jianliang Shen | 28cce57 | 2022-05-02 21:44:03 +0800 | [diff] [blame] | 329 | for line in open(self.map_file, "r"): |
Jianliang Shen | 9b4ba11 | 2022-01-19 14:57:04 +0800 | [diff] [blame] | 330 | line_idx += 1 |
| 331 | if line.find("Code (inc. data) RO Data RW Data ZI Data Debug Object Name") > 0: |
| 332 | line_start = line_idx + 1 |
| 333 | if line_idx > line_start and line_start > 0: |
| 334 | content = line.split() |
| 335 | if len(content) == 7: |
| 336 | self.__cur.execute("insert into Object values (?,?,?,?,?,?,?,?,?,?)", |
| 337 | (content[6], |
| 338 | "no library", |
| 339 | int(content[0]) + int(content[2]) + int(content[3]), |
| 340 | int(content[3]) + int(content[4]), |
| 341 | content[0], |
| 342 | content[2], |
| 343 | content[3], |
| 344 | content[4], |
| 345 | content[1], |
| 346 | content[5])) |
| 347 | else: |
| 348 | break |
| 349 | line_idx, line_start = 0, 0 |
Jianliang Shen | 28cce57 | 2022-05-02 21:44:03 +0800 | [diff] [blame] | 350 | for line in open(self.map_file, "r"): |
Jianliang Shen | 9b4ba11 | 2022-01-19 14:57:04 +0800 | [diff] [blame] | 351 | line_idx += 1 |
| 352 | if line.find("Code (inc. data) RO Data RW Data ZI Data Debug Library Member Name") > 0: |
| 353 | line_start = line_idx + 1 |
| 354 | if line_idx > line_start and line_start > 0: |
| 355 | content = line.split() |
| 356 | if len(content) == 7: |
| 357 | obj_name = content[6] |
| 358 | library_file = "" |
Jianliang Shen | 28cce57 | 2022-05-02 21:44:03 +0800 | [diff] [blame] | 359 | for line in open(self.map_file, "r"): |
Jianliang Shen | 9b4ba11 | 2022-01-19 14:57:04 +0800 | [diff] [blame] | 360 | if line.find(obj_name) > 0: |
| 361 | ch_r = line[line.find(obj_name) + len(obj_name)] |
| 362 | ch_l = line[line.find(obj_name) - 1] |
| 363 | if ch_l == '(' and ch_r == ')': |
| 364 | library_file = line.split()[6][:line.split()[6].find('(')] |
| 365 | if len(library_file) == 0: |
| 366 | library_file = "no library" |
| 367 | self.__cur.execute("insert into Object values (?,?,?,?,?,?,?,?,?,?)", |
| 368 | (content[6], |
| 369 | library_file, |
| 370 | int(content[0]) + int(content[2]) + int(content[3]), |
| 371 | int(content[3]) + int(content[4]), |
| 372 | content[0], |
| 373 | content[2], |
| 374 | content[3], |
| 375 | content[4], |
| 376 | content[1], |
| 377 | content[5])) |
| 378 | else: |
| 379 | break |
| 380 | |
| 381 | def __get_ram_and_flash_start_addr(self): |
| 382 | start = False |
Jianliang Shen | 28cce57 | 2022-05-02 21:44:03 +0800 | [diff] [blame] | 383 | for line in open(self.map_file, "r"): |
Jianliang Shen | 9b4ba11 | 2022-01-19 14:57:04 +0800 | [diff] [blame] | 384 | if line.find('Memory Configuration') >= 0: |
| 385 | start = True |
| 386 | if line.find('Linker script and memory map') == 0: |
| 387 | break |
| 388 | if start: |
Jianliang Shen | 2895e4c | 2022-08-05 13:50:04 +0800 | [diff] [blame] | 389 | if line.find('FLASH') == 0: |
Jianliang Shen | 9b4ba11 | 2022-01-19 14:57:04 +0800 | [diff] [blame] | 390 | flash_start_addr = int(line.split()[1].strip(), 16) |
| 391 | flash_end_addr = int(line.split()[1].strip(), 16) + int(line.split()[2].strip(), 16) |
Jianliang Shen | 2895e4c | 2022-08-05 13:50:04 +0800 | [diff] [blame] | 392 | if line.find('RAM') == 0: |
Jianliang Shen | 9b4ba11 | 2022-01-19 14:57:04 +0800 | [diff] [blame] | 393 | ram_start_addr = int(line.split()[1].strip(), 16) |
| 394 | ram_end_addr = int(line.split()[1].strip(), 16) + int(line.split()[2].strip(), 16) |
| 395 | return flash_start_addr, flash_end_addr, ram_start_addr, ram_end_addr |
| 396 | |
| 397 | def __get_info_from_gnuarm_map(self): |
| 398 | def get_key_content(): |
| 399 | start, end, real_start = False, False, False |
| 400 | content = "" |
Jianliang Shen | 28cce57 | 2022-05-02 21:44:03 +0800 | [diff] [blame] | 401 | for line in open(self.map_file, "r"): |
Jianliang Shen | 9b4ba11 | 2022-01-19 14:57:04 +0800 | [diff] [blame] | 402 | if line.find('Linker script and memory map') >= 0: |
| 403 | start = True |
| 404 | if line.find('OUTPUT(') == 0: |
| 405 | end = True |
| 406 | if start and not real_start: |
| 407 | if(line[0] == '.'): |
| 408 | real_start = True |
| 409 | if real_start and not end: |
| 410 | content += line |
| 411 | return content.split('\n')[:-2] |
| 412 | |
| 413 | def output_to_gnuarm_info(): |
| 414 | type_founded = False |
| 415 | info = [cur_sym_name, cur_sym_size, cur_sym_addr, "type", obj, lib, cur_sec_name] |
| 416 | for type in ["text", "data", "bss", "rodata"]: |
| 417 | info[3] = type |
| 418 | if cur_sym_name.find('.' + type) == 0: |
| 419 | if cur_sym_name.find('.' + type + '.') == 0: |
| 420 | info[0] = cur_sym_name[len(type)+2:] |
| 421 | self.__gnuarm_info.append(info) |
| 422 | type_founded = True |
| 423 | break |
| 424 | self.__gnuarm_info.append(info) |
| 425 | type_founded = True |
| 426 | if not type_founded: |
| 427 | if int(cur_sym_addr,16) >= flash_start_addr and int(cur_sym_addr,16) <= flash_end_addr: |
| 428 | info[3] = "unknown_flash" |
| 429 | self.__gnuarm_info.append(info) |
| 430 | if int(cur_sym_addr,16) >= ram_start_addr and int(cur_sym_addr,16) <= ram_end_addr: |
| 431 | info[3] = "unknown_ram" |
| 432 | self.__gnuarm_info.append(info) |
| 433 | |
| 434 | def get_obj_and_lib(line): |
| 435 | lib = line[line.rfind('/') + 1:line.rfind('.o') + 2] |
| 436 | obj = lib[lib.find("(") + 1:lib.rfind('.o')] + '.o' |
| 437 | if lib.find('(') > 0: |
| 438 | lib = lib[:lib.find("(")] |
| 439 | else: |
| 440 | lib = "no library" |
| 441 | return lib, obj |
| 442 | |
| 443 | def get_part_list(idx): |
| 444 | ret = [] |
| 445 | while len(lines[idx]) > 0 and lines[idx].split()[0].find('0x0000') >= 0: |
| 446 | if len(lines[idx].split()) == 2: |
| 447 | cur_addr = lines[idx].split()[0].strip() |
| 448 | cur_name = lines[idx].split()[1].strip() |
| 449 | if cur_sym_name.find(cur_name) >= 0: |
| 450 | break |
| 451 | else: |
| 452 | delta = -1 |
| 453 | cur_idx = idx + 1 |
| 454 | next_addr = '' |
| 455 | while len(lines[cur_idx]) >= 0: |
| 456 | if lines[cur_idx].find('0x0000') >= 0: |
| 457 | for s in lines[cur_idx].split(): |
| 458 | if s.find('0x0000') >= 0: |
| 459 | next_addr = s.strip() |
| 460 | delta = int(next_addr, 16) - int(cur_addr, 16) |
| 461 | if delta >= 0: |
| 462 | break |
| 463 | cur_idx += 1 |
| 464 | ret.append(['0x' + cur_addr[-8:], cur_sym_name+'.'+cur_name, delta]) |
| 465 | else: |
| 466 | break |
| 467 | idx += 1 |
| 468 | return ret |
| 469 | |
| 470 | lines = get_key_content() |
| 471 | i_max = len(lines) |
| 472 | part_list = [] |
| 473 | cur_sym_name, cur_sym_addr, cur_sym_size, lib, obj = "", "", "", "", "" |
| 474 | flash_start_addr , flash_end_addr , ram_start_addr , ram_end_addr = self.__get_ram_and_flash_start_addr() |
| 475 | for i in range(i_max): |
| 476 | lib, obj = "no_library", "no_object" |
| 477 | if len(lines[i]) > 0 and lines[i][0] == '.': |
| 478 | cur_sec_name = lines[i].split()[0][1:] |
| 479 | if len(lines[i].split()) > 1: |
| 480 | cur_sec_addr = lines[i].split()[1] |
| 481 | cur_sec_size = lines[i].split()[2] |
| 482 | else: |
| 483 | cur_sec_addr = lines[i+1].split()[0] |
| 484 | cur_sec_size = lines[i+1].split()[1] |
| 485 | if cur_sec_addr.find('0x00') < 0: |
| 486 | continue |
| 487 | if int(cur_sec_addr,16) >= flash_start_addr and int(cur_sec_addr,16) <= flash_end_addr: |
| 488 | self.__sec_dict[cur_sec_name] = {'name': cur_sec_name, |
| 489 | 'addr': '0x' + cur_sec_addr[-8:], |
| 490 | 'fill': 0, |
| 491 | 'size': int(cur_sec_size, 16), |
| 492 | 'type': 'flash'} |
| 493 | if int(cur_sec_addr,16) >= ram_start_addr and int(cur_sec_addr,16) <= ram_end_addr: |
| 494 | self.__sec_dict[cur_sec_name] = {'name': cur_sec_name, |
| 495 | 'addr': '0x' + cur_sec_addr[-8:], |
| 496 | 'fill': 0, |
| 497 | 'size': int(cur_sec_size, 16), |
| 498 | 'type': 'ram'} |
| 499 | |
| 500 | if len(lines[i]) > 0 and lines[i][0] == ' ' and lines[i][1] != ' ': |
| 501 | cur_sym_name = lines[i].split()[0].strip() |
| 502 | if len(lines[i].split()) > 2: |
| 503 | cur_sym_addr = lines[i].split()[1].strip() |
| 504 | cur_sym_size = lines[i].split()[2].strip() |
| 505 | if cur_sym_addr.find('0x00') == 0 and cur_sym_size.find('0x') == 0: |
| 506 | cur_sym_addr = '0x' + cur_sym_addr[-8:] |
| 507 | cur_sym_size = int(cur_sym_size, 16) |
| 508 | if lines[i].find('/') > 0: |
| 509 | lib, obj = get_obj_and_lib(lines[i]) |
| 510 | part_list = get_part_list(i+1) |
| 511 | else: |
| 512 | continue |
| 513 | |
| 514 | elif len(lines[i+1]) > 0 and lines[i+1].split()[0].find('0x00') >= 0: |
| 515 | cur_sym_addr = lines[i+1].split()[0].strip() |
| 516 | cur_sym_size = lines[i+1].split()[1].strip() |
| 517 | if cur_sym_addr.find('0x00') == 0 and cur_sym_size.find('0x') == 0: |
| 518 | cur_sym_addr = '0x' + cur_sym_addr[-8:] |
| 519 | cur_sym_size = int(cur_sym_size, 16) |
| 520 | if lines[i+1].find('/') > 0: |
| 521 | lib, obj = get_obj_and_lib(lines[i+1]) |
| 522 | part_list = get_part_list(i+2) |
| 523 | else: |
| 524 | continue |
| 525 | else: |
| 526 | continue |
| 527 | |
Jianliang Shen | 2895e4c | 2022-08-05 13:50:04 +0800 | [diff] [blame] | 528 | if cur_sym_name.find("*fill*") >= 0 and cur_sec_name in self.__sec_dict.keys(): |
Jianliang Shen | 9b4ba11 | 2022-01-19 14:57:04 +0800 | [diff] [blame] | 529 | self.__sec_dict[cur_sec_name]['fill'] += cur_sym_size |
| 530 | continue |
| 531 | |
| 532 | if len(part_list) > 0: |
| 533 | for s in part_list: |
| 534 | cur_sym_addr = s[0] |
| 535 | cur_sym_name = s[1] |
| 536 | cur_sym_size = s[2] |
| 537 | output_to_gnuarm_info() |
| 538 | else: |
| 539 | output_to_gnuarm_info() |
| 540 | |
| 541 | def __output_to_excel(self): |
| 542 | def transform_db_2_excel(table_name): |
| 543 | worksheet = workbook.add_worksheet(name=table_name) |
| 544 | cursor = self.__cur.execute('select * from {}'.format(table_name)) |
| 545 | names = list(map(lambda x: x[0], cursor.description)) |
| 546 | len_list = [] |
| 547 | for s in names: |
| 548 | len_list.append(max(15, len(s))) |
| 549 | for i in range(len(names)): |
| 550 | worksheet.write(0, i, names[i], title_m) |
| 551 | |
| 552 | mysel = self.__cur.execute('select * from {}'.format(table_name)) |
| 553 | for i, row in enumerate(mysel): |
| 554 | for j, value in enumerate(row): |
| 555 | len_list[j] = max(len_list[j], len(str(value))) |
| 556 | worksheet.write(i + 1, j, value, page_m) |
| 557 | worksheet.set_column(j, j, width=len_list[j]) |
| 558 | |
| 559 | table_list = ["Summary", "Section", "Library", "Object", "Function", "Data"] |
| 560 | if self.gnuarm: |
| 561 | table_list.append("Unknown") |
Jianliang Shen | 28cce57 | 2022-05-02 21:44:03 +0800 | [diff] [blame] | 562 | workbook = Workbook(self.__excel_name) |
Jianliang Shen | 9b4ba11 | 2022-01-19 14:57:04 +0800 | [diff] [blame] | 563 | title_m = workbook.add_format({'bold': True, |
| 564 | 'align': 'left', |
| 565 | 'font_size': 12}) |
| 566 | page_m = workbook.add_format({'align': 'left', |
| 567 | 'font_size': 10}) |
| 568 | for table in table_list: |
| 569 | transform_db_2_excel(table) |
| 570 | workbook.close() |
| 571 | |
| 572 | def __collect_set(self, index): |
| 573 | name_list = [] |
| 574 | detail_list = [] |
| 575 | for s in self.__gnuarm_info: |
| 576 | if s[index] not in name_list: |
| 577 | name_list.append(s[index]) |
| 578 | if s[3] == "text": |
| 579 | detail_list.append({'name': s[index], 'Code':s[1],'ZI':0, 'RO':0,'RW':0}) |
| 580 | if s[3] == "rodata": |
| 581 | detail_list.append({'name': s[index], 'Code':0,'ZI':0, 'RO':s[1],'RW':0}) |
| 582 | if s[3] == "data": |
| 583 | detail_list.append({'name': s[index], 'Code':0,'ZI':0, 'RO':0,'RW':s[1]}) |
| 584 | if s[3] == "bss": |
| 585 | detail_list.append({'name': s[index], 'Code':0,'ZI':s[1], 'RO':0,'RW':0}) |
| 586 | else: |
| 587 | for t in detail_list: |
| 588 | if t['name'] == s[index]: |
| 589 | if s[3] == "text": |
| 590 | t['Code'] += s[1] |
| 591 | if s[3] == "rodata": |
| 592 | t['RO'] += s[1] |
| 593 | if s[3] == "data": |
| 594 | t['RW'] += s[1] |
| 595 | if s[3] == "bss": |
| 596 | t['ZI'] += s[1] |
| 597 | return detail_list |
| 598 | |
| 599 | def update(self): |
| 600 | """ |
| 601 | Create the database and collect information from map file, then store |
| 602 | it into the database, and write to excel file for further usage. |
| 603 | """ |
| 604 | self.__new() |
| 605 | if self.gnuarm: |
| 606 | self.__get_info_from_gnuarm_map() |
Jianliang Shen | 28cce57 | 2022-05-02 21:44:03 +0800 | [diff] [blame] | 607 | self.__collect_compiler() |
Jianliang Shen | 9b4ba11 | 2022-01-19 14:57:04 +0800 | [diff] [blame] | 608 | self.__collect_summary() |
| 609 | self.__collect_section() |
| 610 | self.__collect_library() |
| 611 | self.__collect_obj() |
| 612 | self.__con.commit() |
| 613 | self.__output_to_excel() |
| 614 | self.__con.close() |