Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

Missing undefined symbol from function local inline assembly. #34814

Open Quuxplusone opened 6 years ago

Quuxplusone commented 6 years ago
Bugzilla Link PR35841
Status NEW
Importance P normal
Reported by Bjorn Pagen (bjornpagen@gmail.com)
Reported on 2018-01-05 20:39:37 -0800
Last modified on 2020-03-26 12:33:30 -0700
Version trunk
Hardware All Linux
CC dmajor@bugmail.cc, llvm-bugs@lists.llvm.org, ndesaulniers@google.com, peter@pcc.me.uk, rafael@espindo.la, rnk@google.com, ruiu@google.com, samitolvanen@google.com, srhines@google.com
Fixed by commit(s)
Attachments
Blocks
Blocked by
See also
Compiling musl with CFLAGS="-O2 -flto" breaks musl compilation.
lld throws this error:

/usr/bin/x86_64-gentoo-linux-musl-ld: error: undefined symbol: __dls2
>>> referenced by ld-temp.o
>>>               lto.tmp:(_dlstart_c)
clang-5.0: error: linker command failed with exit code 1 (use -v to see
invocation)
Quuxplusone commented 6 years ago
To create this error, I compiled musl using a musl/lld/clang/compiler_rt, and
assigned these variables:
CC=clang
CXX=clang++
CFLAGS="-O2 -pipe -flto"
LDFLAGS="-Wl,-O2 -Wl,--as-needed"
AR="llvm-ar"
NM="llvm-nm"
RANLIB="llvm-ranlib"

Musl compiled flawlessly with these variables:
CC=clang
CXX=clang++
CFLAGS="-O2 -pipe"
LDFLAGS=""
AR="llvm-ar"
NM="llvm-nm"
RANLIB="llvm-ranlib"
Quuxplusone commented 6 years ago
I could reproduce the issue.

The symbol "__dls2" is referenced only by the following macro that is expanded
to an inline assembly. I believe because of that, LTO doesn't recognize that
the symbol needs to be kept.

  #define GETFUNCSYM(fp, sym, got) __asm__ ( \
          ".hidden " #sym "\n" \
          "       lea " #sym "(%%rip),%0\n" \
          : "=r"(*fp) : : "memory" )

Not sure what is the right way to fix the issue. CCing pcc as he know a lot
more than me about LTO.
Quuxplusone commented 6 years ago
The problem is indeed that we currently don't attempt to parse inline asm
(except for module-level inline asm) when building a symbol table for an LTO
object file.

This may be something that we could conceivably do with some effort now that we
support creating LTO symbol tables (basically, we would copy all of a module's
inline asm calls into a function in a second module, replace all non-constant
arguments with undef and codegen the second module with a RecordStreamer to
track the symbol references). There's probably some reason why that wouldn't
work that I haven't thought of, though.

I don't quite understand why musl needs to take the address of a function like
that, but assuming that it is necessary, it looks like you can work around the
problem by adding a module-level asm reference to the symbol.

diff --git a/ldso/dlstart.c b/ldso/dlstart.c
index 4dbe1784..3cb3170a 100644
--- a/ldso/dlstart.c
+++ b/ldso/dlstart.c
@@ -17,6 +17,8 @@
        *(fp) = static_func_ptr; } while(0)
 #endif

+__asm__(".globl __dls2");
+
 __attribute__((__visibility__("hidden")))
 void _dlstart_c(size_t *sp, size_t *dynv)
 {
Quuxplusone commented 6 years ago

Moving the bug and it is something that should be fixed in llvm so that there is an undefined symbol in the bitcode file symbol table.

Quuxplusone commented 6 years ago

Is this the same as bug 35197 and/or bug 35290?

Quuxplusone commented 6 years ago
(In reply to David Major from comment #5)
> Is this the same as bug 35197 and/or bug 35290?

Not sure. Those are MS inline asms, and we do some extra magic for those.
Quuxplusone commented 5 years ago

Rui and/or Peter - any thoughts about how complex this would be to fix in LLVM. This bug affects the Linux kernel, so we would like to eventually be able to revert some workarounds when using LLD to link it.