4

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 with ld and ld.bfd?
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Alec
  • 31,829
  • 7
  • 67
  • 114
  • You should try replacing the Rust object file with a C object file. It's possible that it spits out some metadata that gold doesn't yet know how to handle. – Shepmaster May 09 '18 at 16:42
  • @Shepmaster Note that Rust is emitting a full-fledged static library. I'm certain that gold would have no problem linking a simple C object file instead - that's what it was designed for. – Alec May 09 '18 at 16:49
  • I don't understand where did you define `baz()` ? – Stargateur May 09 '18 at 17:37
  • @Stargateur I intentionally didn't. It should be undefined in `out.o`. Note I'm asking the linker to produce a relocatable output. The idea is that later one, someone can link `out.o` with something that _does_ define `baz`. – Alec May 09 '18 at 17:48
  • (Note that `--emit=obj` is not a good idea in any case: the static library that `--crate-type=staticlib` produces includes object files which collectively define all of extra bells and whistles, like `panic`, that you need.) – Alec May 09 '18 at 18:38
  • *`--emit=obj` is not a good idea in any case* — Well, you will have to add in the Rust standard library yourself, sure, but it's a good idea when you want to have multiple Rust-created static libraries, otherwise you get conflicting symbols. – Shepmaster May 09 '18 at 19:01
  • Debugging has shown that the section `.eh_frame` is a source of this error. – Shepmaster May 09 '18 at 20:24
  • @Shepmaster What makes you think this? – Alec May 09 '18 at 21:27
  • @Alec I edited the source of gold to print out the section and that's the last one before it asserts. – Shepmaster May 09 '18 at 22:29

2 Answers2

1

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).

Alec
  • 31,829
  • 7
  • 67
  • 114
0

What does the error mean?

It means that Gold is failing internal assertion. Probably this one.

How can I achieve the same relocatable object output with ld.gold as with ld and ld.bfd

You need to either fix Gold to handle this input, or to change the input so it doesn't trigger the bug.

Since neither you nor I understand exactly what the bug triggering conditions are, the first step should be to file a bug in bugzilla.

There is already a very similar bug. Not sure if you are hitting the same issue though.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • [Done](https://sourceware.org/bugzilla/show_bug.cgi?id=23155). I'm still unsure if this is actually a bug, or rather if it is the Rust static library that is defective in a way that `ld` and `ld.bfd` allow. – Alec May 10 '18 at 03:09