In short: a library declares a distributed slice and a consumer of that library adds to that slice. On illumos the component of that distributed slice added by the consumer of the library is not present. We can see this in the absence of output from the test cmd.
Looking at ELF data on illumos reveals something interesting:
The rlib where the slice is declared is zero-bytes and non-writeable; the .o where we add to the slice is 8 bytes and writable. The illumos linker sees these as two different sections due to the difference in ELF flags so we end up with two different sections in the resulting binary.
On Linux, the test program works, and the ELF data is as expected:
Note that the section is writable (W) for reasons not readily apparent. Looking at the .o and .rlib files that went into the final binary we see the same disparity on Linux as we did on illumos:
$ readelf -S target/debug/deps/liblib-dbcc34a6ce485a29.rlib | grep -A1 linkme_DOERS
readelf: Error: Not an ELF file - it has the wrong magic bytes at the start
[ 7] linkme_DOERS PROGBITS 0000000000000000 000000d0
0000000000000000 0000000000000000 A 0 0 8
$ readelf -S target/debug/incremental/cmd-3e55fmylgk0vb/s-fwzozwzwjv-zngw3r-3ojl9o3cuvpk4/*.o | grep -A1 linkme_DOERS
[13] linkme_DOERS PROGBITS 0000000000000000 000000c8
0000000000000008 0000000000000000 WA 0 0 8
Note that lib where the slice is defined is not writeable whereas the .o where we add to the slice is writeable.
The proximate problem this PR addresses is a failure on illumos demonstrated in this repo: https://github.com/ahl/linkme-test
In short: a library declares a distributed slice and a consumer of that library adds to that slice. On illumos the component of that distributed slice added by the consumer of the library is not present. We can see this in the absence of output from the test cmd.
Looking at ELF data on illumos reveals something interesting:
We have not one, but two sections named
set_linkme_DOERS
. The first is zero-sized and not-writable; the second is 8 bytes and writable.Looking at the object files and rlibs that went into this build, we see the same:
The rlib where the slice is declared is zero-bytes and non-writeable; the .o where we add to the slice is 8 bytes and writable. The illumos linker sees these as two different sections due to the difference in ELF flags so we end up with two different sections in the resulting binary.
On Linux, the test program works, and the ELF data is as expected:
Note that the section is writable (
W
) for reasons not readily apparent. Looking at the .o and .rlib files that went into the final binary we see the same disparity on Linux as we did on illumos:Note that
lib
where the slice is defined is not writeable whereas the .o where we add to the slice is writeable.With the fix applied:
illumos
The final binary has a single section with the right length and size; we get the expected output from the program.
Linux
The rlib section is now writable; the final binary is unchanged (i.e. same length and flags).
Note that since the modified line is only relevant on illumos and Linux, no other examination seems to be warranted.
I'm not sure how to incorporate a test for this, but would be happy to do so with some guidance.