github.com/epfl-dcsl/gotee@v0.0.0-20200909122901-014b35f5e5e9/src/cmd/go/internal/work/gosec.go (about)

     1  package work
     2  
     3  import (
     4  	"cmd/go/internal/load"
     5  	"fmt"
     6  	"log"
     7  	"os"
     8  	"path/filepath"
     9  	"text/template"
    10  )
    11  
    12  type Entry struct {
    13  	Functions []string
    14  	Imports   []string
    15  }
    16  
    17  const (
    18  	gosectmpl = `
    19  package main
    20  
    21  import(
    22  	"gosecu"
    23  	//"runtime"
    24  	{{range .Imports}}
    25  	{{ printf "%q" . }}{{end}}
    26  )
    27  
    28  func main() {
    29  	// Starting the functions.
    30  
    31  	{{range .Functions}}
    32  
    33  	gosecu.RegisterSecureFunction({{ . }})
    34  
    35  	{{end}}
    36  	gosecu.EcallServer()
    37  }
    38  `
    39  )
    40  
    41  // generateMain creates a temporary file _encl.o that corresponds contains
    42  // a main with go calls to all the gosecure targets.
    43  func generateMain(outfile string, functions, packages []string) string {
    44  	if len(functions) == 0 {
    45  		log.Fatalf("Missing target callees for gosecure keyword.")
    46  	}
    47  
    48  	if outfile == "" {
    49  		log.Fatalf("Missing argument `outfile` for gosec command")
    50  	}
    51  
    52  	data := Entry{functions, packages}
    53  	tmpl, err := template.New("gosec").Parse(gosectmpl)
    54  	if tmpl == nil || err != nil {
    55  		log.Fatalf(`gosec: parsing error "%s"`, err)
    56  	}
    57  
    58  	f, e := os.Create(outfile)
    59  	defer f.Close()
    60  	if e != nil {
    61  		log.Fatalf(`gosec creating outfile failed: "%s"`, e)
    62  	}
    63  
    64  	if err = tmpl.Execute(f, data); err != nil {
    65  		log.Fatalf(`"%s"`, err)
    66  	}
    67  	if _, err := os.Stat(outfile); os.IsNotExist(err) {
    68  		log.Fatalf("The file doesn't exist.")
    69  	}
    70  
    71  	return outfile
    72  }
    73  
    74  // gosec generates calls generateMain to create the main go file for the enclave
    75  // executable.
    76  func (b *Builder) gosec(a *Action) (err error) {
    77  	var functions, packages []string
    78  	ofile := filepath.Dir(a.Objdir) + "encl.go"
    79  	for p, m := range a.Package.PackagePublic.Gosectargets {
    80  		if p == "main" {
    81  			return fmt.Errorf("Invalid gosecure callee defined in main.")
    82  		}
    83  		packages = append(packages, p)
    84  		if len(m) != 0 {
    85  			for _, call := range m {
    86  				functions = append(functions, p+"."+call)
    87  			}
    88  		}
    89  	}
    90  	fname := generateMain(ofile, functions, packages)
    91  	if _, err := os.Stat(fname); os.IsNotExist(err) {
    92  		return err
    93  	}
    94  	// Define the output dir.
    95  	dir, err := os.Getwd()
    96  	if err != nil {
    97  		return err
    98  	}
    99  	efile := dir + "/enclave.out"
   100  	args := []string{"-o", efile, "-relocencl", fname}
   101  	cmd := CmdBuild
   102  	cmd.Flag.Parse(args)
   103  	args = cmd.Flag.Args()
   104  	cmd.Run(cmd, args)
   105  	a.Package.PackagePublic.Efile = efile
   106  	return nil
   107  }
   108  
   109  // CreateEnclaveExec returns an Action that creates the temporary files necessary
   110  // to create the enclave executable.
   111  func (b *Builder) CreateEnclaveExec(p *load.Package) *Action {
   112  	a := &Action{
   113  		Mode:    "build",
   114  		Package: p,
   115  		Func:    (*Builder).gosec,
   116  		Objdir:  b.NewObjdir(),
   117  	}
   118  	a.Target = a.Objdir + "_pkg_.a"
   119  	a.built = a.Target
   120  	return a
   121  }