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/IR/DebugInfoMetadata.h" 17 #include "llvm/IR/GlobalVariable.h" 18 #include "llvm/IR/Instruction.h" 19 #include "llvm/IR/Instructions.h" 20 #include "llvm/IR/Module.h" 21 #include "llvm/IR/PassManager.h" 22 #include "llvm/IR/Type.h" 23 #include "llvm/IR/User.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().startswith("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 = BPFCoreSharedInfo::BTF_TYPE_ID_LOCAL; 86 } else { 87 Reloc = BPFCoreSharedInfo::BTF_TYPE_ID_REMOTE; 88 DIType *Ty = cast<DIType>(MD); 89 while (auto *DTy = dyn_cast<DIDerivedType>(Ty)) { 90 unsigned Tag = DTy->getTag(); 91 if (Tag != dwarf::DW_TAG_const_type && 92 Tag != dwarf::DW_TAG_volatile_type) 93 break; 94 Ty = DTy->getBaseType(); 95 } 96 97 if (Ty->getName().empty()) { 98 if (isa<DISubroutineType>(Ty)) 99 report_fatal_error( 100 "SubroutineType not supported for BTF_TYPE_ID_REMOTE reloc"); 101 else 102 report_fatal_error("Empty type name for BTF_TYPE_ID_REMOTE reloc"); 103 } 104 MD = Ty; 105 } 106 107 BasicBlock *BB = Call->getParent(); 108 IntegerType *VarType = Type::getInt64Ty(BB->getContext()); 109 std::string GVName = 110 BaseName + std::to_string(Count) + "$" + std::to_string(Reloc); 111 GlobalVariable *GV = new GlobalVariable( 112 *M, VarType, false, GlobalVariable::ExternalLinkage, nullptr, GVName); 113 GV->addAttribute(BPFCoreSharedInfo::TypeIdAttr); 114 GV->setMetadata(LLVMContext::MD_preserve_access_index, MD); 115 116 // Load the global variable which represents the type info. 117 auto *LDInst = 118 new LoadInst(Type::getInt64Ty(BB->getContext()), GV, "", Call); 119 Instruction *PassThroughInst = 120 BPFCoreSharedInfo::insertPassThrough(M, BB, LDInst, Call); 121 Call->replaceAllUsesWith(PassThroughInst); 122 Call->eraseFromParent(); 123 Count++; 124 } 125 126 return true; 127 } 128 } // End anonymous namespace 129 130 PreservedAnalyses BPFPreserveDITypePass::run(Function &F, 131 FunctionAnalysisManager &AM) { 132 return BPFPreserveDITypeImpl(F) ? PreservedAnalyses::none() 133 : PreservedAnalyses::all(); 134 } 135