#!/usr/bin/perl # SPDX-License-Identifier: Apache-2.0 # Copyright (c) 2012-2024 Scott Penrose and WII5 Buoy contributors # # This file is part of WII5 Buoy firmware. # See LICENSE for full terms. # Group ELF symbols by subsystem (Network, Storage, Sparton, GPS, Iridium, # Serial, Console, Sh3d, WII5, Other) and report sizes. Useful for understanding # where the firmware is spending its program/data memory. # # Configure with env vars: # WII5_AVR_READELF = path to avr-readelf binary # WII5_ELF = path to wii5_buoy.ino.elf # # Usage: WII5_AVR_READELF=... WII5_ELF=... perl tools/memory.pl [items_max] use strict; use warnings; use Data::Dumper; my $items_max = $ARGV[0] || 0; my $exe_read = $ENV{WII5_AVR_READELF} or die "WII5_AVR_READELF not set\n"; my $elf = $ENV{WII5_ELF} or die "WII5_ELF not set\n"; my $fh; open ($fh, "$exe_read -a $elf |grep OBJECT |") or die "Cannot run readelf: $!\n"; my $grouped = { Serial => {total => 0, items => {}}, Network => {total => 0, items => {}}, Console => {total => 0, items => {}}, Sh3d => {total => 0, items => {}}, Storage => {total => 0, items => {}}, Sparton => {total => 0, items => {}}, GPS => {total => 0, items => {}}, Iridium => {total => 0, items => {}}, WII5 => {total => 0, items => {}}, Other => {total => 0, items => {}}, }; while (<$fh>) { chomp; # Sample line layout (column-aligned): # 1815: 00801796 1 OBJECT GLOBAL HIDDEN 3 _ZN7TwoWire12transmitting my $size = substr($_, 16, 6); my $name = substr($_, 51, 100); if ( ($name =~ /network/i) || ($name =~ /radio/i) ) { $grouped->{Network}{total} += $size; $grouped->{Network}{items}{$name} = $size; } elsif ( ($name =~ /storage/i) || ($name =~ /Sd/) ) { $grouped->{Storage}{total} += $size; $grouped->{Storage}{items}{$name} = $size; } elsif ($name =~ /sparton/i) { $grouped->{Sparton}{total} += $size; $grouped->{Sparton}{items}{$name} = $size; } elsif ($name =~ /gps/i) { $grouped->{GPS}{total} += $size; $grouped->{GPS}{items}{$name} = $size; } elsif ($name =~ /iridium/i) { $grouped->{Iridium}{total} += $size; $grouped->{Iridium}{items}{$name} = $size; } elsif ($name =~ /serial/i) { $grouped->{Serial}{total} += $size; $grouped->{Serial}{items}{$name} = $size; } elsif ($name =~ /console/i) { $grouped->{Console}{total} += $size; $grouped->{Console}{items}{$name} = $size; } elsif ($name =~ /sh3d/i) { $grouped->{Sh3d}{total} += $size; $grouped->{Sh3d}{items}{$name} = $size; } elsif ($name =~ /wii5/i) { $grouped->{WII5}{total} += $size; $grouped->{WII5}{items}{$name} = $size; } else { $grouped->{Other}{total} += $size; $grouped->{Other}{items}{$name} = $size; } } foreach my $group_key (sort {$grouped->{$b}{total} <=> $grouped->{$a}{total} } keys %$grouped) { print "$group_key => " . $grouped->{$group_key}{total} . "\n"; my $item_count = 0; foreach my $item_key ( sort { $grouped->{$group_key}{items}{$b} <=> $grouped->{$group_key}{items}{$a} } keys %{$grouped->{$group_key}{items}} ) { if ($item_count < $items_max) { print " $item_key => " . $grouped->{$group_key}{items}{$item_key} . "\n"; } $item_count++; } }