xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp (revision 753f127f3ace09432b2baeffd71a308760641a62)
1*753f127fSDimitry Andric //=--------- COFFLinkGraphBuilder.cpp - COFF LinkGraph builder ----------===//
2*753f127fSDimitry Andric //
3*753f127fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*753f127fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*753f127fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*753f127fSDimitry Andric //
7*753f127fSDimitry Andric //===----------------------------------------------------------------------===//
8*753f127fSDimitry Andric //
9*753f127fSDimitry Andric // Generic COFF LinkGraph buliding code.
10*753f127fSDimitry Andric //
11*753f127fSDimitry Andric //===----------------------------------------------------------------------===//
12*753f127fSDimitry Andric #include "COFFLinkGraphBuilder.h"
13*753f127fSDimitry Andric 
14*753f127fSDimitry Andric #define DEBUG_TYPE "jitlink"
15*753f127fSDimitry Andric 
16*753f127fSDimitry Andric static const char *CommonSectionName = "__common";
17*753f127fSDimitry Andric 
18*753f127fSDimitry Andric namespace llvm {
19*753f127fSDimitry Andric namespace jitlink {
20*753f127fSDimitry Andric 
21*753f127fSDimitry Andric COFFLinkGraphBuilder::COFFLinkGraphBuilder(
22*753f127fSDimitry Andric     const object::COFFObjectFile &Obj, Triple TT,
23*753f127fSDimitry Andric     LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
24*753f127fSDimitry Andric     : Obj(Obj),
25*753f127fSDimitry Andric       G(std::make_unique<LinkGraph>(
26*753f127fSDimitry Andric           Obj.getFileName().str(), Triple(std::move(TT)), getPointerSize(Obj),
27*753f127fSDimitry Andric           getEndianness(Obj), std::move(GetEdgeKindName))) {
28*753f127fSDimitry Andric   LLVM_DEBUG({
29*753f127fSDimitry Andric     dbgs() << "Created COFFLinkGraphBuilder for \"" << Obj.getFileName()
30*753f127fSDimitry Andric            << "\"\n";
31*753f127fSDimitry Andric   });
32*753f127fSDimitry Andric }
33*753f127fSDimitry Andric 
34*753f127fSDimitry Andric COFFLinkGraphBuilder::~COFFLinkGraphBuilder() = default;
35*753f127fSDimitry Andric 
36*753f127fSDimitry Andric unsigned
37*753f127fSDimitry Andric COFFLinkGraphBuilder::getPointerSize(const object::COFFObjectFile &Obj) {
38*753f127fSDimitry Andric   return Obj.getBytesInAddress();
39*753f127fSDimitry Andric }
40*753f127fSDimitry Andric 
41*753f127fSDimitry Andric support::endianness
42*753f127fSDimitry Andric COFFLinkGraphBuilder::getEndianness(const object::COFFObjectFile &Obj) {
43*753f127fSDimitry Andric   return Obj.isLittleEndian() ? support::little : support::big;
44*753f127fSDimitry Andric }
45*753f127fSDimitry Andric 
46*753f127fSDimitry Andric uint64_t COFFLinkGraphBuilder::getSectionSize(const object::COFFObjectFile &Obj,
47*753f127fSDimitry Andric                                               const object::coff_section *Sec) {
48*753f127fSDimitry Andric   // Consider the difference between executable form and object form.
49*753f127fSDimitry Andric   // More information is inside COFFObjectFile::getSectionSize
50*753f127fSDimitry Andric   if (Obj.getDOSHeader())
51*753f127fSDimitry Andric     return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
52*753f127fSDimitry Andric   return Sec->SizeOfRawData;
53*753f127fSDimitry Andric }
54*753f127fSDimitry Andric 
55*753f127fSDimitry Andric uint64_t
56*753f127fSDimitry Andric COFFLinkGraphBuilder::getSectionAddress(const object::COFFObjectFile &Obj,
57*753f127fSDimitry Andric                                         const object::coff_section *Section) {
58*753f127fSDimitry Andric   return Section->VirtualAddress + Obj.getImageBase();
59*753f127fSDimitry Andric }
60*753f127fSDimitry Andric 
61*753f127fSDimitry Andric bool COFFLinkGraphBuilder::isComdatSection(
62*753f127fSDimitry Andric     const object::coff_section *Section) {
63*753f127fSDimitry Andric   return Section->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT;
64*753f127fSDimitry Andric }
65*753f127fSDimitry Andric 
66*753f127fSDimitry Andric Section &COFFLinkGraphBuilder::getCommonSection() {
67*753f127fSDimitry Andric   if (!CommonSection)
68*753f127fSDimitry Andric     CommonSection =
69*753f127fSDimitry Andric         &G->createSection(CommonSectionName, MemProt::Read | MemProt::Write);
70*753f127fSDimitry Andric   return *CommonSection;
71*753f127fSDimitry Andric }
72*753f127fSDimitry Andric 
73*753f127fSDimitry Andric Expected<std::unique_ptr<LinkGraph>> COFFLinkGraphBuilder::buildGraph() {
74*753f127fSDimitry Andric   if (!Obj.isRelocatableObject())
75*753f127fSDimitry Andric     return make_error<JITLinkError>("Object is not a relocatable COFF file");
76*753f127fSDimitry Andric 
77*753f127fSDimitry Andric   if (auto Err = graphifySections())
78*753f127fSDimitry Andric     return std::move(Err);
79*753f127fSDimitry Andric 
80*753f127fSDimitry Andric   if (auto Err = graphifySymbols())
81*753f127fSDimitry Andric     return std::move(Err);
82*753f127fSDimitry Andric 
83*753f127fSDimitry Andric   if (auto Err = addRelocations())
84*753f127fSDimitry Andric     return std::move(Err);
85*753f127fSDimitry Andric 
86*753f127fSDimitry Andric   return std::move(G);
87*753f127fSDimitry Andric }
88*753f127fSDimitry Andric 
89*753f127fSDimitry Andric StringRef
90*753f127fSDimitry Andric COFFLinkGraphBuilder::getCOFFSectionName(COFFSectionIndex SectionIndex,
91*753f127fSDimitry Andric                                          const object::coff_section *Sec,
92*753f127fSDimitry Andric                                          object::COFFSymbolRef Sym) {
93*753f127fSDimitry Andric   switch (SectionIndex) {
94*753f127fSDimitry Andric   case COFF::IMAGE_SYM_UNDEFINED: {
95*753f127fSDimitry Andric     if (Sym.getValue())
96*753f127fSDimitry Andric       return "(common)";
97*753f127fSDimitry Andric     else
98*753f127fSDimitry Andric       return "(external)";
99*753f127fSDimitry Andric   }
100*753f127fSDimitry Andric   case COFF::IMAGE_SYM_ABSOLUTE:
101*753f127fSDimitry Andric     return "(absolute)";
102*753f127fSDimitry Andric   case COFF::IMAGE_SYM_DEBUG: {
103*753f127fSDimitry Andric     // Used with .file symbol
104*753f127fSDimitry Andric     return "(debug)";
105*753f127fSDimitry Andric   }
106*753f127fSDimitry Andric   default: {
107*753f127fSDimitry Andric     // Non reserved regular section numbers
108*753f127fSDimitry Andric     if (Expected<StringRef> SecNameOrErr = Obj.getSectionName(Sec))
109*753f127fSDimitry Andric       return *SecNameOrErr;
110*753f127fSDimitry Andric   }
111*753f127fSDimitry Andric   }
112*753f127fSDimitry Andric   return "";
113*753f127fSDimitry Andric }
114*753f127fSDimitry Andric 
115*753f127fSDimitry Andric Error COFFLinkGraphBuilder::graphifySections() {
116*753f127fSDimitry Andric   LLVM_DEBUG(dbgs() << "  Creating graph sections...\n");
117*753f127fSDimitry Andric 
118*753f127fSDimitry Andric   GraphBlocks.resize(Obj.getNumberOfSections() + 1);
119*753f127fSDimitry Andric   // For each section...
120*753f127fSDimitry Andric   for (COFFSectionIndex SecIndex = 1;
121*753f127fSDimitry Andric        SecIndex <= static_cast<COFFSectionIndex>(Obj.getNumberOfSections());
122*753f127fSDimitry Andric        SecIndex++) {
123*753f127fSDimitry Andric     Expected<const object::coff_section *> Sec = Obj.getSection(SecIndex);
124*753f127fSDimitry Andric     if (!Sec)
125*753f127fSDimitry Andric       return Sec.takeError();
126*753f127fSDimitry Andric 
127*753f127fSDimitry Andric     StringRef SectionName;
128*753f127fSDimitry Andric     if (Expected<StringRef> SecNameOrErr = Obj.getSectionName(*Sec))
129*753f127fSDimitry Andric       SectionName = *SecNameOrErr;
130*753f127fSDimitry Andric 
131*753f127fSDimitry Andric     bool IsDiscardable =
132*753f127fSDimitry Andric         (*Sec)->Characteristics &
133*753f127fSDimitry Andric         (COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_LNK_INFO);
134*753f127fSDimitry Andric     if (IsDiscardable) {
135*753f127fSDimitry Andric       LLVM_DEBUG(dbgs() << "    " << SecIndex << ": \"" << SectionName
136*753f127fSDimitry Andric                         << "\" is discardable: "
137*753f127fSDimitry Andric                            "No graph section will be created.\n");
138*753f127fSDimitry Andric       continue;
139*753f127fSDimitry Andric     }
140*753f127fSDimitry Andric 
141*753f127fSDimitry Andric     // FIXME: Skip debug info sections
142*753f127fSDimitry Andric 
143*753f127fSDimitry Andric     LLVM_DEBUG({
144*753f127fSDimitry Andric       dbgs() << "    "
145*753f127fSDimitry Andric              << "Creating section for \"" << SectionName << "\"\n";
146*753f127fSDimitry Andric     });
147*753f127fSDimitry Andric 
148*753f127fSDimitry Andric     // Get the section's memory protection flags.
149*753f127fSDimitry Andric     MemProt Prot = MemProt::None;
150*753f127fSDimitry Andric     if ((*Sec)->Characteristics & COFF::IMAGE_SCN_MEM_EXECUTE)
151*753f127fSDimitry Andric       Prot |= MemProt::Exec;
152*753f127fSDimitry Andric     if ((*Sec)->Characteristics & COFF::IMAGE_SCN_MEM_READ)
153*753f127fSDimitry Andric       Prot |= MemProt::Read;
154*753f127fSDimitry Andric     if ((*Sec)->Characteristics & COFF::IMAGE_SCN_MEM_WRITE)
155*753f127fSDimitry Andric       Prot |= MemProt::Write;
156*753f127fSDimitry Andric 
157*753f127fSDimitry Andric     // Look for existing sections first.
158*753f127fSDimitry Andric     auto *GraphSec = G->findSectionByName(SectionName);
159*753f127fSDimitry Andric     if (!GraphSec)
160*753f127fSDimitry Andric       GraphSec = &G->createSection(SectionName, Prot);
161*753f127fSDimitry Andric     if (GraphSec->getMemProt() != Prot)
162*753f127fSDimitry Andric       return make_error<JITLinkError>("MemProt should match");
163*753f127fSDimitry Andric 
164*753f127fSDimitry Andric     Block *B = nullptr;
165*753f127fSDimitry Andric     if ((*Sec)->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
166*753f127fSDimitry Andric       B = &G->createZeroFillBlock(
167*753f127fSDimitry Andric           *GraphSec, getSectionSize(Obj, *Sec),
168*753f127fSDimitry Andric           orc::ExecutorAddr(getSectionAddress(Obj, *Sec)),
169*753f127fSDimitry Andric           (*Sec)->getAlignment(), 0);
170*753f127fSDimitry Andric     else {
171*753f127fSDimitry Andric       ArrayRef<uint8_t> Data;
172*753f127fSDimitry Andric       if (auto Err = Obj.getSectionContents(*Sec, Data))
173*753f127fSDimitry Andric         return Err;
174*753f127fSDimitry Andric 
175*753f127fSDimitry Andric       B = &G->createContentBlock(
176*753f127fSDimitry Andric           *GraphSec,
177*753f127fSDimitry Andric           ArrayRef<char>(reinterpret_cast<const char *>(Data.data()),
178*753f127fSDimitry Andric                          Data.size()),
179*753f127fSDimitry Andric           orc::ExecutorAddr(getSectionAddress(Obj, *Sec)),
180*753f127fSDimitry Andric           (*Sec)->getAlignment(), 0);
181*753f127fSDimitry Andric     }
182*753f127fSDimitry Andric 
183*753f127fSDimitry Andric     setGraphBlock(SecIndex, B);
184*753f127fSDimitry Andric   }
185*753f127fSDimitry Andric 
186*753f127fSDimitry Andric   return Error::success();
187*753f127fSDimitry Andric }
188*753f127fSDimitry Andric 
189*753f127fSDimitry Andric Error COFFLinkGraphBuilder::graphifySymbols() {
190*753f127fSDimitry Andric   LLVM_DEBUG(dbgs() << "  Creating graph symbols...\n");
191*753f127fSDimitry Andric 
192*753f127fSDimitry Andric   SymbolSets.resize(Obj.getNumberOfSections() + 1);
193*753f127fSDimitry Andric   GraphSymbols.resize(Obj.getNumberOfSymbols());
194*753f127fSDimitry Andric 
195*753f127fSDimitry Andric   for (COFFSymbolIndex SymIndex = 0;
196*753f127fSDimitry Andric        SymIndex < static_cast<COFFSymbolIndex>(Obj.getNumberOfSymbols());
197*753f127fSDimitry Andric        SymIndex++) {
198*753f127fSDimitry Andric     Expected<object::COFFSymbolRef> Sym = Obj.getSymbol(SymIndex);
199*753f127fSDimitry Andric     if (!Sym)
200*753f127fSDimitry Andric       return Sym.takeError();
201*753f127fSDimitry Andric 
202*753f127fSDimitry Andric     StringRef SymbolName;
203*753f127fSDimitry Andric     if (Expected<StringRef> SymNameOrErr = Obj.getSymbolName(*Sym))
204*753f127fSDimitry Andric       SymbolName = *SymNameOrErr;
205*753f127fSDimitry Andric 
206*753f127fSDimitry Andric     COFFSectionIndex SectionIndex = Sym->getSectionNumber();
207*753f127fSDimitry Andric     const object::coff_section *Sec = nullptr;
208*753f127fSDimitry Andric 
209*753f127fSDimitry Andric     if (!COFF::isReservedSectionNumber(SectionIndex)) {
210*753f127fSDimitry Andric       auto SecOrErr = Obj.getSection(SectionIndex);
211*753f127fSDimitry Andric       if (!SecOrErr)
212*753f127fSDimitry Andric         return make_error<JITLinkError>(
213*753f127fSDimitry Andric             "Invalid COFF section number:" + formatv("{0:d}: ", SectionIndex) +
214*753f127fSDimitry Andric             " (" + toString(SecOrErr.takeError()) + ")");
215*753f127fSDimitry Andric       Sec = *SecOrErr;
216*753f127fSDimitry Andric     }
217*753f127fSDimitry Andric 
218*753f127fSDimitry Andric     // Create jitlink symbol
219*753f127fSDimitry Andric     jitlink::Symbol *GSym = nullptr;
220*753f127fSDimitry Andric     if (Sym->isFileRecord())
221*753f127fSDimitry Andric       LLVM_DEBUG({
222*753f127fSDimitry Andric         dbgs() << "    " << SymIndex << ": Skipping FileRecord symbol \""
223*753f127fSDimitry Andric                << SymbolName << "\" in "
224*753f127fSDimitry Andric                << getCOFFSectionName(SectionIndex, Sec, *Sym)
225*753f127fSDimitry Andric                << " (index: " << SectionIndex << ") \n";
226*753f127fSDimitry Andric       });
227*753f127fSDimitry Andric     else if (Sym->isUndefined()) {
228*753f127fSDimitry Andric       LLVM_DEBUG({
229*753f127fSDimitry Andric         dbgs() << "    " << SymIndex
230*753f127fSDimitry Andric                << ": Creating external graph symbol for COFF symbol \""
231*753f127fSDimitry Andric                << SymbolName << "\" in "
232*753f127fSDimitry Andric                << getCOFFSectionName(SectionIndex, Sec, *Sym)
233*753f127fSDimitry Andric                << " (index: " << SectionIndex << ") \n";
234*753f127fSDimitry Andric       });
235*753f127fSDimitry Andric       GSym =
236*753f127fSDimitry Andric           &G->addExternalSymbol(SymbolName, Sym->getValue(), Linkage::Strong);
237*753f127fSDimitry Andric     } else if (Sym->isWeakExternal()) {
238*753f127fSDimitry Andric       COFFSymbolIndex TagIndex =
239*753f127fSDimitry Andric           Sym->getAux<object::coff_aux_weak_external>()->TagIndex;
240*753f127fSDimitry Andric       assert(Sym->getAux<object::coff_aux_weak_external>()->Characteristics !=
241*753f127fSDimitry Andric                  COFF::IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY &&
242*753f127fSDimitry Andric              "IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY is not supported.");
243*753f127fSDimitry Andric       assert(Sym->getAux<object::coff_aux_weak_external>()->Characteristics !=
244*753f127fSDimitry Andric                  COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY &&
245*753f127fSDimitry Andric              "IMAGE_WEAK_EXTERN_SEARCH_LIBRARY is not supported.");
246*753f127fSDimitry Andric       WeakAliasRequests.push_back({SymIndex, TagIndex, SymbolName});
247*753f127fSDimitry Andric     } else {
248*753f127fSDimitry Andric       Expected<jitlink::Symbol *> NewGSym =
249*753f127fSDimitry Andric           createDefinedSymbol(SymIndex, SymbolName, *Sym, Sec);
250*753f127fSDimitry Andric       if (!NewGSym)
251*753f127fSDimitry Andric         return NewGSym.takeError();
252*753f127fSDimitry Andric       GSym = *NewGSym;
253*753f127fSDimitry Andric       if (GSym) {
254*753f127fSDimitry Andric         LLVM_DEBUG({
255*753f127fSDimitry Andric           dbgs() << "    " << SymIndex
256*753f127fSDimitry Andric                  << ": Creating defined graph symbol for COFF symbol \""
257*753f127fSDimitry Andric                  << SymbolName << "\" in "
258*753f127fSDimitry Andric                  << getCOFFSectionName(SectionIndex, Sec, *Sym)
259*753f127fSDimitry Andric                  << " (index: " << SectionIndex << ") \n";
260*753f127fSDimitry Andric           dbgs() << "      " << *GSym << "\n";
261*753f127fSDimitry Andric         });
262*753f127fSDimitry Andric       }
263*753f127fSDimitry Andric     }
264*753f127fSDimitry Andric 
265*753f127fSDimitry Andric     // Register the symbol
266*753f127fSDimitry Andric     if (GSym)
267*753f127fSDimitry Andric       setGraphSymbol(SectionIndex, SymIndex, *GSym);
268*753f127fSDimitry Andric     SymIndex += Sym->getNumberOfAuxSymbols();
269*753f127fSDimitry Andric   }
270*753f127fSDimitry Andric 
271*753f127fSDimitry Andric   if (auto Err = flushWeakAliasRequests())
272*753f127fSDimitry Andric     return Err;
273*753f127fSDimitry Andric 
274*753f127fSDimitry Andric   if (auto Err = calculateImplicitSizeOfSymbols())
275*753f127fSDimitry Andric     return Err;
276*753f127fSDimitry Andric 
277*753f127fSDimitry Andric   return Error::success();
278*753f127fSDimitry Andric }
279*753f127fSDimitry Andric 
280*753f127fSDimitry Andric Error COFFLinkGraphBuilder::flushWeakAliasRequests() {
281*753f127fSDimitry Andric   // Export the weak external symbols and alias it
282*753f127fSDimitry Andric   for (auto &WeakAlias : WeakAliasRequests) {
283*753f127fSDimitry Andric     if (auto *Target = getGraphSymbol(WeakAlias.Target)) {
284*753f127fSDimitry Andric       Expected<object::COFFSymbolRef> AliasSymbol =
285*753f127fSDimitry Andric           Obj.getSymbol(WeakAlias.Alias);
286*753f127fSDimitry Andric       if (!AliasSymbol)
287*753f127fSDimitry Andric         return AliasSymbol.takeError();
288*753f127fSDimitry Andric 
289*753f127fSDimitry Andric       // FIXME: Support this when there's a way to handle this.
290*753f127fSDimitry Andric       if (!Target->isDefined())
291*753f127fSDimitry Andric         return make_error<JITLinkError>("Weak external symbol with external "
292*753f127fSDimitry Andric                                         "symbol as alternative not supported.");
293*753f127fSDimitry Andric 
294*753f127fSDimitry Andric       jitlink::Symbol *NewSymbol = &G->addDefinedSymbol(
295*753f127fSDimitry Andric           Target->getBlock(), Target->getOffset(), WeakAlias.SymbolName,
296*753f127fSDimitry Andric           Target->getSize(), Linkage::Weak, Scope::Default,
297*753f127fSDimitry Andric           Target->isCallable(), false);
298*753f127fSDimitry Andric       setGraphSymbol(AliasSymbol->getSectionNumber(), WeakAlias.Alias,
299*753f127fSDimitry Andric                      *NewSymbol);
300*753f127fSDimitry Andric       LLVM_DEBUG({
301*753f127fSDimitry Andric         dbgs() << "    " << WeakAlias.Alias
302*753f127fSDimitry Andric                << ": Creating weak external symbol for COFF symbol \""
303*753f127fSDimitry Andric                << WeakAlias.SymbolName << "\" in section "
304*753f127fSDimitry Andric                << AliasSymbol->getSectionNumber() << "\n";
305*753f127fSDimitry Andric         dbgs() << "      " << *NewSymbol << "\n";
306*753f127fSDimitry Andric       });
307*753f127fSDimitry Andric     } else
308*753f127fSDimitry Andric       return make_error<JITLinkError>("Weak symbol alias requested but actual "
309*753f127fSDimitry Andric                                       "symbol not found for symbol " +
310*753f127fSDimitry Andric                                       formatv("{0:d}", WeakAlias.Alias));
311*753f127fSDimitry Andric   }
312*753f127fSDimitry Andric   return Error::success();
313*753f127fSDimitry Andric }
314*753f127fSDimitry Andric 
315*753f127fSDimitry Andric // In COFF, most of the defined symbols don't contain the size information.
316*753f127fSDimitry Andric // Hence, we calculate the "implicit" size of symbol by taking the delta of
317*753f127fSDimitry Andric // offsets of consecutive symbols within a block. We maintain a balanced tree
318*753f127fSDimitry Andric // set of symbols sorted by offset per each block in order to achieve
319*753f127fSDimitry Andric // logarithmic time complexity of sorted symbol insertion. Symbol is inserted to
320*753f127fSDimitry Andric // the set once it's processed in graphifySymbols. In this function, we iterate
321*753f127fSDimitry Andric // each collected symbol in sorted order and calculate the implicit size.
322*753f127fSDimitry Andric Error COFFLinkGraphBuilder::calculateImplicitSizeOfSymbols() {
323*753f127fSDimitry Andric   for (COFFSectionIndex SecIndex = 1;
324*753f127fSDimitry Andric        SecIndex <= static_cast<COFFSectionIndex>(Obj.getNumberOfSections());
325*753f127fSDimitry Andric        SecIndex++) {
326*753f127fSDimitry Andric     auto &SymbolSet = SymbolSets[SecIndex];
327*753f127fSDimitry Andric     jitlink::Block *B = getGraphBlock(SecIndex);
328*753f127fSDimitry Andric     orc::ExecutorAddrDiff LastOffset = B->getSize();
329*753f127fSDimitry Andric     orc::ExecutorAddrDiff LastDifferentOffset = B->getSize();
330*753f127fSDimitry Andric     orc::ExecutorAddrDiff LastSize = 0;
331*753f127fSDimitry Andric     for (auto It = SymbolSet.rbegin(); It != SymbolSet.rend(); It++) {
332*753f127fSDimitry Andric       orc::ExecutorAddrDiff Offset = It->first;
333*753f127fSDimitry Andric       jitlink::Symbol *Symbol = It->second;
334*753f127fSDimitry Andric       orc::ExecutorAddrDiff CandSize;
335*753f127fSDimitry Andric       // Last offset can be same when aliasing happened
336*753f127fSDimitry Andric       if (Symbol->getOffset() == LastOffset)
337*753f127fSDimitry Andric         CandSize = LastSize;
338*753f127fSDimitry Andric       else
339*753f127fSDimitry Andric         CandSize = LastOffset - Offset;
340*753f127fSDimitry Andric 
341*753f127fSDimitry Andric       LLVM_DEBUG({
342*753f127fSDimitry Andric         if (Offset + Symbol->getSize() > LastDifferentOffset)
343*753f127fSDimitry Andric           dbgs() << "  Overlapping symbol range generated for the following "
344*753f127fSDimitry Andric                     "symbol:"
345*753f127fSDimitry Andric                  << "\n"
346*753f127fSDimitry Andric                  << "    " << *Symbol << "\n";
347*753f127fSDimitry Andric       });
348*753f127fSDimitry Andric       (void)LastDifferentOffset;
349*753f127fSDimitry Andric       if (LastOffset != Offset)
350*753f127fSDimitry Andric         LastDifferentOffset = Offset;
351*753f127fSDimitry Andric       LastSize = CandSize;
352*753f127fSDimitry Andric       LastOffset = Offset;
353*753f127fSDimitry Andric       if (Symbol->getSize()) {
354*753f127fSDimitry Andric         // Non empty symbol can happen in COMDAT symbol.
355*753f127fSDimitry Andric         // We don't consider the possibility of overlapping symbol range that
356*753f127fSDimitry Andric         // could be introduced by disparity between inferred symbol size and
357*753f127fSDimitry Andric         // defined symbol size because symbol size information is currently only
358*753f127fSDimitry Andric         // used by jitlink-check where we have control to not make overlapping
359*753f127fSDimitry Andric         // ranges.
360*753f127fSDimitry Andric         continue;
361*753f127fSDimitry Andric       }
362*753f127fSDimitry Andric 
363*753f127fSDimitry Andric       LLVM_DEBUG({
364*753f127fSDimitry Andric         if (!CandSize)
365*753f127fSDimitry Andric           dbgs() << "  Empty implicit symbol size generated for the following "
366*753f127fSDimitry Andric                     "symbol:"
367*753f127fSDimitry Andric                  << "\n"
368*753f127fSDimitry Andric                  << "    " << *Symbol << "\n";
369*753f127fSDimitry Andric       });
370*753f127fSDimitry Andric 
371*753f127fSDimitry Andric       Symbol->setSize(CandSize);
372*753f127fSDimitry Andric     }
373*753f127fSDimitry Andric   }
374*753f127fSDimitry Andric   return Error::success();
375*753f127fSDimitry Andric }
376*753f127fSDimitry Andric 
377*753f127fSDimitry Andric Expected<Symbol *> COFFLinkGraphBuilder::createDefinedSymbol(
378*753f127fSDimitry Andric     COFFSymbolIndex SymIndex, StringRef SymbolName,
379*753f127fSDimitry Andric     object::COFFSymbolRef Symbol, const object::coff_section *Section) {
380*753f127fSDimitry Andric   if (Symbol.isCommon()) {
381*753f127fSDimitry Andric     // FIXME: correct alignment
382*753f127fSDimitry Andric     return &G->addCommonSymbol(SymbolName, Scope::Default, getCommonSection(),
383*753f127fSDimitry Andric                                orc::ExecutorAddr(), Symbol.getValue(),
384*753f127fSDimitry Andric                                Symbol.getValue(), false);
385*753f127fSDimitry Andric   }
386*753f127fSDimitry Andric   if (Symbol.isAbsolute())
387*753f127fSDimitry Andric     return &G->addAbsoluteSymbol(SymbolName,
388*753f127fSDimitry Andric                                  orc::ExecutorAddr(Symbol.getValue()), 0,
389*753f127fSDimitry Andric                                  Linkage::Strong, Scope::Local, false);
390*753f127fSDimitry Andric 
391*753f127fSDimitry Andric   if (llvm::COFF::isReservedSectionNumber(Symbol.getSectionNumber()))
392*753f127fSDimitry Andric     return make_error<JITLinkError>(
393*753f127fSDimitry Andric         "Reserved section number used in regular symbol " +
394*753f127fSDimitry Andric         formatv("{0:d}", SymIndex));
395*753f127fSDimitry Andric 
396*753f127fSDimitry Andric   Block *B = getGraphBlock(Symbol.getSectionNumber());
397*753f127fSDimitry Andric   if (Symbol.isExternal()) {
398*753f127fSDimitry Andric     // This is not a comdat sequence, export the symbol as it is
399*753f127fSDimitry Andric     if (!isComdatSection(Section))
400*753f127fSDimitry Andric       return &G->addDefinedSymbol(
401*753f127fSDimitry Andric           *B, Symbol.getValue(), SymbolName, 0, Linkage::Strong, Scope::Default,
402*753f127fSDimitry Andric           Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION, false);
403*753f127fSDimitry Andric     else {
404*753f127fSDimitry Andric       if (!PendingComdatExport)
405*753f127fSDimitry Andric         return make_error<JITLinkError>("No pending COMDAT export for symbol " +
406*753f127fSDimitry Andric                                         formatv("{0:d}", SymIndex));
407*753f127fSDimitry Andric       if (PendingComdatExport->SectionIndex != Symbol.getSectionNumber())
408*753f127fSDimitry Andric         return make_error<JITLinkError>(
409*753f127fSDimitry Andric             "COMDAT export section number mismatch for symbol " +
410*753f127fSDimitry Andric             formatv("{0:d}", SymIndex));
411*753f127fSDimitry Andric       return exportCOMDATSymbol(SymIndex, SymbolName, Symbol);
412*753f127fSDimitry Andric     }
413*753f127fSDimitry Andric   }
414*753f127fSDimitry Andric 
415*753f127fSDimitry Andric   if (Symbol.getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC) {
416*753f127fSDimitry Andric     const object::coff_aux_section_definition *Definition =
417*753f127fSDimitry Andric         Symbol.getSectionDefinition();
418*753f127fSDimitry Andric     if (!Definition || !isComdatSection(Section)) {
419*753f127fSDimitry Andric       // Handle typical static symbol
420*753f127fSDimitry Andric       return &G->addDefinedSymbol(
421*753f127fSDimitry Andric           *B, Symbol.getValue(), SymbolName, 0, Linkage::Strong, Scope::Local,
422*753f127fSDimitry Andric           Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION, false);
423*753f127fSDimitry Andric     }
424*753f127fSDimitry Andric     if (Definition->Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
425*753f127fSDimitry Andric       // FIXME: don't dead strip this when parent section is alive
426*753f127fSDimitry Andric       return &G->addDefinedSymbol(
427*753f127fSDimitry Andric           *B, Symbol.getValue(), SymbolName, 0, Linkage::Strong, Scope::Local,
428*753f127fSDimitry Andric           Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION, false);
429*753f127fSDimitry Andric     }
430*753f127fSDimitry Andric     if (PendingComdatExport)
431*753f127fSDimitry Andric       return make_error<JITLinkError>(
432*753f127fSDimitry Andric           "COMDAT export request already exists before symbol " +
433*753f127fSDimitry Andric           formatv("{0:d}", SymIndex));
434*753f127fSDimitry Andric     return createCOMDATExportRequest(SymIndex, Symbol, Definition);
435*753f127fSDimitry Andric   }
436*753f127fSDimitry Andric   return make_error<JITLinkError>("Unsupported storage class " +
437*753f127fSDimitry Andric                                   formatv("{0:d}", Symbol.getStorageClass()) +
438*753f127fSDimitry Andric                                   " in symbol " + formatv("{0:d}", SymIndex));
439*753f127fSDimitry Andric }
440*753f127fSDimitry Andric 
441*753f127fSDimitry Andric // COMDAT handling:
442*753f127fSDimitry Andric // When IMAGE_SCN_LNK_COMDAT flag is set in the flags of a section,
443*753f127fSDimitry Andric // the section is called a COMDAT section. It contains two symbols
444*753f127fSDimitry Andric // in a sequence that specifes the behavior. First symbol is the section
445*753f127fSDimitry Andric // symbol which contains the size and name of the section. It also contains
446*753f127fSDimitry Andric // selection type that specifies how duplicate of the symbol is handled.
447*753f127fSDimitry Andric // Second symbol is COMDAT symbol which usually defines the external name and
448*753f127fSDimitry Andric // data type.
449*753f127fSDimitry Andric //
450*753f127fSDimitry Andric // Since two symbols always come in a specific order, we initiate pending COMDAT
451*753f127fSDimitry Andric // export request when we encounter the first symbol and actually exports it
452*753f127fSDimitry Andric // when we process the second symbol.
453*753f127fSDimitry Andric //
454*753f127fSDimitry Andric // Process the first symbol of COMDAT sequence.
455*753f127fSDimitry Andric Expected<Symbol *> COFFLinkGraphBuilder::createCOMDATExportRequest(
456*753f127fSDimitry Andric     COFFSymbolIndex SymIndex, object::COFFSymbolRef Symbol,
457*753f127fSDimitry Andric     const object::coff_aux_section_definition *Definition) {
458*753f127fSDimitry Andric   Block *B = getGraphBlock(Symbol.getSectionNumber());
459*753f127fSDimitry Andric   Linkage L = Linkage::Strong;
460*753f127fSDimitry Andric   switch (Definition->Selection) {
461*753f127fSDimitry Andric   case COFF::IMAGE_COMDAT_SELECT_NODUPLICATES: {
462*753f127fSDimitry Andric     L = Linkage::Strong;
463*753f127fSDimitry Andric     break;
464*753f127fSDimitry Andric   }
465*753f127fSDimitry Andric   case COFF::IMAGE_COMDAT_SELECT_ANY: {
466*753f127fSDimitry Andric     L = Linkage::Weak;
467*753f127fSDimitry Andric     break;
468*753f127fSDimitry Andric   }
469*753f127fSDimitry Andric   case COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH:
470*753f127fSDimitry Andric   case COFF::IMAGE_COMDAT_SELECT_SAME_SIZE: {
471*753f127fSDimitry Andric     // FIXME: Implement size/content validation when LinkGraph is able to
472*753f127fSDimitry Andric     // handle this.
473*753f127fSDimitry Andric     L = Linkage::Weak;
474*753f127fSDimitry Andric     break;
475*753f127fSDimitry Andric   }
476*753f127fSDimitry Andric   case COFF::IMAGE_COMDAT_SELECT_LARGEST: {
477*753f127fSDimitry Andric     // FIXME: Support IMAGE_COMDAT_SELECT_LARGEST when LinkGraph is able to
478*753f127fSDimitry Andric     // handle this.
479*753f127fSDimitry Andric     return make_error<JITLinkError>(
480*753f127fSDimitry Andric         "IMAGE_COMDAT_SELECT_LARGEST is not supported.");
481*753f127fSDimitry Andric   }
482*753f127fSDimitry Andric   case COFF::IMAGE_COMDAT_SELECT_NEWEST: {
483*753f127fSDimitry Andric     // Even link.exe doesn't support this selection properly.
484*753f127fSDimitry Andric     return make_error<JITLinkError>(
485*753f127fSDimitry Andric         "IMAGE_COMDAT_SELECT_NEWEST is not supported.");
486*753f127fSDimitry Andric   }
487*753f127fSDimitry Andric   default: {
488*753f127fSDimitry Andric     return make_error<JITLinkError>("Invalid comdat selection type: " +
489*753f127fSDimitry Andric                                     formatv("{0:d}", Definition->Selection));
490*753f127fSDimitry Andric   }
491*753f127fSDimitry Andric   }
492*753f127fSDimitry Andric   PendingComdatExport = {SymIndex, Symbol.getSectionNumber(), L};
493*753f127fSDimitry Andric   return &G->addAnonymousSymbol(*B, Symbol.getValue(), Definition->Length,
494*753f127fSDimitry Andric                                 false, false);
495*753f127fSDimitry Andric }
496*753f127fSDimitry Andric 
497*753f127fSDimitry Andric // Process the second symbol of COMDAT sequence.
498*753f127fSDimitry Andric Expected<Symbol *>
499*753f127fSDimitry Andric COFFLinkGraphBuilder::exportCOMDATSymbol(COFFSymbolIndex SymIndex,
500*753f127fSDimitry Andric                                          StringRef SymbolName,
501*753f127fSDimitry Andric                                          object::COFFSymbolRef Symbol) {
502*753f127fSDimitry Andric   COFFSymbolIndex TargetIndex = PendingComdatExport->SymbolIndex;
503*753f127fSDimitry Andric   Linkage L = PendingComdatExport->Linkage;
504*753f127fSDimitry Andric   jitlink::Symbol *Target = getGraphSymbol(TargetIndex);
505*753f127fSDimitry Andric   assert(Target && "COMDAT leaader is invalid.");
506*753f127fSDimitry Andric   assert((llvm::count_if(G->defined_symbols(),
507*753f127fSDimitry Andric                          [&](const jitlink::Symbol *Sym) {
508*753f127fSDimitry Andric                            return Sym->getName() == SymbolName;
509*753f127fSDimitry Andric                          }) == 0) &&
510*753f127fSDimitry Andric          "Duplicate defined symbol");
511*753f127fSDimitry Andric   Target->setName(SymbolName);
512*753f127fSDimitry Andric   Target->setLinkage(L);
513*753f127fSDimitry Andric   Target->setCallable(Symbol.getComplexType() ==
514*753f127fSDimitry Andric                       COFF::IMAGE_SYM_DTYPE_FUNCTION);
515*753f127fSDimitry Andric   Target->setScope(Scope::Default);
516*753f127fSDimitry Andric   LLVM_DEBUG({
517*753f127fSDimitry Andric     dbgs() << "    " << SymIndex
518*753f127fSDimitry Andric            << ": Exporting COMDAT graph symbol for COFF symbol \"" << SymbolName
519*753f127fSDimitry Andric            << "\" in section " << Symbol.getSectionNumber() << "\n";
520*753f127fSDimitry Andric     dbgs() << "      " << *Target << "\n";
521*753f127fSDimitry Andric   });
522*753f127fSDimitry Andric   PendingComdatExport = None;
523*753f127fSDimitry Andric   return Target;
524*753f127fSDimitry Andric }
525*753f127fSDimitry Andric 
526*753f127fSDimitry Andric } // namespace jitlink
527*753f127fSDimitry Andric } // namespace llvm