Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 16 additions & 15 deletions lld/MachO/SymbolTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,22 +78,23 @@ static void transplantSymbolsAtOffset(InputSection *fromIsec,
auto insertIt = llvm::upper_bound(toIsec->symbols, toOff, symSucceedsOff);
llvm::erase_if(fromIsec->symbols, [&](Symbol *s) {
auto *d = cast<Defined>(s);
if (d->value != fromOff)
if (d == skip)
return true;
if (d->value != fromOff || d->isExternal())
return false;
if (d != skip) {
// This repeated insertion will be quadratic unless insertIt is the end
// iterator. However, that is typically the case for files that have
// .subsections_via_symbols set.
insertIt = toIsec->symbols.insert(insertIt, d);
d->originalIsec = toIsec;
d->value = toOff;
// We don't want to have more than one unwindEntry at a given address, so
// drop the redundant ones. We We can safely drop the unwindEntries of
// the symbols in fromIsec since we will be adding another unwindEntry as
// we finish parsing toIsec's file. (We can assume that toIsec has its
// own unwindEntry because of the ODR.)
d->originalUnwindEntry = nullptr;
}

// This repeated insertion will be quadratic unless insertIt is the end
// iterator. However, that is typically the case for files that have
// .subsections_via_symbols set.
insertIt = toIsec->symbols.insert(insertIt, d);
d->originalIsec = toIsec;
d->value = toOff;
// We don't want to have more than one unwindEntry at a given address, so
// drop the redundant ones. We We can safely drop the unwindEntries of
// the symbols in fromIsec since we will be adding another unwindEntry as
// we finish parsing toIsec's file. (We can assume that toIsec has its
// own unwindEntry because of the ODR.)
d->originalUnwindEntry = nullptr;
return true;
});
}
Expand Down
97 changes: 97 additions & 0 deletions lld/test/MachO/weak-alias-override.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# REQUIRES: x86
# RUN: rm -rf %t; split-file %s %t
# RUN: mkdir -p %t/bin

# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos -o %t/weak.o %t/weak.s
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos -o %t/strong_a.o %t/strong_a.s
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos -o %t/strong_b.o %t/strong_b.s

# --- Test Case 1: No overrides
# RUN: %lld %t/weak.o -o %t/bin/alone -e _s
# RUN: llvm-nm -am %t/bin/alone | FileCheck --check-prefix=NM_ALONE %s

# NM_ALONE: [[P_ADDR:[0-9a-f]+]] (__TEXT,__const) weak external _placeholder_int
# NM_ALONE: [[P_ADDR]] (__TEXT,__const) weak external _weak_a
# NM_ALONE: [[P_ADDR]] (__TEXT,__const) weak external _weak_b

# --- Test Case 2: Override weak_a
# RUN: %lld %t/weak.o %t/strong_a.o -o %t/bin/with_a -e _s
# RUN: llvm-nm -am %t/bin/with_a | FileCheck --check-prefix=NM_WITH_A %s
# RUN: llvm-nm -am %t/bin/with_a | FileCheck --check-prefix=NM_WITH_A_BAD %s

# NM_WITH_A: [[P_ADDR:[0-9a-f]+]] (__TEXT,__const) weak external _placeholder_int
# NM_WITH_A: [[A_ADDR:[0-9a-f]+]] (__TEXT,__const) external _strong_a
# NM_WITH_A: [[A_ADDR]] (__TEXT,__const) external _weak_a
# NM_WITH_A: [[P_ADDR]] (__TEXT,__const) weak external _weak_b

# --- Addresses of _placeholder_int and _strong_a must not match.
# NM_WITH_A_BAD: [[P_ADDR:[0-9a-f]+]] (__TEXT,__const) weak external _placeholder_int
# NM_WITH_A_BAD-NOT: [[P_ADDR]] (__TEXT,__const) external _strong_a

# --- Test Case 3: Override weak_b
# RUN: %lld %t/weak.o %t/strong_b.o -o %t/bin/with_b -e _s
# RUN: llvm-nm -am %t/bin/with_b | FileCheck --check-prefix=NM_WITH_B %s
# RUN: llvm-nm -am %t/bin/with_b | FileCheck --check-prefix=NM_WITH_B_BAD %s

# NM_WITH_B: [[P_ADDR:[0-9a-f]+]] (__TEXT,__const) weak external _placeholder_int
# NM_WITH_B: [[B_ADDR:[0-9a-f]+]] (__TEXT,__const) external _strong_b
# NM_WITH_B: [[P_ADDR]] (__TEXT,__const) weak external _weak_a
# NM_WITH_B: [[B_ADDR]] (__TEXT,__const) external _weak_b

# --- Addresses of _placeholder_int and _strong_a must not match.
# NM_WITH_B_BAD: [[P_ADDR:[0-9a-f]+]] (__TEXT,__const) weak external _placeholder_int
# NM_WITH_B_BAD-NOT: [[P_ADDR]] (__TEXT,__const) external _strong_b

# --- Test Case 4: Override weak_a and weak_b
# RUN: %lld %t/weak.o %t/strong_a.o %t/strong_b.o -o %t/bin/with_ab -e _s
# RUN: llvm-nm -am %t/bin/with_ab | FileCheck --check-prefix=NM_WITH_AB %s
# RUN: llvm-nm -am %t/bin/with_ab | FileCheck --check-prefix=NM_WITH_AB_BAD %s

# NM_WITH_AB: [[P_ADDR:[0-9a-f]+]] (__TEXT,__const) weak external _placeholder_int
# NM_WITH_AB: [[A_ADDR:[0-9a-f]+]] (__TEXT,__const) external _strong_a
# NM_WITH_AB: [[B_ADDR:[0-9a-f]+]] (__TEXT,__const) external _strong_b
# NM_WITH_AB: [[A_ADDR]] (__TEXT,__const) external _weak_a
# NM_WITH_AB: [[B_ADDR]] (__TEXT,__const) external _weak_b

# --- Addresses of _placeholder_int, _strong_a, and _strong_b must all be distinct
# NM_WITH_AB_BAD: [[P_ADDR:[0-9a-f]+]] (__TEXT,__const) weak external _placeholder_int
# NM_WITH_AB_BAD-NOT: [[P_ADDR]] (__TEXT,__const) external _strong_a
# NM_WITH_AB_BAD-NOT: [[P_ADDR]] (__TEXT,__const) external _strong_b

#--- weak.s
.section __TEXT,__const
.globl _placeholder_int
.weak_definition _placeholder_int
_placeholder_int:
.long 0

.globl _weak_a
.set _weak_a, _placeholder_int
.weak_definition _weak_a

.globl _weak_b
.set _weak_b, _placeholder_int
.weak_definition _weak_b

.globl _s
_s:
.quad _weak_a
.quad _weak_b

#--- strong_a.s
.section __TEXT,__const
.globl _strong_a
_strong_a:
.long 1

.globl _weak_a
_weak_a = _strong_a

#--- strong_b.s
.section __TEXT,__const
.globl _strong_b
_strong_b:
.long 2

.globl _weak_b
_weak_b = _strong_b
Loading