xref: /llvm-project/bolt/lib/Rewrite/ExecutableFileMemoryManager.cpp (revision f3ea4228fd357090e80eb668cc15692150523d0e)
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