-
Notifications
You must be signed in to change notification settings - Fork 2.1k
devtool: strip release binaries out of debug info #1957
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
devtool: strip release binaries out of debug info #1957
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you should also shrink the binary size limits in the associated integ test, the new binaries should be smaller.
.cargo/config
Outdated
"-C", "link-arg=-lgcc", | ||
"-C", "link-arg=-lfdt", | ||
] | ||
target-dir = "build/cargo_target" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: add newline
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With these change, simply doing "cargo build --target aarch64-unknown-linux-musl
" won't work anymore :( we do not want that, do we?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you are right. I'll fix the cargo build issue.
tools/devtool
Outdated
# On aarch64 musl depends on some libgcc functions (i.e `__addtf3` and other `*tf3` functions) for logic that uses | ||
# long double. Such functions are not builtin in the rust compiler, so we need to get them from libgcc. | ||
# No need for the `crt_static` flag as rustc appends it by default. | ||
[ $machine = "aarch64" ] && RUSTFLAGS="-C link-arg=-lgcc -C link-arg=-lfdt" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: you can collapse multiple linker args into link-args=-lgcc -lfdt
tools/devtool
Outdated
[ $machine = "aarch64" ] && RUSTFLAGS="-C link-arg=-lgcc -C link-arg=-lfdt" | ||
# Strip away debug info, since cargo adds them by default event when building artifacts for release. | ||
# See: https://github.com/rust-lang/cargo/issues/4122. | ||
[ $profile = "release" ] && cargo_args+=("--release") && RUSTFLAGS="$RUSTFLAGS -C link-arg=-s" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would leave it to the user to decide whether or not they want symbols. We might need the unstripped binary for debugging, and with this change the user can't force a build with symbols. How about a new devtool parameter (devtool build --release --keepsyms
or smth) that lets us to both?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea. To not break things, we might want to leave the default behavior to be as it is and provide a flag --strip_debug_info
, to enforce debug info stripping.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would not bother modifying the devtool
for this since users always have the choice of using "cargo build --release" if they want the unaltered version of what cargo obtains.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This removes all symbols, not only debug symbols. This means stack traces would be difficult to read. Keeping a small subset of symbols via strip --discard-locals --strip-debug
would allow you to remove most symbols without breaking stack traces. It also means you don't have to change the linking, which doesn't work the same on all toolchains.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would not bother modifying the devtool for this since users always have the choice of using "cargo build --release" if they want the unaltered version of what cargo obtains.
@dianpopa , do you suggest to implement stripping support as the default way of building the release binaries? Now I would prefer adding optional support for stripping, when building with tools/devtool build --release
, rather than adding by default stripping support while being open to break customers. Using cargo build --release
to get unstripped binaries depends on setting up the rust dev environment.
I see two ways for implementing this:
- adding a flag to devtool, which strips away debug info would not break customers and will provide optional support for stripping debug info.
- stripping debug info by default, when building the release binaries with devtool, will drop the support for building release binaries the "cargo" way (with debug info). If users need to build release binaries with
cargo build --release
they would need to set up rust dev environment (rust, cargo, rustup, toolchains etc).
Please let me know which you prefer and why.
This removes all symbols, not only debug symbols. This means stack traces would be difficult to read. Keeping a small subset of symbols via strip --discard-locals --strip-debug would allow you to remove most symbols without breaking stack traces.
@petreeftime , stripping only what is necessary is a valid point. I wasn't aware of selective stripping until now. I'll try to incorporate your suggestion.
It also means you don't have to change the linking, which doesn't work the same on all toolchains.
This argument conflicts with the suggestion to use strip
. strip
is part of the GNU binutils
, which currently provides GNU ld
and GNU as
, used by tools/devtool build --release
. So even if we change the toolchain, we can not say that we move away from GNU binutils (this is a core part of Linux toolchains in general). To me it seems that GNU ld
and GNU as
(GNU binutils in general) are core parts of Linux toolchains and changing stripping alternative from linker flags to strip tool it shouldn't make any difference while GNU binutils
is still used as a core part of the toolchain we build against.
I am not sure we need to do this as part of the build system. I would leave the build system just as it is and move the stripping a step further into the release pipeline where the binary is stripped and a copy of the original is kept in cold storage for debugging purposes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Typos in commit body (i.e Othwerwise and RUSTBACKTRACE ->. RUST_BACKTRACE).
- We need to update the documentation when instructing users about building firecracker
- An integration test would be nice (i.e check that the file command does not contain not stripped)
.cargo/config
Outdated
"-C", "link-arg=-lgcc", | ||
"-C", "link-arg=-lfdt", | ||
] | ||
target-dir = "build/cargo_target" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With these change, simply doing "cargo build --target aarch64-unknown-linux-musl
" won't work anymore :( we do not want that, do we?
tools/devtool
Outdated
[ $machine = "aarch64" ] && RUSTFLAGS="-C link-arg=-lgcc -C link-arg=-lfdt" | ||
# Strip away debug info, since cargo adds them by default event when building artifacts for release. | ||
# See: https://github.com/rust-lang/cargo/issues/4122. | ||
[ $profile = "release" ] && cargo_args+=("--release") && RUSTFLAGS="$RUSTFLAGS -C link-arg=-s" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would not bother modifying the devtool
for this since users always have the choice of using "cargo build --release" if they want the unaltered version of what cargo obtains.
tools/devtool
Outdated
# long double. Such functions are not builtin in the rust compiler, so we need to get them from libgcc. | ||
# No need for the `crt_static` flag as rustc appends it by default. | ||
[ $machine = "aarch64" ] && RUSTFLAGS="-C link-arg=-lgcc -C link-arg=-lfdt" | ||
# Strip away debug info, since cargo adds them by default event when building artifacts for release. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: typo for "event"
+1 on this. I was imagining this being implemented such that we have a devtool command that does building release binaries + stripping them at once (or as separate commands), without impacting in any way With that in mind, I wouldn't like us to modify |
Why to separate the stripping of debug symbols (embedded into the release binaries at build time) in a separate step, inside the release pipeline? My understanding is that these debug symbols can be added or not when we build the executable files, so to me it seems that this is the step were we should provide optional build flags which can be used for building the binaries with our without debug info. Let me know what you think.
We wouldn't need to store binaries with debug symbols. We can get these binaries if we checkout on the release tag and build it. |
Right, this makes sense. However, having something inside the devtool for building and stripping at once was not the suggestion of @sandreim , as far as I can tell. I will keep the .cargo/config, to not impact
We can expose support for binaries stripping with a |
I probably misunderstood then, sorry.
I think we should keep |
+1 on this. Let's just have |
Correct. Looked within the container with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3. An integration test would be nice (i.e check that the file command does not contain not stripped)
@dianpopa , I am not sure how can we test this easily. Our integration tests has other means for building firecracker binaries, others than devtool. Testing how devtool works would need devtool specific tests, outside the pytest framework. Testing the devtool stripping functionality in our integration tests means porting the same functionality there and then test it. I can do this, but this would not test the added functionality from devtool.
.cargo/config
Outdated
"-C", "link-arg=-lgcc", | ||
"-C", "link-arg=-lfdt", | ||
] | ||
target-dir = "build/cargo_target" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you are right. I'll fix the cargo build issue.
de6456a
to
5358b92
Compare
@aghecenco , adding stripping support for devtool does not interfere with building firecracker binaries inside integration tests. Do you suggest to strip the binaries in the integration tests as well and then update the binaries sizes in the corresponding test? |
5358b92
to
d818be3
Compare
The integration tests should be run with the binary that ends up being used by our customers. |
d818be3
to
f4fce84
Compare
I've stripped away debug_info, after integration tests build step and updated the |
f4fce84
to
b55f915
Compare
tools/devtool
Outdated
say "Stripped binaries placed under $cargo_bin_dir." | ||
} | ||
|
||
return $? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It needs one more change, before merging. I'll update soon.
return $? | |
return $ret |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
b6c9fc8
to
7592923
Compare
tools/devtool
Outdated
@@ -385,6 +385,15 @@ cmd_help() { | |||
echo " -l, --libc musl|gnu Choose the libc flavor against which Firecracker will" | |||
echo " be linked. Default is musl." | |||
echo "" | |||
echo " strip [--target-libc musl|gnu]" | |||
echo " Strip from debug symbols the Firecracker release binaries." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: "Strip debug symbols from the.."?
CHANGELOG.md
Outdated
@@ -25,6 +25,7 @@ | |||
snapshot. | |||
- Added a new API call, `PUT /snapshot/load`, for loading a snapshot. | |||
- Added metrics for the vsock device. | |||
- Added devtool strip command to strip release binaries out of DWARF sections. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm, "strip the binary out of?" We are not removing DWARF sections, right? Should we?
Anyhow, I'd change this to something more obvious "Added devtool strip
command which removes debug symbols from the release binaries."
tests/host_tools/cargo_build.py
Outdated
@@ -69,6 +69,9 @@ def get_firecracker_binaries(): | |||
fc_bin_path = "{}/{}".format(out_dir, FC_BINARY_NAME) | |||
jailer_bin_path = "{}/{}".format(out_dir, JAILER_BINARY_NAME) | |||
|
|||
cmd = "strip --strip-debug {} {}".format(fc_bin_path, jailer_bin_path) | |||
utils.run_cmd(cmd) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utils.run_cmd(cmd) | |
utils.run_cmd( | |
"strip --strip-debug {} {}".format(fc_bin_path, jailer_bin_path)) |
7592923
to
b9a87d7
Compare
Added `devtool strip` command. This command can strip debug symbols from Firecracker release binaries. The command can be parameterized by `--target-libc (musl|gnu)`, which sets the libc used by a specific toolchain (e.g. x86_64-uknown-linux-${libc_flavor}). Signed-off-by: Iulian Barbu <[email protected]>
b9a87d7
to
73321bb
Compare
@dianpopa, @gc-plp , I've addressed your feedback! PTAL. |
Reason for This PR
Cargo adds by default DWARF sections to release binaries. It is recommended to strip release binaries out of debug information because of security concerns, but also because this information is not relevant in a production environment.
#1652
Description of Changes
The provided solution adds a devtool command (
devtool strip [--target-libc (musl|gnu)]
) which strips release binaries out of debug information (DWARF sections). This solution is based onGNU strip
tool, which strips away only debug information (using --strip-debug).License Acceptance
By submitting this pull request, I confirm that my contribution is made under
the terms of the Apache 2.0 license.
PR Checklist
git commit -s
).unsafe
code is properly documented.firecracker/swagger.yaml
.CHANGELOG.md
.