diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp index 244975f4a51ac8..0ca2130150a64f 100644 --- a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp @@ -544,7 +544,6 @@ class ELFLinkGraphBuilder_x86_64 { // Type != ELF::STT_COMMON) { // continue; // } - std::pair bindings; auto Name = SymRef.getName(*StringTable); // I am not sure on If this is going to hold as an invariant. Revisit. if (!Name) @@ -560,11 +559,43 @@ class ELFLinkGraphBuilder_x86_64 { continue; } - // TODO: weak and hidden - if (SymRef.isExternal()) - bindings = {Linkage::Strong, Scope::Default}; - else - bindings = {Linkage::Strong, Scope::Local}; + // Map Visibility and Binding to Scope and Linkage: + Linkage L = Linkage::Strong; + Scope S = Scope::Default; + + switch (SymRef.getBinding()) { + case ELF::STB_LOCAL: + S = Scope::Local; + break; + case ELF::STB_GLOBAL: + // Nothing to do here. + break; + case ELF::STB_WEAK: + L = Linkage::Weak; + break; + default: + return make_error("Unrecognized symbol binding for " + + *Name, + inconvertibleErrorCode()); + } + + switch (SymRef.getVisibility()) { + case ELF::STV_DEFAULT: + case ELF::STV_PROTECTED: + // FIXME: Make STV_DEFAULT symbols pre-emptible? This probably needs + // Orc support. + // Otherwise nothing to do here. + break; + case ELF::STV_HIDDEN: + // Default scope -> Hidden scope. No effect on local scope. + if (S == Scope::Default) + S = Scope::Hidden; + break; + case ELF::STV_INTERNAL: + return make_error("Unrecognized symbol visibility for " + + *Name, + inconvertibleErrorCode()); + } if (SymRef.isDefined() && (Type == ELF::STT_FUNC || Type == ELF::STT_OBJECT || @@ -591,17 +622,17 @@ class ELFLinkGraphBuilder_x86_64 { return make_error( "Section has no block", llvm::inconvertibleErrorCode()); - auto B = *bs.begin(); + auto *B = *bs.begin(); LLVM_DEBUG({ dbgs() << " " << *Name << " at index " << SymbolIndex << "\n"; }); if (SymRef.getType() == ELF::STT_SECTION) *Name = *sectName; - auto &S = G->addDefinedSymbol( - *B, SymRef.getValue(), *Name, SymRef.st_size, bindings.first, - bindings.second, SymRef.getType() == ELF::STT_FUNC, false); - JITSymbolTable[SymbolIndex] = &S; + auto &Sym = G->addDefinedSymbol( + *B, SymRef.getValue(), *Name, SymRef.st_size, L, S, + SymRef.getType() == ELF::STT_FUNC, false); + JITSymbolTable[SymbolIndex] = &Sym; } else if (SymRef.isUndefined() && SymRef.isExternal()) { - auto &S = G->addExternalSymbol(*Name, SymRef.st_size, bindings.first); - JITSymbolTable[SymbolIndex] = &S; + auto &Sym = G->addExternalSymbol(*Name, SymRef.st_size, L); + JITSymbolTable[SymbolIndex] = &Sym; } else LLVM_DEBUG({ dbgs() diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp index 41b5423dc33599..93dfba9c759bc0 100644 --- a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp @@ -64,7 +64,7 @@ const char *getGenericEdgeKindName(Edge::Kind K) { case Edge::KeepAlive: return "Keep-Alive"; default: - llvm_unreachable("Unrecognized relocation kind"); + return ""; } } diff --git a/llvm/test/ExecutionEngine/JITLink/X86/ELF_weak_definitions.s b/llvm/test/ExecutionEngine/JITLink/X86/ELF_weak_definitions.s new file mode 100644 index 00000000000000..9085f42098dbdf --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/X86/ELF_weak_definitions.s @@ -0,0 +1,52 @@ +# RUN: rm -rf %t && mkdir -p %t +# RUN: llvm-mc -triple x86_64-pc-linux-gnu -filetype=obj \ +# RUN: -o %t/ELF_weak_defs_extra.o %S/Inputs/ELF_weak_defs_extra.s +# RUN: llvm-mc -triple x86_64-pc-linux-gnu -filetype=obj \ +# RUN: -o %t/ELF_weak_definitions.o %s +# RUN: llvm-jitlink -noexec -check=%s %t/ELF_weak_definitions.o \ +# RUN: %t/ELF_weak_defs_extra.o +# +# Check that objects linked separately agree on the address of weak symbols. +# +# jitlink-check: *{8}WeakDefAddrInThisFile = *{8}WeakDefAddrInExtraFile + + .text + .file "ELF_weak_definitions.c" + .globl main + .p2align 4, 0x90 + .type main,@function +main: + movq WeakDef@GOTPCREL(%rip), %rax + movl (%rax), %eax + retq +.Lfunc_end0: + .size main, .Lfunc_end0-main + + .type WeakDef,@object + .data + .weak WeakDef + .p2align 2 +WeakDef: + .long 1 + .size WeakDef, 4 + + .type WeakDefAddrInThisFile,@object + .globl WeakDefAddrInThisFile + .p2align 3 +WeakDefAddrInThisFile: + .quad WeakDef + .size WeakDefAddrInThisFile, 8 + + + .type extra_file_anchor,@object + .globl extra_file_anchor + .p2align 3 +extra_file_anchor: + .quad WeakDefAddrInExtraFile + .size extra_file_anchor, 8 + + .ident "clang version 10.0.0-4ubuntu1 " + .section ".note.GNU-stack","",@progbits + .addrsig + .addrsig_sym WeakDef + .addrsig_sym WeakDefAddrInExtraFile diff --git a/llvm/test/ExecutionEngine/JITLink/X86/Inputs/ELF_weak_defs_extra.s b/llvm/test/ExecutionEngine/JITLink/X86/Inputs/ELF_weak_defs_extra.s new file mode 100644 index 00000000000000..aa696dd5081799 --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/X86/Inputs/ELF_weak_defs_extra.s @@ -0,0 +1,24 @@ +# Supplies a weak def, WeakDef, and a pointer holding its address, +# WeakDefAddrInExtraFile. + + .text + .file "ELF_weak_defs_extra.c" + .type WeakDef,@object + .data + .weak WeakDef + .p2align 2 +WeakDef: + .long 2 + .size WeakDef, 4 + + .type WeakDefAddrInExtraFile,@object + .globl WeakDefAddrInExtraFile + .p2align 3 +WeakDefAddrInExtraFile: + .quad WeakDef + .size WeakDefAddrInExtraFile, 8 + + .ident "clang version 10.0.0-4ubuntu1 " + .section ".note.GNU-stack","",@progbits + .addrsig + .addrsig_sym WeakDef