ld: error: duplicate symbol: dis_info
>>> defined at i386_disasm.c:1665
>>> otool-i386_disasm.o:(dis_info)
>>> defined at arm_disasm.c:163
>>> otool-arm_disasm.o:(.bss+0x8)
ld: error: duplicate symbol: dis_info
>>> defined at i386_disasm.c:1665
>>> otool-i386_disasm.o:(dis_info)
>>> defined at arm64_disasm.c:62
>>> otool-arm64_disasm.o:(.bss+0x0)
clang-11: error: linker command failed with exit code 1 (use -v to see invocation)
When performing LTO, `ld64` reads in any LLVM bitcode files, creates
atoms for them, and compiles the bitcode files to their corresponding
in-memory Mach-O files. These Mach-O files are then
loaded (lto_file.cpp:Parser::loadMachO), and information from the atoms
in the Mach-O files is then synced to the corresponding atoms from the
LLVM bitcode files.
However, the underlying function (ld.hpp:Atom::setAttributesFromAtom)
fails to copy over the alias bit from the Mach-O symbol. This omission
means that the original LLVM atom is not correctly marked as an alias
and therefore not correctly sorted prior to the symbol it is an alias
for (order.cpp:Layout::Comparer::operator()). The end result is that
the alias symbol winds up pointing at a different symbol, with
predictably disastrous consequences when the aliased symbol is called.
This problem has been observed when performing cross-language LTO with
Firefox. See also
https://bugzilla.mozilla.org/show_bug.cgi?id=1486042#c92 for more
details.
The fix is simple: we need to copy the alias bit over, just like other
fields.
When finalizing an archive, ranlib performs the following operations:
1. stat to obtain the current mtime (pre-write mtime)
2. rewrite the timestamp in the archive header
3. utime to restore the pre-write mtime
Unfortunately, utime only supports a 1s resolution. This means that on systems
with sub-second filesystem timestamps resolution (one notable example being
APFS), the following sequence of events can happen:
1. stat to obtain the current mtime (pre-write mtime) returns hh:mm:ss.123
2. rewrite the timestamp in the archive header
3. utime to restore the pre-write mtime ends up restoring hh:mm:ss.000.
This can cause ranlib to roll back the mtime of an archive in the past instead
of moving it into the future. Given that "make" heavily relies on filesystem
timestamps to determine dependencies and required rebuilds, this can lead to
many problems. This was discovered because it caused random failures when
parallel building postgresql.
To address the issue, we attempt to use utimensat if available. This is checked
via autoconf, but on macOS this is not enough: utimensat can be present at
compile time without being available at link time, and it was only added very
recently (10.13). Inspired by how CPython is handling this, we use #pragma weak
to make the runtime dependency optional.
When doing ThinLTO, the linker updates LTO proxy atoms to point to the
right linker atoms. When there are atoms with different scope with the
same name (in the case where e.g. one translation unit has a static
instance of data and another has a global instance of data with the same
name), we may end up making all translation units using a symbol with
that name link against the one global symbol with that name.
Presumably, the same problem can happen with static/global functions
with the same name too.
When the data/code under those names happen to be identical, that's
fine, but when they're not, bad things happen.
So when dealing with LTO proxy atoms for the translation unit scope,
don't look up in the list of atoms from the linker (for global symbols).
Fixes#58
When ThinLTO is enabled, this leads to a spurious warning to create
a directory at best, or a segfault while trying to print that
warning in the worst case.
Mostly make sure not to use a few glibc-isms. I should note that cctools'
ar doesn't work properly when built against musl. I didn't investigate
further because dropping in llvm-ar works just fine. The error you see
with the broken ar is:
```
`x86_64-apple-darwin14-ranlib: archive member: libgcc.a(3) size too large (archive member extends past the end of the file)`
```
if you set a libexecdir via configure, the as tool does not find its assembler.
This is caused by a wrong search-path used. I compared it with the old odcctools which I used before, and found that the define for the directory was not used anymore
This allows scripts to see how cctools resolves inputs. The flags are
\0-separated.
Fixes#32; See that issue for a more in-depth explanation of the
purpose of this change.