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