|
|
|
@ -4,8 +4,16 @@
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"crypto/sha256"
|
|
|
|
|
"encoding/base64"
|
|
|
|
|
"flag"
|
|
|
|
|
"fmt"
|
|
|
|
|
"go/ast"
|
|
|
|
|
"go/parser"
|
|
|
|
|
"go/printer"
|
|
|
|
|
"go/token"
|
|
|
|
|
"io"
|
|
|
|
|
"io/ioutil"
|
|
|
|
|
"log"
|
|
|
|
|
"os"
|
|
|
|
|
"os/exec"
|
|
|
|
@ -29,7 +37,14 @@ Usage of garble:
|
|
|
|
|
|
|
|
|
|
func main() { os.Exit(main1()) }
|
|
|
|
|
|
|
|
|
|
var workingDir string
|
|
|
|
|
var (
|
|
|
|
|
workingDir string
|
|
|
|
|
deferred []func() error
|
|
|
|
|
fset = token.NewFileSet()
|
|
|
|
|
|
|
|
|
|
b64 = base64.NewEncoding("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_z")
|
|
|
|
|
printerConfig = printer.Config{Mode: printer.RawFormat}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func main1() int {
|
|
|
|
|
if err := flagSet.Parse(os.Args[1:]); err != nil {
|
|
|
|
@ -57,6 +72,13 @@ func main1() int {
|
|
|
|
|
return 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
defer func() {
|
|
|
|
|
for _, fn := range deferred {
|
|
|
|
|
if err := fn(); err != nil {
|
|
|
|
|
fmt.Fprintln(os.Stderr, err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
cmd := exec.Command(args[0], transformed...)
|
|
|
|
|
cmd.Stdout = os.Stdout
|
|
|
|
|
cmd.Stderr = os.Stderr
|
|
|
|
@ -83,9 +105,74 @@ func transformCompile(args []string) ([]string, error) {
|
|
|
|
|
if !strings.Contains(trimpath, workingDir) {
|
|
|
|
|
return nil, fmt.Errorf("-toolexec=garble should be used alongside -trimpath")
|
|
|
|
|
}
|
|
|
|
|
std := flagValue(flags, "-std") == "true"
|
|
|
|
|
buildid := flagValue(flags, "-buildid")
|
|
|
|
|
for i, file := range files {
|
|
|
|
|
if std {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
var err error
|
|
|
|
|
files[i], err = transformGoFile(buildid, file)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return append(flags, files...), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func hashWith(salt, value string) string {
|
|
|
|
|
const length = 8
|
|
|
|
|
|
|
|
|
|
d := sha256.New()
|
|
|
|
|
io.WriteString(d, salt)
|
|
|
|
|
io.WriteString(d, value)
|
|
|
|
|
sum := b64.EncodeToString(d.Sum(nil))
|
|
|
|
|
|
|
|
|
|
for i := 0; i < len(sum)-length; i++ {
|
|
|
|
|
if '0' <= sum[i] && sum[i] <= '9' {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
return sum[i : i+length]
|
|
|
|
|
}
|
|
|
|
|
return "_" + sum[:length-1]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// transformGoFile creates a garbled copy of the Go file at path, and returns
|
|
|
|
|
// the path to the copy.
|
|
|
|
|
func transformGoFile(buildid, path string) (string, error) {
|
|
|
|
|
file, err := parser.ParseFile(fset, path, nil, 0)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
ast.Inspect(file, func(node ast.Node) bool {
|
|
|
|
|
switch node := node.(type) {
|
|
|
|
|
case *ast.Ident:
|
|
|
|
|
switch {
|
|
|
|
|
case node.Obj == nil:
|
|
|
|
|
// a builtin name, or the package name
|
|
|
|
|
case node.Name == "main":
|
|
|
|
|
// possibly the main func
|
|
|
|
|
default:
|
|
|
|
|
node.Name = hashWith(buildid, node.Name)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true
|
|
|
|
|
})
|
|
|
|
|
f, err := ioutil.TempFile("", "garble")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
defer f.Close()
|
|
|
|
|
printerConfig.Fprint(os.Stderr, fset, file)
|
|
|
|
|
if err := printerConfig.Fprint(f, fset, file); err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
if err := f.Close(); err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
return f.Name(), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func transformLink(args []string) ([]string, error) {
|
|
|
|
|
flags, files := splitFlagsFromFiles(args, ".a")
|
|
|
|
|
if len(files) == 0 {
|
|
|
|
@ -117,9 +204,15 @@ func flagValue(flags []string, name string) string {
|
|
|
|
|
// -name=value
|
|
|
|
|
return val
|
|
|
|
|
}
|
|
|
|
|
if arg == name && i+1 < len(flags) {
|
|
|
|
|
// -name value
|
|
|
|
|
return flags[i+1]
|
|
|
|
|
if arg == name {
|
|
|
|
|
if i+1 < len(flags) {
|
|
|
|
|
if val := flags[i+1]; !strings.HasPrefix(val, "-") {
|
|
|
|
|
// -name value
|
|
|
|
|
return flags[i+1]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// -name, equivalent to -name=true
|
|
|
|
|
return "true"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ""
|
|
|
|
|