1 //===----------- BPFPreserveDIType.cpp - Preserve DebugInfo Types ---------===// 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 // Preserve Debuginfo types encoded in __builtin_btf_type_id() metadata. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "BPF.h" 14 #include "BPFCORE.h" 15 #include "llvm/BinaryFormat/Dwarf.h" 16 #include "llvm/DebugInfo/BTF/BTF.h" 17 #include "llvm/IR/DebugInfoMetadata.h" 18 #include "llvm/IR/GlobalVariable.h" 19 #include "llvm/IR/Instruction.h" 20 #include "llvm/IR/Instructions.h" 21 #include "llvm/IR/Module.h" 22 #include "llvm/IR/PassManager.h" 23 #include "llvm/IR/Type.h" 24 #include "llvm/IR/Value.h" 25 #include "llvm/Pass.h" 26 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 27 28 #define DEBUG_TYPE "bpf-preserve-di-type" 29 30 namespace llvm { 31 constexpr StringRef BPFCoreSharedInfo::TypeIdAttr; 32 } // namespace llvm 33 34 using namespace llvm; 35 36 namespace { 37 38 static bool BPFPreserveDITypeImpl(Function &F) { 39 LLVM_DEBUG(dbgs() << "********** preserve debuginfo type **********\n"); 40 41 Module *M = F.getParent(); 42 43 // Bail out if no debug info. 44 if (M->debug_compile_units().empty()) 45 return false; 46 47 std::vector<CallInst *> PreserveDITypeCalls; 48 49 for (auto &BB : F) { 50 for (auto &I : BB) { 51 auto *Call = dyn_cast<CallInst>(&I); 52 if (!Call) 53 continue; 54 55 const auto *GV = dyn_cast<GlobalValue>(Call->getCalledOperand()); 56 if (!GV) 57 continue; 58 59 if (GV->getName().starts_with("llvm.bpf.btf.type.id")) { 60 if (!Call->getMetadata(LLVMContext::MD_preserve_access_index)) 61 report_fatal_error( 62 "Missing metadata for llvm.bpf.btf.type.id intrinsic"); 63 PreserveDITypeCalls.push_back(Call); 64 } 65 } 66 } 67 68 if (PreserveDITypeCalls.empty()) 69 return false; 70 71 std::string BaseName = "llvm.btf_type_id."; 72 static int Count = 0; 73 for (auto *Call : PreserveDITypeCalls) { 74 const ConstantInt *Flag = dyn_cast<ConstantInt>(Call->getArgOperand(1)); 75 assert(Flag); 76 uint64_t FlagValue = Flag->getValue().getZExtValue(); 77 78 if (FlagValue >= BPFCoreSharedInfo::MAX_BTF_TYPE_ID_FLAG) 79 report_fatal_error("Incorrect flag for llvm.bpf.btf.type.id intrinsic"); 80 81 MDNode *MD = Call->getMetadata(LLVMContext::MD_preserve_access_index); 82 83 uint32_t Reloc; 84 if (FlagValue == BPFCoreSharedInfo::BTF_TYPE_ID_LOCAL_RELOC) { 85 Reloc = BTF::BTF_TYPE_ID_LOCAL; 86 } else { 87 Reloc = BTF::BTF_TYPE_ID_REMOTE; 88 } 89 DIType *Ty = cast<DIType>(MD); 90 while (auto *DTy = dyn_cast<DIDerivedType>(Ty)) { 91 unsigned Tag = DTy->getTag(); 92 if (Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type) 93 break; 94 Ty = DTy->getBaseType(); 95 } 96 97 if (Reloc == BTF::BTF_TYPE_ID_REMOTE) { 98 if (Ty->getName().empty()) { 99 if (isa<DISubroutineType>(Ty)) 100 report_fatal_error( 101 "SubroutineType not supported for BTF_TYPE_ID_REMOTE reloc"); 102 else 103 report_fatal_error("Empty type name for BTF_TYPE_ID_REMOTE reloc"); 104 } 105 } 106 MD = Ty; 107 108 BasicBlock *BB = Call->getParent(); 109 IntegerType *VarType = Type::getInt64Ty(BB->getContext()); 110 std::string GVName = 111 BaseName + std::to_string(Count) + "$" + std::to_string(Reloc); 112 GlobalVariable *GV = new GlobalVariable( 113 *M, VarType, false, GlobalVariable::ExternalLinkage, nullptr, GVName); 114 GV->addAttribute(BPFCoreSharedInfo::TypeIdAttr); 115 GV->setMetadata(LLVMContext::MD_preserve_access_index, MD); 116 117 // Load the global variable which represents the type info. 118 auto *LDInst = new LoadInst(Type::getInt64Ty(BB->getContext()), GV, "", 119 Call->getIterator()); 120 Instruction *PassThroughInst = 121 BPFCoreSharedInfo::insertPassThrough(M, BB, LDInst, Call); 122 Call->replaceAllUsesWith(PassThroughInst); 123 Call->eraseFromParent(); 124 Count++; 125 } 126 127 return true; 128 } 129 } // End anonymous namespace 130 131 PreservedAnalyses BPFPreserveDITypePass::run(Function &F, 132 FunctionAnalysisManager &AM) { 133 return BPFPreserveDITypeImpl(F) ? PreservedAnalyses::none() 134 : PreservedAnalyses::all(); 135 } 136