xref: /llvm-project/bolt/lib/Rewrite/ExecutableFileMemoryManager.cpp (revision f3ea4228fd357090e80eb668cc15692150523d0e)
12f09f445SMaksim Panchenko //===- bolt/Rewrite/ExecutableFileMemoryManager.cpp -----------------------===//
2a34c753fSRafael Auler //
3a34c753fSRafael Auler // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a34c753fSRafael Auler // See https://llvm.org/LICENSE.txt for license information.
5a34c753fSRafael Auler // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a34c753fSRafael Auler //
7a34c753fSRafael Auler //===----------------------------------------------------------------------===//
8a34c753fSRafael Auler 
9a34c753fSRafael Auler #include "bolt/Rewrite/ExecutableFileMemoryManager.h"
10a34c753fSRafael Auler #include "bolt/Rewrite/RewriteInstance.h"
111d539352SMaksim Panchenko #include "llvm/Support/MemAlloc.h"
12a34c753fSRafael Auler 
13a34c753fSRafael Auler #undef  DEBUG_TYPE
14a34c753fSRafael Auler #define DEBUG_TYPE "efmm"
15a34c753fSRafael Auler 
16a34c753fSRafael Auler using namespace llvm;
17a34c753fSRafael Auler using namespace object;
18a34c753fSRafael Auler using namespace bolt;
19a34c753fSRafael Auler 
20a34c753fSRafael Auler namespace llvm {
21a34c753fSRafael Auler 
22a34c753fSRafael Auler namespace bolt {
23a34c753fSRafael Auler 
241d539352SMaksim Panchenko uint8_t *ExecutableFileMemoryManager::allocateSection(
251d539352SMaksim Panchenko     uintptr_t Size, unsigned Alignment, unsigned SectionID,
261d539352SMaksim Panchenko     StringRef SectionName, bool IsCode, bool IsReadOnly) {
271d539352SMaksim Panchenko   uint8_t *Ret = static_cast<uint8_t *>(llvm::allocate_buffer(Size, Alignment));
281d539352SMaksim Panchenko   AllocatedSections.push_back(AllocInfo{Ret, Size, Alignment});
291d539352SMaksim Panchenko 
30*f3ea4228SJob Noorman   // A Size of 1 might mean an empty section for which RuntimeDyld decided to
31*f3ea4228SJob Noorman   // allocate 1 byte. In this case, the allocation will never be initialized
32*f3ea4228SJob Noorman   // causing non-deterministic output section contents.
33*f3ea4228SJob Noorman   if (Size == 1)
34*f3ea4228SJob Noorman     *Ret = 0;
35*f3ea4228SJob Noorman 
36a34c753fSRafael Auler   // Register a debug section as a note section.
37a34c753fSRafael Auler   if (!ObjectsLoaded && RewriteInstance::isDebugSection(SectionName)) {
38a34c753fSRafael Auler     BinarySection &Section =
391d539352SMaksim Panchenko         BC.registerOrUpdateNoteSection(SectionName, Ret, Size, Alignment);
40a34c753fSRafael Auler     Section.setSectionID(SectionID);
41a34c753fSRafael Auler     assert(!Section.isAllocatable() && "note sections cannot be allocatable");
421d539352SMaksim Panchenko     return Ret;
43a34c753fSRafael Auler   }
44a34c753fSRafael Auler 
4540c2e0faSMaksim Panchenko   if (!IsCode && (SectionName == ".strtab" || SectionName == ".symtab" ||
46ee0e9ccbSMaksim Panchenko                   SectionName == "" || SectionName.startswith(".rela.")))
471d539352SMaksim Panchenko     return Ret;
48a34c753fSRafael Auler 
49a34c753fSRafael Auler   SmallVector<char, 256> Buf;
50a34c753fSRafael Auler   if (ObjectsLoaded > 0) {
51a34c753fSRafael Auler     if (BC.isELF()) {
52a34c753fSRafael Auler       SectionName = (Twine(SectionName) + ".bolt.extra." + Twine(ObjectsLoaded))
53a34c753fSRafael Auler                         .toStringRef(Buf);
54a34c753fSRafael Auler     } else if (BC.isMachO()) {
55a34c753fSRafael Auler       assert((SectionName == "__text" || SectionName == "__data" ||
56a34c753fSRafael Auler               SectionName == "__fini" || SectionName == "__setup" ||
57a34c753fSRafael Auler               SectionName == "__cstring" || SectionName == "__literal16") &&
58a34c753fSRafael Auler              "Unexpected section in the instrumentation library");
59a34c753fSRafael Auler       // Sections coming from the instrumentation runtime are prefixed with "I".
60a34c753fSRafael Auler       SectionName = ("I" + Twine(SectionName)).toStringRef(Buf);
61a34c753fSRafael Auler     }
62a34c753fSRafael Auler   }
63a34c753fSRafael Auler 
644d3a0cadSMaksim Panchenko   BinarySection *Section = nullptr;
654d3a0cadSMaksim Panchenko   if (!OrgSecPrefix.empty() && SectionName.startswith(OrgSecPrefix)) {
664d3a0cadSMaksim Panchenko     // Update the original section contents.
674d3a0cadSMaksim Panchenko     ErrorOr<BinarySection &> OrgSection =
684d3a0cadSMaksim Panchenko         BC.getUniqueSectionByName(SectionName.substr(OrgSecPrefix.length()));
694d3a0cadSMaksim Panchenko     assert(OrgSection && OrgSection->isAllocatable() &&
704d3a0cadSMaksim Panchenko            "Original section must exist and be allocatable.");
71a34c753fSRafael Auler 
724d3a0cadSMaksim Panchenko     Section = &OrgSection.get();
734d3a0cadSMaksim Panchenko     Section->updateContents(Ret, Size);
744d3a0cadSMaksim Panchenko   } else {
754d3a0cadSMaksim Panchenko     // If the input contains a section with the section name, rename it in the
764d3a0cadSMaksim Panchenko     // output file to avoid the section name conflict and emit the new section
774d3a0cadSMaksim Panchenko     // under a unique internal name.
784d3a0cadSMaksim Panchenko     ErrorOr<BinarySection &> OrgSection =
794d3a0cadSMaksim Panchenko         BC.getUniqueSectionByName(SectionName);
804d3a0cadSMaksim Panchenko     bool UsePrefix = false;
814d3a0cadSMaksim Panchenko     if (OrgSection && OrgSection->hasSectionRef()) {
824d3a0cadSMaksim Panchenko       OrgSection->setOutputName(OrgSecPrefix + SectionName);
834d3a0cadSMaksim Panchenko       UsePrefix = true;
844d3a0cadSMaksim Panchenko     }
854d3a0cadSMaksim Panchenko 
864d3a0cadSMaksim Panchenko     // Register the new section under a unique name to avoid name collision with
874d3a0cadSMaksim Panchenko     // sections in the input file.
884d3a0cadSMaksim Panchenko     BinarySection &NewSection = BC.registerOrUpdateSection(
894d3a0cadSMaksim Panchenko         UsePrefix ? NewSecPrefix + SectionName : SectionName, ELF::SHT_PROGBITS,
904d3a0cadSMaksim Panchenko         BinarySection::getFlags(IsReadOnly, IsCode, true), Ret, Size,
914d3a0cadSMaksim Panchenko         Alignment);
924d3a0cadSMaksim Panchenko     if (UsePrefix)
934d3a0cadSMaksim Panchenko       NewSection.setOutputName(SectionName);
944d3a0cadSMaksim Panchenko     Section = &NewSection;
954d3a0cadSMaksim Panchenko   }
964d3a0cadSMaksim Panchenko 
974d3a0cadSMaksim Panchenko   LLVM_DEBUG({
98a34c753fSRafael Auler     dbgs() << "BOLT: allocating "
99a34c753fSRafael Auler            << (IsCode ? "code" : (IsReadOnly ? "read-only data" : "data"))
1004d3a0cadSMaksim Panchenko            << " section : " << Section->getOutputName() << " ("
1014d3a0cadSMaksim Panchenko            << Section->getName() << ")"
1024d3a0cadSMaksim Panchenko            << " with size " << Size << ", alignment " << Alignment << " at "
1034d3a0cadSMaksim Panchenko            << Ret << ", ID = " << SectionID << "\n";
1044d3a0cadSMaksim Panchenko   });
1054d3a0cadSMaksim Panchenko 
1064d3a0cadSMaksim Panchenko   Section->setSectionID(SectionID);
1074d3a0cadSMaksim Panchenko 
108a34c753fSRafael Auler   return Ret;
109a34c753fSRafael Auler }
110a34c753fSRafael Auler 
1111d539352SMaksim Panchenko ExecutableFileMemoryManager::~ExecutableFileMemoryManager() {
1121d539352SMaksim Panchenko   for (const AllocInfo &AI : AllocatedSections)
1131d539352SMaksim Panchenko     llvm::deallocate_buffer(AI.Address, AI.Size, AI.Alignment);
114a34c753fSRafael Auler }
115a34c753fSRafael Auler 
11640c2e0faSMaksim Panchenko } // namespace bolt
117a34c753fSRafael Auler 
11840c2e0faSMaksim Panchenko } // namespace llvm
119