Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Currently, there isn't a reliable way to build #20

Draft
wants to merge 1 commit into
base: release-0.46
Choose a base branch
from

Conversation

srosenberg
Copy link
Member

@srosenberg srosenberg commented May 22, 2024

Go test binaries with libfuzzer instrumentation [1]. An attempt such as
bazel run --@io_bazel_rules_go//go/config:gc_goopts=-d=libfuzzer ... fails to compile owing to unresolved symbols, e.g., runtime.libfuzzerTraceConstCmp8 [2].

This patch adds libfuzzer_shim.go (identical to trace.go [2]) to the bzltestutil package, which ensures the shim is linked with a Go test binary. Furthermore, we exclude -d=libfuzzer, when compiling any of the external dependencies,
or Go's stdlib.

[1] bazel-contrib#3088 (comment)
[2] golang/go@74f49f3

@srosenberg
Copy link
Member Author

srosenberg commented May 22, 2024

Tested on gceworker,

bazel run --override_repository=io_bazel_rules_go=/home/srosenberg/go/src/github.com/cockroachdb/rules_go --@io_bazel_rules_go//go/config:gc_goopts=-d=libfuzzer pkg/keys:keys_test -- -test.run notests -test.fuzz FuzzPrettyPrint  -test.fuzzcachedir /tmp/foobar/ -test.v

However, I also needed to inject libfuzzer_shim.go into some of the internal tools/generators, which were require build dependencies [1].

[1] srosenberg/cockroach@24b0adb

@srosenberg srosenberg force-pushed the sr/support_libfuzzer_instrumentation branch from 8f31dca to e104af2 Compare May 22, 2024 17:19
Go test binaries with libfuzzer instrumentation [1].
An attempt such as
`bazel run --@io_bazel_rules_go//go/config:gc_goopts=-d=libfuzzer ...`
fails to compile owing to unresolved symbols, e.g.,
runtime.libfuzzerTraceConstCmp8 [2].

This patch adds `libfuzzer_shim.go` (identical to `trace.go` [2])
to the `bzltestutil` package, which ensures the shim is linked
with a Go test binary. Furthermore, we exclude `-d=libfuzzer`,
when compiling any of the _external_ dependencies, or Go's stdlib.

[1] bazel-contrib#3088 (comment)
[2] golang/go@74f49f3
@srosenberg srosenberg force-pushed the sr/support_libfuzzer_instrumentation branch from e104af2 to 893191b Compare May 22, 2024 17:22
@@ -343,6 +344,17 @@ func compileArchive(
cgoSrcs[i-len(goSrcs)] = coverSrc
}
}
if strings.Contains(outLinkObj, "external/") && slices.Contains(gcFlags, "-d=libfuzzer") {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rickystewart I couldn't find a cleaner way to determine whether we're compiling an external dependency, but this seems to work. Maybe you have a better idea?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably how I would do it.

@srosenberg
Copy link
Member Author

srosenberg commented May 22, 2024

However, I also needed to inject libfuzzer_shim.go into some of the internal tools/generators, which were require build dependencies [1].
[1] srosenberg/cockroach@24b0adb

@rickystewart Is there an automated way to inject the shim to all the possible internal tools/generators? Otherwise, we may end up with a linker error (for a dependent generator) when building some other test binary.

@srosenberg srosenberg requested a review from Nukitt May 29, 2024 02:05
Copy link

@rickystewart rickystewart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, I also needed to inject libfuzzer_shim.go into some of the internal tools/generators, which were require build dependencies [1].
[1] srosenberg/cockroach@24b0adb

@rickystewart Is there an automated way to inject the shim to all the possible internal tools/generators? Otherwise, we may end up with a linker error (for a dependent generator) when building some other test binary.

Can you go into a little more detail? I don't really know what "all possible internal tools/generators" means. Maybe an example?

}
// Log instrumented objs for ease of tracking/debugging.
if slices.Contains(gcFlags, "-d=libfuzzer") {
fmt.Printf("%s -- gcFlags=%s\n", outLinkObj, gcFlags)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we want this checked in.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I'll remove; couldn't find a standard way of logging debug messages, which would get suppressed by default.

@@ -343,6 +344,17 @@ func compileArchive(
cgoSrcs[i-len(goSrcs)] = coverSrc
}
}
if strings.Contains(outLinkObj, "external/") && slices.Contains(gcFlags, "-d=libfuzzer") {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably how I would do it.

@srosenberg
Copy link
Member Author

Can you go into a little more detail? I don't really know what "all possible internal tools/generators" means. Maybe an example?

I meant all targets which contain genrule. E.g., pkg/sql/opt/optgen/lang/BUILD.bazel has these,

":gen-expr",  # keep
":gen-operator",  # keep
":gen-operator-stringer",  # keep
":gen-token-stringer",  # keep

where gen-expr requires building a binary in pkg/sql/opt/optgen/cmd/langgen. If we get the (transitive) set of all these generated binaries, then in theory it should suffice to drop libfuzzer_shim.go in each. Alternatively, we could try to exclude them from instrumentation, but there isn't seemingly a unique prefix or other pattern to match.

@rickystewart
Copy link

rickystewart commented May 29, 2024

If we get the (transitive) set of all these generated binaries, then in theory it should suffice to drop libfuzzer_shim.go in each.

I guess I still don't really get your point. But I think the point of any patch you're making here is that the build should "just work" either way. Does this not work unless we specifically drop libfuzzer_shim.go into "every" binary in the tree? Are you planning on checking that into cockroach?

Alternatively, we could try to exclude them from instrumentation, but there isn't seemingly a unique prefix or other pattern to match.

This doesn't really make any sense as the set of code that is linked into these helper binaries is not disjoint with the set of code linked into cockroach, i.e., they share code. So it's not really going to be possible to do as you're suggesting.

@srosenberg
Copy link
Member Author

Does this not work unless we specifically drop libfuzzer_shim.go into "every" binary in the tree?

It does, but feels hacky. The minute someone creates a new package with a binary, ./dev fuzz may fail. Maybe that's ok, considering that ./dev fuzz doesn't even exist at this point :) (I was planning to send a PR after we get this one merged.)

Are you planning on checking that into cockroach?

Yep, whatever you deem as the best path forward, I'll oblige :)

@rickystewart
Copy link

It does, but feels hacky. The minute someone creates a new package with a binary, ./dev fuzz may fail. Maybe that's ok, considering that ./dev fuzz doesn't even exist at this point :) (I was planning to send a PR after we get this one merged.)

OK, so what I expect then is that compilepkg.go should "insert" the file transparently wherever it's needed. i.e., if the build action is to compile 10 Go files, then it should compile those 10 files in addition to libfuzzer_shim.go. Does that make sense?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants