#!/usr/bin/perl -w # Transform assembly in order to clean each stack frame for X86_64. use strict; $SIG{__WARN__} = sub { die @_ }; # Whether we are still scanning the content of a function: our $scanproc = 0; # Save lines of the function: our $lines = ""; # Size of the stack for this function: our $size = 0; # Counter for assigning unique ids to labels: our $id=0; sub emit_code { my $qsize = $size / 8; my $offset = - $size - 8; if($size != 0) { # This is a crude hack to disable the stack cleaning on the main # stack. It rellies on the fact that the main stack is high in # the address space and the other stacks are in the heap (lower). print("\tmovq \$0x7fff00000000, %r11\n"); print("\tcmpq %r11, %rsp\n"); print("\tjae .Lstack_cleaner_done$id\n"); # Loop over the stack frame quadwords and zero it: print("\tmovabsq \$$qsize, %r11\n"); print(".Lstack_cleaner_loop$id:\n"); print("\tmovq \$0, $offset(%rsp,%r11,8)\n"); print("\tsubq \$1, %r11\n"); print("\tjne .Lstack_cleaner_loop$id\n"); print(".Lstack_cleaner_done$id:\n"); } print $lines; $id = $id + 1; $size = 0; $lines = ""; $scanproc = 0; } while (<>) { if ($scanproc) { $lines = $lines . $_; if (m/^[ \t]*.cfi_endproc$/) { emit_code(); } elsif (m/^[ \t]*pushq/) { $size += 8; } elsif (m/^[ \t]*subq[\t *]\$([0-9]*),[ \t]*%rsp$/) { my $val = $1; $val = oct($val) if $val =~ /^0/; $size += $val; emit_code(); } } elsif (m/^[ \t]*.cfi_startproc$/) { print $_; $scanproc = 1; } else { print $_; } }