-
Daniel Friesel authoredDaniel Friesel authored
static-stack-analyze.pl 6.72 KiB
#!/usr/bin/env perl
#
# Copyright 2018 Daniel Friesel
#
# SPDX-License-Identifier: BSD-2-Clause
use strict;
use warnings;
use 5.010;
use File::Slurp qw(read_file);
use Getopt::Long;
use List::Util qw(uniq);
our $VERSION = '0.00';
my $machine_readable = 0;
GetOptions(
'm|machine-readable!' => \$machine_readable,
);
if (@ARGV < 3) {
die("Usage: $0 <objdump binary> <architecture> <oject files ...>\n");
}
my %arch_data = (
x64 => {
# For each function call, the 8-Byte return address is pushed onto the stack.
call_cost => 8,
call_relocation => 'R_X86_64_PLT32',
},
avr => {
# On each function call, the 2-Byte return address is pushed onto the stack.
# (unhandled exception: ATTiny2313 and other devices with <= 256 Bytes of RAM)
call_cost => 2,
call_relocation => 'R_AVR_CALL',
},
msp430 => {
# For each function call, the 2-Byte (16 bits at 2-Byte alignment) return
# address is pushed onto the stack.
call_cost => 2,
call_relocation => 'R_MSP430X_ABS16',
},
msp430large => {
# For each function call, the 4-Byte (20 bits at 4-Byte alignment) return
# address is pushed onto the stack.
call_cost => 4,
call_relocation => 'R_MSP430X_ABS20_ADR_DST',
},
stm32f4 => {
# For each function call, the 4-Byte (32 bits) return
# address is pushed onto the stack.
call_cost => 4,
call_relocation => 'R_ARM_THM_CALL',
},
);
my %addresses;
my %call_graph;
my %frame_size;
my ($objdump_path, $arch, @object_files) = @ARGV;
sub add_call {
my ($parent, $child) = @_;
push(@{$call_graph{$parent}{children}}, $child);
push(@{$call_graph{$child}{parents}}, $parent);
#say "$parent -> $child;";