1*1db9f3b2SDimitry Andric //===- DWARFLinkerDeclContext.cpp -----------------------------------------===// 2*1db9f3b2SDimitry Andric // 3*1db9f3b2SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*1db9f3b2SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*1db9f3b2SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*1db9f3b2SDimitry Andric // 7*1db9f3b2SDimitry Andric //===----------------------------------------------------------------------===// 8*1db9f3b2SDimitry Andric 9*1db9f3b2SDimitry Andric #include "llvm/DWARFLinker/Classic/DWARFLinkerDeclContext.h" 10*1db9f3b2SDimitry Andric #include "llvm/DWARFLinker/Classic/DWARFLinkerCompileUnit.h" 11*1db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFContext.h" 12*1db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDie.h" 13*1db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 14*1db9f3b2SDimitry Andric 15*1db9f3b2SDimitry Andric namespace llvm { 16*1db9f3b2SDimitry Andric 17*1db9f3b2SDimitry Andric using namespace dwarf_linker; 18*1db9f3b2SDimitry Andric using namespace dwarf_linker::classic; 19*1db9f3b2SDimitry Andric 20*1db9f3b2SDimitry Andric /// Set the last DIE/CU a context was seen in and, possibly invalidate the 21*1db9f3b2SDimitry Andric /// context if it is ambiguous. 22*1db9f3b2SDimitry Andric /// 23*1db9f3b2SDimitry Andric /// In the current implementation, we don't handle overloaded functions well, 24*1db9f3b2SDimitry Andric /// because the argument types are not taken into account when computing the 25*1db9f3b2SDimitry Andric /// DeclContext tree. 26*1db9f3b2SDimitry Andric /// 27*1db9f3b2SDimitry Andric /// Some of this is mitigated byt using mangled names that do contain the 28*1db9f3b2SDimitry Andric /// arguments types, but sometimes (e.g. with function templates) we don't have 29*1db9f3b2SDimitry Andric /// that. In that case, just do not unique anything that refers to the contexts 30*1db9f3b2SDimitry Andric /// we are not able to distinguish. 31*1db9f3b2SDimitry Andric /// 32*1db9f3b2SDimitry Andric /// If a context that is not a namespace appears twice in the same CU, we know 33*1db9f3b2SDimitry Andric /// it is ambiguous. Make it invalid. 34*1db9f3b2SDimitry Andric bool DeclContext::setLastSeenDIE(CompileUnit &U, const DWARFDie &Die) { 35*1db9f3b2SDimitry Andric if (LastSeenCompileUnitID == U.getUniqueID()) { 36*1db9f3b2SDimitry Andric DWARFUnit &OrigUnit = U.getOrigUnit(); 37*1db9f3b2SDimitry Andric uint32_t FirstIdx = OrigUnit.getDIEIndex(LastSeenDIE); 38*1db9f3b2SDimitry Andric U.getInfo(FirstIdx).Ctxt = nullptr; 39*1db9f3b2SDimitry Andric return false; 40*1db9f3b2SDimitry Andric } 41*1db9f3b2SDimitry Andric 42*1db9f3b2SDimitry Andric LastSeenCompileUnitID = U.getUniqueID(); 43*1db9f3b2SDimitry Andric LastSeenDIE = Die; 44*1db9f3b2SDimitry Andric return true; 45*1db9f3b2SDimitry Andric } 46*1db9f3b2SDimitry Andric 47*1db9f3b2SDimitry Andric PointerIntPair<DeclContext *, 1> 48*1db9f3b2SDimitry Andric DeclContextTree::getChildDeclContext(DeclContext &Context, const DWARFDie &DIE, 49*1db9f3b2SDimitry Andric CompileUnit &U, bool InClangModule) { 50*1db9f3b2SDimitry Andric unsigned Tag = DIE.getTag(); 51*1db9f3b2SDimitry Andric 52*1db9f3b2SDimitry Andric // FIXME: dsymutil-classic compat: We should bail out here if we 53*1db9f3b2SDimitry Andric // have a specification or an abstract_origin. We will get the 54*1db9f3b2SDimitry Andric // parent context wrong here. 55*1db9f3b2SDimitry Andric 56*1db9f3b2SDimitry Andric switch (Tag) { 57*1db9f3b2SDimitry Andric default: 58*1db9f3b2SDimitry Andric // By default stop gathering child contexts. 59*1db9f3b2SDimitry Andric return PointerIntPair<DeclContext *, 1>(nullptr); 60*1db9f3b2SDimitry Andric case dwarf::DW_TAG_module: 61*1db9f3b2SDimitry Andric break; 62*1db9f3b2SDimitry Andric case dwarf::DW_TAG_compile_unit: 63*1db9f3b2SDimitry Andric return PointerIntPair<DeclContext *, 1>(&Context); 64*1db9f3b2SDimitry Andric case dwarf::DW_TAG_subprogram: 65*1db9f3b2SDimitry Andric // Do not unique anything inside CU local functions. 66*1db9f3b2SDimitry Andric if ((Context.getTag() == dwarf::DW_TAG_namespace || 67*1db9f3b2SDimitry Andric Context.getTag() == dwarf::DW_TAG_compile_unit) && 68*1db9f3b2SDimitry Andric !dwarf::toUnsigned(DIE.find(dwarf::DW_AT_external), 0)) 69*1db9f3b2SDimitry Andric return PointerIntPair<DeclContext *, 1>(nullptr); 70*1db9f3b2SDimitry Andric [[fallthrough]]; 71*1db9f3b2SDimitry Andric case dwarf::DW_TAG_member: 72*1db9f3b2SDimitry Andric case dwarf::DW_TAG_namespace: 73*1db9f3b2SDimitry Andric case dwarf::DW_TAG_structure_type: 74*1db9f3b2SDimitry Andric case dwarf::DW_TAG_class_type: 75*1db9f3b2SDimitry Andric case dwarf::DW_TAG_union_type: 76*1db9f3b2SDimitry Andric case dwarf::DW_TAG_enumeration_type: 77*1db9f3b2SDimitry Andric case dwarf::DW_TAG_typedef: 78*1db9f3b2SDimitry Andric // Artificial things might be ambiguous, because they might be created on 79*1db9f3b2SDimitry Andric // demand. For example implicitly defined constructors are ambiguous 80*1db9f3b2SDimitry Andric // because of the way we identify contexts, and they won't be generated 81*1db9f3b2SDimitry Andric // every time everywhere. 82*1db9f3b2SDimitry Andric if (dwarf::toUnsigned(DIE.find(dwarf::DW_AT_artificial), 0)) 83*1db9f3b2SDimitry Andric return PointerIntPair<DeclContext *, 1>(nullptr); 84*1db9f3b2SDimitry Andric break; 85*1db9f3b2SDimitry Andric } 86*1db9f3b2SDimitry Andric 87*1db9f3b2SDimitry Andric StringRef NameRef; 88*1db9f3b2SDimitry Andric StringRef FileRef; 89*1db9f3b2SDimitry Andric 90*1db9f3b2SDimitry Andric if (const char *LinkageName = DIE.getLinkageName()) 91*1db9f3b2SDimitry Andric NameRef = StringPool.internString(LinkageName); 92*1db9f3b2SDimitry Andric else if (const char *ShortName = DIE.getShortName()) 93*1db9f3b2SDimitry Andric NameRef = StringPool.internString(ShortName); 94*1db9f3b2SDimitry Andric 95*1db9f3b2SDimitry Andric bool IsAnonymousNamespace = NameRef.empty() && Tag == dwarf::DW_TAG_namespace; 96*1db9f3b2SDimitry Andric if (IsAnonymousNamespace) { 97*1db9f3b2SDimitry Andric // FIXME: For dsymutil-classic compatibility. I think uniquing within 98*1db9f3b2SDimitry Andric // anonymous namespaces is wrong. There is no ODR guarantee there. 99*1db9f3b2SDimitry Andric NameRef = "(anonymous namespace)"; 100*1db9f3b2SDimitry Andric } 101*1db9f3b2SDimitry Andric 102*1db9f3b2SDimitry Andric if (Tag != dwarf::DW_TAG_class_type && Tag != dwarf::DW_TAG_structure_type && 103*1db9f3b2SDimitry Andric Tag != dwarf::DW_TAG_union_type && 104*1db9f3b2SDimitry Andric Tag != dwarf::DW_TAG_enumeration_type && NameRef.empty()) 105*1db9f3b2SDimitry Andric return PointerIntPair<DeclContext *, 1>(nullptr); 106*1db9f3b2SDimitry Andric 107*1db9f3b2SDimitry Andric unsigned Line = 0; 108*1db9f3b2SDimitry Andric unsigned ByteSize = std::numeric_limits<uint32_t>::max(); 109*1db9f3b2SDimitry Andric 110*1db9f3b2SDimitry Andric if (!InClangModule) { 111*1db9f3b2SDimitry Andric // Gather some discriminating data about the DeclContext we will be 112*1db9f3b2SDimitry Andric // creating: File, line number and byte size. This shouldn't be necessary, 113*1db9f3b2SDimitry Andric // because the ODR is just about names, but given that we do some 114*1db9f3b2SDimitry Andric // approximations with overloaded functions and anonymous namespaces, use 115*1db9f3b2SDimitry Andric // these additional data points to make the process safer. 116*1db9f3b2SDimitry Andric // 117*1db9f3b2SDimitry Andric // This is disabled for clang modules, because forward declarations of 118*1db9f3b2SDimitry Andric // module-defined types do not have a file and line. 119*1db9f3b2SDimitry Andric ByteSize = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_byte_size), 120*1db9f3b2SDimitry Andric std::numeric_limits<uint64_t>::max()); 121*1db9f3b2SDimitry Andric if (Tag != dwarf::DW_TAG_namespace || IsAnonymousNamespace) { 122*1db9f3b2SDimitry Andric if (unsigned FileNum = 123*1db9f3b2SDimitry Andric dwarf::toUnsigned(DIE.find(dwarf::DW_AT_decl_file), 0)) { 124*1db9f3b2SDimitry Andric if (const auto *LT = U.getOrigUnit().getContext().getLineTableForUnit( 125*1db9f3b2SDimitry Andric &U.getOrigUnit())) { 126*1db9f3b2SDimitry Andric // FIXME: dsymutil-classic compatibility. I'd rather not 127*1db9f3b2SDimitry Andric // unique anything in anonymous namespaces, but if we do, then 128*1db9f3b2SDimitry Andric // verify that the file and line correspond. 129*1db9f3b2SDimitry Andric if (IsAnonymousNamespace) 130*1db9f3b2SDimitry Andric FileNum = 1; 131*1db9f3b2SDimitry Andric 132*1db9f3b2SDimitry Andric if (LT->hasFileAtIndex(FileNum)) { 133*1db9f3b2SDimitry Andric Line = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_decl_line), 0); 134*1db9f3b2SDimitry Andric // Cache the resolved paths based on the index in the line table, 135*1db9f3b2SDimitry Andric // because calling realpath is expensive. 136*1db9f3b2SDimitry Andric FileRef = getResolvedPath(U, FileNum, *LT); 137*1db9f3b2SDimitry Andric } 138*1db9f3b2SDimitry Andric } 139*1db9f3b2SDimitry Andric } 140*1db9f3b2SDimitry Andric } 141*1db9f3b2SDimitry Andric } 142*1db9f3b2SDimitry Andric 143*1db9f3b2SDimitry Andric if (!Line && NameRef.empty()) 144*1db9f3b2SDimitry Andric return PointerIntPair<DeclContext *, 1>(nullptr); 145*1db9f3b2SDimitry Andric 146*1db9f3b2SDimitry Andric // We hash NameRef, which is the mangled name, in order to get most 147*1db9f3b2SDimitry Andric // overloaded functions resolve correctly. 148*1db9f3b2SDimitry Andric // 149*1db9f3b2SDimitry Andric // Strictly speaking, hashing the Tag is only necessary for a 150*1db9f3b2SDimitry Andric // DW_TAG_module, to prevent uniquing of a module and a namespace 151*1db9f3b2SDimitry Andric // with the same name. 152*1db9f3b2SDimitry Andric // 153*1db9f3b2SDimitry Andric // FIXME: dsymutil-classic won't unique the same type presented 154*1db9f3b2SDimitry Andric // once as a struct and once as a class. Using the Tag in the fully 155*1db9f3b2SDimitry Andric // qualified name hash to get the same effect. 156*1db9f3b2SDimitry Andric unsigned Hash = hash_combine(Context.getQualifiedNameHash(), Tag, NameRef); 157*1db9f3b2SDimitry Andric 158*1db9f3b2SDimitry Andric // FIXME: dsymutil-classic compatibility: when we don't have a name, 159*1db9f3b2SDimitry Andric // use the filename. 160*1db9f3b2SDimitry Andric if (IsAnonymousNamespace) 161*1db9f3b2SDimitry Andric Hash = hash_combine(Hash, FileRef); 162*1db9f3b2SDimitry Andric 163*1db9f3b2SDimitry Andric // Now look if this context already exists. 164*1db9f3b2SDimitry Andric DeclContext Key(Hash, Line, ByteSize, Tag, NameRef, FileRef, Context); 165*1db9f3b2SDimitry Andric auto ContextIter = Contexts.find(&Key); 166*1db9f3b2SDimitry Andric 167*1db9f3b2SDimitry Andric if (ContextIter == Contexts.end()) { 168*1db9f3b2SDimitry Andric // The context wasn't found. 169*1db9f3b2SDimitry Andric bool Inserted; 170*1db9f3b2SDimitry Andric DeclContext *NewContext = 171*1db9f3b2SDimitry Andric new (Allocator) DeclContext(Hash, Line, ByteSize, Tag, NameRef, FileRef, 172*1db9f3b2SDimitry Andric Context, DIE, U.getUniqueID()); 173*1db9f3b2SDimitry Andric std::tie(ContextIter, Inserted) = Contexts.insert(NewContext); 174*1db9f3b2SDimitry Andric assert(Inserted && "Failed to insert DeclContext"); 175*1db9f3b2SDimitry Andric (void)Inserted; 176*1db9f3b2SDimitry Andric } else if (Tag != dwarf::DW_TAG_namespace && 177*1db9f3b2SDimitry Andric !(*ContextIter)->setLastSeenDIE(U, DIE)) { 178*1db9f3b2SDimitry Andric // The context was found, but it is ambiguous with another context 179*1db9f3b2SDimitry Andric // in the same file. Mark it invalid. 180*1db9f3b2SDimitry Andric return PointerIntPair<DeclContext *, 1>(*ContextIter, /* IntVal= */ 1); 181*1db9f3b2SDimitry Andric } 182*1db9f3b2SDimitry Andric 183*1db9f3b2SDimitry Andric assert(ContextIter != Contexts.end()); 184*1db9f3b2SDimitry Andric // FIXME: dsymutil-classic compatibility. Union types aren't 185*1db9f3b2SDimitry Andric // uniques, but their children might be. 186*1db9f3b2SDimitry Andric if ((Tag == dwarf::DW_TAG_subprogram && 187*1db9f3b2SDimitry Andric Context.getTag() != dwarf::DW_TAG_structure_type && 188*1db9f3b2SDimitry Andric Context.getTag() != dwarf::DW_TAG_class_type) || 189*1db9f3b2SDimitry Andric (Tag == dwarf::DW_TAG_union_type)) 190*1db9f3b2SDimitry Andric return PointerIntPair<DeclContext *, 1>(*ContextIter, /* IntVal= */ 1); 191*1db9f3b2SDimitry Andric 192*1db9f3b2SDimitry Andric return PointerIntPair<DeclContext *, 1>(*ContextIter); 193*1db9f3b2SDimitry Andric } 194*1db9f3b2SDimitry Andric 195*1db9f3b2SDimitry Andric StringRef 196*1db9f3b2SDimitry Andric DeclContextTree::getResolvedPath(CompileUnit &CU, unsigned FileNum, 197*1db9f3b2SDimitry Andric const DWARFDebugLine::LineTable &LineTable) { 198*1db9f3b2SDimitry Andric std::pair<unsigned, unsigned> Key = {CU.getUniqueID(), FileNum}; 199*1db9f3b2SDimitry Andric 200*1db9f3b2SDimitry Andric ResolvedPathsMap::const_iterator It = ResolvedPaths.find(Key); 201*1db9f3b2SDimitry Andric if (It == ResolvedPaths.end()) { 202*1db9f3b2SDimitry Andric std::string FileName; 203*1db9f3b2SDimitry Andric bool FoundFileName = LineTable.getFileNameByIndex( 204*1db9f3b2SDimitry Andric FileNum, CU.getOrigUnit().getCompilationDir(), 205*1db9f3b2SDimitry Andric DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, FileName); 206*1db9f3b2SDimitry Andric (void)FoundFileName; 207*1db9f3b2SDimitry Andric assert(FoundFileName && "Must get file name from line table"); 208*1db9f3b2SDimitry Andric 209*1db9f3b2SDimitry Andric // Second level of caching, this time based on the file's parent 210*1db9f3b2SDimitry Andric // path. 211*1db9f3b2SDimitry Andric StringRef ResolvedPath = PathResolver.resolve(FileName, StringPool); 212*1db9f3b2SDimitry Andric 213*1db9f3b2SDimitry Andric It = ResolvedPaths.insert(std::make_pair(Key, ResolvedPath)).first; 214*1db9f3b2SDimitry Andric } 215*1db9f3b2SDimitry Andric 216*1db9f3b2SDimitry Andric return It->second; 217*1db9f3b2SDimitry Andric } 218*1db9f3b2SDimitry Andric 219*1db9f3b2SDimitry Andric } // namespace llvm 220