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/IR/DebugInfoMetadata.h" 16 #include "llvm/IR/GlobalVariable.h" 17 #include "llvm/IR/Instruction.h" 18 #include "llvm/IR/Instructions.h" 19 #include "llvm/IR/Module.h" 20 #include "llvm/IR/Type.h" 21 #include "llvm/IR/User.h" 22 #include "llvm/IR/Value.h" 23 #include "llvm/Pass.h" 24 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 25 26 #define DEBUG_TYPE "bpf-preserve-di-type" 27 28 namespace llvm { 29 constexpr StringRef BPFCoreSharedInfo::TypeIdAttr; 30 } // namespace llvm 31 32 using namespace llvm; 33 34 namespace { 35 36 class BPFPreserveDIType final : public ModulePass { 37 StringRef getPassName() const override { 38 return "BPF Preserve DebugInfo Type"; 39 } 40 41 bool runOnModule(Module &M) override; 42 43 public: 44 static char ID; 45 BPFPreserveDIType() : ModulePass(ID) {} 46 47 private: 48 bool doTransformation(Module &M); 49 }; 50 } // End anonymous namespace 51 52 char BPFPreserveDIType::ID = 0; 53 INITIALIZE_PASS(BPFPreserveDIType, DEBUG_TYPE, "preserve debuginfo type", false, 54 false) 55 56 ModulePass *llvm::createBPFPreserveDIType() { return new BPFPreserveDIType(); } 57 58 bool BPFPreserveDIType::runOnModule(Module &M) { 59 LLVM_DEBUG(dbgs() << "********** preserve debuginfo type **********\n"); 60 61 // Bail out if no debug info. 62 if (M.debug_compile_units().empty()) 63 return false; 64 65 return doTransformation(M); 66 } 67 68 bool BPFPreserveDIType::doTransformation(Module &M) { 69 std::vector<CallInst *> PreserveDITypeCalls; 70 71 for (auto &F : M) { 72 for (auto &BB : F) { 73 for (auto &I : BB) { 74 auto *Call = dyn_cast<CallInst>(&I); 75 if (!Call) 76 continue; 77 78 const auto *GV = dyn_cast<GlobalValue>(Call->getCalledOperand()); 79 if (!GV) 80 continue; 81 82 if (GV->getName().startswith("llvm.bpf.btf.type.id")) { 83 if (!Call->getMetadata(LLVMContext::MD_preserve_access_index)) 84 report_fatal_error( 85 "Missing metadata for llvm.bpf.btf.type.id intrinsic"); 86 PreserveDITypeCalls.push_back(Call); 87 } 88 } 89 } 90 } 91 92 if (PreserveDITypeCalls.empty()) 93 return false; 94 95 std::string BaseName = "llvm.btf_type_id."; 96 int Count = 0; 97 for (auto Call : PreserveDITypeCalls) { 98 const ConstantInt *Flag = dyn_cast<ConstantInt>(Call->getArgOperand(2)); 99 assert(Flag); 100 uint64_t FlagValue = Flag->getValue().getZExtValue(); 101 102 if (FlagValue >= BPFCoreSharedInfo::MAX_BTF_TYPE_ID_FLAG) 103 report_fatal_error("Incorrect flag for llvm.bpf.btf.type.id intrinsic"); 104 105 uint32_t Reloc; 106 if (FlagValue == BPFCoreSharedInfo::BTF_TYPE_ID_LOCAL_RELOC) 107 Reloc = BPFCoreSharedInfo::BTF_TYPE_ID_LOCAL; 108 else 109 Reloc = BPFCoreSharedInfo::BTF_TYPE_ID_REMOTE; 110 111 BasicBlock *BB = Call->getParent(); 112 IntegerType *VarType = Type::getInt32Ty(BB->getContext()); 113 std::string GVName = BaseName + std::to_string(Count) + "$" + 114 std::to_string(Reloc); 115 GlobalVariable *GV = 116 new GlobalVariable(M, VarType, false, GlobalVariable::ExternalLinkage, 117 NULL, GVName); 118 GV->addAttribute(BPFCoreSharedInfo::TypeIdAttr); 119 MDNode *MD = Call->getMetadata(LLVMContext::MD_preserve_access_index); 120 GV->setMetadata(LLVMContext::MD_preserve_access_index, MD); 121 122 // Load the global variable which represents the type info. 123 auto *LDInst = new LoadInst(Type::getInt32Ty(BB->getContext()), GV, "", 124 Call); 125 Call->replaceAllUsesWith(LDInst); 126 Call->eraseFromParent(); 127 Count++; 128 } 129 130 return true; 131 } 132