From a8e05d067d4ecc7e1ed434f8f05b4a3c49e4440a Mon Sep 17 00:00:00 2001 From: Maksim Panchenko Date: Tue, 9 Apr 2019 12:29:40 -0700 Subject: [PATCH] [BOLT] Add interface to extract values from static addresses (cherry picked from FBD14858028) --- bolt/src/BinaryContext.cpp | 32 ++++++++++++++++++----- bolt/src/BinaryContext.h | 18 ++++++++++--- bolt/src/Exceptions.cpp | 7 +++-- bolt/src/Passes/IndirectCallPromotion.cpp | 2 +- bolt/src/RewriteInstance.cpp | 17 ++++-------- bolt/src/RewriteInstance.h | 3 +-- bolt/src/Target/X86/X86MCPlusBuilder.cpp | 2 +- 7 files changed, 50 insertions(+), 31 deletions(-) diff --git a/bolt/src/BinaryContext.cpp b/bolt/src/BinaryContext.cpp index ab430ace9e87..76a2d69311ba 100644 --- a/bolt/src/BinaryContext.cpp +++ b/bolt/src/BinaryContext.cpp @@ -1079,17 +1079,35 @@ BinarySection &BinaryContext::absoluteSection() { } ErrorOr -BinaryContext::extractPointerAtAddress(uint64_t Address) const { - auto Section = getSectionForAddress(Address); +BinaryContext::getUnsignedValueAtAddress(uint64_t Address, + size_t Size) const { + const auto Section = getSectionForAddress(Address); if (!Section) return std::make_error_code(std::errc::bad_address); - StringRef SectionContents = Section->getContents(); - DataExtractor DE(SectionContents, - AsmInfo->isLittleEndian(), + if (Section->isVirtual()) + return 0; + + DataExtractor DE(Section->getContents(), AsmInfo->isLittleEndian(), AsmInfo->getCodePointerSize()); - uint32_t SectionOffset = Address - Section->getAddress(); - return DE.getAddress(&SectionOffset); + auto ValueOffset = static_cast(Address - Section->getAddress()); + return DE.getUnsigned(&ValueOffset, Size); +} + +ErrorOr +BinaryContext::getSignedValueAtAddress(uint64_t Address, + size_t Size) const { + const auto Section = getSectionForAddress(Address); + if (!Section) + return std::make_error_code(std::errc::bad_address); + + if (Section->isVirtual()) + return 0; + + DataExtractor DE(Section->getContents(), AsmInfo->isLittleEndian(), + AsmInfo->getCodePointerSize()); + auto ValueOffset = static_cast(Address - Section->getAddress()); + return DE.getSigned(&ValueOffset, Size); } void BinaryContext::addRelocation(uint64_t Address, diff --git a/bolt/src/BinaryContext.h b/bolt/src/BinaryContext.h index 18638bf46518..977cacb518f0 100644 --- a/bolt/src/BinaryContext.h +++ b/bolt/src/BinaryContext.h @@ -731,10 +731,20 @@ public: return std::make_error_code(std::errc::bad_address); } - /// Given \p Address in the binary, extract and return a pointer value at that - /// address. The address has to be a valid statically allocated address for - /// the binary. - ErrorOr extractPointerAtAddress(uint64_t Address) const; + /// Return an unsigned value of \p Size stored at \p Address. The address has + /// to be a valid statically allocated address for the binary. + ErrorOr getUnsignedValueAtAddress(uint64_t Address, + size_t Size) const; + + /// Return a signed value of \p Size stored at \p Address. The address has + /// to be a valid statically allocated address for the binary. + ErrorOr getSignedValueAtAddress(uint64_t Address, + size_t Size) const; + + /// Special case of getUnsignedValueAtAddress() that uses a pointer size. + ErrorOr getPointerAtAddress(uint64_t Address) const { + return getUnsignedValueAtAddress(Address, AsmInfo->getCodePointerSize()); + } /// Replaces all references to \p ChildBF with \p ParentBF. \p ChildBF is then /// removed from the list of functions \p BFs. The profile data of \p ChildBF diff --git a/bolt/src/Exceptions.cpp b/bolt/src/Exceptions.cpp index 9b9258884bde..87f1eb853d81 100644 --- a/bolt/src/Exceptions.cpp +++ b/bolt/src/Exceptions.cpp @@ -266,7 +266,7 @@ void BinaryFunction::parseLSDA(ArrayRef LSDASectionData, return; } if (TTypeEncoding & DW_EH_PE_indirect) { - auto PointerOrErr = BC.extractPointerAtAddress(TypeAddress); + auto PointerOrErr = BC.getPointerAtAddress(TypeAddress); assert(PointerOrErr && "failed to decode indirect address"); TypeAddress = *PointerOrErr; } @@ -349,9 +349,8 @@ void BinaryFunction::parseLSDA(ArrayRef LSDASectionData, if ((TTypeEncoding & DW_EH_PE_pcrel) && (TypeAddress == TTEntryAddress)) { TypeAddress = 0; } - if (TypeAddress && - (TTypeEncoding & DW_EH_PE_indirect)) { - auto PointerOrErr = BC.extractPointerAtAddress(TypeAddress); + if (TypeAddress && (TTypeEncoding & DW_EH_PE_indirect)) { + auto PointerOrErr = BC.getPointerAtAddress(TypeAddress); assert(PointerOrErr && "failed to decode indirect address"); TypeAddress = *PointerOrErr; } diff --git a/bolt/src/Passes/IndirectCallPromotion.cpp b/bolt/src/Passes/IndirectCallPromotion.cpp index 4457585d6a13..68d2fe685be5 100644 --- a/bolt/src/Passes/IndirectCallPromotion.cpp +++ b/bolt/src/Passes/IndirectCallPromotion.cpp @@ -647,7 +647,7 @@ IndirectCallPromotion::maybeGetVtableSyms( << "+" << MethodOffset << "/" << MI.Count << "\n"); - if (auto MethodAddr = BC.extractPointerAtAddress(Address)) { + if (auto MethodAddr = BC.getPointerAtAddress(Address)) { auto *MethodBD = BC.getBinaryDataAtAddress(MethodAddr.get()); if (!MethodBD) // skip unknown methods continue; diff --git a/bolt/src/RewriteInstance.cpp b/bolt/src/RewriteInstance.cpp index 87823fe1b4bf..5d082f73a72b 100644 --- a/bolt/src/RewriteInstance.cpp +++ b/bolt/src/RewriteInstance.cpp @@ -1838,7 +1838,6 @@ int64_t getRelocationAddend(const ELFObjectFileBase *Obj, } // anonymous namespace bool RewriteInstance::analyzeRelocation(const RelocationRef &Rel, - SectionRef RelocatedSection, std::string &SymbolName, bool &IsSectionRelocation, uint64_t &SymbolAddress, @@ -1849,16 +1848,11 @@ bool RewriteInstance::analyzeRelocation(const RelocationRef &Rel, const bool IsAArch64 = BC->isAArch64(); - // Extract the value. - StringRef RelocatedSectionContents; - RelocatedSection.getContents(RelocatedSectionContents); - DataExtractor DE(RelocatedSectionContents, - BC->AsmInfo->isLittleEndian(), - BC->AsmInfo->getCodePointerSize()); - uint32_t RelocationOffset = Rel.getOffset() - RelocatedSection.getAddress(); const auto RelSize = Relocation::getSizeForType(Rel.getType()); - ExtractedValue = static_cast(DE.getSigned(&RelocationOffset, - RelSize)); + + auto Value = BC->getUnsignedValueAtAddress(Rel.getOffset(), RelSize); + assert(Value && "failed to extract relocated value"); + ExtractedValue = *Value; if (IsAArch64) { ExtractedValue = Relocation::extractValue(Rel.getType(), ExtractedValue, @@ -1867,7 +1861,7 @@ bool RewriteInstance::analyzeRelocation(const RelocationRef &Rel, Addend = getRelocationAddend(InputFile, Rel); - const bool IsPCRelative = Relocation::isPCRelative(Rel.getType()); + const auto IsPCRelative = Relocation::isPCRelative(Rel.getType()); const auto PCRelOffset = IsPCRelative && !IsAArch64 ? Rel.getOffset() : 0; bool SkipVerification = false; auto SymbolIter = Rel.getSymbol(); @@ -2026,7 +2020,6 @@ void RewriteInstance::readRelocations(const SectionRef &Section) { uint64_t ExtractedValue; bool IsSectionRelocation; if (!analyzeRelocation(Rel, - RelocatedSection, SymbolName, IsSectionRelocation, SymbolAddress, diff --git a/bolt/src/RewriteInstance.h b/bolt/src/RewriteInstance.h index 7e9e7f5cff6a..fa7a1a9e2c85 100644 --- a/bolt/src/RewriteInstance.h +++ b/bolt/src/RewriteInstance.h @@ -163,12 +163,11 @@ private: /// Make .eh_frame section relocatable. void relocateEHFrameSection(); - /// Analyze relocation \p Rel contained in section \p RelocatedSection. + /// Analyze relocation \p Rel. /// Return true if the relocation was successfully processed, false otherwise. /// The \p SymbolName, \p SymbolAddress, \p Addend and \p ExtractedValue /// parameters will be set on success. bool analyzeRelocation(const RelocationRef &Rel, - SectionRef RelocatedSection, std::string &SymbolName, bool &IsSectionRelocation, uint64_t &SymbolAddress, diff --git a/bolt/src/Target/X86/X86MCPlusBuilder.cpp b/bolt/src/Target/X86/X86MCPlusBuilder.cpp index b758146999a1..ea8e0eb1943a 100644 --- a/bolt/src/Target/X86/X86MCPlusBuilder.cpp +++ b/bolt/src/Target/X86/X86MCPlusBuilder.cpp @@ -1893,7 +1893,7 @@ public: assert(Offset + I.DataSize <= ConstantData.size() && "invalid offset for given constant data"); int64_t ImmVal = - DataExtractor(ConstantData, true, 64).getSigned(&Offset, I.DataSize); + DataExtractor(ConstantData, true, 8).getSigned(&Offset, I.DataSize); // Compute the new opcode. unsigned NewOpcode = 0;