Let me preface this by saying that I'm a noob in things related to linkers. If something I say seems like it makes no sense, it probably doesn't - please call me out on it.
I've got the following files:
bar.rs
#[no_mangle] pub extern fn bar(x: isize) -> isize { x + 1 }
foo.c
extern int bar(int); extern int baz(int); int foo(int x) { return bar(x) + baz(x); }
I can link these into one relocatable object file with:
$ rustc --crate-type=staticlib bar.rs -o bar.a
$ gcc -c foo.c -o foo.o
$ ld -r foo.o bar.a -o out.o
I'm not sure what is happening under the hood, but I sure do get the output I wanted: bar
and foo
are defined while baz
isn't.
$ nm out.o | grep '\(foo\|bar\|baz\)$'
0000000000000000 T bar
U baz
0000000000000000 T foo
Exactly the same thing happens if I replace ld
with ld.bfd
. However, things fall apart with ld.gold
.
$ ld.gold -r foo.o bar.a -o out.o
ld.gold: internal error in set_info_section, at ../../gold/output.h:3198
This is with both ld.gold
packaged with binutils 2.24 and 2.26.
The problem persists with binutils 2.30, although the line number I get is different:
$ ld.gold -r foo.o bar.a -o out.o
ld.gold: internal error in set_info_section, at ../../gold/output.h:3386
Also, the error persists even with --emit=obj
instead of --crate-type=staticlib
So:
- What does the error mean?
- How can I achieve the same relocatable object output with
ld.gold
as withld
andld.bfd
?