From 5dd6b2dc43c46e0105012977ce9ab93a21e1360d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Thu, 12 Jan 2023 16:20:58 +0000 Subject: [PATCH] support assembly references to package names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Go's package runtime/internal/atomic contains references to functions which refer to the current package by its package name alone: src/runtime/internal/atomic/atomic_loong64.s: JMP atomic·Load(SB) src/runtime/internal/atomic/atomic_loong64.s: JMP atomic·Load64(SB) src/runtime/internal/atomic/atomic_loong64.s: JMP atomic·Load64(SB) src/runtime/internal/atomic/atomic_mips64x.s: JMP atomic·Load(SB) src/runtime/internal/atomic/atomic_mips64x.s: JMP atomic·Load64(SB) src/runtime/internal/atomic/atomic_mips64x.s: JMP atomic·Load64(SB) We could only handle unqualified or fully qualified references, like: JMP ·Load64(SB) JMP runtime∕internal∕atomic·Load64(SB) Apparently, all three forms are equally valid. Add a test case and fix it. I checked whether referencing an imported package by its name worked; it does not seem to be the case. This feature appears to be restricted to the current package alone. While here, we only need goPkgPath when we need to call listPackage. Fixes #619. --- main.go | 24 ++++++++++++-------- testdata/script/asm.txtar | 48 +++++++++++++++++++++++++++------------ 2 files changed, 49 insertions(+), 23 deletions(-) diff --git a/main.go b/main.go index 5c4e770..c5c3fb4 100644 --- a/main.go +++ b/main.go @@ -787,28 +787,34 @@ func replaceAsmNames(buf *bytes.Buffer, remaining []byte) { i += size } asmPkgPath := string(remaining[pkgStart:pkgEnd]) - goPkgPath := asmPkgPath - goPkgPath = strings.ReplaceAll(goPkgPath, string(asmPeriod), string(goPeriod)) - goPkgPath = strings.ReplaceAll(goPkgPath, string(asmSlash), string(goSlash)) // Write the bytes before our unqualified `·foo` or qualified `pkg·foo`. buf.Write(remaining[:pkgStart]) // If the name was qualified, fetch the package, and write the // obfuscated import path if needed. + // Note that we don't obfuscate the package path "main". + // // Note that runtime/internal/startlinetest refers to runtime_test in // one of its assembly files, and we currently do not always collect // test packages in appendListedPackages for the sake of performance. // We don't care about testing the runtime just yet, so work around it. + // TODO(mvdan): this runtime_test reference was removed in Go 1.20 per + // https://github.com/golang/go/issues/57334; remove at a later time. lpkg := curPkg - if asmPkgPath != "" && asmPkgPath != "runtime_test" { - var err error - lpkg, err = listPackage(goPkgPath) - if err != nil { - panic(err) // shouldn't happen + if asmPkgPath != "" && asmPkgPath != "main" && asmPkgPath != "runtime_test" { + if asmPkgPath != curPkg.Name { + goPkgPath := asmPkgPath + goPkgPath = strings.ReplaceAll(goPkgPath, string(asmPeriod), string(goPeriod)) + goPkgPath = strings.ReplaceAll(goPkgPath, string(asmSlash), string(goSlash)) + var err error + lpkg, err = listPackage(goPkgPath) + if err != nil { + panic(err) // shouldn't happen + } } if lpkg.ToObfuscate { - // Note that we don't need to worry about asmPkgSlash here, + // Note that we don't need to worry about asmSlash here, // because our obfuscated import paths contain no slashes right now. buf.WriteString(lpkg.obfuscatedImportPath()) } else { diff --git a/testdata/script/asm.txtar b/testdata/script/asm.txtar index 23b321c..fd0bd7e 100644 --- a/testdata/script/asm.txtar +++ b/testdata/script/asm.txtar @@ -6,7 +6,7 @@ garble build exec ./main cmp stderr main.stderr -! binsubstr main$exe 'test/main' 'privateAdd' 'PublicAdd' 'garble_' +! binsubstr main$exe 'test/main' 'addJmp' 'AddImpl' 'garble_' # We used to panic on broken packages with assembly. ! garble build ./broken/... @@ -24,12 +24,12 @@ stdin empty-reverse.txt garble -tiny build exec ./main cmp stderr main.stderr -! binsubstr main$exe 'privateAdd' 'PublicAdd' +! binsubstr main$exe 'addJmp' 'AddImpl' go build exec ./main cmp stderr main.stderr -binsubstr main$exe 'privateAdd' 'PublicAdd' +binsubstr main$exe 'addJmp' 'AddImpl' -- go.mod -- module test/with.many.dots/main @@ -41,7 +41,8 @@ import ( "test/with.many.dots/main/imported" ) -func privateAdd(x, y int32) int32 +func addJmpPkgPath(x, y int32) int32 +func addJmpPkgName(x, y int32) int32 // goData is used from both assembly and header files. var goData = [4]uint64{1, 2, 3, 4} @@ -50,7 +51,8 @@ func modifyGoData() func modifyGoData2() func main() { - println(privateAdd(1, 2)) + println(addJmpPkgPath(1, 2)) + println(addJmpPkgName(1, 2)) println(goData[0], goData[1]) modifyGoData() @@ -58,7 +60,7 @@ func main() { modifyGoData2() println(goData[0], goData[1]) - println(imported.PublicAdd(3, 4)) + println(imported.AddImpl(3, 4)) } -- garble_main_amd64.s -- #include "garble_define_amd64.h" @@ -69,8 +71,13 @@ func main() { // Or the same with leading whitespace: // A comment may include many·special∕asm·runes and it's okay. -TEXT ·privateAdd(SB),$0-16 - JMP test∕with·many·dots∕main∕imported·PublicAdd(SB) +// Reference an imported package by its package path. +TEXT ·addJmpPkgPath(SB),$0-16 + JMP test∕with·many·dots∕main∕imported·AddImpl(SB) + +// Reference the current package by its package name. +TEXT ·addJmpPkgName(SB),$0-16 + JMP main·addJmpPkgPath(SB) TEXT ·modifyGoData(SB),$0-16 addGoDataTo($12) @@ -93,22 +100,34 @@ TEXT ·modifyGoData2(SB),$0-16 -- imported/imported.go -- package imported -func PublicAdd(x, y int32) int32 +func AddImpl(x, y int32) int32 + +// Reference the current package by its package path. +func addJmpPkgPath(x, y int32) int32 + +// Reference the current package by its package path. +func addJmpPkgName(x, y int32) int32 -- imported/imported_amd64.s -- -TEXT ·PublicAdd(SB),$0-16 +TEXT ·AddImpl(SB),$0-16 MOVL x+0(FP), BX MOVL y+4(FP), BP ADDL BP, BX MOVL BX, ret+8(FP) RET + +TEXT ·addJmpPkgPath(SB),$0-16 + JMP test∕with·many·dots∕main∕imported·AddImpl(SB) + +TEXT ·addJmpPkgName(SB),$0-16 + JMP imported·AddImpl(SB) -- broken/syntax/broken.go -- package broken -func PublicAdd +func AddImpl -- broken/asm/imported_amd64.s -- -TEXT ·PublicAdd(SB),$0-16 +TEXT ·AddImpl(SB),$0-16 MOVL x+0(FP), BX MOVL y+4(FP), BP ADDL BP, BX @@ -117,10 +136,10 @@ TEXT ·PublicAdd(SB),$0-16 -- broken/asm/broken.go -- package broken -func PublicAdd(x, y int32) MissingType +func AddImpl(x, y int32) MissingType -- broken/imported_amd64.s -- -TEXT ·PublicAdd(SB),$0-16 +TEXT ·AddImpl(SB),$0-16 MOVL x+0(FP), BX MOVL y+4(FP), BP ADDL BP, BX @@ -128,6 +147,7 @@ TEXT ·PublicAdd(SB),$0-16 RET -- main.stderr -- 3 +3 1 2 13 36 25 70