Skip to content

bintools-wrapper: Set ZERO_AR_DATE and re-enable LC_UUID on Darwin#188347

Merged
lovesegfault merged 1 commit intoNixOS:stagingfrom
zhaofengli:darwin-uuid
Nov 30, 2023
Merged

bintools-wrapper: Set ZERO_AR_DATE and re-enable LC_UUID on Darwin#188347
lovesegfault merged 1 commit intoNixOS:stagingfrom
zhaofengli:darwin-uuid

Conversation

@zhaofengli
Copy link
Member

@zhaofengli zhaofengli commented Aug 26, 2022

Background

(See #178366)

macOS uses UUIDs to associate binaries with the corresponding debug symbol bundles (.dSYM). #77632 added -no_uuid to the linker flags in the wrapper so UUIDs aren't added in order to improve reproducibility. This breaks normal symbolication for debugging and profiling.

However, the UUIDs generated by ld64 should be deterministic by default, based on the contents of the output file. See related discussion in the Chromium list: https://groups.google.com/a/chromium.org/g/security-dev/c/xAL44GDnaVI/m/qJJm5mNkAAAJ

Why is the UUID not deterministic?

Since LC_UUID is supposed to be deterministic, there must be some differences in the input. I built libuv twice, and here is the diffoscope output against the two build directories.

Immediately we see the values of the SymDebugTable symbols (N_STAB) are different:

   Symbol {
     Name: /private/tmp/nix-build-libuv-1.44.2.drv-1/source/src/.libs/libuv_la-fs-poll.o (12596)
     Type: SymDebugTable (0x66)
     Section:  (0x0)
     RefType: ReferenceFlagUndefinedLazy (0x1)
     Flags [ (0x0)
     ]
-    Value: 0x6307EE91
+    Value: 0x6307F1B8
   }

This 0x6307F1B8 value is a timestamp generated here. To disable it, we can simply set ZERO_AR_DATE.

But a --check build still shows differences!

Sadly, without sandboxing, --check builds expose a different $out to the builder, leading to a different UUID in the resulting binaries (logs). If --keep-failed is used, the different build directories for subsequent builds also cause the UUID to change (e.g., /private/tmp/nix-build-libuv-1.44.2.drv-0 and /private/tmp/nix-build-libuv-1.44.2.drv-1).

The UUIDs seem to be stable across initial builds and --check builds with the same build directory.

How do I test that this works without rebuilding stdenv?

I have a branch with an overridden stdenv (stdenvWip) that uses a modified bintools-wrapper: https://github.com/zhaofengli/nixpkgs/commits/darwin-uuid-wip. To test:

$ nix-build -A libuvWip --no-out-link
[...]
 ***      UUID of libuv.1.dylib in $out:     uuid D7737082-E47B-3BC7-851B-44D4540BAC19
/nix/store/nasrlj1wz0lhm0aj1k90fs8cf5w65wni-libuv-1.44.2
$ sudo nix-store --delete /nix/store/nasrlj1wz0lhm0aj1k90fs8cf5w65wni-libuv-1.44.2
[...]
$ nix-build -A libuvWip --no-out-link
[...]
 ***      UUID of libuv.1.dylib in $out:     uuid D7737082-E47B-3BC7-851B-44D4540BAC19
/nix/store/nasrlj1wz0lhm0aj1k90fs8cf5w65wni-libuv-1.44.2
Things done
  • Built on platform(s)
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • For non-Linux: Is sandbox = true set in nix.conf? (See Nix manual)
  • Tested, as applicable:
  • Tested compilation of all packages that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage
  • Tested basic functionality of all binary files (usually in ./result/bin/)
  • 22.11 Release Notes (or backporting 22.05 Release notes)
    • (Package updates) Added a release notes entry if the change is major or breaking
    • (Module updates) Added a release notes entry if the change is significant
    • (Module addition) Added a release notes entry if adding a new NixOS module
    • (Release notes changes) Ran nixos/doc/manual/md-to-db.sh to update generated release notes
  • Fits CONTRIBUTING.md.

The LC_UUID is a hash over the output file contents.
@ofborg ofborg bot added the 6.topic: darwin Running or building packages on Darwin label Aug 26, 2022
@ofborg ofborg bot added the 10.rebuild-darwin-stdenv This PR causes stdenv to rebuild on Darwin and must target a staging branch. label Aug 26, 2022
@ofborg ofborg bot requested a review from lovesegfault August 26, 2022 03:42
@ofborg ofborg bot added 10.rebuild-darwin: 501+ This PR causes many rebuilds on Darwin and should normally target the staging branches. 10.rebuild-darwin: 5001+ This PR causes many rebuilds on Darwin and must target the staging branches. 10.rebuild-linux: 0 This PR does not cause any packages to rebuild on Linux. labels Aug 26, 2022
@symphorien symphorien mentioned this pull request Mar 4, 2023
12 tasks
@tjni
Copy link
Contributor

tjni commented Jun 6, 2023

@zhaofengli

Last year I ran across this PR when looking for a way to enable debug symbols on Darwin. Today, I encountered the same need and found this again. Do you remember if there is any additional work or testing left to do?

@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/announcing-nixseparatedebuginfod-a-tool-to-fetch-sources-debug-symbols-of-nix-packages-in-gdb/25171/3

@reckenrode
Copy link
Contributor

While Darwin will be using llvm-ar by default once the stdenv rework lands in master (which zeroes out dates, uids, and gids by default), it would still be great if this could be merged to improve the debugging experience on Darwin. Is there anything else this needs to be made ready for review?

@tjni
Copy link
Contributor

tjni commented Jul 15, 2023

I can spend some time testing if this still works. Do I understand correctly:

  1. Even though llvm-ar zeroes out dates, not every package invokes it?
  2. While we still use Apple's linker, we need to set ZERO_AR_DATE.

@zhaofengli
Copy link
Member Author

I think this is ready for review and testing already. To reduce the blast radius, we could gate the removal of -no_uuid behind a environment variable so users can opt into it themselves.

@zhaofengli zhaofengli marked this pull request as ready for review July 15, 2023 18:33
@reckenrode
Copy link
Contributor

reckenrode commented Jul 15, 2023

Even though llvm-ar zeroes out dates, not every package invokes it?

I don’t think anything is reverting back to ar from cctools (yet?), so everything should be invoking it. It doesn’t hurt to include the environment variable just in case though.

Edit: Also, I didn’t notice that ld64 also respects this variable. It’s worth setting for that as well.

@joshchngs
Copy link
Contributor

I've been using a bintools-wrapper with this patch applied for 7 months now – it hasn't caused any problems and works for getting debuggable outputs. I haven't done any formal verification of their reproducibility though.

@lovesegfault lovesegfault merged commit 6e08608 into NixOS:staging Nov 30, 2023
@lovesegfault
Copy link
Member

Let's see how it cooks in staging :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

6.topic: darwin Running or building packages on Darwin 10.rebuild-darwin: 501+ This PR causes many rebuilds on Darwin and should normally target the staging branches. 10.rebuild-darwin: 5001+ This PR causes many rebuilds on Darwin and must target the staging branches. 10.rebuild-darwin-stdenv This PR causes stdenv to rebuild on Darwin and must target a staging branch. 10.rebuild-linux: 0 This PR does not cause any packages to rebuild on Linux.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants