[BOLT] Skip PLT search for zero-value weak reference symbols (#69136)
Take a common weak reference pattern for example
```
__attribute__((weak)) void undef_weak_fun();
if (&undef_weak_fun)
undef_weak_fun();
```
In this case, an undefined weak symbol `undef_weak_fun` has an address
of zero, and Bolt incorrectly changes the relocation for the
corresponding symbol to symbol@PLT, leading to incorrect runtime
behavior.
This commit is contained in:
@@ -2143,6 +2143,14 @@ bool RewriteInstance::analyzeRelocation(
|
||||
if (!Relocation::isSupported(RType))
|
||||
return false;
|
||||
|
||||
auto IsWeakReference = [](const SymbolRef &Symbol) {
|
||||
Expected<uint32_t> SymFlagsOrErr = Symbol.getFlags();
|
||||
if (!SymFlagsOrErr)
|
||||
return false;
|
||||
return (*SymFlagsOrErr & SymbolRef::SF_Undefined) &&
|
||||
(*SymFlagsOrErr & SymbolRef::SF_Weak);
|
||||
};
|
||||
|
||||
const bool IsAArch64 = BC->isAArch64();
|
||||
|
||||
const size_t RelSize = Relocation::getSizeForType(RType);
|
||||
@@ -2174,7 +2182,8 @@ bool RewriteInstance::analyzeRelocation(
|
||||
// Section symbols are marked as ST_Debug.
|
||||
IsSectionRelocation = (cantFail(Symbol.getType()) == SymbolRef::ST_Debug);
|
||||
// Check for PLT entry registered with symbol name
|
||||
if (!SymbolAddress && (IsAArch64 || BC->isRISCV())) {
|
||||
if (!SymbolAddress && !IsWeakReference(Symbol) &&
|
||||
(IsAArch64 || BC->isRISCV())) {
|
||||
const BinaryData *BD = BC->getPLTBinaryDataByName(SymbolName);
|
||||
SymbolAddress = BD ? BD->getAddress() : 0;
|
||||
}
|
||||
|
||||
34
bolt/test/AArch64/update-weak-reference-symbol.s
Normal file
34
bolt/test/AArch64/update-weak-reference-symbol.s
Normal file
@@ -0,0 +1,34 @@
|
||||
// This test checks whether BOLT can correctly handle relocations against weak symbols.
|
||||
|
||||
// RUN: %clang %cflags -Wl,-z,notext -shared -Wl,-q %s -o %t.so
|
||||
// RUN: llvm-bolt %t.so -o %t.so.bolt
|
||||
// RUN: llvm-nm -n %t.so.bolt > %t.out.txt
|
||||
// RUN: llvm-objdump -dj .rodata %t.so.bolt >> %t.out.txt
|
||||
// RUN: FileCheck %s --input-file=%t.out.txt
|
||||
|
||||
# CHECK: w func_1
|
||||
# CHECK: {{0+}}[[#%x,ADDR:]] W func_2
|
||||
|
||||
# CHECK: {{.*}} <.rodata>:
|
||||
# CHECK-NEXT: {{.*}} .word 0x00000000
|
||||
# CHECK-NEXT: {{.*}} .word 0x00000000
|
||||
# CHECK-NEXT: {{.*}} .word 0x{{[0]+}}[[#ADDR]]
|
||||
# CHECK-NEXT: {{.*}} .word 0x00000000
|
||||
|
||||
.text
|
||||
.weak func_2
|
||||
.weak func_1
|
||||
.global wow
|
||||
.type wow, %function
|
||||
wow:
|
||||
bl func_1
|
||||
bl func_2
|
||||
ret
|
||||
.type func_2, %function
|
||||
func_2:
|
||||
ret
|
||||
.section .rodata
|
||||
.LC0:
|
||||
.xword func_1
|
||||
.LC1:
|
||||
.xword func_2
|
||||
Reference in New Issue
Block a user