1353940Sdim//=--------- MachOLinkGraphBuilder.cpp - MachO LinkGraph builder ----------===// 2353940Sdim// 3353940Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353940Sdim// See https://llvm.org/LICENSE.txt for license information. 5353940Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6353940Sdim// 7353940Sdim//===----------------------------------------------------------------------===// 8353940Sdim// 9353940Sdim// Generic MachO LinkGraph buliding code. 10353940Sdim// 11353940Sdim//===----------------------------------------------------------------------===// 12353940Sdim 13353940Sdim#include "MachOLinkGraphBuilder.h" 14353940Sdim 15353940Sdim#define DEBUG_TYPE "jitlink" 16353940Sdim 17353940Sdimstatic const char *CommonSectionName = "__common"; 18353940Sdim 19353940Sdimnamespace llvm { 20353940Sdimnamespace jitlink { 21353940Sdim 22353940SdimMachOLinkGraphBuilder::~MachOLinkGraphBuilder() {} 23353940Sdim 24353940SdimExpected<std::unique_ptr<LinkGraph>> MachOLinkGraphBuilder::buildGraph() { 25353940Sdim 26353940Sdim // Sanity check: we only operate on relocatable objects. 27353940Sdim if (!Obj.isRelocatableObject()) 28353940Sdim return make_error<JITLinkError>("Object is not a relocatable MachO"); 29353940Sdim 30353940Sdim if (auto Err = createNormalizedSections()) 31353940Sdim return std::move(Err); 32353940Sdim 33353940Sdim if (auto Err = createNormalizedSymbols()) 34353940Sdim return std::move(Err); 35353940Sdim 36353940Sdim if (auto Err = graphifyRegularSymbols()) 37353940Sdim return std::move(Err); 38353940Sdim 39353940Sdim if (auto Err = graphifySectionsWithCustomParsers()) 40353940Sdim return std::move(Err); 41353940Sdim 42353940Sdim if (auto Err = addRelocations()) 43353940Sdim return std::move(Err); 44353940Sdim 45353940Sdim return std::move(G); 46353940Sdim} 47353940Sdim 48353940SdimMachOLinkGraphBuilder::MachOLinkGraphBuilder(const object::MachOObjectFile &Obj) 49353940Sdim : Obj(Obj), 50353940Sdim G(std::make_unique<LinkGraph>(Obj.getFileName(), getPointerSize(Obj), 51353940Sdim getEndianness(Obj))) {} 52353940Sdim 53353940Sdimvoid MachOLinkGraphBuilder::addCustomSectionParser( 54353940Sdim StringRef SectionName, SectionParserFunction Parser) { 55353940Sdim assert(!CustomSectionParserFunctions.count(SectionName) && 56353940Sdim "Custom parser for this section already exists"); 57353940Sdim CustomSectionParserFunctions[SectionName] = std::move(Parser); 58353940Sdim} 59353940Sdim 60353940SdimLinkage MachOLinkGraphBuilder::getLinkage(uint16_t Desc) { 61353940Sdim if ((Desc & MachO::N_WEAK_DEF) || (Desc & MachO::N_WEAK_REF)) 62353940Sdim return Linkage::Weak; 63353940Sdim return Linkage::Strong; 64353940Sdim} 65353940Sdim 66353940SdimScope MachOLinkGraphBuilder::getScope(StringRef Name, uint8_t Type) { 67353940Sdim if (Name.startswith("l")) 68353940Sdim return Scope::Local; 69353940Sdim if (Type & MachO::N_PEXT) 70353940Sdim return Scope::Hidden; 71353940Sdim if (Type & MachO::N_EXT) 72353940Sdim return Scope::Default; 73353940Sdim return Scope::Local; 74353940Sdim} 75353940Sdim 76353940Sdimbool MachOLinkGraphBuilder::isAltEntry(const NormalizedSymbol &NSym) { 77353940Sdim return NSym.Desc & MachO::N_ALT_ENTRY; 78353940Sdim} 79353940Sdim 80353940Sdimunsigned 81353940SdimMachOLinkGraphBuilder::getPointerSize(const object::MachOObjectFile &Obj) { 82353940Sdim return Obj.is64Bit() ? 8 : 4; 83353940Sdim} 84353940Sdim 85353940Sdimsupport::endianness 86353940SdimMachOLinkGraphBuilder::getEndianness(const object::MachOObjectFile &Obj) { 87353940Sdim return Obj.isLittleEndian() ? support::little : support::big; 88353940Sdim} 89353940Sdim 90353940SdimSection &MachOLinkGraphBuilder::getCommonSection() { 91353940Sdim if (!CommonSection) { 92353940Sdim auto Prot = static_cast<sys::Memory::ProtectionFlags>( 93353940Sdim sys::Memory::MF_READ | sys::Memory::MF_WRITE); 94353940Sdim CommonSection = &G->createSection(CommonSectionName, Prot); 95353940Sdim } 96353940Sdim return *CommonSection; 97353940Sdim} 98353940Sdim 99353940SdimError MachOLinkGraphBuilder::createNormalizedSections() { 100353940Sdim // Build normalized sections. Verifies that section data is in-range (for 101353940Sdim // sections with content) and that address ranges are non-overlapping. 102353940Sdim 103353940Sdim LLVM_DEBUG(dbgs() << "Creating normalized sections...\n"); 104353940Sdim 105353940Sdim for (auto &SecRef : Obj.sections()) { 106353940Sdim NormalizedSection NSec; 107353940Sdim uint32_t DataOffset = 0; 108353940Sdim 109353940Sdim auto SecIndex = Obj.getSectionIndex(SecRef.getRawDataRefImpl()); 110353940Sdim 111353940Sdim auto Name = SecRef.getName(); 112353940Sdim if (!Name) 113353940Sdim return Name.takeError(); 114353940Sdim 115353940Sdim if (Obj.is64Bit()) { 116353940Sdim const MachO::section_64 &Sec64 = 117353940Sdim Obj.getSection64(SecRef.getRawDataRefImpl()); 118353940Sdim 119353940Sdim NSec.Address = Sec64.addr; 120353940Sdim NSec.Size = Sec64.size; 121353940Sdim NSec.Alignment = 1ULL << Sec64.align; 122353940Sdim NSec.Flags = Sec64.flags; 123353940Sdim DataOffset = Sec64.offset; 124353940Sdim } else { 125353940Sdim const MachO::section &Sec32 = Obj.getSection(SecRef.getRawDataRefImpl()); 126353940Sdim NSec.Address = Sec32.addr; 127353940Sdim NSec.Size = Sec32.size; 128353940Sdim NSec.Alignment = 1ULL << Sec32.align; 129353940Sdim NSec.Flags = Sec32.flags; 130353940Sdim DataOffset = Sec32.offset; 131353940Sdim } 132353940Sdim 133353940Sdim LLVM_DEBUG({ 134353940Sdim dbgs() << " " << *Name << ": " << formatv("{0:x16}", NSec.Address) 135353940Sdim << " -- " << formatv("{0:x16}", NSec.Address + NSec.Size) 136353940Sdim << ", align: " << NSec.Alignment << ", index: " << SecIndex 137353940Sdim << "\n"; 138353940Sdim }); 139353940Sdim 140353940Sdim // Get the section data if any. 141353940Sdim { 142353940Sdim unsigned SectionType = NSec.Flags & MachO::SECTION_TYPE; 143353940Sdim if (SectionType != MachO::S_ZEROFILL && 144353940Sdim SectionType != MachO::S_GB_ZEROFILL) { 145353940Sdim 146353940Sdim if (DataOffset + NSec.Size > Obj.getData().size()) 147353940Sdim return make_error<JITLinkError>( 148353940Sdim "Section data extends past end of file"); 149353940Sdim 150353940Sdim NSec.Data = Obj.getData().data() + DataOffset; 151353940Sdim } 152353940Sdim } 153353940Sdim 154353940Sdim // Get prot flags. 155353940Sdim // FIXME: Make sure this test is correct (it's probably missing cases 156353940Sdim // as-is). 157353940Sdim sys::Memory::ProtectionFlags Prot; 158353940Sdim if (NSec.Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) 159353940Sdim Prot = static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ | 160353940Sdim sys::Memory::MF_EXEC); 161353940Sdim else 162353940Sdim Prot = static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ | 163353940Sdim sys::Memory::MF_WRITE); 164353940Sdim 165353940Sdim NSec.GraphSection = &G->createSection(*Name, Prot); 166353940Sdim IndexToSection.insert(std::make_pair(SecIndex, std::move(NSec))); 167353940Sdim } 168353940Sdim 169353940Sdim std::vector<NormalizedSection *> Sections; 170353940Sdim Sections.reserve(IndexToSection.size()); 171353940Sdim for (auto &KV : IndexToSection) 172353940Sdim Sections.push_back(&KV.second); 173353940Sdim 174353940Sdim // If we didn't end up creating any sections then bail out. The code below 175353940Sdim // assumes that we have at least one section. 176353940Sdim if (Sections.empty()) 177353940Sdim return Error::success(); 178353940Sdim 179353940Sdim llvm::sort(Sections, 180353940Sdim [](const NormalizedSection *LHS, const NormalizedSection *RHS) { 181353940Sdim assert(LHS && RHS && "Null section?"); 182357095Sdim if (LHS->Address != RHS->Address) 183357095Sdim return LHS->Address < RHS->Address; 184357095Sdim return LHS->Size < RHS->Size; 185353940Sdim }); 186353940Sdim 187353940Sdim for (unsigned I = 0, E = Sections.size() - 1; I != E; ++I) { 188353940Sdim auto &Cur = *Sections[I]; 189353940Sdim auto &Next = *Sections[I + 1]; 190353940Sdim if (Next.Address < Cur.Address + Cur.Size) 191353940Sdim return make_error<JITLinkError>( 192353940Sdim "Address range for section " + Cur.GraphSection->getName() + 193353940Sdim formatv(" [ {0:x16} -- {1:x16} ] ", Cur.Address, 194353940Sdim Cur.Address + Cur.Size) + 195353940Sdim "overlaps " + 196353940Sdim formatv(" [ {0:x16} -- {1:x16} ] ", Next.Address, 197353940Sdim Next.Address + Next.Size)); 198353940Sdim } 199353940Sdim 200353940Sdim return Error::success(); 201353940Sdim} 202353940Sdim 203353940SdimError MachOLinkGraphBuilder::createNormalizedSymbols() { 204353940Sdim LLVM_DEBUG(dbgs() << "Creating normalized symbols...\n"); 205353940Sdim 206353940Sdim for (auto &SymRef : Obj.symbols()) { 207353940Sdim 208353940Sdim unsigned SymbolIndex = Obj.getSymbolIndex(SymRef.getRawDataRefImpl()); 209353940Sdim uint64_t Value; 210353940Sdim uint32_t NStrX; 211353940Sdim uint8_t Type; 212353940Sdim uint8_t Sect; 213353940Sdim uint16_t Desc; 214353940Sdim 215353940Sdim if (Obj.is64Bit()) { 216353940Sdim const MachO::nlist_64 &NL64 = 217353940Sdim Obj.getSymbol64TableEntry(SymRef.getRawDataRefImpl()); 218353940Sdim Value = NL64.n_value; 219353940Sdim NStrX = NL64.n_strx; 220353940Sdim Type = NL64.n_type; 221353940Sdim Sect = NL64.n_sect; 222353940Sdim Desc = NL64.n_desc; 223353940Sdim } else { 224353940Sdim const MachO::nlist &NL32 = 225353940Sdim Obj.getSymbolTableEntry(SymRef.getRawDataRefImpl()); 226353940Sdim Value = NL32.n_value; 227353940Sdim NStrX = NL32.n_strx; 228353940Sdim Type = NL32.n_type; 229353940Sdim Sect = NL32.n_sect; 230353940Sdim Desc = NL32.n_desc; 231353940Sdim } 232353940Sdim 233353940Sdim // Skip stabs. 234353940Sdim // FIXME: Are there other symbols we should be skipping? 235353940Sdim if (Type & MachO::N_STAB) 236353940Sdim continue; 237353940Sdim 238353940Sdim Optional<StringRef> Name; 239353940Sdim if (NStrX) { 240353940Sdim if (auto NameOrErr = SymRef.getName()) 241353940Sdim Name = *NameOrErr; 242353940Sdim else 243353940Sdim return NameOrErr.takeError(); 244353940Sdim } 245353940Sdim 246353940Sdim LLVM_DEBUG({ 247353940Sdim dbgs() << " "; 248353940Sdim if (!Name) 249353940Sdim dbgs() << "<anonymous symbol>"; 250353940Sdim else 251353940Sdim dbgs() << *Name; 252353940Sdim dbgs() << ": value = " << formatv("{0:x16}", Value) 253353940Sdim << ", type = " << formatv("{0:x2}", Type) 254353940Sdim << ", desc = " << formatv("{0:x4}", Desc) << ", sect = "; 255353940Sdim if (Sect) 256353940Sdim dbgs() << static_cast<unsigned>(Sect - 1); 257353940Sdim else 258353940Sdim dbgs() << "none"; 259353940Sdim dbgs() << "\n"; 260353940Sdim }); 261353940Sdim 262353940Sdim // If this symbol has a section, sanity check that the addresses line up. 263353940Sdim NormalizedSection *NSec = nullptr; 264353940Sdim if (Sect != 0) { 265353940Sdim if (auto NSecOrErr = findSectionByIndex(Sect - 1)) 266353940Sdim NSec = &*NSecOrErr; 267353940Sdim else 268353940Sdim return NSecOrErr.takeError(); 269353940Sdim 270353940Sdim if (Value < NSec->Address || Value > NSec->Address + NSec->Size) 271353940Sdim return make_error<JITLinkError>("Symbol address does not fall within " 272353940Sdim "section"); 273353940Sdim } 274353940Sdim 275353940Sdim IndexToSymbol[SymbolIndex] = 276353940Sdim &createNormalizedSymbol(*Name, Value, Type, Sect, Desc, 277353940Sdim getLinkage(Type), getScope(*Name, Type)); 278353940Sdim } 279353940Sdim 280353940Sdim return Error::success(); 281353940Sdim} 282353940Sdim 283353940Sdimvoid MachOLinkGraphBuilder::addSectionStartSymAndBlock( 284353940Sdim Section &GraphSec, uint64_t Address, const char *Data, uint64_t Size, 285353940Sdim uint32_t Alignment, bool IsLive) { 286353940Sdim Block &B = 287353940Sdim Data ? G->createContentBlock(GraphSec, StringRef(Data, Size), Address, 288353940Sdim Alignment, 0) 289353940Sdim : G->createZeroFillBlock(GraphSec, Size, Address, Alignment, 0); 290353940Sdim auto &Sym = G->addAnonymousSymbol(B, 0, Size, false, IsLive); 291353940Sdim assert(!AddrToCanonicalSymbol.count(Sym.getAddress()) && 292353940Sdim "Anonymous block start symbol clashes with existing symbol address"); 293353940Sdim AddrToCanonicalSymbol[Sym.getAddress()] = &Sym; 294353940Sdim} 295353940Sdim 296353940SdimError MachOLinkGraphBuilder::graphifyRegularSymbols() { 297353940Sdim 298353940Sdim LLVM_DEBUG(dbgs() << "Creating graph symbols...\n"); 299353940Sdim 300353940Sdim /// We only have 256 section indexes: Use a vector rather than a map. 301353940Sdim std::vector<std::vector<NormalizedSymbol *>> SecIndexToSymbols; 302353940Sdim SecIndexToSymbols.resize(256); 303353940Sdim 304353940Sdim // Create commons, externs, and absolutes, and partition all other symbols by 305353940Sdim // section. 306353940Sdim for (auto &KV : IndexToSymbol) { 307353940Sdim auto &NSym = *KV.second; 308353940Sdim 309353940Sdim switch (NSym.Type & MachO::N_TYPE) { 310353940Sdim case MachO::N_UNDF: 311353940Sdim if (NSym.Value) { 312353940Sdim if (!NSym.Name) 313353940Sdim return make_error<JITLinkError>("Anonymous common symbol at index " + 314353940Sdim Twine(KV.first)); 315353940Sdim NSym.GraphSymbol = &G->addCommonSymbol( 316357095Sdim *NSym.Name, NSym.S, getCommonSection(), 0, NSym.Value, 317353940Sdim 1ull << MachO::GET_COMM_ALIGN(NSym.Desc), 318353940Sdim NSym.Desc & MachO::N_NO_DEAD_STRIP); 319353940Sdim } else { 320353940Sdim if (!NSym.Name) 321353940Sdim return make_error<JITLinkError>("Anonymous external symbol at " 322353940Sdim "index " + 323353940Sdim Twine(KV.first)); 324357095Sdim NSym.GraphSymbol = &G->addExternalSymbol( 325357095Sdim *NSym.Name, 0, 326357095Sdim NSym.Desc & MachO::N_WEAK_REF ? Linkage::Weak : Linkage::Strong); 327353940Sdim } 328353940Sdim break; 329353940Sdim case MachO::N_ABS: 330353940Sdim if (!NSym.Name) 331353940Sdim return make_error<JITLinkError>("Anonymous absolute symbol at index " + 332353940Sdim Twine(KV.first)); 333353940Sdim NSym.GraphSymbol = &G->addAbsoluteSymbol( 334353940Sdim *NSym.Name, NSym.Value, 0, Linkage::Strong, Scope::Default, 335353940Sdim NSym.Desc & MachO::N_NO_DEAD_STRIP); 336353940Sdim break; 337353940Sdim case MachO::N_SECT: 338353940Sdim SecIndexToSymbols[NSym.Sect - 1].push_back(&NSym); 339353940Sdim break; 340353940Sdim case MachO::N_PBUD: 341353940Sdim return make_error<JITLinkError>( 342353940Sdim "Unupported N_PBUD symbol " + 343353940Sdim (NSym.Name ? ("\"" + *NSym.Name + "\"") : Twine("<anon>")) + 344353940Sdim " at index " + Twine(KV.first)); 345353940Sdim case MachO::N_INDR: 346353940Sdim return make_error<JITLinkError>( 347353940Sdim "Unupported N_INDR symbol " + 348353940Sdim (NSym.Name ? ("\"" + *NSym.Name + "\"") : Twine("<anon>")) + 349353940Sdim " at index " + Twine(KV.first)); 350353940Sdim default: 351353940Sdim return make_error<JITLinkError>( 352353940Sdim "Unrecognized symbol type " + Twine(NSym.Type & MachO::N_TYPE) + 353353940Sdim " for symbol " + 354353940Sdim (NSym.Name ? ("\"" + *NSym.Name + "\"") : Twine("<anon>")) + 355353940Sdim " at index " + Twine(KV.first)); 356353940Sdim } 357353940Sdim } 358353940Sdim 359353940Sdim // Loop over sections performing regular graphification for those that 360353940Sdim // don't have custom parsers. 361353940Sdim for (auto &KV : IndexToSection) { 362353940Sdim auto SecIndex = KV.first; 363353940Sdim auto &NSec = KV.second; 364353940Sdim 365353940Sdim // Skip sections with custom parsers. 366353940Sdim if (CustomSectionParserFunctions.count(NSec.GraphSection->getName())) { 367353940Sdim LLVM_DEBUG({ 368353940Sdim dbgs() << " Skipping section " << NSec.GraphSection->getName() 369353940Sdim << " as it has a custom parser.\n"; 370353940Sdim }); 371353940Sdim continue; 372353940Sdim } else 373353940Sdim LLVM_DEBUG({ 374353940Sdim dbgs() << " Processing section " << NSec.GraphSection->getName() 375353940Sdim << "...\n"; 376353940Sdim }); 377353940Sdim 378353940Sdim bool SectionIsNoDeadStrip = NSec.Flags & MachO::S_ATTR_NO_DEAD_STRIP; 379353940Sdim bool SectionIsText = NSec.Flags & MachO::S_ATTR_PURE_INSTRUCTIONS; 380353940Sdim 381353940Sdim auto &SecNSymStack = SecIndexToSymbols[SecIndex]; 382353940Sdim 383353940Sdim // If this section is non-empty but there are no symbols covering it then 384353940Sdim // create one block and anonymous symbol to cover the entire section. 385353940Sdim if (SecNSymStack.empty()) { 386353940Sdim if (NSec.Size > 0) { 387353940Sdim LLVM_DEBUG({ 388353940Sdim dbgs() << " Section non-empty, but contains no symbols. " 389353940Sdim "Creating anonymous block to cover " 390353940Sdim << formatv("{0:x16}", NSec.Address) << " -- " 391353940Sdim << formatv("{0:x16}", NSec.Address + NSec.Size) << "\n"; 392353940Sdim }); 393353940Sdim addSectionStartSymAndBlock(*NSec.GraphSection, NSec.Address, NSec.Data, 394353940Sdim NSec.Size, NSec.Alignment, 395353940Sdim SectionIsNoDeadStrip); 396353940Sdim } else 397353940Sdim LLVM_DEBUG({ 398353940Sdim dbgs() << " Section empty and contains no symbols. Skipping.\n"; 399353940Sdim }); 400353940Sdim continue; 401353940Sdim } 402353940Sdim 403353940Sdim // Sort the symbol stack in by address, alt-entry status, scope, and name. 404353940Sdim // We sort in reverse order so that symbols will be visited in the right 405353940Sdim // order when we pop off the stack below. 406353940Sdim llvm::sort(SecNSymStack, [](const NormalizedSymbol *LHS, 407353940Sdim const NormalizedSymbol *RHS) { 408353940Sdim if (LHS->Value != RHS->Value) 409353940Sdim return LHS->Value > RHS->Value; 410353940Sdim if (isAltEntry(*LHS) != isAltEntry(*RHS)) 411353940Sdim return isAltEntry(*RHS); 412353940Sdim if (LHS->S != RHS->S) 413353940Sdim return static_cast<uint8_t>(LHS->S) < static_cast<uint8_t>(RHS->S); 414353940Sdim return LHS->Name < RHS->Name; 415353940Sdim }); 416353940Sdim 417353940Sdim // The first symbol in a section can not be an alt-entry symbol. 418353940Sdim if (!SecNSymStack.empty() && isAltEntry(*SecNSymStack.back())) 419353940Sdim return make_error<JITLinkError>( 420353940Sdim "First symbol in " + NSec.GraphSection->getName() + " is alt-entry"); 421353940Sdim 422353940Sdim // If the section is non-empty but there is no symbol covering the start 423353940Sdim // address then add an anonymous one. 424353940Sdim if (SecNSymStack.back()->Value != NSec.Address) { 425353940Sdim auto AnonBlockSize = SecNSymStack.back()->Value - NSec.Address; 426353940Sdim LLVM_DEBUG({ 427353940Sdim dbgs() << " Section start not covered by symbol. " 428353940Sdim << "Creating anonymous block to cover [ " 429353940Sdim << formatv("{0:x16}", NSec.Address) << " -- " 430353940Sdim << formatv("{0:x16}", NSec.Address + AnonBlockSize) << " ]\n"; 431353940Sdim }); 432353940Sdim addSectionStartSymAndBlock(*NSec.GraphSection, NSec.Address, NSec.Data, 433353940Sdim AnonBlockSize, NSec.Alignment, 434353940Sdim SectionIsNoDeadStrip); 435353940Sdim } 436353940Sdim 437353940Sdim // Visit section symbols in order by popping off the reverse-sorted stack, 438353940Sdim // building blocks for each alt-entry chain and creating symbols as we go. 439353940Sdim while (!SecNSymStack.empty()) { 440353940Sdim SmallVector<NormalizedSymbol *, 8> BlockSyms; 441353940Sdim 442353940Sdim BlockSyms.push_back(SecNSymStack.back()); 443353940Sdim SecNSymStack.pop_back(); 444353940Sdim while (!SecNSymStack.empty() && 445353940Sdim (isAltEntry(*SecNSymStack.back()) || 446353940Sdim SecNSymStack.back()->Value == BlockSyms.back()->Value)) { 447353940Sdim BlockSyms.push_back(SecNSymStack.back()); 448353940Sdim SecNSymStack.pop_back(); 449353940Sdim } 450353940Sdim 451353940Sdim // BlockNSyms now contains the block symbols in reverse canonical order. 452353940Sdim JITTargetAddress BlockStart = BlockSyms.front()->Value; 453353940Sdim JITTargetAddress BlockEnd = SecNSymStack.empty() 454353940Sdim ? NSec.Address + NSec.Size 455353940Sdim : SecNSymStack.back()->Value; 456353940Sdim JITTargetAddress BlockOffset = BlockStart - NSec.Address; 457353940Sdim JITTargetAddress BlockSize = BlockEnd - BlockStart; 458353940Sdim 459353940Sdim LLVM_DEBUG({ 460353940Sdim dbgs() << " Creating block for " << formatv("{0:x16}", BlockStart) 461353940Sdim << " -- " << formatv("{0:x16}", BlockEnd) << ": " 462353940Sdim << NSec.GraphSection->getName() << " + " 463353940Sdim << formatv("{0:x16}", BlockOffset) << " with " 464353940Sdim << BlockSyms.size() << " symbol(s)...\n"; 465353940Sdim }); 466353940Sdim 467353940Sdim Block &B = 468353940Sdim NSec.Data 469353940Sdim ? G->createContentBlock( 470353940Sdim *NSec.GraphSection, 471353940Sdim StringRef(NSec.Data + BlockOffset, BlockSize), BlockStart, 472353940Sdim NSec.Alignment, BlockStart % NSec.Alignment) 473353940Sdim : G->createZeroFillBlock(*NSec.GraphSection, BlockSize, 474353940Sdim BlockStart, NSec.Alignment, 475353940Sdim BlockStart % NSec.Alignment); 476353940Sdim 477353940Sdim Optional<JITTargetAddress> LastCanonicalAddr; 478353940Sdim JITTargetAddress SymEnd = BlockEnd; 479353940Sdim while (!BlockSyms.empty()) { 480353940Sdim auto &NSym = *BlockSyms.back(); 481353940Sdim BlockSyms.pop_back(); 482353940Sdim 483353940Sdim bool SymLive = 484353940Sdim (NSym.Desc & MachO::N_NO_DEAD_STRIP) || SectionIsNoDeadStrip; 485353940Sdim 486353940Sdim LLVM_DEBUG({ 487353940Sdim dbgs() << " " << formatv("{0:x16}", NSym.Value) << " -- " 488353940Sdim << formatv("{0:x16}", SymEnd) << ": "; 489353940Sdim if (!NSym.Name) 490353940Sdim dbgs() << "<anonymous symbol>"; 491353940Sdim else 492353940Sdim dbgs() << NSym.Name; 493353940Sdim if (SymLive) 494353940Sdim dbgs() << " [no-dead-strip]"; 495353940Sdim if (LastCanonicalAddr == NSym.Value) 496353940Sdim dbgs() << " [non-canonical]"; 497353940Sdim dbgs() << "\n"; 498353940Sdim }); 499353940Sdim 500353940Sdim auto &Sym = 501353940Sdim NSym.Name 502353940Sdim ? G->addDefinedSymbol(B, NSym.Value - BlockStart, *NSym.Name, 503353940Sdim SymEnd - NSym.Value, NSym.L, NSym.S, 504353940Sdim SectionIsText, SymLive) 505353940Sdim : G->addAnonymousSymbol(B, NSym.Value - BlockStart, 506353940Sdim SymEnd - NSym.Value, SectionIsText, 507353940Sdim SymLive); 508353940Sdim NSym.GraphSymbol = &Sym; 509353940Sdim if (LastCanonicalAddr != Sym.getAddress()) { 510353940Sdim if (LastCanonicalAddr) 511353940Sdim SymEnd = *LastCanonicalAddr; 512353940Sdim LastCanonicalAddr = Sym.getAddress(); 513353940Sdim setCanonicalSymbol(Sym); 514353940Sdim } 515353940Sdim } 516353940Sdim } 517353940Sdim } 518353940Sdim 519353940Sdim return Error::success(); 520353940Sdim} 521353940Sdim 522353940SdimError MachOLinkGraphBuilder::graphifySectionsWithCustomParsers() { 523353940Sdim // Graphify special sections. 524353940Sdim for (auto &KV : IndexToSection) { 525353940Sdim auto &NSec = KV.second; 526353940Sdim 527353940Sdim auto HI = CustomSectionParserFunctions.find(NSec.GraphSection->getName()); 528353940Sdim if (HI != CustomSectionParserFunctions.end()) { 529353940Sdim auto &Parse = HI->second; 530353940Sdim if (auto Err = Parse(NSec)) 531353940Sdim return Err; 532353940Sdim } 533353940Sdim } 534353940Sdim 535353940Sdim return Error::success(); 536353940Sdim} 537353940Sdim 538353940Sdim} // end namespace jitlink 539353940Sdim} // end namespace llvm 540