Skip to content

Instantly share code, notes, and snippets.

@iamahuman
Last active February 22, 2018 07:14
Show Gist options
  • Save iamahuman/12a1f1ae6cc0639393877e3aa063d18f to your computer and use it in GitHub Desktop.
Save iamahuman/12a1f1ae6cc0639393877e3aa063d18f to your computer and use it in GitHub Desktop.
clang wrapper for use with NDK
#!/usr/bin/perl
# NOTE symlinked from NDK, be cautious!
use strict;
use warnings;
use File::Basename;
use File::Spec;
use File::Copy;
our $DEBUG = '';
sub parse_argfile {
my ($fh) = @_;
my ($st, $arg) = (0, '');
my (@args) = ();
for (;;) {
my $k = read $fh, my $buf, 1;
unless (defined $k) {
$_[1] = ''; return;
}
last unless $k;
if ($st < 0) {
$st *= -1;
$arg .= $buf;
} elsif ($buf eq "\\") {
$st = -($st || 1);
} elsif ($buf eq "\"") {
($st == 0 || $st == 1) ? ($st = 2) :
($st == 2) ? ($st = 1) :
($st == 3) ? ($arg .= $buf) :
(die "assert fail");
} elsif ($buf eq "'") {
($st == 0 || $st == 1) ? ($st = 3) :
($st == 3) ? ($st = 1) :
($st == 2) ? ($arg .= $buf) :
(die "assert fail");
} elsif ($buf =~ m/\s/) {
if ($st == 1) {
push @args, $arg;
$arg = ''; $st = 0;
} elsif ($st >= 2) {
$arg .= $buf;
}
} elsif ($buf ne "") {
$st = 1 if $st == 0;
$arg .= $buf;
}
}
push @args, $arg if $st != 0;
$_[1] = 1;
return @args;
}
our %text_relocs = map {$_ => 1} (
"R_ARM_CALL",
"R_ARM_JUMP24",
"R_ARM_THM_ABS5", # Direct & 0x7C (LDR, STR).
"R_ARM_MOVW_ABS_NC", # Direct 16-bit (MOVW).
"R_ARM_MOVT_ABS", # Direct high 16-bit (MOVT).
"R_ARM_THM_MOVW_ABS_NC", # Direct 16 bit (Thumb32 MOVW).
"R_ARM_THM_MOVT_ABS", # Direct high 16 bit
);
sub is_not_pic {
my ($objdump, $infile) = @_;
$infile =~ s#^-#./-#;
my $pid = open my $ph, "-|";
return unless defined $pid;
unless ($pid) {
open STDERR, ">", File::Spec->devnull();
exec {$objdump} $objdump, "-r", $infile;
exit 127;
}
my $res = '';
{
local $/ = "\n";
while (<$ph>) {
# FIXME hacky text relocation detection
if (m/^\s*[0-9a-fA-F]+\s+(R_\w*)/ && $text_relocs{$1}) {
$res = 1; last;
}
}
}
close $ph;
waitpid $pid, 0;
return $res;
}
sub get_invoke_args {
return @ARGV if $#ARGV < 0 || $ARGV[0] eq "-cc1";
my ($nolink, $reloc, $nostdlib, $explicit_pie, $has_input, $skp) = ('')x6;
(my $objdump = $0) =~ s/[^-]+$/objdump/ or die "unknown invocation\n";
my @stack = reverse @ARGV;
while (@stack) {
my $arg = pop @stack;
if ($arg =~ m/^@(.+)$/ and open my $fh, "<", $1) {
# FIXME May fail if argfile is not a regular file
push @stack, reverse parse_argfile($fh, my $ok);
close $fh; next if $ok;
}
warn " ** Argument [$arg]\n" if $DEBUG;
$_ = $arg;
if ($skp) {
$skp = '';
} elsif (!m/^-/) {
$has_input = 1;
$explicit_pie = -1 if !$explicit_pie && is_not_pic($objdump, $arg);
copy($arg, "/tmp/ccwrap-$1") if $DEBUG && $arg =~ m,([^/]+\.s)$,;
} elsif (m/^-[oLIDU]$/) {
$skp = 1;
} elsif (m/^-[cSE]$/) {
$nolink = 1;
} elsif (m/^-r$/) {
$reloc = 1;
} elsif (m/^-nostdlib$/) {
$nostdlib = 1;
} elsif (m/^-(?:nopie|pie|shared|static)$/) {
$explicit_pie = 1 if $arg ne "-nopie" || !$explicit_pie;
} elsif (m/^-Wl,(.+)$/) {
foreach (split /,/, $1) {
if (m/^-(?:r|-relocatable)$/) {
$reloc = 1;
} elsif (m/^-(?:pie|shared|static)$/) {
$explicit_pie = 1;
}
}
}
}
warn "\n" if $DEBUG;
$nolink ||= !$has_input;
warn " ** Detected a non-PIC object as input; switching to -static **\n"
if !$nolink && !$reloc && $explicit_pie eq -1;
return (qw(-target armv7a-none-linux-androideabi),
"--sysroot", (dirname($0) . "/../sysroot"),
qw(-D__ANDROID_API__=24),
qw(-fPIC -mthumb -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16),
($nolink ? () : "-Wl,--fix-cortex-a8"),
($nolink || $reloc || $explicit_pie eq 1 ? () : ($explicit_pie eq -1 ? "-static" : "-pie")),
@ARGV,
($nolink || $reloc || $nostdlib ? () : "-lluke1337-android-support"));
}
unless (defined caller) {
my $exe = dirname($0) . ($0 =~ m/\+\+$/ ? "/clang50++" : "/clang50");
exec {$exe} $exe, get_invoke_args();
exit 127;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment