1 //===- bolt/Rewrite/ExecutableFileMemoryManager.cpp -----------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "bolt/Rewrite/ExecutableFileMemoryManager.h" 10 #include "bolt/Rewrite/RewriteInstance.h" 11 #include "llvm/Support/MemAlloc.h" 12 13 #undef DEBUG_TYPE 14 #define DEBUG_TYPE "efmm" 15 16 using namespace llvm; 17 using namespace object; 18 using namespace bolt; 19 20 namespace llvm { 21 22 namespace bolt { 23 24 uint8_t *ExecutableFileMemoryManager::allocateSection( 25 uintptr_t Size, unsigned Alignment, unsigned SectionID, 26 StringRef SectionName, bool IsCode, bool IsReadOnly) { 27 uint8_t *Ret = static_cast<uint8_t *>(llvm::allocate_buffer(Size, Alignment)); 28 AllocatedSections.push_back(AllocInfo{Ret, Size, Alignment}); 29 30 // A Size of 1 might mean an empty section for which RuntimeDyld decided to 31 // allocate 1 byte. In this case, the allocation will never be initialized 32 // causing non-deterministic output section contents. 33 if (Size == 1) 34 *Ret = 0; 35 36 // Register a debug section as a note section. 37 if (!ObjectsLoaded && RewriteInstance::isDebugSection(SectionName)) { 38 BinarySection &Section = 39 BC.registerOrUpdateNoteSection(SectionName, Ret, Size, Alignment); 40 Section.setSectionID(SectionID); 41 assert(!Section.isAllocatable() && "note sections cannot be allocatable"); 42 return Ret; 43 } 44 45 if (!IsCode && (SectionName == ".strtab" || SectionName == ".symtab" || 46 SectionName == "" || SectionName.startswith(".rela."))) 47 return Ret; 48 49 SmallVector<char, 256> Buf; 50 if (ObjectsLoaded > 0) { 51 if (BC.isELF()) { 52 SectionName = (Twine(SectionName) + ".bolt.extra." + Twine(ObjectsLoaded)) 53 .toStringRef(Buf); 54 } else if (BC.isMachO()) { 55 assert((SectionName == "__text" || SectionName == "__data" || 56 SectionName == "__fini" || SectionName == "__setup" || 57 SectionName == "__cstring" || SectionName == "__literal16") && 58 "Unexpected section in the instrumentation library"); 59 // Sections coming from the instrumentation runtime are prefixed with "I". 60 SectionName = ("I" + Twine(SectionName)).toStringRef(Buf); 61 } 62 } 63 64 BinarySection *Section = nullptr; 65 if (!OrgSecPrefix.empty() && SectionName.startswith(OrgSecPrefix)) { 66 // Update the original section contents. 67 ErrorOr<BinarySection &> OrgSection = 68 BC.getUniqueSectionByName(SectionName.substr(OrgSecPrefix.length())); 69 assert(OrgSection && OrgSection->isAllocatable() && 70 "Original section must exist and be allocatable."); 71 72 Section = &OrgSection.get(); 73 Section->updateContents(Ret, Size); 74 } else { 75 // If the input contains a section with the section name, rename it in the 76 // output file to avoid the section name conflict and emit the new section 77 // under a unique internal name. 78 ErrorOr<BinarySection &> OrgSection = 79 BC.getUniqueSectionByName(SectionName); 80 bool UsePrefix = false; 81 if (OrgSection && OrgSection->hasSectionRef()) { 82 OrgSection->setOutputName(OrgSecPrefix + SectionName); 83 UsePrefix = true; 84 } 85 86 // Register the new section under a unique name to avoid name collision with 87 // sections in the input file. 88 BinarySection &NewSection = BC.registerOrUpdateSection( 89 UsePrefix ? NewSecPrefix + SectionName : SectionName, ELF::SHT_PROGBITS, 90 BinarySection::getFlags(IsReadOnly, IsCode, true), Ret, Size, 91 Alignment); 92 if (UsePrefix) 93 NewSection.setOutputName(SectionName); 94 Section = &NewSection; 95 } 96 97 LLVM_DEBUG({ 98 dbgs() << "BOLT: allocating " 99 << (IsCode ? "code" : (IsReadOnly ? "read-only data" : "data")) 100 << " section : " << Section->getOutputName() << " (" 101 << Section->getName() << ")" 102 << " with size " << Size << ", alignment " << Alignment << " at " 103 << Ret << ", ID = " << SectionID << "\n"; 104 }); 105 106 Section->setSectionID(SectionID); 107 108 return Ret; 109 } 110 111 ExecutableFileMemoryManager::~ExecutableFileMemoryManager() { 112 for (const AllocInfo &AI : AllocatedSections) 113 llvm::deallocate_buffer(AI.Address, AI.Size, AI.Alignment); 114 } 115 116 } // namespace bolt 117 118 } // namespace llvm 119