]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/objabi: expand -trimpath syntax
authorRuss Cox <rsc@golang.org>
Tue, 23 Apr 2019 03:48:51 +0000 (23:48 -0400)
committerRuss Cox <rsc@golang.org>
Wed, 24 Apr 2019 12:01:30 +0000 (12:01 +0000)
This CL affects the low-level -trimpath flag provided
by both cmd/asm and cmd/compile. Previously, the flag
took the name of a single directory that would be trimmed
from recorded paths in the resulting object file.
This CL makes the flag take a semicolon-separated list of paths.
Further, each path can now end in an optional "=>replacement"
to specify what to replace that leading path prefix with,
instead of only dropping it.

A followup CL will add a mode to cmd/go that uses this
richer -trimpath to build binaries that do not contain any
local path names.

For #16860.

Change-Id: I246811750f37607c7f7a8fbecd56c5475ebe1ea5
Reviewed-on: https://go-review.googlesource.com/c/go/+/173344
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
src/cmd/internal/objabi/line.go
src/cmd/internal/objabi/line_test.go [new file with mode: 0644]

index 1c671b211f8310cfb72048b055afa5716728e9db..178c8363d95d8a39b74167636f3b4972ccbfa975 100644 (file)
@@ -7,6 +7,7 @@ package objabi
 import (
        "os"
        "path/filepath"
+       "strings"
 )
 
 // WorkingDir returns the current working directory
@@ -21,32 +22,63 @@ func WorkingDir() string {
        return filepath.ToSlash(path)
 }
 
-// AbsFile returns the absolute filename for file in the given directory.
-// It also removes a leading pathPrefix, or else rewrites a leading $GOROOT
-// prefix to the literal "$GOROOT".
+// AbsFile returns the absolute filename for file in the given directory,
+// as rewritten by the rewrites argument.
+// For unrewritten paths, AbsFile rewrites a leading $GOROOT prefix to the literal "$GOROOT".
 // If the resulting path is the empty string, the result is "??".
-func AbsFile(dir, file, pathPrefix string) string {
+//
+// The rewrites argument is a ;-separated list of rewrites.
+// Each rewrite is of the form "prefix" or "prefix=>replace",
+// where prefix must match a leading sequence of path elements
+// and is either removed entirely or replaced by the replacement.
+func AbsFile(dir, file, rewrites string) string {
        abs := file
        if dir != "" && !filepath.IsAbs(file) {
                abs = filepath.Join(dir, file)
        }
 
-       if pathPrefix != "" && hasPathPrefix(abs, pathPrefix) {
-               if abs == pathPrefix {
-                       abs = ""
-               } else {
-                       abs = abs[len(pathPrefix)+1:]
+       start := 0
+       for i := 0; i <= len(rewrites); i++ {
+               if i == len(rewrites) || rewrites[i] == ';' {
+                       if new, ok := applyRewrite(abs, rewrites[start:i]); ok {
+                               abs = new
+                               goto Rewritten
+                       }
+                       start = i + 1
                }
-       } else if hasPathPrefix(abs, GOROOT) {
+       }
+       if hasPathPrefix(abs, GOROOT) {
                abs = "$GOROOT" + abs[len(GOROOT):]
        }
+
+Rewritten:
        if abs == "" {
                abs = "??"
        }
-
        return abs
 }
 
+// applyRewrite applies the rewrite to the path,
+// returning the rewritten path and a boolean
+// indicating whether the rewrite applied at all.
+func applyRewrite(path, rewrite string) (string, bool) {
+       prefix, replace := rewrite, ""
+       if j := strings.LastIndex(rewrite, "=>"); j >= 0 {
+               prefix, replace = rewrite[:j], rewrite[j+len("=>"):]
+       }
+
+       if prefix == "" || !hasPathPrefix(path, prefix) {
+               return path, false
+       }
+       if len(path) == len(prefix) {
+               return replace, true
+       }
+       if replace == "" {
+               return path[len(prefix)+1:], true
+       }
+       return replace + path[len(prefix):], true
+}
+
 // Does s have t as a path prefix?
 // That is, does s == t or does s begin with t followed by a slash?
 // For portability, we allow ASCII case folding, so that hasPathPrefix("a/b/c", "A/B") is true.
diff --git a/src/cmd/internal/objabi/line_test.go b/src/cmd/internal/objabi/line_test.go
new file mode 100644 (file)
index 0000000..1fa0ff1
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package objabi
+
+import (
+       "path/filepath"
+       "runtime"
+       "testing"
+)
+
+// On Windows, "/foo" is reported as a relative path
+// (it is relative to the current drive letter),
+// so we need add a drive letter to test absolute path cases.
+func drive() string {
+       if runtime.GOOS == "windows" {
+               return "c:"
+       }
+       return ""
+}
+
+var absFileTests = []struct {
+       dir      string
+       file     string
+       rewrites string
+       abs      string
+}{
+       {"/d", "f", "", "/d/f"},
+       {"/d", drive() + "/f", "", drive() + "/f"},
+       {"/d", "f/g", "", "/d/f/g"},
+       {"/d", drive() + "/f/g", "", drive() + "/f/g"},
+
+       {"/d", "f", "/d/f", "??"},
+       {"/d", "f/g", "/d/f", "g"},
+       {"/d", "f/g", "/d/f=>h", "h/g"},
+       {"/d", "f/g", "/d/f=>/h", "/h/g"},
+       {"/d", "f/g", "/d/f=>/h;/d/e=>/i", "/h/g"},
+       {"/d", "e/f", "/d/f=>/h;/d/e=>/i", "/i/f"},
+}
+
+func TestAbsFile(t *testing.T) {
+       for _, tt := range absFileTests {
+               abs := filepath.FromSlash(AbsFile(filepath.FromSlash(tt.dir), filepath.FromSlash(tt.file), tt.rewrites))
+               want := filepath.FromSlash(tt.abs)
+               if abs != want {
+                       t.Errorf("AbsFile(%q, %q, %q) = %q, want %q", tt.dir, tt.file, tt.rewrites, abs, want)
+               }
+       }
+}