From f06a1455eac57aa3ddcbc156c8b9496224dc9539 Mon Sep 17 00:00:00 2001 From: Maksim Panchenko Date: Tue, 14 Feb 2017 22:55:10 -0800 Subject: [PATCH] [BOLT] Add support for *GOTPCRELX relocation type. Summary: gcc5 can generate new types of relocations that give linker a freedom to substitute instructions. These relocations are PC-relative, and since we manually process such relocations they don't present much of a problem. Additionally, detect non-pc-relative access from code into a middle of a function. Occasionally I've seen such code, but don't know exactly how to trigger its generation. Just issue a warning for now. (cherry picked from FBD4566473) --- bolt/BinaryFunction.cpp | 4 ++++ bolt/BinaryFunction.h | 2 ++ bolt/RewriteInstance.cpp | 19 +++++++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/bolt/BinaryFunction.cpp b/bolt/BinaryFunction.cpp index f6f14f681323..de4cf2715310 100644 --- a/bolt/BinaryFunction.cpp +++ b/bolt/BinaryFunction.cpp @@ -3834,6 +3834,8 @@ size_t Relocation::getSizeForType(uint64_t Type) { case ELF::R_X86_64_GOTPCREL: case ELF::R_X86_64_GOTTPOFF: case ELF::R_X86_64_TPOFF32: + case ELF::R_X86_64_GOTPCRELX: + case ELF::R_X86_64_REX_GOTPCRELX: return 4; case ELF::R_X86_64_PC64: case ELF::R_X86_64_64: @@ -3857,6 +3859,8 @@ bool Relocation::isPCRelative(uint64_t Type) { case ELF::R_X86_64_GOTPCREL: case ELF::R_X86_64_PLT32: case ELF::R_X86_64_GOTTPOFF: + case ELF::R_X86_64_GOTPCRELX: + case ELF::R_X86_64_REX_GOTPCRELX: return true; } } diff --git a/bolt/BinaryFunction.h b/bolt/BinaryFunction.h index 2d74ec3ca7e4..7952b0561cb2 100644 --- a/bolt/BinaryFunction.h +++ b/bolt/BinaryFunction.h @@ -986,6 +986,8 @@ public: case ELF::R_X86_64_PC32: case ELF::R_X86_64_PC8: case ELF::R_X86_64_PLT32: + case ELF::R_X86_64_GOTPCRELX: + case ELF::R_X86_64_REX_GOTPCRELX: break; // The following relocations are ignored. diff --git a/bolt/RewriteInstance.cpp b/bolt/RewriteInstance.cpp index d76e553db2dc..27c17c9837ba 100644 --- a/bolt/RewriteInstance.cpp +++ b/bolt/RewriteInstance.cpp @@ -1398,10 +1398,12 @@ void RewriteInstance::readRelocations(const SectionRef &Section) { } else { Address = SymbolAddress + Addend; } + bool SymbolIsSection = false; if (SymbolIter != InputFile->symbol_end()) { SymbolName = (*(*SymbolIter).getName()); if (SymbolIter->getType() == SymbolRef::ST_Debug) { // Weird stuff - section symbols are marked as ST_Debug. + SymbolIsSection = true; auto SymbolSection = SymbolIter->getSection(); if (SymbolSection && *SymbolSection != InputFile->section_end()) { StringRef SymbolSectionName; @@ -1418,6 +1420,23 @@ void RewriteInstance::readRelocations(const SectionRef &Section) { ForceRelocation = true; } + if (!IsPCRelative && Addend != 0 && IsFromCode && !SymbolIsSection) { + auto RefSection = BC->getSectionForAddress(SymbolAddress); + if (RefSection && RefSection->isText()) { + errs() << "BOLT-WARNING: detected absolute reference from code into a " + << "middle of a function:\n" + << " offset = 0x" << Twine::utohexstr(Rel.getOffset()) + << "; symbol = " << SymbolName + << "; symbol address = 0x" << Twine::utohexstr(SymbolAddress) + << "; addend = 0x" << Twine::utohexstr(Addend) + << "; address = 0x" << Twine::utohexstr(Address) + << "; type = " << Rel.getType() + << "; type name = " << TypeName + << '\n'; + assert(ExtractedValue == SymbolAddress + Addend && "value mismatch"); + } + } + if (Addend < 0 && IsPCRelative) { Address -= Addend; } else {