Skip to content

Commit

Permalink
merge main into amd-staging
Browse files Browse the repository at this point in the history
Change-Id: I03a7c2468660104117e64b9080946a4ffc763806
  • Loading branch information
ronlieb committed Aug 7, 2024
2 parents 8864ebb + c31ac81 commit eb1939d
Show file tree
Hide file tree
Showing 309 changed files with 8,802 additions and 1,605 deletions.
2 changes: 1 addition & 1 deletion bolt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ endforeach()

set(BOLT_ENABLE_RUNTIME_default OFF)
if ((CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64"
OR CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
OR CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)$")
AND (CMAKE_SYSTEM_NAME STREQUAL "Linux"
OR CMAKE_SYSTEM_NAME STREQUAL "Darwin")
AND (NOT CMAKE_CROSSCOMPILING))
Expand Down
3 changes: 2 additions & 1 deletion bolt/include/bolt/Core/BinaryContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -911,7 +911,8 @@ class BinaryContext {
/// of \p Flags.
MCSymbol *registerNameAtAddress(StringRef Name, uint64_t Address,
uint64_t Size, uint16_t Alignment,
unsigned Flags = 0);
unsigned Flags = 0,
BinarySection *Section = NULL);

/// Return BinaryData registered at a given \p Address or nullptr if no
/// global symbol was registered at the location.
Expand Down
22 changes: 16 additions & 6 deletions bolt/lib/Core/BinaryContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1056,18 +1056,28 @@ void BinaryContext::adjustCodePadding() {
MCSymbol *BinaryContext::registerNameAtAddress(StringRef Name, uint64_t Address,
uint64_t Size,
uint16_t Alignment,
unsigned Flags) {
unsigned Flags,
BinarySection *Section) {
// Register the name with MCContext.
MCSymbol *Symbol = Ctx->getOrCreateSymbol(Name);
BinaryData *BD;

// Register out of section symbols only in GlobalSymbols map
if (Section && Section->getEndAddress() == Address) {
BD = new BinaryData(*Symbol, Address, Size, Alignment ? Alignment : 1,
*Section, Flags);
GlobalSymbols[Name] = BD;
return Symbol;
}

auto GAI = BinaryDataMap.find(Address);
BinaryData *BD;
if (GAI == BinaryDataMap.end()) {
ErrorOr<BinarySection &> SectionOrErr = getSectionForAddress(Address);
BinarySection &Section =
SectionOrErr ? SectionOrErr.get() : absoluteSection();
BinarySection &SectionRef = Section ? *Section
: SectionOrErr ? SectionOrErr.get()
: absoluteSection();
BD = new BinaryData(*Symbol, Address, Size, Alignment ? Alignment : 1,
Section, Flags);
SectionRef, Flags);
GAI = BinaryDataMap.emplace(Address, BD).first;
GlobalSymbols[Name] = BD;
updateObjectNesting(GAI);
Expand Down Expand Up @@ -1402,7 +1412,7 @@ void BinaryContext::postProcessSymbolTable() {
if ((BD->getName().starts_with("SYMBOLat") ||
BD->getName().starts_with("DATAat")) &&
!BD->getParent() && !BD->getSize() && !BD->isAbsolute() &&
BD->getSection()) {
BD->getSection().getSize()) {
this->errs() << "BOLT-WARNING: zero-sized top level symbol: " << *BD
<< "\n";
Valid = false;
Expand Down
5 changes: 4 additions & 1 deletion bolt/lib/Core/BinaryFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2502,7 +2502,10 @@ void BinaryFunction::annotateCFIState() {
}
}

assert(StateStack.empty() && "corrupt CFI stack");
if (!StateStack.empty()) {
BC.errs() << "BOLT-WARNING: non-empty CFI stack at the end of " << *this
<< '\n';
}
}

namespace {
Expand Down
4 changes: 2 additions & 2 deletions bolt/lib/Rewrite/BinaryPassManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,8 @@ Error BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) {

Manager.registerPass(
std::make_unique<VeneerElimination>(PrintVeneerElimination));

Manager.registerPass(std::make_unique<ADRRelaxationPass>());
}

if (BC.isRISCV()) {
Expand Down Expand Up @@ -490,8 +492,6 @@ Error BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) {
Manager.registerPass(std::make_unique<ReorderData>());

if (BC.isAArch64()) {
Manager.registerPass(std::make_unique<ADRRelaxationPass>());

// Tighten branches according to offset differences between branch and
// targets. No extra instructions after this pass, otherwise we may have
// relocations out of range and crash during linking.
Expand Down
72 changes: 63 additions & 9 deletions bolt/lib/Rewrite/RewriteInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -955,13 +955,13 @@ void RewriteInstance::discoverFileObjects() {
uint64_t SymbolSize = ELFSymbolRef(Symbol).getSize();
uint64_t SymbolAlignment = Symbol.getAlignment();

auto registerName = [&](uint64_t FinalSize) {
auto registerName = [&](uint64_t FinalSize, BinarySection *Section = NULL) {
// Register names even if it's not a function, e.g. for an entry point.
BC->registerNameAtAddress(UniqueName, SymbolAddress, FinalSize,
SymbolAlignment, SymbolFlags);
SymbolAlignment, SymbolFlags, Section);
if (!AlternativeName.empty())
BC->registerNameAtAddress(AlternativeName, SymbolAddress, FinalSize,
SymbolAlignment, SymbolFlags);
SymbolAlignment, SymbolFlags, Section);
};

section_iterator Section =
Expand All @@ -986,12 +986,25 @@ void RewriteInstance::discoverFileObjects() {
<< " for function\n");

if (SymbolAddress == Section->getAddress() + Section->getSize()) {
ErrorOr<BinarySection &> SectionOrError =
BC->getSectionForAddress(Section->getAddress());

// Skip symbols from invalid sections
if (!SectionOrError) {
BC->errs() << "BOLT-WARNING: " << UniqueName << " (0x"
<< Twine::utohexstr(SymbolAddress)
<< ") does not have any section\n";
continue;
}

assert(SymbolSize == 0 &&
"unexpect non-zero sized symbol at end of section");
LLVM_DEBUG(
dbgs()
<< "BOLT-DEBUG: rejecting as symbol points to end of its section\n");
registerName(SymbolSize);
LLVM_DEBUG({
dbgs() << "BOLT-DEBUG: rejecting as symbol " << UniqueName
<< " points to end of " << SectionOrError->getName()
<< " section\n";
});
registerName(SymbolSize, &SectionOrError.get());
continue;
}

Expand Down Expand Up @@ -2143,6 +2156,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);
Expand Down Expand Up @@ -2174,7 +2195,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;
}
Expand Down Expand Up @@ -2603,7 +2625,7 @@ void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection,
Expected<StringRef> SectionName = Section->getName();
if (SectionName && !SectionName->empty())
ReferencedSection = BC->getUniqueSectionByName(*SectionName);
} else if (ReferencedSymbol && ContainingBF &&
} else if (BC->isRISCV() && ReferencedSymbol && ContainingBF &&
(cantFail(Symbol.getFlags()) & SymbolRef::SF_Absolute)) {
// This might be a relocation for an ABS symbols like __global_pointer$ on
// RISC-V
Expand All @@ -2614,6 +2636,30 @@ void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection,
}
}

if (Relocation::isGOT(RType) && !Relocation::isTLS(RType)) {
auto exitOnGotEndSymol = [&](StringRef Name) {
BC->errs() << "BOLT-ERROR: GOT table contains currently unsupported "
"section end symbol "
<< Name << "\n";
exit(1);
};

if (SymbolIter != InputFile->symbol_end() && ReferencedSection) {
if (cantFail(SymbolIter->getAddress()) ==
ReferencedSection->getEndAddress())
exitOnGotEndSymol(cantFail(SymbolIter->getName()));
} else {
// If no section and symbol are provided by relocation, try to find the
// symbol by its name, including the possibility that the symbol is local.
BinaryData *BD = BC->getBinaryDataByName(SymbolName);
if (!BD && NR.getUniquifiedNameCount(SymbolName) == 1)
BD = BC->getBinaryDataByName(NR.getUniqueName(SymbolName, 1));

if ((BD && BD->getAddress() == BD->getSection().getEndAddress()))
exitOnGotEndSymol(BD->getName());
}
}

if (!ReferencedSection)
ReferencedSection = BC->getSectionForAddress(SymbolAddress);

Expand Down Expand Up @@ -5509,6 +5555,14 @@ uint64_t RewriteInstance::getNewFunctionOrDataAddress(uint64_t OldAddress) {
if (const BinaryFunction *BF =
BC->getBinaryFunctionContainingAddress(OldAddress)) {
if (BF->isEmitted()) {
// If OldAddress is the another entry point of
// the function, then BOLT could get the new address.
if (BF->isMultiEntry()) {
for (const BinaryBasicBlock &BB : *BF)
if (BB.isEntryPoint() &&
(BF->getAddress() + BB.getOffset()) == OldAddress)
return BF->getOutputAddress() + BB.getOffset();
}
BC->errs() << "BOLT-ERROR: unable to get new address corresponding to "
"input address 0x"
<< Twine::utohexstr(OldAddress) << " in function " << *BF
Expand Down
9 changes: 9 additions & 0 deletions bolt/test/AArch64/Inputs/build_id.ldscript
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
SECTIONS
{
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
.note.gnu.build-id (0x400400):
{
build_id_note = ABSOLUTE(.);
*(.note.gnu.build-id)
}
}
6 changes: 6 additions & 0 deletions bolt/test/AArch64/Inputs/got_end_of_section_symbol.lld_script
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
SECTIONS {
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
.data : { *(.data) *(.array) }
.text : { *(.text) }
.got : { *(.got) *(.igot) }
}
25 changes: 25 additions & 0 deletions bolt/test/AArch64/build_id.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// This test checks that referencing build_id through GOT table
// would result in GOT access after disassembly, not directly
// to build_id address.

// RUN: %clang %cflags -fuse-ld=lld -Wl,-T,%S/Inputs/build_id.ldscript -Wl,-q \
// RUN: -Wl,--no-relax -Wl,--build-id=sha1 %s -o %t.exe
// RUN: llvm-bolt -print-disasm --print-only=get_build_id %t.exe -o %t.bolt | \
// RUN: FileCheck %s

// CHECK: adrp [[REG:x[0-28]+]], __BOLT_got_zero
// CHECK: ldr x{{.*}}, [[[REG]], :lo12:__BOLT_got_zero{{.*}}]

struct build_id_note {
char pad[16];
char hash[20];
};

extern const struct build_id_note build_id_note;

__attribute__((noinline)) char get_build_id() { return build_id_note.hash[0]; }

int main() {
get_build_id();
return 0;
}
28 changes: 28 additions & 0 deletions bolt/test/AArch64/got_end_of_section_symbol.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown \
# RUN: %s -o %t.o
# RUN: %clang %cflags -nostartfiles -nodefaultlibs -static -Wl,--no-relax \
# RUN: -Wl,-q -Wl,-T %S/Inputs/got_end_of_section_symbol.lld_script \
# RUN: %t.o -o %t.exe
# RUN: not llvm-bolt %t.exe -o %t.bolt 2>&1 | FileCheck %s

# CHECK: BOLT-ERROR: GOT table contains currently unsupported section end
# CHECK-SAME: symbol array_end

.section .array, "a", @progbits
.globl array_start
.globl array_end
array_start:
.word 0
array_end:

.section .text
.globl _start
.type _start, %function
_start:
adrp x1, #:got:array_start
ldr x1, [x1, #:got_lo12:array_start]
adrp x0, #:got:array_end
ldr x0, [x0, #:got_lo12:array_end]
adrp x2, #:got:_start
ldr x2, [x2, #:got_lo12:_start]
ret
34 changes: 34 additions & 0 deletions bolt/test/AArch64/update-weak-reference-symbol.s
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit eb1939d

Please sign in to comment.