From: Florian Krohm Date: Thu, 18 Sep 2025 21:06:31 +0000 (+0000) Subject: s390-runone overhaul X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=dbf880ca15d14202adb5edc93c827b3a987e136f;p=thirdparty%2Fvalgrind.git s390-runone overhaul Rewritten in perl. Command line options added. Minimise assembler file by throwing out any function prologue stuff GCC might stick into a function. Also remove insns following the svc as they are not reachable. Error handling: capture errors/warnings from the assembler. Why all this? https://bugs.kde.org/show_bug.cgi?id=509572 --- diff --git a/auxprogs/s390-runone b/auxprogs/s390-runone index 2079a5e46..f8d0288dd 100755 --- a/auxprogs/s390-runone +++ b/auxprogs/s390-runone @@ -1,5 +1,9 @@ -#!/bin/sh -# +#!/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. @@ -7,79 +11,207 @@ # through the multi-pass process of figuring out which SB contains the # code we're interested in. # -# Here is a template: +# 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"); -# return 0; // shuts up GCC +# asm volatile ("svc 0"); // terminate process +# asm volatile ("csch"); // end mark: do not remove +# return 0; # } # -# When running the executable created by this script under valgrind -# there will be only a single super block! Which is exactly what we want -# for debugging. +# 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: b3 c1 00 0b ldgr %f0,%r11 -# 10000b4: b9 04 00 bf lgr %r11,%r15 -# 10000b8: a7 19 00 01 lghi %r1,1 <--- -# 10000bc: a7 29 00 09 lghi %r2,9 <--- -# 10000c0: 0a 00 svc 0 <--- -# 10000c2: a7 18 00 00 lhi %r1,0 -# 10000c6: b9 14 00 11 lgfr %r1,%r1 -# 10000ca: b9 04 00 21 lgr %r2,%r1 -# 10000ce: b3 cd 00 b0 lgdr %r11,%f0 -# 10000d2: 07 fe br %r14 -# 10000d4: 07 07 nopr %r7 -# 10000d6: 07 07 nopr %r7 +# 10000b0: a7 19 00 01 lghi %r1,1 +# 10000b4: a7 29 00 00 lghi %r2,0 +# 10000b8: 0a 00 svc 0 # -# There are only 2 extra insns ahead of our asm code sequence. -# Everything after the svc insn is not reachable. #----------------------------------------------------------------------- # -if [ "x$1" = "x" ]; then - echo "Usage: s390-runone C-file" 1>&2 - echo " or: s390-runone -t" 1>&2 - exit 1 -fi - -if [ "x$1" = "x-t" ]; then - echo 'int main(void)' - echo '{' - echo ' //FIXME: insert test code here:' - echo ' asm volatile ("lghi %r1,1"); // __NR_exit' - echo ' asm volatile ("lghi %r2,0"); // return code = 0' - echo ' asm volatile ("svc 0");' - echo ' return 0; // shuts up GCC' - echo '}' - exit 0 -fi - -file="$1" -base=`basename "$file" .c` -asm="$base.s" -exe="$base" - -if [ "$base" = "$file" ]; then - echo "$file is not a C file" 1>&2 - exit 1 -fi +&main; + +sub usage { + my $text =< sub { $template = 1; $build = 0; }, + "build|b" => sub { $template = 0; $build = 1; }, + "help|h" => \$help, + "insn|i=s" => \$insn, + "arch|a=s" => \$arch + ) 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); + } 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 = <$file") || fatal("Cannot open '$file': $!\n"); + print OUT $template; + close(OUT); + } else { + print $template; + } +} + +sub build_exe +{ + my ($file, $arch) = @_; + + my $base = `basename "$file" .c`; + chomp($base); + my $asm = "$base.s"; + my $exe = "$base"; # Compile the testprogram to assembler -gcc -S -fno-ident -march=arch14 $file -mv "$asm" "$asm.orig" # save the result + my $stderr = `gcc -S -fno-ident -march=$arch $file 2>&1`; + if ($? != 0) { + error("GCC: 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 = ) { + chomp($line); + next if ($line =~ /^#/); # 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 $gcc = "gcc -static -Wa,--fatal-warnings -Wl,--build-id=none" + . " -nodefaultlibs -nostartfiles"; + $stderr = `$gcc "$asm" -o "$exe" 2>&1`; -# Rename main with _start, remove cfi stuff and comment lines -sed 's/main/_start/g' "$asm.orig" | grep -v \.cfi_ | grep -v ^# > "$asm" + if ($? != 0) { + error("GCC: Linking executable failed"); + for my $line (split /\n/,$stderr) { + print STDERR "$line\n" if ($line !~ /treating warnings as errors/); + } + return 1; + } +} -# Link to executable -gcc -static -Wl,--build-id=none -nodefaultlibs -nostartfiles "$asm" -o "$exe" +sub error +{ + print STDERR "*** $_[0]\n"; +} -echo "$exe created" -exit 0 +sub fatal +{ + error($_[0]); + exit 1; +}