mirror of
git://sourceware.org/git/valgrind.git
synced 2026-01-12 00:19:31 +08:00
221 lines
5.5 KiB
Perl
Executable File
221 lines
5.5 KiB
Perl
Executable File
#!/usr/bin/env perl
|
|
|
|
use strict;
|
|
use warnings;
|
|
use Getopt::Long;
|
|
|
|
#-----------------------------------------------------------------------
|
|
# Compile a small C program containing a sequence of assembler
|
|
# instructions into an executable that does not need a dynamic linker.
|
|
# Very handy for debugging new insns or small snippets without going
|
|
# through the multi-pass process of figuring out which SB contains the
|
|
# code we're interested in.
|
|
#
|
|
# Step #1: s390-runone -t bla.c
|
|
#
|
|
# Creates a template which looks like so:
|
|
#
|
|
# int main(void)
|
|
# {
|
|
# asm volatile ("csch"); // begin mark: do not remove
|
|
# //FIXME: insert test code here:
|
|
# asm volatile ("lghi %r1,1"); // __NR_exit
|
|
# asm volatile ("lghi %r2,0"); // return code = 0
|
|
# asm volatile ("svc 0"); // terminate process
|
|
# asm volatile ("csch"); // end mark: do not remove
|
|
# return 0;
|
|
# }
|
|
#
|
|
# Step #2: Replace the FIXME line with one or more asm statements.
|
|
# Skip this step if you used --insn=... in step #1.
|
|
#
|
|
# Step #3: s390-runone --build bla.c
|
|
#
|
|
# Compiles and links "bla.c" into an executable "bla" which does not
|
|
# require the dynamic loader and which contains only those insns between
|
|
# the two marker insns (csch).
|
|
#
|
|
# objdump -d:
|
|
#
|
|
# 00000000010000b0 <_start>:
|
|
# 10000b0: a7 19 00 01 lghi %r1,1
|
|
# 10000b4: a7 29 00 00 lghi %r2,0
|
|
# 10000b8: 0a 00 svc 0
|
|
#
|
|
#-----------------------------------------------------------------------
|
|
#
|
|
|
|
&main;
|
|
|
|
sub usage {
|
|
my $text =<<END
|
|
|
|
Usage: s390-runone [options] FILE
|
|
|
|
Options:
|
|
--template Write template
|
|
--build Build executable from C file
|
|
--insn INSN Add INSN to template
|
|
--arch ARCH Passed as -march=ARCH to the compiler
|
|
--cc COMP Use COMP as compiler
|
|
--help Write this text
|
|
|
|
FILE is mandatory with --build
|
|
|
|
END
|
|
;
|
|
print $text;
|
|
exit 0;
|
|
}
|
|
|
|
sub main {
|
|
my $template = 0;
|
|
my $build = 0;
|
|
my $help = 0;
|
|
my $insn = "";
|
|
my $arch = "arch14";
|
|
my $cc = "gcc";
|
|
|
|
GetOptions("template|t" => sub { $template = 1; $build = 0; },
|
|
"build|b" => sub { $template = 0; $build = 1; },
|
|
"help|h" => \$help,
|
|
"insn|i=s" => \$insn,
|
|
"arch|a=s" => \$arch,
|
|
"cc=s" => \$cc
|
|
) or usage();
|
|
|
|
usage() if ($help);
|
|
|
|
my $num_arg = $#ARGV + 1;
|
|
my $file = "";
|
|
|
|
if ($num_arg != 1) {
|
|
fatal("Missing file name") if ($build);
|
|
} else {
|
|
$file = $ARGV[0];
|
|
}
|
|
|
|
my $rc = 0;
|
|
if ($template) {
|
|
write_template($file, $insn);
|
|
} elsif ($build) {
|
|
$rc = build_exe($file, $arch, $cc);
|
|
} else {
|
|
print "Nothing happens\n";
|
|
}
|
|
exit $rc;
|
|
}
|
|
|
|
sub write_template
|
|
{
|
|
my ($file, $insn) = @_;
|
|
my $asm;
|
|
|
|
if ($insn eq "") {
|
|
$asm = "//FIXME: insert test code here:";
|
|
} else {
|
|
$asm = "asm volatile (\"$insn\");";
|
|
}
|
|
|
|
my $template = <<END2
|
|
int main(void)
|
|
{
|
|
asm volatile ("csch"); // begin mark: do not remove
|
|
$asm
|
|
asm volatile ("lghi %r1,1"); // __NR_exit
|
|
asm volatile ("lghi %r2,0"); // return code = 0
|
|
asm volatile ("svc 0"); // terminate process
|
|
asm volatile ("csch"); // end mark: do not remove
|
|
return 0;
|
|
}
|
|
END2
|
|
;
|
|
if ($file ne "") {
|
|
open(OUT, ">$file") || fatal("Cannot open '$file': $!\n");
|
|
print OUT $template;
|
|
close(OUT);
|
|
} else {
|
|
print $template;
|
|
}
|
|
}
|
|
|
|
sub build_exe
|
|
{
|
|
my ($file, $arch, $cc) = @_;
|
|
|
|
my $base = `basename "$file" .c`;
|
|
chomp($base);
|
|
my $asm = "$base.s";
|
|
my $exe = "$base";
|
|
|
|
# Compile the testprogram to assembler
|
|
my $stderr = `$cc -S -fno-ident -march=$arch $file 2>&1`;
|
|
if ($? != 0) {
|
|
error("$cc: Compilation failed\n $stderr");
|
|
return 1;
|
|
}
|
|
`mv "$asm" "$asm.orig"`; # save before massaging
|
|
|
|
# Massage assembler file:
|
|
# - rename main ---> _start
|
|
# - remove cfi stuff
|
|
# - remove comment lines
|
|
# - remove insns preceeding 1st mark (csch)
|
|
# - remove insns succeeding 2nd mark (csch)
|
|
|
|
my $in_main = 0;
|
|
my $mark_seen = 0;
|
|
my $output = "";
|
|
open(IN, "$asm.orig") || fatal("Cannot open '$file': $!\n");
|
|
while (my $line = <IN>) {
|
|
chomp($line);
|
|
next if ($line =~ /^\s*#/); # comment
|
|
next if ($line =~ /\.cfi_/); # cfi stuff
|
|
if ($in_main == 0) {
|
|
$in_main = 1 if ($line =~ /^main:/);
|
|
} else {
|
|
if ($mark_seen == 0) {
|
|
if ($line =~ /csch/) {
|
|
$mark_seen = 1;
|
|
next;
|
|
}
|
|
next if ($line =~ /^\t[a-z]/); # skip insn
|
|
} else {
|
|
if ($line =~ /csch/) {
|
|
$mark_seen = 0;
|
|
next;
|
|
}
|
|
}
|
|
}
|
|
$line =~ s/main/_start/g;
|
|
$output .= "$line\n";
|
|
}
|
|
open(OUT, ">$asm") || fatal("Cannot open '$asm': $!\n");
|
|
print OUT $output;
|
|
close(OUT);
|
|
|
|
# Assemble file and link to executable
|
|
my $ccc = "$cc -static -Wa,--fatal-warnings -Wl,--build-id=none"
|
|
. " -nodefaultlibs -nostartfiles";
|
|
$stderr = `$ccc "$asm" -o "$exe" 2>&1`;
|
|
|
|
if ($? != 0) {
|
|
error("$cc: Linking executable failed");
|
|
for my $line (split /\n/,$stderr) {
|
|
print STDERR "$line\n" if ($line !~ /treating warnings as errors/);
|
|
}
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
sub error
|
|
{
|
|
print STDERR "*** $_[0]\n";
|
|
}
|
|
|
|
sub fatal
|
|
{
|
|
error($_[0]);
|
|
exit 1;
|
|
}
|