]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
s390-runone overhaul
authorFlorian Krohm <flo2030@eich-krohm.de>
Thu, 18 Sep 2025 21:06:31 +0000 (21:06 +0000)
committerFlorian Krohm <flo2030@eich-krohm.de>
Thu, 18 Sep 2025 21:06:31 +0000 (21:06 +0000)
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

auxprogs/s390-runone

index 2079a5e4607fdcfa10a502770fbabb4f9ac9acb4..f8d0288dde56f9def65b873143ddc8a68bbefe55 100755 (executable)
@@ -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.
 # 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 =<<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 GCC
+     --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";
+
+    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
+        ) 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 = <<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) = @_;
+
+    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 = <IN>) {
+        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;
+}