BVB Source Codes

goreplay Show mksyscall_solaris.pl Source code

Return Download goreplay: download mksyscall_solaris.pl Source code - Download goreplay Source code - Type:.pl
  1. #!/usr/bin/env perl
  2. # Copyright 2009 The Go Authors. All rights reserved.
  3. # Use of this source code is governed by a BSD-style
  4. # license that can be found in the LICENSE file.
  5.  
  6. # This program reads a file containing function prototypes
  7. # (like syscall_solaris.go) and generates system call bodies.
  8. # The prototypes are marked by lines beginning with "//sys"
  9. # and read like func declarations if //sys is replaced by func, but:
  10. #       * The parameter lists must give a name for each argument.
  11. #         This includes return parameters.
  12. #       * The parameter lists must give a type for each argument:
  13. #         the (x, y, z int) shorthand is not allowed.
  14. #       * If the return parameter is an error number, it must be named err.
  15. #       * If go func name needs to be different than its libc name,
  16. #       * or the function is not in libc, name could be specified
  17. #       * at the end, after "=" sign, like
  18. #         //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
  19.  
  20. use strict;
  21.  
  22. my $cmdline = "mksyscall_solaris.pl " . join(' ', @ARGV);
  23. my $errors = 0;
  24. my $_32bit = "";
  25.  
  26. binmode STDOUT;
  27.  
  28. if($ARGV[0] eq "-b32") {
  29.         $_32bit = "big-endian";
  30.         shift;
  31. } elsif($ARGV[0] eq "-l32") {
  32.         $_32bit = "little-endian";
  33.         shift;
  34. }
  35.  
  36. if($ARGV[0] =~ /^-/) {
  37.         print STDERR "usage: mksyscall_solaris.pl [-b32 | -l32] [file ...]\n";
  38.         exit 1;
  39. }
  40.  
  41. if($ENV{'GOARCH'} eq "" || $ENV{'GOOS'} eq "") {
  42.         print STDERR "GOARCH or GOOS not defined in environment\n";
  43.         exit 1;
  44. }
  45.  
  46. sub parseparamlist($) {
  47.         my ($list) = @_;
  48.         $list =~ s/^\s*//;
  49.         $list =~ s/\s*$//;
  50.         if($list eq "") {
  51.                 return ();
  52.         }
  53.         return split(/\s*,\s*/, $list);
  54. }
  55.  
  56. sub parseparam($) {
  57.         my ($p) = @_;
  58.         if($p !~ /^(\S*) (\S*)$/) {
  59.                 print STDERR "$ARGV:$.: malformed parameter: $p\n";
  60.                 $errors = 1;
  61.                 return ("xx", "int");
  62.         }
  63.         return ($1, $2);
  64. }
  65.  
  66. my $package = "";
  67. my $text = "";
  68. my $dynimports = "";
  69. my $linknames = "";
  70. my @vars = ();
  71. while(<>) {
  72.         chomp;
  73.         s/\s+/ /g;
  74.         s/^\s+//;
  75.         s/\s+$//;
  76.         $package = $1 if !$package && /^package (\S+)$/;
  77.         my $nonblock = /^\/\/sysnb /;
  78.         next if !/^\/\/sys / && !$nonblock;
  79.  
  80.         # Line must be of the form
  81.         #       func Open(path string, mode int, perm int) (fd int, err error)
  82.         # Split into name, in params, out params.
  83.         if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$/) {
  84.                 print STDERR "$ARGV:$.: malformed //sys declaration\n";
  85.                 $errors = 1;
  86.                 next;
  87.         }
  88.         my ($nb, $func, $in, $out, $modname, $sysname) = ($1, $2, $3, $4, $5, $6);
  89.  
  90.         # Split argument lists on comma.
  91.         my @in = parseparamlist($in);
  92.         my @out = parseparamlist($out);
  93.  
  94.         # So file name.
  95.         if($modname eq "") {
  96.                 $modname = "libc";
  97.         }
  98.  
  99.         # System call name.
  100.         if($sysname eq "") {
  101.                 $sysname = "$func";
  102.         }
  103.  
  104.         # System call pointer variable name.
  105.         my $sysvarname = "proc$sysname";
  106.  
  107.         my $strconvfunc = "BytePtrFromString";
  108.         my $strconvtype = "*byte";
  109.  
  110.         $sysname =~ y/A-Z/a-z/; # All libc functions are lowercase.
  111.  
  112.         # Runtime import of function to allow cross-platform builds.
  113.         $dynimports .= "//go:cgo_import_dynamic libc_${sysname} ${sysname} \"$modname.so\"\n";
  114.         # Link symbol to proc address variable.
  115.         $linknames .= "//go:linkname ${sysvarname} libc_${sysname}\n";
  116.         # Library proc address variable.
  117.         push @vars, $sysvarname;
  118.  
  119.         # Go function header.
  120.         $out = join(', ', @out);
  121.         if($out ne "") {
  122.                 $out = " ($out)";
  123.         }
  124.         if($text ne "") {
  125.                 $text .= "\n"
  126.         }
  127.         $text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out;
  128.  
  129.         # Check if err return available
  130.         my $errvar = "";
  131.         foreach my $p (@out) {
  132.                 my ($name, $type) = parseparam($p);
  133.                 if($type eq "error") {
  134.                         $errvar = $name;
  135.                         last;
  136.                 }
  137.         }
  138.  
  139.         # Prepare arguments to Syscall.
  140.         my @args = ();
  141.         my @uses = ();
  142.         my $n = 0;
  143.         foreach my $p (@in) {
  144.                 my ($name, $type) = parseparam($p);
  145.                 if($type =~ /^\*/) {
  146.                         push @args, "uintptr(unsafe.Pointer($name))";
  147.                 } elsif($type eq "string" && $errvar ne "") {
  148.                         $text .= "\tvar _p$n $strconvtype\n";
  149.                         $text .= "\t_p$n, $errvar = $strconvfunc($name)\n";
  150.                         $text .= "\tif $errvar != nil {\n\t\treturn\n\t}\n";
  151.                         push @args, "uintptr(unsafe.Pointer(_p$n))";
  152.                         push @uses, "use(unsafe.Pointer(_p$n))";
  153.                         $n++;
  154.                 } elsif($type eq "string") {
  155.                         print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n";
  156.                         $text .= "\tvar _p$n $strconvtype\n";
  157.                         $text .= "\t_p$n, _ = $strconvfunc($name)\n";
  158.                         push @args, "uintptr(unsafe.Pointer(_p$n))";
  159.                         push @uses, "use(unsafe.Pointer(_p$n))";
  160.                         $n++;
  161.                 } elsif($type =~ /^\[\](.*)/) {
  162.                         # Convert slice into pointer, length.
  163.                         # Have to be careful not to take address of &a[0] if len == 0:
  164.                         # pass nil in that case.
  165.                         $text .= "\tvar _p$n *$1\n";
  166.                         $text .= "\tif len($name) > 0 {\n\t\t_p$n = \&$name\[0]\n\t}\n";
  167.                         push @args, "uintptr(unsafe.Pointer(_p$n))", "uintptr(len($name))";
  168.                         $n++;
  169.                 } elsif($type eq "int64" && $_32bit ne "") {
  170.                         if($_32bit eq "big-endian") {
  171.                                 push @args, "uintptr($name >> 32)", "uintptr($name)";
  172.                         } else {
  173.                                 push @args, "uintptr($name)", "uintptr($name >> 32)";
  174.                         }
  175.                 } elsif($type eq "bool") {
  176.                         $text .= "\tvar _p$n uint32\n";
  177.                         $text .= "\tif $name {\n\t\t_p$n = 1\n\t} else {\n\t\t_p$n = 0\n\t}\n";
  178.                         push @args, "uintptr(_p$n)";
  179.                         $n++;
  180.                 } else {
  181.                         push @args, "uintptr($name)";
  182.                 }
  183.         }
  184.         my $nargs = @args;
  185.  
  186.         # Determine which form to use; pad args with zeros.
  187.         my $asm = "sysvicall6";
  188.         if ($nonblock) {
  189.                 $asm = "rawSysvicall6";
  190.         }
  191.         if(@args <= 6) {
  192.                 while(@args < 6) {
  193.                         push @args, "0";
  194.                 }
  195.         } else {
  196.                 print STDERR "$ARGV:$.: too many arguments to system call\n";
  197.         }
  198.  
  199.         # Actual call.
  200.         my $args = join(', ', @args);
  201.         my $call = "$asm(uintptr(unsafe.Pointer(&$sysvarname)), $nargs, $args)";
  202.  
  203.         # Assign return values.
  204.         my $body = "";
  205.         my $failexpr = "";
  206.         my @ret = ("_", "_", "_");
  207.         my @pout= ();
  208.         my $do_errno = 0;
  209.         for(my $i=0; $i<@out; $i++) {
  210.                 my $p = $out[$i];
  211.                 my ($name, $type) = parseparam($p);
  212.                 my $reg = "";
  213.                 if($name eq "err") {
  214.                         $reg = "e1";
  215.                         $ret[2] = $reg;
  216.                         $do_errno = 1;
  217.                 } else {
  218.                         $reg = sprintf("r%d", $i);
  219.                         $ret[$i] = $reg;
  220.                 }
  221.                 if($type eq "bool") {
  222.                         $reg = "$reg != 0";
  223.                 }
  224.                 if($type eq "int64" && $_32bit ne "") {
  225.                         # 64-bit number in r1:r0 or r0:r1.
  226.                         if($i+2 > @out) {
  227.                                 print STDERR "$ARGV:$.: not enough registers for int64 return\n";
  228.                         }
  229.                         if($_32bit eq "big-endian") {
  230.                                 $reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i, $i+1);
  231.                         } else {
  232.                                 $reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i+1, $i);
  233.                         }
  234.                         $ret[$i] = sprintf("r%d", $i);
  235.                         $ret[$i+1] = sprintf("r%d", $i+1);
  236.                 }
  237.                 if($reg ne "e1") {
  238.                         $body .= "\t$name = $type($reg)\n";
  239.                 }
  240.         }
  241.         if ($ret[0] eq "_" && $ret[1] eq "_" && $ret[2] eq "_") {
  242.                 $text .= "\t$call\n";
  243.         } else {
  244.                 $text .= "\t$ret[0], $ret[1], $ret[2] := $call\n";
  245.         }
  246.         foreach my $use (@uses) {
  247.                 $text .= "\t$use\n";
  248.         }
  249.         $text .= $body;
  250.  
  251.         if ($do_errno) {
  252.                 $text .= "\tif e1 != 0 {\n";
  253.                 $text .= "\t\terr = e1\n";
  254.                 $text .= "\t}\n";
  255.         }
  256.         $text .= "\treturn\n";
  257.         $text .= "}\n";
  258. }
  259.  
  260. if($errors) {
  261.         exit 1;
  262. }
  263.  
  264. print <<EOF;
  265. // $cmdline
  266. // MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
  267.  
  268. // +build $ENV{'GOARCH'},$ENV{'GOOS'}
  269.  
  270. package $package
  271.  
  272. import (
  273.         "syscall"
  274.         "unsafe"
  275. )
  276. EOF
  277.  
  278. print "import \"golang.org/x/sys/unix\"\n" if $package ne "unix";
  279.  
  280. my $vardecls = "\t" . join(",\n\t", @vars);
  281. $vardecls .= " syscallFunc";
  282.  
  283. chomp($_=<<EOF);
  284.  
  285. $dynimports
  286. $linknames
  287. var (
  288. $vardecls
  289. )
  290.  
  291. $text
  292. EOF
  293. print $_;
  294. exit 0;
  295.  
downloadmksyscall_solaris.pl Source code - Download goreplay Source code
Related Source Codes/Software:
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10
django-rest-framework - Web APIs for Django. http:/... 2017-06-10
lectures - Oxford Deep NLP 2017 course 2017-06-10
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
postal - 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10

 Back to top