--- /dev/null
+Provides stack-cleaning compilers for x86_64:
+
+ * as
+ * cc
+ * c++
+
+Each of them modify the generated/given X86_64 assembly by prepending
+stack-cleanup code to each function:
+
+ movq $QSIZE, %r11
+.Lloop:
+ movq $0, OFFSET(%rsp,%r11,8)
+ subq $1, %r11
+ jne .Lloop
+
+The modification of the assembly is done by the clean-stack-filter
+program.
+
+If the underlying compiler is clang, it might be necessary to add the
+-no-integrated-as flag in order to force the usage of an external
+assembler.
--- /dev/null
+#!/usr/bin/ruby
+# Wrapper around the real `as` which adds filtering capabilities.
+
+require "tempfile"
+require "fileutils"
+
+def wrapped_as(argv)
+
+ args=[]
+ input=nil
+
+ i = 0
+ while i<argv.size
+ case argv[i]
+ when "-o", "-I"
+ args.push(argv[i])
+ args.push(argv[i+1])
+ i = i + 1
+ when /^-/
+ args.push(argv[i])
+ else
+ if input
+ exit 1
+ else
+ input = argv[i]
+ end
+ end
+ i = i + 1
+ end
+
+ if input==nil
+ # We dont handle pipe yet:
+ exit 1
+ end
+
+ # Generate temp file
+ tempfile = Tempfile.new("as-filter")
+ unless system(File.dirname($0) + "/clean-stack-filter", 0 => input, 1 => tempfile)
+ status=$?.exitstatus
+ FileUtils.rm tempfile
+ exit status
+ end
+ args.push(tempfile.path)
+
+ # Call the real assembler:
+ res = system("as", *args)
+ status = if res != nil
+ $?.exitstatus
+ else
+ 1
+ end
+ FileUtils.rm tempfile
+ exit status
+
+end
+
+wrapped_as(ARGV)
--- /dev/null
+#!/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) {
+ 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 $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 $_;
+ }
+}