You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
garble/testdata/script/linkname.txtar

172 lines
4.4 KiB
Plaintext

exec garble build
exec ./main
cmp stderr main.stderr
support go:linkname directives pointing at methods This is not common, but it is done by a few projects. Namely, github.com/goccy/go-json reached into reflect's guts, which included a number of methods: internal/runtime/rtype.go 11://go:linkname rtype_Align reflect.(*rtype).Align 19://go:linkname rtype_FieldAlign reflect.(*rtype).FieldAlign 27://go:linkname rtype_Method reflect.(*rtype).Method 35://go:linkname rtype_MethodByName reflect.(*rtype).MethodByName [...] Add tests for such go:linkname directives pointing at methods. Note that there are two possible symbol string variants; "pkg/path.(*Receiver).method" for methods with pointer receivers, and "pkg/path.Receiver.method" for the rest. We can't assume that the presence of two dots means a method either. For example, a package path may be "pkg/path.with.dots", and so "pkg/path.with.dots.SomeFunc" is the function "SomeFunc" rather than the method "SomeFunc" on a type "dots". To account for this ambiguity, rather than splitting on the last dot like we used to, try to find a package path prefix by splitting on an increasing number of first dots. This can in theory still be ambiguous. For example, we could have the package "pkg/path" expose the method "foo.bar", and the package "pkg/path.foo" expose the func "bar". Then, the symbol string "pkg/path.foo.bar" could mean either of them. However, this seems extremely unlikely to happen in practice, and I'm not sure that Go's toolchain would support it either. I also noticed that goccy/go-json still failed to build after the fix. The reason was that the type reflect.rtype wasn't being obfuscated. We could, and likely should, teach our assembly and linkname transformers about which names we chose not to obfuscate due to the use of reflection. However, in this particular case, reflect's own types can be obfuscated safely, so just do that. Fixes #656.
1 year ago
# TODO: why is 'obfuscatedMethod' present?
! binsubstr main$exe 'obfuscatedFunc' 'ObfuscatedFunc'
support go:linkname directives pointing at methods This is not common, but it is done by a few projects. Namely, github.com/goccy/go-json reached into reflect's guts, which included a number of methods: internal/runtime/rtype.go 11://go:linkname rtype_Align reflect.(*rtype).Align 19://go:linkname rtype_FieldAlign reflect.(*rtype).FieldAlign 27://go:linkname rtype_Method reflect.(*rtype).Method 35://go:linkname rtype_MethodByName reflect.(*rtype).MethodByName [...] Add tests for such go:linkname directives pointing at methods. Note that there are two possible symbol string variants; "pkg/path.(*Receiver).method" for methods with pointer receivers, and "pkg/path.Receiver.method" for the rest. We can't assume that the presence of two dots means a method either. For example, a package path may be "pkg/path.with.dots", and so "pkg/path.with.dots.SomeFunc" is the function "SomeFunc" rather than the method "SomeFunc" on a type "dots". To account for this ambiguity, rather than splitting on the last dot like we used to, try to find a package path prefix by splitting on an increasing number of first dots. This can in theory still be ambiguous. For example, we could have the package "pkg/path" expose the method "foo.bar", and the package "pkg/path.foo" expose the func "bar". Then, the symbol string "pkg/path.foo.bar" could mean either of them. However, this seems extremely unlikely to happen in practice, and I'm not sure that Go's toolchain would support it either. I also noticed that goccy/go-json still failed to build after the fix. The reason was that the type reflect.rtype wasn't being obfuscated. We could, and likely should, teach our assembly and linkname transformers about which names we chose not to obfuscate due to the use of reflection. However, in this particular case, reflect's own types can be obfuscated safely, so just do that. Fixes #656.
1 year ago
binsubstr main$exe 'UnobfuscatedMethod'
[short] stop # no need to verify this with -short
go build
exec ./main
cmp stderr main.stderr
-- go.mod --
module test/main
go 1.20
replace big.chungus/meme => ./big.chungus/meme
require big.chungus/meme v0.0.0
-- a.go --
package main
// Call a function which is linknamed to another symbol.
// What's special here is that we obfuscate this call before the function declaration.
// If we decide not to obfuscate the name in the function declaration,
// we shouldn't obfuscate the name here either.
func linknameCalledInPkg() {
println(obfuscatedFunc())
}
-- main.go --
package main
import (
_ "os/exec"
support go:linkname directives pointing at methods This is not common, but it is done by a few projects. Namely, github.com/goccy/go-json reached into reflect's guts, which included a number of methods: internal/runtime/rtype.go 11://go:linkname rtype_Align reflect.(*rtype).Align 19://go:linkname rtype_FieldAlign reflect.(*rtype).FieldAlign 27://go:linkname rtype_Method reflect.(*rtype).Method 35://go:linkname rtype_MethodByName reflect.(*rtype).MethodByName [...] Add tests for such go:linkname directives pointing at methods. Note that there are two possible symbol string variants; "pkg/path.(*Receiver).method" for methods with pointer receivers, and "pkg/path.Receiver.method" for the rest. We can't assume that the presence of two dots means a method either. For example, a package path may be "pkg/path.with.dots", and so "pkg/path.with.dots.SomeFunc" is the function "SomeFunc" rather than the method "SomeFunc" on a type "dots". To account for this ambiguity, rather than splitting on the last dot like we used to, try to find a package path prefix by splitting on an increasing number of first dots. This can in theory still be ambiguous. For example, we could have the package "pkg/path" expose the method "foo.bar", and the package "pkg/path.foo" expose the func "bar". Then, the symbol string "pkg/path.foo.bar" could mean either of them. However, this seems extremely unlikely to happen in practice, and I'm not sure that Go's toolchain would support it either. I also noticed that goccy/go-json still failed to build after the fix. The reason was that the type reflect.rtype wasn't being obfuscated. We could, and likely should, teach our assembly and linkname transformers about which names we chose not to obfuscate due to the use of reflection. However, in this particular case, reflect's own types can be obfuscated safely, so just do that. Fixes #656.
1 year ago
"reflect"
_ "strings"
support go:linkname directives pointing at methods This is not common, but it is done by a few projects. Namely, github.com/goccy/go-json reached into reflect's guts, which included a number of methods: internal/runtime/rtype.go 11://go:linkname rtype_Align reflect.(*rtype).Align 19://go:linkname rtype_FieldAlign reflect.(*rtype).FieldAlign 27://go:linkname rtype_Method reflect.(*rtype).Method 35://go:linkname rtype_MethodByName reflect.(*rtype).MethodByName [...] Add tests for such go:linkname directives pointing at methods. Note that there are two possible symbol string variants; "pkg/path.(*Receiver).method" for methods with pointer receivers, and "pkg/path.Receiver.method" for the rest. We can't assume that the presence of two dots means a method either. For example, a package path may be "pkg/path.with.dots", and so "pkg/path.with.dots.SomeFunc" is the function "SomeFunc" rather than the method "SomeFunc" on a type "dots". To account for this ambiguity, rather than splitting on the last dot like we used to, try to find a package path prefix by splitting on an increasing number of first dots. This can in theory still be ambiguous. For example, we could have the package "pkg/path" expose the method "foo.bar", and the package "pkg/path.foo" expose the func "bar". Then, the symbol string "pkg/path.foo.bar" could mean either of them. However, this seems extremely unlikely to happen in practice, and I'm not sure that Go's toolchain would support it either. I also noticed that goccy/go-json still failed to build after the fix. The reason was that the type reflect.rtype wasn't being obfuscated. We could, and likely should, teach our assembly and linkname transformers about which names we chose not to obfuscate due to the use of reflection. However, in this particular case, reflect's own types can be obfuscated safely, so just do that. Fixes #656.
1 year ago
"unsafe"
_ "big.chungus/meme"
"test/main/imported"
)
// A linkname to an external non-obfuscated func.
//go:linkname byteIndex strings.IndexByte
func byteIndex(s string, c byte) int
// A linkname to an external non-obfuscated non-exported func.
//go:linkname interfaceEqual os/exec.interfaceEqual
func interfaceEqual(a, b any) bool
// A linkname to an external obfuscated func.
//go:linkname obfuscatedFunc test/main/imported.ObfuscatedFuncImpl
func obfuscatedFunc() string
support go:linkname directives pointing at methods This is not common, but it is done by a few projects. Namely, github.com/goccy/go-json reached into reflect's guts, which included a number of methods: internal/runtime/rtype.go 11://go:linkname rtype_Align reflect.(*rtype).Align 19://go:linkname rtype_FieldAlign reflect.(*rtype).FieldAlign 27://go:linkname rtype_Method reflect.(*rtype).Method 35://go:linkname rtype_MethodByName reflect.(*rtype).MethodByName [...] Add tests for such go:linkname directives pointing at methods. Note that there are two possible symbol string variants; "pkg/path.(*Receiver).method" for methods with pointer receivers, and "pkg/path.Receiver.method" for the rest. We can't assume that the presence of two dots means a method either. For example, a package path may be "pkg/path.with.dots", and so "pkg/path.with.dots.SomeFunc" is the function "SomeFunc" rather than the method "SomeFunc" on a type "dots". To account for this ambiguity, rather than splitting on the last dot like we used to, try to find a package path prefix by splitting on an increasing number of first dots. This can in theory still be ambiguous. For example, we could have the package "pkg/path" expose the method "foo.bar", and the package "pkg/path.foo" expose the func "bar". Then, the symbol string "pkg/path.foo.bar" could mean either of them. However, this seems extremely unlikely to happen in practice, and I'm not sure that Go's toolchain would support it either. I also noticed that goccy/go-json still failed to build after the fix. The reason was that the type reflect.rtype wasn't being obfuscated. We could, and likely should, teach our assembly and linkname transformers about which names we chose not to obfuscate due to the use of reflection. However, in this particular case, reflect's own types can be obfuscated safely, so just do that. Fixes #656.
1 year ago
// A linkname to an external obfuscated method.
//go:linkname obfuscatedMethod test/main/imported.Receiver.obfuscatedMethod
func obfuscatedMethod(imported.Receiver) string
// A linkname to an external unobfuscated method.
//go:linkname unobfuscatedMethod test/main/imported.Receiver.UnobfuscatedMethod
func unobfuscatedMethod(imported.Receiver) string
// A linkname to an external obfuscated pointer method, with an extra parameter.
//go:linkname obfuscatedPointerMethod test/main/imported.(*Receiver).obfuscatedPointerMethod
func obfuscatedPointerMethod(*imported.Receiver, string) string
// Similar to the above, but for std, plus having to define a type.
// Some libraries do abuse reflect in this way, unfortunately.
type rtype struct{}
//go:linkname rtype_ptrTo reflect.(*rtype).ptrTo
func rtype_ptrTo(*rtype) *rtype
//go:linkname rtype_NumMethod reflect.(*rtype).NumMethod
func rtype_NumMethod(*rtype) int
// A linkname to an entirely made up name, implemented elsewhere.
//go:linkname renamedFunc madeup.newName
func renamedFunc() string
// A linkname to an external non-obfuscated func in another
// module whose package path has a dot in it.
//go:linkname tagline big.chungus/meme.chungify
func tagline() string
func main() {
println(byteIndex("01234", '3'))
println(interfaceEqual("Sephiroth", 7))
support go:linkname directives pointing at methods This is not common, but it is done by a few projects. Namely, github.com/goccy/go-json reached into reflect's guts, which included a number of methods: internal/runtime/rtype.go 11://go:linkname rtype_Align reflect.(*rtype).Align 19://go:linkname rtype_FieldAlign reflect.(*rtype).FieldAlign 27://go:linkname rtype_Method reflect.(*rtype).Method 35://go:linkname rtype_MethodByName reflect.(*rtype).MethodByName [...] Add tests for such go:linkname directives pointing at methods. Note that there are two possible symbol string variants; "pkg/path.(*Receiver).method" for methods with pointer receivers, and "pkg/path.Receiver.method" for the rest. We can't assume that the presence of two dots means a method either. For example, a package path may be "pkg/path.with.dots", and so "pkg/path.with.dots.SomeFunc" is the function "SomeFunc" rather than the method "SomeFunc" on a type "dots". To account for this ambiguity, rather than splitting on the last dot like we used to, try to find a package path prefix by splitting on an increasing number of first dots. This can in theory still be ambiguous. For example, we could have the package "pkg/path" expose the method "foo.bar", and the package "pkg/path.foo" expose the func "bar". Then, the symbol string "pkg/path.foo.bar" could mean either of them. However, this seems extremely unlikely to happen in practice, and I'm not sure that Go's toolchain would support it either. I also noticed that goccy/go-json still failed to build after the fix. The reason was that the type reflect.rtype wasn't being obfuscated. We could, and likely should, teach our assembly and linkname transformers about which names we chose not to obfuscate due to the use of reflection. However, in this particular case, reflect's own types can be obfuscated safely, so just do that. Fixes #656.
1 year ago
println(obfuscatedFunc())
support go:linkname directives pointing at methods This is not common, but it is done by a few projects. Namely, github.com/goccy/go-json reached into reflect's guts, which included a number of methods: internal/runtime/rtype.go 11://go:linkname rtype_Align reflect.(*rtype).Align 19://go:linkname rtype_FieldAlign reflect.(*rtype).FieldAlign 27://go:linkname rtype_Method reflect.(*rtype).Method 35://go:linkname rtype_MethodByName reflect.(*rtype).MethodByName [...] Add tests for such go:linkname directives pointing at methods. Note that there are two possible symbol string variants; "pkg/path.(*Receiver).method" for methods with pointer receivers, and "pkg/path.Receiver.method" for the rest. We can't assume that the presence of two dots means a method either. For example, a package path may be "pkg/path.with.dots", and so "pkg/path.with.dots.SomeFunc" is the function "SomeFunc" rather than the method "SomeFunc" on a type "dots". To account for this ambiguity, rather than splitting on the last dot like we used to, try to find a package path prefix by splitting on an increasing number of first dots. This can in theory still be ambiguous. For example, we could have the package "pkg/path" expose the method "foo.bar", and the package "pkg/path.foo" expose the func "bar". Then, the symbol string "pkg/path.foo.bar" could mean either of them. However, this seems extremely unlikely to happen in practice, and I'm not sure that Go's toolchain would support it either. I also noticed that goccy/go-json still failed to build after the fix. The reason was that the type reflect.rtype wasn't being obfuscated. We could, and likely should, teach our assembly and linkname transformers about which names we chose not to obfuscate due to the use of reflection. However, in this particular case, reflect's own types can be obfuscated safely, so just do that. Fixes #656.
1 year ago
r := imported.Receiver{Field: "field value"}
println(obfuscatedMethod(r))
println(unobfuscatedMethod(r))
println(obfuscatedPointerMethod(&r, "another value"))
typ := reflect.TypeOf(new(error)).Elem()
type emptyInterface struct {
_ *rtype
ptr unsafe.Pointer
}
rtyp := (*rtype)(((*emptyInterface)(unsafe.Pointer(&typ))).ptr)
println("rtype_ptrTo non-nil", rtype_ptrTo(rtyp) != nil)
println("rtype_NumMethod", rtype_NumMethod(rtyp))
println(renamedFunc())
println(tagline())
println(imported.ByteIndex("01234", '3'))
linknameCalledInPkg()
}
-- imported/imported.go --
package imported
import (
_ "strings"
_ "unsafe"
)
func ObfuscatedFuncImpl() string {
return "obfuscated func"
}
support go:linkname directives pointing at methods This is not common, but it is done by a few projects. Namely, github.com/goccy/go-json reached into reflect's guts, which included a number of methods: internal/runtime/rtype.go 11://go:linkname rtype_Align reflect.(*rtype).Align 19://go:linkname rtype_FieldAlign reflect.(*rtype).FieldAlign 27://go:linkname rtype_Method reflect.(*rtype).Method 35://go:linkname rtype_MethodByName reflect.(*rtype).MethodByName [...] Add tests for such go:linkname directives pointing at methods. Note that there are two possible symbol string variants; "pkg/path.(*Receiver).method" for methods with pointer receivers, and "pkg/path.Receiver.method" for the rest. We can't assume that the presence of two dots means a method either. For example, a package path may be "pkg/path.with.dots", and so "pkg/path.with.dots.SomeFunc" is the function "SomeFunc" rather than the method "SomeFunc" on a type "dots". To account for this ambiguity, rather than splitting on the last dot like we used to, try to find a package path prefix by splitting on an increasing number of first dots. This can in theory still be ambiguous. For example, we could have the package "pkg/path" expose the method "foo.bar", and the package "pkg/path.foo" expose the func "bar". Then, the symbol string "pkg/path.foo.bar" could mean either of them. However, this seems extremely unlikely to happen in practice, and I'm not sure that Go's toolchain would support it either. I also noticed that goccy/go-json still failed to build after the fix. The reason was that the type reflect.rtype wasn't being obfuscated. We could, and likely should, teach our assembly and linkname transformers about which names we chose not to obfuscate due to the use of reflection. However, in this particular case, reflect's own types can be obfuscated safely, so just do that. Fixes #656.
1 year ago
type Receiver struct{
Field string
}
func (r Receiver) obfuscatedMethod() string {
return "obfuscated method: " + r.Field
}
func (r *Receiver) obfuscatedPointerMethod(extra string) string {
return "obfuscated pointer method: " + r.Field + " plus " + extra
}
func (r Receiver) UnobfuscatedMethod() string {
return "unobfuscated method: " + r.Field
}
//go:linkname renamedFunc madeup.newName
func renamedFunc() string {
return "renamed func"
}
// A linkname to an external non-obfuscated func.
// Different from byteIndex, as we call this from an importer package.
//go:linkname ByteIndex strings.IndexByte
func ByteIndex(s string, c byte) int
-- big.chungus/meme/go.mod --
module test/main
go 1.20
-- big.chungus/meme/dante.go --
package meme
func chungify() string {
return "featuring Dante from the Devil May Cry series"
}
-- main.stderr --
3
false
obfuscated func
support go:linkname directives pointing at methods This is not common, but it is done by a few projects. Namely, github.com/goccy/go-json reached into reflect's guts, which included a number of methods: internal/runtime/rtype.go 11://go:linkname rtype_Align reflect.(*rtype).Align 19://go:linkname rtype_FieldAlign reflect.(*rtype).FieldAlign 27://go:linkname rtype_Method reflect.(*rtype).Method 35://go:linkname rtype_MethodByName reflect.(*rtype).MethodByName [...] Add tests for such go:linkname directives pointing at methods. Note that there are two possible symbol string variants; "pkg/path.(*Receiver).method" for methods with pointer receivers, and "pkg/path.Receiver.method" for the rest. We can't assume that the presence of two dots means a method either. For example, a package path may be "pkg/path.with.dots", and so "pkg/path.with.dots.SomeFunc" is the function "SomeFunc" rather than the method "SomeFunc" on a type "dots". To account for this ambiguity, rather than splitting on the last dot like we used to, try to find a package path prefix by splitting on an increasing number of first dots. This can in theory still be ambiguous. For example, we could have the package "pkg/path" expose the method "foo.bar", and the package "pkg/path.foo" expose the func "bar". Then, the symbol string "pkg/path.foo.bar" could mean either of them. However, this seems extremely unlikely to happen in practice, and I'm not sure that Go's toolchain would support it either. I also noticed that goccy/go-json still failed to build after the fix. The reason was that the type reflect.rtype wasn't being obfuscated. We could, and likely should, teach our assembly and linkname transformers about which names we chose not to obfuscate due to the use of reflection. However, in this particular case, reflect's own types can be obfuscated safely, so just do that. Fixes #656.
1 year ago
obfuscated method: field value
unobfuscated method: field value
obfuscated pointer method: field value plus another value
rtype_ptrTo non-nil true
rtype_NumMethod 1
renamed func
featuring Dante from the Devil May Cry series
3
obfuscated func