1 //===----------- Mangling.cpp -- Name Mangling Utilities for ORC ----------===// 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 "llvm/ExecutionEngine/Orc/Mangling.h" 10 #include "llvm/IR/Constants.h" 11 #include "llvm/IR/Mangler.h" 12 #include "llvm/Object/MachO.h" 13 #include "llvm/Object/ObjectFile.h" 14 #include "llvm/Support/Debug.h" 15 16 #define DEBUG_TYPE "orc" 17 18 namespace llvm { 19 namespace orc { 20 21 MangleAndInterner::MangleAndInterner(ExecutionSession &ES, const DataLayout &DL) 22 : ES(ES), DL(DL) {} 23 24 SymbolStringPtr MangleAndInterner::operator()(StringRef Name) { 25 std::string MangledName; 26 { 27 raw_string_ostream MangledNameStream(MangledName); 28 Mangler::getNameWithPrefix(MangledNameStream, Name, DL); 29 } 30 return ES.intern(MangledName); 31 } 32 33 void IRSymbolMapper::add(ExecutionSession &ES, const ManglingOptions &MO, 34 ArrayRef<GlobalValue *> GVs, 35 SymbolFlagsMap &SymbolFlags, 36 SymbolNameToDefinitionMap *SymbolToDefinition) { 37 if (GVs.empty()) 38 return; 39 40 MangleAndInterner Mangle(ES, GVs[0]->getParent()->getDataLayout()); 41 for (auto *G : GVs) { 42 assert(G && "GVs cannot contain null elements"); 43 if (!G->hasName() || G->isDeclaration() || G->hasLocalLinkage() || 44 G->hasAvailableExternallyLinkage() || G->hasAppendingLinkage()) 45 continue; 46 47 if (G->isThreadLocal() && MO.EmulatedTLS) { 48 auto *GV = cast<GlobalVariable>(G); 49 50 auto Flags = JITSymbolFlags::fromGlobalValue(*GV); 51 52 auto EmuTLSV = Mangle(("__emutls_v." + GV->getName()).str()); 53 SymbolFlags[EmuTLSV] = Flags; 54 if (SymbolToDefinition) 55 (*SymbolToDefinition)[EmuTLSV] = GV; 56 57 // If this GV has a non-zero initializer we'll need to emit an 58 // __emutls.t symbol too. 59 if (GV->hasInitializer()) { 60 const auto *InitVal = GV->getInitializer(); 61 62 // Skip zero-initializers. 63 if (isa<ConstantAggregateZero>(InitVal)) 64 continue; 65 const auto *InitIntValue = dyn_cast<ConstantInt>(InitVal); 66 if (InitIntValue && InitIntValue->isZero()) 67 continue; 68 69 auto EmuTLST = Mangle(("__emutls_t." + GV->getName()).str()); 70 SymbolFlags[EmuTLST] = Flags; 71 if (SymbolToDefinition) 72 (*SymbolToDefinition)[EmuTLST] = GV; 73 } 74 continue; 75 } 76 77 // Otherwise we just need a normal linker mangling. 78 auto MangledName = Mangle(G->getName()); 79 SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(*G); 80 if (SymbolToDefinition) 81 (*SymbolToDefinition)[MangledName] = G; 82 } 83 } 84 85 Expected<std::pair<SymbolFlagsMap, SymbolStringPtr>> 86 getObjectSymbolInfo(ExecutionSession &ES, MemoryBufferRef ObjBuffer) { 87 auto Obj = object::ObjectFile::createObjectFile(ObjBuffer); 88 89 if (!Obj) 90 return Obj.takeError(); 91 92 bool IsMachO = isa<object::MachOObjectFile>(Obj->get()); 93 94 SymbolFlagsMap SymbolFlags; 95 for (auto &Sym : (*Obj)->symbols()) { 96 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags(); 97 if (!SymFlagsOrErr) 98 // TODO: Test this error. 99 return SymFlagsOrErr.takeError(); 100 101 // Skip symbols not defined in this object file. 102 if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) 103 continue; 104 105 // Skip symbols that are not global. 106 if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) 107 continue; 108 109 // Skip symbols that have type SF_File. 110 if (auto SymType = Sym.getType()) { 111 if (*SymType == object::SymbolRef::ST_File) 112 continue; 113 } else 114 return SymType.takeError(); 115 116 auto Name = Sym.getName(); 117 if (!Name) 118 return Name.takeError(); 119 auto InternedName = ES.intern(*Name); 120 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); 121 if (!SymFlags) 122 return SymFlags.takeError(); 123 124 // Strip the 'exported' flag from MachO linker-private symbols. 125 if (IsMachO && Name->startswith("l")) 126 *SymFlags &= ~JITSymbolFlags::Exported; 127 128 SymbolFlags[InternedName] = std::move(*SymFlags); 129 } 130 131 SymbolStringPtr InitSymbol; 132 133 if (IsMachO) { 134 auto &MachOObj = cast<object::MachOObjectFile>(*Obj->get()); 135 for (auto &Sec : MachOObj.sections()) { 136 auto SecType = MachOObj.getSectionType(Sec); 137 if ((SecType & MachO::SECTION_TYPE) == MachO::S_MOD_INIT_FUNC_POINTERS) { 138 size_t Counter = 0; 139 while (true) { 140 std::string InitSymString; 141 raw_string_ostream(InitSymString) 142 << "$." << ObjBuffer.getBufferIdentifier() << ".__inits." 143 << Counter++; 144 InitSymbol = ES.intern(InitSymString); 145 if (SymbolFlags.count(InitSymbol)) 146 continue; 147 SymbolFlags[InitSymbol] = 148 JITSymbolFlags::MaterializationSideEffectsOnly; 149 break; 150 } 151 break; 152 } 153 } 154 } 155 156 return std::make_pair(std::move(SymbolFlags), std::move(InitSymbol)); 157 } 158 159 } // End namespace orc. 160 } // End namespace llvm. 161