When compiling a package that instantiates a generic type from another
package, info.Types only contains the instantiated *types.Named. The
*types.Struct case in recordFieldToStruct returns early on instantiated
structs (field != field.Origin()), so the origin struct was never
recorded in fieldToStruct. At rewrite time, looking up the origin field
then failed with "could not find struct for field X".
Fix by also recursing into typ.Origin() for instantiated named types,
so the uninstantiated struct is visited and its fields are recorded.
Fixes#1027.
The Go assembler generates go_asm.h with constants like TypeName__size
and TypeName_FieldName for struct types. When garble obfuscates type
and field names, these constants use the obfuscated names, but the
assembly source still refers to the originals, causing build failures.
During transformCompile, save the original-to-obfuscated name mapping
to the build cache. In the second asm pass (after compile has run),
load the mapping and rewrite the .s files with a strings.Replacer.
The work is shared between the compiler and assembler steps
because it would be too much work for the assembler step by itself.
These constants follow patterns like Type_field or Type__size,
so they don't use special characters that we can easily locate.
And the go_asm.h file that the compiler generates already uses
the obfuscated names, which we cannot reverse without the originals.
Fetching the original names and fields would require parsing
and typechecking, which is something that the compiler step does.
Without the fix, the added test fails as follows:
> exec garble build
[stderr]
# test/with.many.dots/main
./.tmp/[...]/IQSArvqP.s:30: expected pseudo-register; found R11
./.tmp/[...]/IQSArvqP.s:31: expected pseudo-register; found R11
./.tmp/[...]/IQSArvqP.s:37: illegal or missing addressing mode for symbol Args__size
asm: assembly of ./.tmp/[...]/IQSArvqP.s failed
Thanks to Golo Roden for figuring out a test reproducer
as well as the overall approach for a fix to the problem.
The test added here is simplified from his code,
and the fix is inspired by his approach.
Fixes#948.
There are no integration tests because writing one is fairly tricky.
Luckily, the added code is fairly simple.
Windows in CI works as a form of regression test.
First, the current iteration of this code only needs to look at
go/types.Info.Types; looking at the Uses and Defs is redundant.
Note that we still need to fill Uses and Defs for ObjectOf to work.
Second, for consistent hashing in the face of generic types,
we have been using uninstantiated or "origin" field vars
when looking up fieldToStruct entries.
computeFieldToStruct tried to only look at these origin types,
but it didn't do so correctly. The test case added in #1016
made this evident given the added inconsistency panic check.
Third, resolve this by only checking the Origin method when we are
looping over the struct fields; if any of them is an instance,
abort as we are currently on an instantiated type.
This is not ideal, hence the TODO, but it works for now.
This resolves intermittent test failures with the test case
added in #1016; the fix there wasn't entirely incorrect,
but the code was buggy as we would loop over go/types.Info.Types
in the random map iteration order, so it was a coin flip
whether we would record the uninstantiated or instantiated types.
We don't add a test because adding one is tricky, but luckily,
the added assertion catches any such inconsistency in our logic,
so that should work as a form of a regression test.
Beyond the usual updating of version strings, re-running `go generate`,
and updating the patches for the linker, we needed extra changes.
First, the linker started being stricter about which packages
are allowed to linkname runtime names by import path.
Stop obfuscating import paths in runtimeAndLinknamed.
Second, the compiler's intrinsics code adds an "add" function
much like the existing "addF", so tweak the regular expression.
Third, note that there is a new runtimeAndDeps windows-only package,
which we find thanks to the recent improvement to cover many platforms.
Fourth, the code around magic numbers in the runtime has changed,
so rewrite the code which patches it via go/ast.
Fixes#990.
Use `types.Var.Origin()` when mapping and hashing struct fields so selector and
declaration sites share the same canonical field identity. This fixes build
failures for generic aliases and named types over those aliases.
Fixes#924
This makes the unobfuscated state easily accessible, for debugging.
Obfuscated code is output to: `./<debugdir>/garbled`
The original source code is output to:
`./<debugdir>/source`
Also enable caching for debugdir to allow for faster iteration.
* reflect_abi_patch.go was added into reflect.go
* shared.go was renamed into cache_shared.go and package caching was moved to cache_pkg.go
* transformer methods in main.go are moved to transformer.go