xiaohu.huang | 29fd84c | 2022-12-19 15:27:00 +0800 | [diff] [blame] | 1 | #!/usr/bin/python3 |
| 2 | #coding:utf-8 |
| 3 | # |
| 4 | # Copyright (c) 2021-2022 Amlogic, Inc. All rights reserved. |
| 5 | # |
| 6 | # SPDX-License-Identifier: MIT |
| 7 | # |
| 8 | |
| 9 | |
| 10 | from __future__ import print_function |
| 11 | |
| 12 | import sys |
| 13 | import os |
| 14 | import argparse |
| 15 | import operator |
| 16 | |
| 17 | parser = argparse.ArgumentParser(description='total size of each object file in an ld linker map.') |
| 18 | parser.add_argument('map_file', help="A map file generated by passing -M/--print-map to ld during linking.") |
| 19 | parser.add_argument('--combine', action='store_true', |
| 20 | help="All object files in an .a archive or in a directory are combined") |
| 21 | args = parser.parse_args() |
| 22 | |
| 23 | class SectionSize(): |
| 24 | text = 0 |
| 25 | data = 0 # Including metadata like import tables |
| 26 | bss = 0 |
| 27 | customize = 0 |
| 28 | def rom(self): |
| 29 | return self.text + self.data |
| 30 | def ram(self): |
| 31 | return self.data + self.bss |
| 32 | def total(self): |
| 33 | return self.text + self.data + self.bss |
| 34 | def add_clang_llvm_section(self, section, size): |
| 35 | if section == ".text": |
| 36 | self.text += size |
| 37 | elif section == ".bss": |
| 38 | self.bss += size |
| 39 | elif section == ".data" or section == ".rodata": |
| 40 | self.data += size |
| 41 | else: |
| 42 | if (size > 0): |
| 43 | print("customer section:%s, size:%d" % (section, size)) |
| 44 | self.customize += size |
| 45 | |
| 46 | size_by_source = {} |
| 47 | current_section = None |
| 48 | last_section = None |
| 49 | last_source = None |
| 50 | current_addr = 0x00; |
| 51 | last_addr = "0" |
| 52 | size = 0x00; |
| 53 | last_size = 0x00; |
| 54 | last_real_size = 0x00; |
| 55 | heap = 0 |
| 56 | stack = 0 |
| 57 | with open(args.map_file) as f: |
| 58 | print("clang+llvm toolchain map analyzer") |
| 59 | lines = iter(f) |
| 60 | for line in lines: |
| 61 | line = line.strip('\n') |
| 62 | |
| 63 | if operator.contains(line, ":(.debug_") or operator.contains(line, ":(.comment"): |
| 64 | continue |
| 65 | elif operator.contains(line, ":(.shstrtab") or operator.contains(line, ":(.symtab") or operator.contains(line, ":(.strtab"): |
| 66 | continue |
| 67 | elif (line.endswith(".text")) or (line.endswith(".data")) or (line.endswith(".rodata")) or (line.endswith(".bss")): |
| 68 | pieces = line.split(None, 5) |
| 69 | current_section = pieces[4] |
| 70 | elif operator.contains(line, ":(.") \ |
| 71 | or operator.contains(line, ".heap") \ |
| 72 | or operator.contains(line, ".stack") \ |
| 73 | or operator.contains(line, ":(.text") \ |
| 74 | or operator.contains(line, ":(.data") \ |
| 75 | or operator.contains(line, ":(.bss") \ |
| 76 | or operator.contains(line, ":(.rodata."): |
| 77 | pieces = line.split(None, 5) # Don't split paths containing spaces |
| 78 | size = int(pieces[2], 16) |
| 79 | source = pieces[4] |
| 80 | current_addr = pieces[1] |
| 81 | if operator.contains(line, '.heap'): |
| 82 | heap += size |
| 83 | elif operator.contains(line, '.stack'): |
| 84 | stack += size |
| 85 | |
| 86 | if args.combine: |
| 87 | if '.a(' in source: |
| 88 | source = source[:source.index('.a(') + 2] |
| 89 | elif '.dir' in source: |
| 90 | source = source[:source.find(".dir")] |
| 91 | elif '<internal>' in source: |
| 92 | source = last_source |
| 93 | else: |
| 94 | source = os.path.basename(source) |
| 95 | |
| 96 | if source not in size_by_source: |
| 97 | size_by_source[source] = SectionSize() |
| 98 | |
| 99 | last_real_size = operator.sub(int(current_addr, 16), int(last_addr, 16)) |
| 100 | if operator.ne(last_size, 0x00) and operator.gt(last_real_size, last_size): |
| 101 | #fixed the last size from address by the size not from last section |
| 102 | if (last_section != None) and (current_section != last_section ): |
| 103 | #fixed the last size from last source |
| 104 | if (last_source != None) and (source != last_source): |
| 105 | size_by_source[last_source].add_clang_llvm_section(last_section, (last_real_size - last_size)) |
| 106 | else: |
| 107 | size_by_source[source].add_clang_llvm_section(last_section, (last_real_size - last_size)) |
| 108 | else: |
| 109 | if (last_source != None) and (source != last_source): |
| 110 | size_by_source[last_source].add_clang_llvm_section(current_section, (last_real_size - last_size)) |
| 111 | else: |
| 112 | size_by_source[source].add_clang_llvm_section(current_section, (last_real_size - last_size)) |
| 113 | size_by_source[source].add_clang_llvm_section(current_section, size) |
| 114 | |
| 115 | last_addr = current_addr |
| 116 | last_size = size |
| 117 | last_section = current_section; |
| 118 | last_source = source; |
| 119 | |
| 120 | # Print out summary |
| 121 | sources = list(size_by_source.keys()) |
| 122 | sources.sort(key = lambda x: size_by_source[x].total()) |
| 123 | sumrom = sumram = sumcode = sumdata = sumbss = sumcustomize = 0 |
| 124 | |
| 125 | print('---------------------------------------------------------------------------------------------------') |
| 126 | col_format = "%-20s\t%-12s\t%-12s\t%-7s\t%-12s\t%-12s\t%-7s" |
| 127 | print(col_format % ("module file", "ROM(text+data)", "RAM(data+bss)", ".text", ".data", ".bss", "customize")) |
| 128 | for source in sources: |
| 129 | size = size_by_source[source] |
| 130 | sumcode += size.text |
| 131 | sumdata += size.data |
| 132 | sumbss += size.bss |
| 133 | sumrom += size.rom() |
| 134 | sumram += size.ram() |
| 135 | sumcustomize += size.customize |
| 136 | print(col_format % (os.path.basename(source), size.rom(), size.ram(), size.text, size.data, size.bss, size.customize)) |
| 137 | |
| 138 | print('---------------------------------------------------------------------------------------------------') |
| 139 | col_format = "%-5s\t%-12s\t%-12s\t%-7s\t%-12s\t%-12s\t%-7s\t%-7s\t%-7s" |
| 140 | print(col_format % (" ", "ROM(text+data)", "RAM(data+bss)", ".text", ".data", ".bss", "cust", "stack", "heap" )) |
| 141 | print(col_format % ("total", sumrom, sumram, sumcode, sumdata, sumbss, sumcustomize, stack, heap)) |
| 142 | print('---------------------------------------------------------------------------------------------------') |