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:
ld.gold
as with ld
and ld.bfd
?Reported here. Turns out this is already fixed in trunk, so I guess the solution is to wait until binutils 2.31 (or build binutils from scratch).