Skip to content

darwin stdenv's ld -no_uuid linker flag breaks normal symbolication for debugging + profiling #178366

@mstone

Description

@mstone

Describe the bug

#77632 made builds on darwin reproducible (yay!) in part by causing the darwin stdenv’s cc wrapper to set the -no_uuid linker flag so as to avoid random uuid build-ids being added to all compiled binaries and libraries.

Unfortunately, while setting this flag was effective for improving reproducibility, I think (and will hopefully soon test) that setting it also had the side-effect of breaking symbolication of binaries built with the resulting toolchain, for example, interfering with profiling them with Instruments or debugging them with lldb.

Desired resolution

Ideally, I imagine we’d find a way to set UUIDs deterministically, I suppose a little bit like how placeholder hash insertion works.

Failing that, in the shorter term, I'd love for there to be a well-documented way to remove the -no_uuid flag so that users who want UUIDs can readily obtain them or, I suppose, to add new UUIDs after the fact?

Anyway, what I've found so far is: in simple situations, overriding via an overlay can help, like so:

...
      final: prev: rec {
        bintools = prev.bintools.overrideAttrs (old: {
          postFixup = builtins.replaceStrings ["-no_uuid"] [""] old.postFixup;
        });
        cc = prev.stdenv.cc.overrideAttrs (old: {
          bintools = bintools;
        });
        stdenv = prev.overrideCC prev.stdenv cc;
        sigtool = stdenv.mkDerivation {
          inherit name;
          src = self;
          nativeBuildInputs = [ pkg-config meson ninja ];
          buildInputs = [ openssl ];
          dontStrip = true;
          separateDebugInfo = true;
          mesonBuildType = "debug";
          ninjaFlags = "-v";
        };
     ...
     }

however, I'm still struggling to make this approach work well with more complex situations, for example, using https://github.com/oxalica/rust-overlay.

(There, trying to use this simple approach runs in to difficulty because it's not clear where and how to override the darwin stdenv: trying to do so alongside a new build isn't quite enough because (at least the way I'm loading it) the rust-overlay captures the wrong stdenv; however, trying to do so via an earlier overlay runs into challenges with the staged structure of the darwin stdenv, such that the cc = prev.stdenv.cc.overrideAttrs override can fail because prev.stdenv.cc is set to the string "/dev/null" in early stages, and hence has no overrideAttrs attr itself.)

Note: you can test whether or not built binaries have uuids in a variety of ways, including

dwarfdump -u <path>

which exit with success and will print nothing when UUIDs are missing, or by using any of a variety of other DWARF tools, searching for the LC_UUID tag.

Notify maintainers

cc: @thefloweringash @LnL7

Metadata

Metadata

Assignees

No one assigned

    Labels

    0.kind: bugSomething is broken6.topic: darwinRunning or building packages on Darwin
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions