Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

--start-lib/--end-lib broken with LTO #27048

Closed
eugenis opened this issue Feb 20, 2016 · 4 comments
Closed

--start-lib/--end-lib broken with LTO #27048

eugenis opened this issue Feb 20, 2016 · 4 comments
Labels
bugzilla Issues migrated from bugzilla

Comments

@eugenis
Copy link
Contributor

eugenis commented Feb 20, 2016

Bugzilla Link 26674
Resolution FIXED
Resolved on Mar 03, 2016 18:26
Version trunk
OS Linux

Extended Description

$ cat bin.cc
int main() {}

$ cat 1.cc
attribute((constructor(0))) void ctor() {}

$ ./bin/clang++ -flto bin.cc -c
$ ./bin/clang++ -flto 1.cc -c
$ ./bin/clang++ -fuse-ld=gold -flto bin.o -Wl,--start-lib 1.o -Wl,--end-lib
/tmp/lto-llvm-2af7ce.o(.init_array.0+0x0): error: undefined reference to 'ctor()'
clang-3.9: error: linker command failed with exit code 1 (use -v to see invocation)

With -Wl,-plugin-opt,save-temps the merged IR (before link time optimizations) looks like this:

[...]
@​llvm.global_ctors = appending global [1 x { i32, void (), i8 }] [{ i32, void (), i8 } { i32 0, void ()* @​_Z4ctorv, i8* null }]

; Function Attrs: norecurse nounwind uwtable
define i32 @​main() #​0 {
entry:
ret i32 0
}

; Function Attrs: nounwind uwtable
declare void @​_Z4ctorv() #​1
[...]

$ /usr/bin/ld.gold --version
GNU gold (GNU Binutils for Ubuntu 2.24) 1.11

@eugenis
Copy link
Contributor Author

eugenis commented Feb 20, 2016

Gold says that ctor() is LDPR_PREEMPTED_REG.

I think we hit this code in get_symbol_resolution_info():
// We never decided to include this object. We mark all symbols as
// preempted.
gold_assert(this->symbols_.size() == 0);
for (int i = 0; i < nsyms; i++)
syms[i].resolution = LDPR_PREEMPTED_REG;

Why are we still trying to add it then?

@llvmbot
Copy link
Collaborator

llvmbot commented Feb 22, 2016

This reduces to just

@​llvm.global_ctors = appending global [1 x { i32, void (), i8 }] [{ i32, void
(), i8 } { i32 0, void ()* @​foo, i8* null }]

define void @​foo() {
ret void
}

link with

$ ld -plugin LLVMgold.so -shared --start-lib 1.bc --end-lib -o t.so

t.so will have an undefined reference to foo.

What is going on is

We see @​foo is preemepted_reg and we do not include it.

The problem is that llvm.global_ctors is one of the magical llvm append variables and in handled by llvm directly. Gold doesn't know it exists. We then get an undefined reference to foo from it.

This would still be an issue even with a more direct representation of static constructors:

@​ctor1 = private constant void()* @​foo, section "llvm.metadata.ctros"

since it would be a private variable, it would still be unknown to gold.

The fundamental problem is that there is no way for the plugin api to distinguish two different cases

  • The file was not included in the link.
  • The file was included in the link, but every linker visible symbol is preemepted_reg

A possible way to extend it would be to add a LDPT_GET_SYMBOLS_V3 that returns a new LDPS_NOT_INCLUDED_IN_LINK for the first case.

@eugenis
Copy link
Contributor Author

eugenis commented Mar 4, 2016

Fixed in http://reviews.llvm.org/rL262676 with ToT gold.

@eugenis
Copy link
Contributor Author

eugenis commented Nov 26, 2021

mentioned in issue llvm/llvm-bugzilla-archive#26807

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 10, 2021
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla
Projects
None yet
Development

No branches or pull requests

2 participants