3 # Process gcc binutils 'size -A' output to show more specific and summarized information about memory segment usage.
5 # This script expects some variables to be set on the command line with -v:
6 # names : list of segment names ("Flash", "RAM" etc.)
7 # addrs : list of segment start addresses in hex/oct/dec (in same order as names)
8 # sizes : list of segment sizes in KB (in same order as names)
9 # elf : name of elf file (optional, for display only)
10 # mcu : name of MCU (optional, for display only)
11 # skip_data : skip duplicate .data in Flash (0/1 default: 0)
13 # NOTE: The memory segments should be specified in increasing address order (low to high).
16 # arm-none-eabi-size -A -x firmware.elf | ./elf-size-report.awk \
17 # -v elf="firmware.elf" \
18 # -v mcu="STM32F401VG" \
19 # -v names="Flash RAM" \
20 # -v addrs "0x08000000 0x100000000" \
23 # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
24 # Copyright (c)2016 Maxim Paperno
25 # Copyright (c)2017 OpenTX
31 len =
split(names
, a_names
, " ");
32 alen =
split(addrs
, a_addrs
, " ");
33 slen =
split(sizes
, a_sizes
, " ");
34 if (!len
|| len
!= alen
|| len
!= slen
) {
35 print "Error: No segment data provided or array sizes mismatch, exiting.";
41 a
[i
] = n
; d
[n
]["addr"] = a_addrs
[i
]; d
[n
]["size"] = a_sizes
[i
]; d
[n
]["sum"] =
0;
42 if (tolower(n
) ~
/flash
/)
45 flmax = d
[flash_name
]["addr"];
46 fmtstr =
"%-20s %7d 0x%08x %s\n";
48 printf("\n---- Size report");
49 if (length(elf
)) printf(" for %s", elf
);
50 if (length(mcu
)) printf(" (MCU: %s)", mcu
);
52 printf("Section Details:\n");
53 printf("%-20s %7s %10s %s\n", "section", "size(B)", "addr", "loc");
55 # Process each line of 'size' output listing the program's sections,
56 # skip line if sections size or address are zero.
57 NR > 2 && $
2 != 0 && $
3 != 0 {
59 # .data section is always in Flash but 'size' reports it only in RAM (sometimes twice)
60 d
[flash_name
]["sum"] += $
2;
61 printf(fmtstr
, $
1 " (added)", $
2, flmax
, flash_name
);
63 if (skip_data
) { next; }
65 # Walk over each specified memory segment looking for a match
66 # note: (this assumes segments were passed in ascending memory order)
67 PROCINFO
["sorted_in"] =
"@ind_num_desc"
68 addr = d
[a
[len
]]["addr"];
72 # check for overflow into contigious region
73 t = d
[n
]["sum"] + $
2 - (d
[n
]["size"] * 1024);
74 if (t
> 0 && i
< len
&& d
[a
[i
+1]]["addr"] = d
[n
]["addr"] + d
[n
]["size"] + 1) {
75 d
[n
]["sum"] += $
2 - t
;
76 d
[a
[i
+1]]["sum"] += t
;
83 printf(fmtstr
, $
1, $
2, $
3, seg
);
84 # track maximum flash address used
90 addr = d
[a
[i
-1]]["addr"];
95 fmtstr =
"%7s: %8.2f %6.2f%% %6d\t%7.2f\n";
96 printf("\nTotals %8s usage of ttl\tKB free\n", "KB");
97 PROCINFO
["sorted_in"] =
"@ind_num_asc"
100 if (d
[n
]["size"] > 0)
101 printf(fmtstr
, n
, d
[n
]["sum"]/1024, d
[n
]["sum"]/(d
[n
]["size"]*1024)*100, d
[n
]["size"], d
[n
]["size"] - d
[n
]["sum"]/1024 );