lld spits out an obscure error when it encounters a thin archive containing a nested, non-thin archive.
Reproducer is below. I tested the four permutations of combining thin and non-thin outer+inner nested archives. Only thin-inside-thin works.
I also tested against bfd ld and gold. They do handle this case, although they don't inherently document that they intend to; they only explicitly mention thin-inside-thin.
All 3 fail in the case where an archive (thin or otherwise) is nested in a non-thin archive.
outer
nested entry
success?
note
thin
thin
success
thin
non-thin
fail
opaque error about malformed archive
nonthin
thin
fail
symbol resolution failure
nonthin
nonthin
fail
symbol resolution failure
It may be that it's deliberate not to support this, but it does deviate in feature parity from the other two linkers. And the error message is quite cryptic.
This was with the 18.1.8 release built from source.
u@u:~/t17/tmp$ ./drive.sh
${PREFIX}/g++ -o foo1.o -c foo1.cpp
${PREFIX}/g++ -o foo2.o -c foo2.cpp
${PREFIX}/gcc-ar -rc nonthin1.a foo1.o
${PREFIX}/gcc-ar -rTc thin1.a foo1.o
${PREFIX}/gcc-ar -rTc thin2_thin1.a foo2.o thin1.a
${PREFIX}/gcc-ar -rTc thin2_nonthin1.a foo2.o nonthin1.a
${PREFIX}/gcc-ar -rc nonthin2_thin1.a foo2.o thin1.a
${PREFIX}/gcc-ar -rc nonthin2_nonthin1.a foo2.o nonthin1.a
${PREFIX}/g++ -o driver.o -c driver.cpp
${PREFIX}/g++ -B ${PREFIX} -o run driver.o thin2_thin1.a -fuse-ld=lld
${PREFIX}/g++ -B ${PREFIX} -o run driver.o thin2_nonthin1.a -fuse-ld=lld
ld.lld: error: thin2_nonthin1.a: could not get the buffer for a child of the archive: truncated or malformed archive (long name offset characters after the '/' are not all decimal numbers: '8:86' for archive member header at offset 252)
collect2: error: ld returned 1 exit status
${PREFIX}/g++ -B ${PREFIX} -o run driver.o nonthin2_thin1.a -fuse-ld=lld
ld.lld: warning: nonthin2_thin1.a: archive member 'thin1.a' is neither ET_REL nor LLVM bitcode
ld.lld: error: undefined symbol: foo1()
>>> referenced by driver.cpp
>>> driver.o:(main)
>>> did you mean: foo2()
>>> defined in: nonthin2_thin1.a(foo2.o)
collect2: error: ld returned 1 exit status
${PREFIX}/g++ -B ${PREFIX} -o run driver.o nonthin2_nonthin1.a -fuse-ld=lld
ld.lld: warning: nonthin2_nonthin1.a: archive member 'nonthin1.a' is neither ET_REL nor LLVM bitcode
ld.lld: error: undefined symbol: foo1()
>>> referenced by driver.cpp
>>> driver.o:(main)
>>> did you mean: foo2()
>>> defined in: nonthin2_nonthin1.a(foo2.o)
collect2: error: ld returned 1 exit status
u@u:~/t17/tmp$
lld spits out an obscure error when it encounters a thin archive containing a nested, non-thin archive.
Reproducer is below. I tested the four permutations of combining thin and non-thin outer+inner nested archives. Only thin-inside-thin works.
I also tested against bfd ld and gold. They *do* handle this case, although they don't inherently document that they intend to; they only explicitly mention thin-inside-thin.
All 3 fail in the case where an archive (thin or otherwise) is nested in a non-thin archive.
| outer | nested entry | success? | note |
|-|-|-|-|
| thin | thin | success | |
| thin | non-thin | fail | opaque error about malformed archive
| nonthin | thin | fail | symbol resolution failure
| nonthin | nonthin | fail | symbol resolution failure
It may be that it's deliberate not to support this, but it does deviate in feature parity from the other two linkers. And the error message is quite cryptic.
This was with the 18.1.8 release built from source.
```c++
u@u:~/t17/tmp$ cat foo1.cpp
#include "foo1.hpp"
int foo1() {
return 4;
}
u@u:~/t17/tmp$ cat foo2.cpp
#include "foo2.hpp"
int foo2() {
return 5;
}
u@u:~/t17/tmp$ cat foo1.hpp
int foo1();
u@u:~/t17/tmp$ cat foo2.hpp
int foo2();
u@u:~/t17/tmp$ cat driver.cpp
#include "foo1.hpp"
#include "foo2.hpp"
int main(int argc, char **argv) {
return argc + foo1() + foo2();
}
```
```bash
u@u:~/t17/tmp$ ./drive.sh
${PREFIX}/g++ -o foo1.o -c foo1.cpp
${PREFIX}/g++ -o foo2.o -c foo2.cpp
${PREFIX}/gcc-ar -rc nonthin1.a foo1.o
${PREFIX}/gcc-ar -rTc thin1.a foo1.o
${PREFIX}/gcc-ar -rTc thin2_thin1.a foo2.o thin1.a
${PREFIX}/gcc-ar -rTc thin2_nonthin1.a foo2.o nonthin1.a
${PREFIX}/gcc-ar -rc nonthin2_thin1.a foo2.o thin1.a
${PREFIX}/gcc-ar -rc nonthin2_nonthin1.a foo2.o nonthin1.a
${PREFIX}/g++ -o driver.o -c driver.cpp
${PREFIX}/g++ -B ${PREFIX} -o run driver.o thin2_thin1.a -fuse-ld=lld
${PREFIX}/g++ -B ${PREFIX} -o run driver.o thin2_nonthin1.a -fuse-ld=lld
ld.lld: error: thin2_nonthin1.a: could not get the buffer for a child of the archive: truncated or malformed archive (long name offset characters after the '/' are not all decimal numbers: '8:86' for archive member header at offset 252)
collect2: error: ld returned 1 exit status
${PREFIX}/g++ -B ${PREFIX} -o run driver.o nonthin2_thin1.a -fuse-ld=lld
ld.lld: warning: nonthin2_thin1.a: archive member 'thin1.a' is neither ET_REL nor LLVM bitcode
ld.lld: error: undefined symbol: foo1()
>>> referenced by driver.cpp
>>> driver.o:(main)
>>> did you mean: foo2()
>>> defined in: nonthin2_thin1.a(foo2.o)
collect2: error: ld returned 1 exit status
${PREFIX}/g++ -B ${PREFIX} -o run driver.o nonthin2_nonthin1.a -fuse-ld=lld
ld.lld: warning: nonthin2_nonthin1.a: archive member 'nonthin1.a' is neither ET_REL nor LLVM bitcode
ld.lld: error: undefined symbol: foo1()
>>> referenced by driver.cpp
>>> driver.o:(main)
>>> did you mean: foo2()
>>> defined in: nonthin2_nonthin1.a(foo2.o)
collect2: error: ld returned 1 exit status
u@u:~/t17/tmp$
```
lld spits out an obscure error when it encounters a thin archive containing a nested, non-thin archive.
Reproducer is below. I tested the four permutations of combining thin and non-thin outer+inner nested archives. Only thin-inside-thin works.
I also tested against bfd ld and gold. They do handle this case, although they don't inherently document that they intend to; they only explicitly mention thin-inside-thin.
All 3 fail in the case where an archive (thin or otherwise) is nested in a non-thin archive.
It may be that it's deliberate not to support this, but it does deviate in feature parity from the other two linkers. And the error message is quite cryptic.
This was with the 18.1.8 release built from source.