Skip to content

[lld/mac] Resolve defined symbols before undefined symbols in bitcode #67445

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

Merged
merged 1 commit into from
Sep 26, 2023

Conversation

nico
Copy link
Contributor

@nico nico commented Sep 26, 2023

Ports https://reviews.llvm.org/D106293 to bitcode, or bd448f01a6 from ELF to MachO.

See also #59162 for some vaguely related discussion.

@nico nico requested review from MaskRay and int3 September 26, 2023 15:43
Ports https://reviews.llvm.org/D106293 to bitcode, or
llvm@bd448f01a6 from ELF to MachO.

See also llvm#59162 for some vaguely related discussion.
@llvmbot
Copy link
Member

llvmbot commented Sep 26, 2023

@llvm/pr-subscribers-lld

@llvm/pr-subscribers-lld-macho

Changes

Ports https://reviews.llvm.org/D106293 to bitcode, or bd448f01a6 from ELF to MachO.

See also #59162 for some vaguely related discussion.


Full diff: https://github.com/llvm/llvm-project/pull/67445.diff

2 Files Affected:

  • (modified) lld/MachO/InputFiles.cpp (+10-3)
  • (added) lld/test/MachO/weak-definition-in-main-file.ll (+46)
diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index a882c96dc221c56..8f737beee768bee 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -2291,9 +2291,16 @@ void BitcodeFile::parse() {
   // Convert LTO Symbols to LLD Symbols in order to perform resolution. The
   // "winning" symbol will then be marked as Prevailing at LTO compilation
   // time.
-  symbols.clear();
-  for (const lto::InputFile::Symbol &objSym : obj->symbols())
-    symbols.push_back(createBitcodeSymbol(objSym, *this));
+  symbols.resize(obj->symbols().size());
+
+  // Process defined symbols first. See the comment at the end of
+  // ObjFile<>::parseSymbols.
+  for (auto it : llvm::enumerate(obj->symbols()))
+    if (!it.value().isUndefined())
+      symbols[it.index()] = createBitcodeSymbol(it.value(), *this);
+  for (auto it : llvm::enumerate(obj->symbols()))
+    if (it.value().isUndefined())
+      symbols[it.index()] = createBitcodeSymbol(it.value(), *this);
 }
 
 void BitcodeFile::parseLazy() {
diff --git a/lld/test/MachO/weak-definition-in-main-file.ll b/lld/test/MachO/weak-definition-in-main-file.ll
new file mode 100644
index 000000000000000..58a7a8695803a4f
--- /dev/null
+++ b/lld/test/MachO/weak-definition-in-main-file.ll
@@ -0,0 +1,46 @@
+; REQUIRES: aarch64
+; RUN: rm -rf %t; split-file %s %t
+
+;; Test that a weak symbol in a direct .o file wins over
+;; a weak symbol in a .a file.
+;; Like weak-definition-in-main-file.s, but in bitcode.
+
+; RUN: llvm-as %t/test.ll -o %t/test.o
+; RUN: llvm-as %t/weakfoo.ll -o %t/weakfoo.o
+
+; RUN: llvm-ar --format=darwin rcs %t/weakfoo.a %t/weakfoo.o
+
+; PREFER-DIRECT-OBJECT-NOT: O __TEXT,weak _foo
+
+; RUN: %lld -lSystem -o %t/out %t/weakfoo.a %t/test.o
+; RUN: llvm-objdump --syms %t/out | FileCheck %s --check-prefix=PREFER-DIRECT-OBJECT
+
+;--- weakfoo.ll
+target triple = "x86_64-apple-macosx10.15.0"
+target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @baz() noinline optnone {
+  ret void
+}
+
+define weak void @foo() noinline optnone section "__TEXT,weak" {
+  ret void
+}
+
+;--- test.ll
+target triple = "x86_64-apple-macosx10.15.0"
+target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+
+declare void @baz();
+
+define weak void @foo() noinline optnone {
+  ret void
+}
+
+define void @main() {
+  ; This pulls in weakfoo.a due to the __baz undef, but __foo should
+  ; still be resolved against the weak symbol in this file.
+  call void @baz()
+  call void @foo()
+  ret void
+}

@nico nico merged commit 210e898 into llvm:main Sep 26, 2023
@nico nico deleted the lld-mac-undef-bitcode branch September 26, 2023 19:31
nico added a commit that referenced this pull request Sep 27, 2023
Noticed by chapuni:
#67445 (review)

Fixes a test failure if X86 isn't in LLVM_TARGETS_TO_BUILD.
Guzhu-AMD pushed a commit to GPUOpen-Drivers/llvm-project that referenced this pull request Sep 28, 2023
Local branch amd-gfx b56415c Merged main:4effda09d897 into amd-gfx:3d7ab622862d
Remote branch main 210e898 [lld/mac] Resolve defined symbols before undefined symbols in bitcode (llvm#67445)
legrosbuffle pushed a commit to legrosbuffle/llvm-project that referenced this pull request Sep 29, 2023
legrosbuffle pushed a commit to legrosbuffle/llvm-project that referenced this pull request Sep 29, 2023
Noticed by chapuni:
llvm#67445 (review)

Fixes a test failure if X86 isn't in LLVM_TARGETS_TO_BUILD.
nico added a commit that referenced this pull request Jan 24, 2025
…434 (#124294)

This is a follow-up to #120452 in a way.

Since lld/COFF does not yet insert all defined in an obj file before all
undefineds (ELF and MachO do this, see #67445 and things linked from
there), it's possible that:

1. We add an obj file a.obj
2. a.obj contains an undefined that's in b.obj, causing b.obj to be
added
3. b.obj contains an undefined that's in a part of a.obj that's not yet
in the symbol table, causing a recursive load of a.obj, which adds the
symbols in there twice, leading to duplicate symbol errors.

For normal archives, `ArchiveFile::addMember()` has a `seen` check to
prevent this. For start-lib lazy objects, we can just check if the
archive is still lazy at the recursive call.

This bug is similar to issue #59162.

(Eventually, we'll probably want to do what the MachO and ELF ports do.)

Includes a test that caused duplicate symbol diagnostics before this
code change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants