1 //===------ BPFAbstractMemberAccess.cpp - Abstracting Member Accesses -----===// 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 // This pass abstracted struct/union member accesses in order to support 10 // compile-once run-everywhere (CO-RE). The CO-RE intends to compile the program 11 // which can run on different kernels. In particular, if bpf program tries to 12 // access a particular kernel data structure member, the details of the 13 // intermediate member access will be remembered so bpf loader can do 14 // necessary adjustment right before program loading. 15 // 16 // For example, 17 // 18 // struct s { 19 // int a; 20 // int b; 21 // }; 22 // struct t { 23 // struct s c; 24 // int d; 25 // }; 26 // struct t e; 27 // 28 // For the member access e.c.b, the compiler will generate code 29 // &e + 4 30 // 31 // The compile-once run-everywhere instead generates the following code 32 // r = 4 33 // &e + r 34 // The "4" in "r = 4" can be changed based on a particular kernel version. 35 // For example, on a particular kernel version, if struct s is changed to 36 // 37 // struct s { 38 // int new_field; 39 // int a; 40 // int b; 41 // } 42 // 43 // By repeating the member access on the host, the bpf loader can 44 // adjust "r = 4" as "r = 8". 45 // 46 // This feature relies on the following three intrinsic calls: 47 // addr = preserve_array_access_index(base, dimension, index) 48 // addr = preserve_union_access_index(base, di_index) 49 // !llvm.preserve.access.index <union_ditype> 50 // addr = preserve_struct_access_index(base, gep_index, di_index) 51 // !llvm.preserve.access.index <struct_ditype> 52 // 53 // Bitfield member access needs special attention. User cannot take the 54 // address of a bitfield acceess. To facilitate kernel verifier 55 // for easy bitfield code optimization, a new clang intrinsic is introduced: 56 // uint32_t __builtin_preserve_field_info(member_access, info_kind) 57 // In IR, a chain with two (or more) intrinsic calls will be generated: 58 // ... 59 // addr = preserve_struct_access_index(base, 1, 1) !struct s 60 // uint32_t result = bpf_preserve_field_info(addr, info_kind) 61 // 62 // Suppose the info_kind is FIELD_SIGNEDNESS, 63 // The above two IR intrinsics will be replaced with 64 // a relocatable insn: 65 // signness = /* signness of member_access */ 66 // and signness can be changed by bpf loader based on the 67 // types on the host. 68 // 69 // User can also test whether a field exists or not with 70 // uint32_t result = bpf_preserve_field_info(member_access, FIELD_EXISTENCE) 71 // The field will be always available (result = 1) during initial 72 // compilation, but bpf loader can patch with the correct value 73 // on the target host where the member_access may or may not be available 74 // 75 //===----------------------------------------------------------------------===// 76 77 #include "BPF.h" 78 #include "BPFCORE.h" 79 #include "BPFTargetMachine.h" 80 #include "llvm/BinaryFormat/Dwarf.h" 81 #include "llvm/IR/DebugInfoMetadata.h" 82 #include "llvm/IR/GlobalVariable.h" 83 #include "llvm/IR/Instruction.h" 84 #include "llvm/IR/Instructions.h" 85 #include "llvm/IR/IntrinsicsBPF.h" 86 #include "llvm/IR/Module.h" 87 #include "llvm/IR/PassManager.h" 88 #include "llvm/IR/Type.h" 89 #include "llvm/IR/User.h" 90 #include "llvm/IR/Value.h" 91 #include "llvm/Pass.h" 92 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 93 #include <stack> 94 95 #define DEBUG_TYPE "bpf-abstract-member-access" 96 97 namespace llvm { 98 constexpr StringRef BPFCoreSharedInfo::AmaAttr; 99 uint32_t BPFCoreSharedInfo::SeqNum; 100 101 Instruction *BPFCoreSharedInfo::insertPassThrough(Module *M, BasicBlock *BB, 102 Instruction *Input, 103 Instruction *Before) { 104 Function *Fn = Intrinsic::getDeclaration( 105 M, Intrinsic::bpf_passthrough, {Input->getType(), Input->getType()}); 106 Constant *SeqNumVal = ConstantInt::get(Type::getInt32Ty(BB->getContext()), 107 BPFCoreSharedInfo::SeqNum++); 108 109 auto *NewInst = CallInst::Create(Fn, {SeqNumVal, Input}); 110 BB->getInstList().insert(Before->getIterator(), NewInst); 111 return NewInst; 112 } 113 } // namespace llvm 114 115 using namespace llvm; 116 117 namespace { 118 class BPFAbstractMemberAccess final { 119 public: 120 BPFAbstractMemberAccess(BPFTargetMachine *TM) : TM(TM) {} 121 122 bool run(Function &F); 123 124 struct CallInfo { 125 uint32_t Kind; 126 uint32_t AccessIndex; 127 MaybeAlign RecordAlignment; 128 MDNode *Metadata; 129 Value *Base; 130 }; 131 typedef std::stack<std::pair<CallInst *, CallInfo>> CallInfoStack; 132 133 private: 134 enum : uint32_t { 135 BPFPreserveArrayAI = 1, 136 BPFPreserveUnionAI = 2, 137 BPFPreserveStructAI = 3, 138 BPFPreserveFieldInfoAI = 4, 139 }; 140 141 TargetMachine *TM; 142 const DataLayout *DL = nullptr; 143 Module *M = nullptr; 144 145 static std::map<std::string, GlobalVariable *> GEPGlobals; 146 // A map to link preserve_*_access_index intrinsic calls. 147 std::map<CallInst *, std::pair<CallInst *, CallInfo>> AIChain; 148 // A map to hold all the base preserve_*_access_index intrinsic calls. 149 // The base call is not an input of any other preserve_* 150 // intrinsics. 151 std::map<CallInst *, CallInfo> BaseAICalls; 152 153 bool doTransformation(Function &F); 154 155 void traceAICall(CallInst *Call, CallInfo &ParentInfo); 156 void traceBitCast(BitCastInst *BitCast, CallInst *Parent, 157 CallInfo &ParentInfo); 158 void traceGEP(GetElementPtrInst *GEP, CallInst *Parent, 159 CallInfo &ParentInfo); 160 void collectAICallChains(Function &F); 161 162 bool IsPreserveDIAccessIndexCall(const CallInst *Call, CallInfo &Cinfo); 163 bool IsValidAIChain(const MDNode *ParentMeta, uint32_t ParentAI, 164 const MDNode *ChildMeta); 165 bool removePreserveAccessIndexIntrinsic(Function &F); 166 void replaceWithGEP(std::vector<CallInst *> &CallList, 167 uint32_t NumOfZerosIndex, uint32_t DIIndex); 168 bool HasPreserveFieldInfoCall(CallInfoStack &CallStack); 169 void GetStorageBitRange(DIDerivedType *MemberTy, Align RecordAlignment, 170 uint32_t &StartBitOffset, uint32_t &EndBitOffset); 171 uint32_t GetFieldInfo(uint32_t InfoKind, DICompositeType *CTy, 172 uint32_t AccessIndex, uint32_t PatchImm, 173 MaybeAlign RecordAlignment); 174 175 Value *computeBaseAndAccessKey(CallInst *Call, CallInfo &CInfo, 176 std::string &AccessKey, MDNode *&BaseMeta); 177 MDNode *computeAccessKey(CallInst *Call, CallInfo &CInfo, 178 std::string &AccessKey, bool &IsInt32Ret); 179 uint64_t getConstant(const Value *IndexValue); 180 bool transformGEPChain(CallInst *Call, CallInfo &CInfo); 181 }; 182 183 std::map<std::string, GlobalVariable *> BPFAbstractMemberAccess::GEPGlobals; 184 185 class BPFAbstractMemberAccessLegacyPass final : public FunctionPass { 186 BPFTargetMachine *TM; 187 188 bool runOnFunction(Function &F) override { 189 return BPFAbstractMemberAccess(TM).run(F); 190 } 191 192 public: 193 static char ID; 194 195 // Add optional BPFTargetMachine parameter so that BPF backend can add the 196 // phase with target machine to find out the endianness. The default 197 // constructor (without parameters) is used by the pass manager for managing 198 // purposes. 199 BPFAbstractMemberAccessLegacyPass(BPFTargetMachine *TM = nullptr) 200 : FunctionPass(ID), TM(TM) {} 201 }; 202 203 } // End anonymous namespace 204 205 char BPFAbstractMemberAccessLegacyPass::ID = 0; 206 INITIALIZE_PASS(BPFAbstractMemberAccessLegacyPass, DEBUG_TYPE, 207 "BPF Abstract Member Access", false, false) 208 209 FunctionPass *llvm::createBPFAbstractMemberAccess(BPFTargetMachine *TM) { 210 return new BPFAbstractMemberAccessLegacyPass(TM); 211 } 212 213 bool BPFAbstractMemberAccess::run(Function &F) { 214 LLVM_DEBUG(dbgs() << "********** Abstract Member Accesses **********\n"); 215 216 M = F.getParent(); 217 if (!M) 218 return false; 219 220 // Bail out if no debug info. 221 if (M->debug_compile_units().empty()) 222 return false; 223 224 DL = &M->getDataLayout(); 225 return doTransformation(F); 226 } 227 228 static bool SkipDIDerivedTag(unsigned Tag, bool skipTypedef) { 229 if (Tag != dwarf::DW_TAG_typedef && Tag != dwarf::DW_TAG_const_type && 230 Tag != dwarf::DW_TAG_volatile_type && 231 Tag != dwarf::DW_TAG_restrict_type && 232 Tag != dwarf::DW_TAG_member) 233 return false; 234 if (Tag == dwarf::DW_TAG_typedef && !skipTypedef) 235 return false; 236 return true; 237 } 238 239 static DIType * stripQualifiers(DIType *Ty, bool skipTypedef = true) { 240 while (auto *DTy = dyn_cast<DIDerivedType>(Ty)) { 241 if (!SkipDIDerivedTag(DTy->getTag(), skipTypedef)) 242 break; 243 Ty = DTy->getBaseType(); 244 } 245 return Ty; 246 } 247 248 static const DIType * stripQualifiers(const DIType *Ty) { 249 while (auto *DTy = dyn_cast<DIDerivedType>(Ty)) { 250 if (!SkipDIDerivedTag(DTy->getTag(), true)) 251 break; 252 Ty = DTy->getBaseType(); 253 } 254 return Ty; 255 } 256 257 static uint32_t calcArraySize(const DICompositeType *CTy, uint32_t StartDim) { 258 DINodeArray Elements = CTy->getElements(); 259 uint32_t DimSize = 1; 260 for (uint32_t I = StartDim; I < Elements.size(); ++I) { 261 if (auto *Element = dyn_cast_or_null<DINode>(Elements[I])) 262 if (Element->getTag() == dwarf::DW_TAG_subrange_type) { 263 const DISubrange *SR = cast<DISubrange>(Element); 264 auto *CI = SR->getCount().dyn_cast<ConstantInt *>(); 265 DimSize *= CI->getSExtValue(); 266 } 267 } 268 269 return DimSize; 270 } 271 272 static Type *getBaseElementType(const CallInst *Call) { 273 // Element type is stored in an elementtype() attribute on the first param. 274 return Call->getParamElementType(0); 275 } 276 277 /// Check whether a call is a preserve_*_access_index intrinsic call or not. 278 bool BPFAbstractMemberAccess::IsPreserveDIAccessIndexCall(const CallInst *Call, 279 CallInfo &CInfo) { 280 if (!Call) 281 return false; 282 283 const auto *GV = dyn_cast<GlobalValue>(Call->getCalledOperand()); 284 if (!GV) 285 return false; 286 if (GV->getName().startswith("llvm.preserve.array.access.index")) { 287 CInfo.Kind = BPFPreserveArrayAI; 288 CInfo.Metadata = Call->getMetadata(LLVMContext::MD_preserve_access_index); 289 if (!CInfo.Metadata) 290 report_fatal_error("Missing metadata for llvm.preserve.array.access.index intrinsic"); 291 CInfo.AccessIndex = getConstant(Call->getArgOperand(2)); 292 CInfo.Base = Call->getArgOperand(0); 293 CInfo.RecordAlignment = DL->getABITypeAlign(getBaseElementType(Call)); 294 return true; 295 } 296 if (GV->getName().startswith("llvm.preserve.union.access.index")) { 297 CInfo.Kind = BPFPreserveUnionAI; 298 CInfo.Metadata = Call->getMetadata(LLVMContext::MD_preserve_access_index); 299 if (!CInfo.Metadata) 300 report_fatal_error("Missing metadata for llvm.preserve.union.access.index intrinsic"); 301 CInfo.AccessIndex = getConstant(Call->getArgOperand(1)); 302 CInfo.Base = Call->getArgOperand(0); 303 return true; 304 } 305 if (GV->getName().startswith("llvm.preserve.struct.access.index")) { 306 CInfo.Kind = BPFPreserveStructAI; 307 CInfo.Metadata = Call->getMetadata(LLVMContext::MD_preserve_access_index); 308 if (!CInfo.Metadata) 309 report_fatal_error("Missing metadata for llvm.preserve.struct.access.index intrinsic"); 310 CInfo.AccessIndex = getConstant(Call->getArgOperand(2)); 311 CInfo.Base = Call->getArgOperand(0); 312 CInfo.RecordAlignment = DL->getABITypeAlign(getBaseElementType(Call)); 313 return true; 314 } 315 if (GV->getName().startswith("llvm.bpf.preserve.field.info")) { 316 CInfo.Kind = BPFPreserveFieldInfoAI; 317 CInfo.Metadata = nullptr; 318 // Check validity of info_kind as clang did not check this. 319 uint64_t InfoKind = getConstant(Call->getArgOperand(1)); 320 if (InfoKind >= BPFCoreSharedInfo::MAX_FIELD_RELOC_KIND) 321 report_fatal_error("Incorrect info_kind for llvm.bpf.preserve.field.info intrinsic"); 322 CInfo.AccessIndex = InfoKind; 323 return true; 324 } 325 if (GV->getName().startswith("llvm.bpf.preserve.type.info")) { 326 CInfo.Kind = BPFPreserveFieldInfoAI; 327 CInfo.Metadata = Call->getMetadata(LLVMContext::MD_preserve_access_index); 328 if (!CInfo.Metadata) 329 report_fatal_error("Missing metadata for llvm.preserve.type.info intrinsic"); 330 uint64_t Flag = getConstant(Call->getArgOperand(1)); 331 if (Flag >= BPFCoreSharedInfo::MAX_PRESERVE_TYPE_INFO_FLAG) 332 report_fatal_error("Incorrect flag for llvm.bpf.preserve.type.info intrinsic"); 333 if (Flag == BPFCoreSharedInfo::PRESERVE_TYPE_INFO_EXISTENCE) 334 CInfo.AccessIndex = BPFCoreSharedInfo::TYPE_EXISTENCE; 335 else if (Flag == BPFCoreSharedInfo::PRESERVE_TYPE_INFO_MATCH) 336 CInfo.AccessIndex = BPFCoreSharedInfo::TYPE_MATCH; 337 else 338 CInfo.AccessIndex = BPFCoreSharedInfo::TYPE_SIZE; 339 return true; 340 } 341 if (GV->getName().startswith("llvm.bpf.preserve.enum.value")) { 342 CInfo.Kind = BPFPreserveFieldInfoAI; 343 CInfo.Metadata = Call->getMetadata(LLVMContext::MD_preserve_access_index); 344 if (!CInfo.Metadata) 345 report_fatal_error("Missing metadata for llvm.preserve.enum.value intrinsic"); 346 uint64_t Flag = getConstant(Call->getArgOperand(2)); 347 if (Flag >= BPFCoreSharedInfo::MAX_PRESERVE_ENUM_VALUE_FLAG) 348 report_fatal_error("Incorrect flag for llvm.bpf.preserve.enum.value intrinsic"); 349 if (Flag == BPFCoreSharedInfo::PRESERVE_ENUM_VALUE_EXISTENCE) 350 CInfo.AccessIndex = BPFCoreSharedInfo::ENUM_VALUE_EXISTENCE; 351 else 352 CInfo.AccessIndex = BPFCoreSharedInfo::ENUM_VALUE; 353 return true; 354 } 355 356 return false; 357 } 358 359 void BPFAbstractMemberAccess::replaceWithGEP(std::vector<CallInst *> &CallList, 360 uint32_t DimensionIndex, 361 uint32_t GEPIndex) { 362 for (auto Call : CallList) { 363 uint32_t Dimension = 1; 364 if (DimensionIndex > 0) 365 Dimension = getConstant(Call->getArgOperand(DimensionIndex)); 366 367 Constant *Zero = 368 ConstantInt::get(Type::getInt32Ty(Call->getParent()->getContext()), 0); 369 SmallVector<Value *, 4> IdxList; 370 for (unsigned I = 0; I < Dimension; ++I) 371 IdxList.push_back(Zero); 372 IdxList.push_back(Call->getArgOperand(GEPIndex)); 373 374 auto *GEP = GetElementPtrInst::CreateInBounds( 375 getBaseElementType(Call), Call->getArgOperand(0), IdxList, "", Call); 376 Call->replaceAllUsesWith(GEP); 377 Call->eraseFromParent(); 378 } 379 } 380 381 bool BPFAbstractMemberAccess::removePreserveAccessIndexIntrinsic(Function &F) { 382 std::vector<CallInst *> PreserveArrayIndexCalls; 383 std::vector<CallInst *> PreserveUnionIndexCalls; 384 std::vector<CallInst *> PreserveStructIndexCalls; 385 bool Found = false; 386 387 for (auto &BB : F) 388 for (auto &I : BB) { 389 auto *Call = dyn_cast<CallInst>(&I); 390 CallInfo CInfo; 391 if (!IsPreserveDIAccessIndexCall(Call, CInfo)) 392 continue; 393 394 Found = true; 395 if (CInfo.Kind == BPFPreserveArrayAI) 396 PreserveArrayIndexCalls.push_back(Call); 397 else if (CInfo.Kind == BPFPreserveUnionAI) 398 PreserveUnionIndexCalls.push_back(Call); 399 else 400 PreserveStructIndexCalls.push_back(Call); 401 } 402 403 // do the following transformation: 404 // . addr = preserve_array_access_index(base, dimension, index) 405 // is transformed to 406 // addr = GEP(base, dimenion's zero's, index) 407 // . addr = preserve_union_access_index(base, di_index) 408 // is transformed to 409 // addr = base, i.e., all usages of "addr" are replaced by "base". 410 // . addr = preserve_struct_access_index(base, gep_index, di_index) 411 // is transformed to 412 // addr = GEP(base, 0, gep_index) 413 replaceWithGEP(PreserveArrayIndexCalls, 1, 2); 414 replaceWithGEP(PreserveStructIndexCalls, 0, 1); 415 for (auto Call : PreserveUnionIndexCalls) { 416 Call->replaceAllUsesWith(Call->getArgOperand(0)); 417 Call->eraseFromParent(); 418 } 419 420 return Found; 421 } 422 423 /// Check whether the access index chain is valid. We check 424 /// here because there may be type casts between two 425 /// access indexes. We want to ensure memory access still valid. 426 bool BPFAbstractMemberAccess::IsValidAIChain(const MDNode *ParentType, 427 uint32_t ParentAI, 428 const MDNode *ChildType) { 429 if (!ChildType) 430 return true; // preserve_field_info, no type comparison needed. 431 432 const DIType *PType = stripQualifiers(cast<DIType>(ParentType)); 433 const DIType *CType = stripQualifiers(cast<DIType>(ChildType)); 434 435 // Child is a derived/pointer type, which is due to type casting. 436 // Pointer type cannot be in the middle of chain. 437 if (isa<DIDerivedType>(CType)) 438 return false; 439 440 // Parent is a pointer type. 441 if (const auto *PtrTy = dyn_cast<DIDerivedType>(PType)) { 442 if (PtrTy->getTag() != dwarf::DW_TAG_pointer_type) 443 return false; 444 return stripQualifiers(PtrTy->getBaseType()) == CType; 445 } 446 447 // Otherwise, struct/union/array types 448 const auto *PTy = dyn_cast<DICompositeType>(PType); 449 const auto *CTy = dyn_cast<DICompositeType>(CType); 450 assert(PTy && CTy && "ParentType or ChildType is null or not composite"); 451 452 uint32_t PTyTag = PTy->getTag(); 453 assert(PTyTag == dwarf::DW_TAG_array_type || 454 PTyTag == dwarf::DW_TAG_structure_type || 455 PTyTag == dwarf::DW_TAG_union_type); 456 457 uint32_t CTyTag = CTy->getTag(); 458 assert(CTyTag == dwarf::DW_TAG_array_type || 459 CTyTag == dwarf::DW_TAG_structure_type || 460 CTyTag == dwarf::DW_TAG_union_type); 461 462 // Multi dimensional arrays, base element should be the same 463 if (PTyTag == dwarf::DW_TAG_array_type && PTyTag == CTyTag) 464 return PTy->getBaseType() == CTy->getBaseType(); 465 466 DIType *Ty; 467 if (PTyTag == dwarf::DW_TAG_array_type) 468 Ty = PTy->getBaseType(); 469 else 470 Ty = dyn_cast<DIType>(PTy->getElements()[ParentAI]); 471 472 return dyn_cast<DICompositeType>(stripQualifiers(Ty)) == CTy; 473 } 474 475 void BPFAbstractMemberAccess::traceAICall(CallInst *Call, 476 CallInfo &ParentInfo) { 477 for (User *U : Call->users()) { 478 Instruction *Inst = dyn_cast<Instruction>(U); 479 if (!Inst) 480 continue; 481 482 if (auto *BI = dyn_cast<BitCastInst>(Inst)) { 483 traceBitCast(BI, Call, ParentInfo); 484 } else if (auto *CI = dyn_cast<CallInst>(Inst)) { 485 CallInfo ChildInfo; 486 487 if (IsPreserveDIAccessIndexCall(CI, ChildInfo) && 488 IsValidAIChain(ParentInfo.Metadata, ParentInfo.AccessIndex, 489 ChildInfo.Metadata)) { 490 AIChain[CI] = std::make_pair(Call, ParentInfo); 491 traceAICall(CI, ChildInfo); 492 } else { 493 BaseAICalls[Call] = ParentInfo; 494 } 495 } else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) { 496 if (GI->hasAllZeroIndices()) 497 traceGEP(GI, Call, ParentInfo); 498 else 499 BaseAICalls[Call] = ParentInfo; 500 } else { 501 BaseAICalls[Call] = ParentInfo; 502 } 503 } 504 } 505 506 void BPFAbstractMemberAccess::traceBitCast(BitCastInst *BitCast, 507 CallInst *Parent, 508 CallInfo &ParentInfo) { 509 for (User *U : BitCast->users()) { 510 Instruction *Inst = dyn_cast<Instruction>(U); 511 if (!Inst) 512 continue; 513 514 if (auto *BI = dyn_cast<BitCastInst>(Inst)) { 515 traceBitCast(BI, Parent, ParentInfo); 516 } else if (auto *CI = dyn_cast<CallInst>(Inst)) { 517 CallInfo ChildInfo; 518 if (IsPreserveDIAccessIndexCall(CI, ChildInfo) && 519 IsValidAIChain(ParentInfo.Metadata, ParentInfo.AccessIndex, 520 ChildInfo.Metadata)) { 521 AIChain[CI] = std::make_pair(Parent, ParentInfo); 522 traceAICall(CI, ChildInfo); 523 } else { 524 BaseAICalls[Parent] = ParentInfo; 525 } 526 } else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) { 527 if (GI->hasAllZeroIndices()) 528 traceGEP(GI, Parent, ParentInfo); 529 else 530 BaseAICalls[Parent] = ParentInfo; 531 } else { 532 BaseAICalls[Parent] = ParentInfo; 533 } 534 } 535 } 536 537 void BPFAbstractMemberAccess::traceGEP(GetElementPtrInst *GEP, CallInst *Parent, 538 CallInfo &ParentInfo) { 539 for (User *U : GEP->users()) { 540 Instruction *Inst = dyn_cast<Instruction>(U); 541 if (!Inst) 542 continue; 543 544 if (auto *BI = dyn_cast<BitCastInst>(Inst)) { 545 traceBitCast(BI, Parent, ParentInfo); 546 } else if (auto *CI = dyn_cast<CallInst>(Inst)) { 547 CallInfo ChildInfo; 548 if (IsPreserveDIAccessIndexCall(CI, ChildInfo) && 549 IsValidAIChain(ParentInfo.Metadata, ParentInfo.AccessIndex, 550 ChildInfo.Metadata)) { 551 AIChain[CI] = std::make_pair(Parent, ParentInfo); 552 traceAICall(CI, ChildInfo); 553 } else { 554 BaseAICalls[Parent] = ParentInfo; 555 } 556 } else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) { 557 if (GI->hasAllZeroIndices()) 558 traceGEP(GI, Parent, ParentInfo); 559 else 560 BaseAICalls[Parent] = ParentInfo; 561 } else { 562 BaseAICalls[Parent] = ParentInfo; 563 } 564 } 565 } 566 567 void BPFAbstractMemberAccess::collectAICallChains(Function &F) { 568 AIChain.clear(); 569 BaseAICalls.clear(); 570 571 for (auto &BB : F) 572 for (auto &I : BB) { 573 CallInfo CInfo; 574 auto *Call = dyn_cast<CallInst>(&I); 575 if (!IsPreserveDIAccessIndexCall(Call, CInfo) || 576 AIChain.find(Call) != AIChain.end()) 577 continue; 578 579 traceAICall(Call, CInfo); 580 } 581 } 582 583 uint64_t BPFAbstractMemberAccess::getConstant(const Value *IndexValue) { 584 const ConstantInt *CV = dyn_cast<ConstantInt>(IndexValue); 585 assert(CV); 586 return CV->getValue().getZExtValue(); 587 } 588 589 /// Get the start and the end of storage offset for \p MemberTy. 590 void BPFAbstractMemberAccess::GetStorageBitRange(DIDerivedType *MemberTy, 591 Align RecordAlignment, 592 uint32_t &StartBitOffset, 593 uint32_t &EndBitOffset) { 594 uint32_t MemberBitSize = MemberTy->getSizeInBits(); 595 uint32_t MemberBitOffset = MemberTy->getOffsetInBits(); 596 597 if (RecordAlignment > 8) { 598 // If the Bits are within an aligned 8-byte, set the RecordAlignment 599 // to 8, other report the fatal error. 600 if (MemberBitOffset / 64 != (MemberBitOffset + MemberBitSize) / 64) 601 report_fatal_error("Unsupported field expression for llvm.bpf.preserve.field.info, " 602 "requiring too big alignment"); 603 RecordAlignment = Align(8); 604 } 605 606 uint32_t AlignBits = RecordAlignment.value() * 8; 607 if (MemberBitSize > AlignBits) 608 report_fatal_error("Unsupported field expression for llvm.bpf.preserve.field.info, " 609 "bitfield size greater than record alignment"); 610 611 StartBitOffset = MemberBitOffset & ~(AlignBits - 1); 612 if ((StartBitOffset + AlignBits) < (MemberBitOffset + MemberBitSize)) 613 report_fatal_error("Unsupported field expression for llvm.bpf.preserve.field.info, " 614 "cross alignment boundary"); 615 EndBitOffset = StartBitOffset + AlignBits; 616 } 617 618 uint32_t BPFAbstractMemberAccess::GetFieldInfo(uint32_t InfoKind, 619 DICompositeType *CTy, 620 uint32_t AccessIndex, 621 uint32_t PatchImm, 622 MaybeAlign RecordAlignment) { 623 if (InfoKind == BPFCoreSharedInfo::FIELD_EXISTENCE) 624 return 1; 625 626 uint32_t Tag = CTy->getTag(); 627 if (InfoKind == BPFCoreSharedInfo::FIELD_BYTE_OFFSET) { 628 if (Tag == dwarf::DW_TAG_array_type) { 629 auto *EltTy = stripQualifiers(CTy->getBaseType()); 630 PatchImm += AccessIndex * calcArraySize(CTy, 1) * 631 (EltTy->getSizeInBits() >> 3); 632 } else if (Tag == dwarf::DW_TAG_structure_type) { 633 auto *MemberTy = cast<DIDerivedType>(CTy->getElements()[AccessIndex]); 634 if (!MemberTy->isBitField()) { 635 PatchImm += MemberTy->getOffsetInBits() >> 3; 636 } else { 637 unsigned SBitOffset, NextSBitOffset; 638 GetStorageBitRange(MemberTy, *RecordAlignment, SBitOffset, 639 NextSBitOffset); 640 PatchImm += SBitOffset >> 3; 641 } 642 } 643 return PatchImm; 644 } 645 646 if (InfoKind == BPFCoreSharedInfo::FIELD_BYTE_SIZE) { 647 if (Tag == dwarf::DW_TAG_array_type) { 648 auto *EltTy = stripQualifiers(CTy->getBaseType()); 649 return calcArraySize(CTy, 1) * (EltTy->getSizeInBits() >> 3); 650 } else { 651 auto *MemberTy = cast<DIDerivedType>(CTy->getElements()[AccessIndex]); 652 uint32_t SizeInBits = MemberTy->getSizeInBits(); 653 if (!MemberTy->isBitField()) 654 return SizeInBits >> 3; 655 656 unsigned SBitOffset, NextSBitOffset; 657 GetStorageBitRange(MemberTy, *RecordAlignment, SBitOffset, 658 NextSBitOffset); 659 SizeInBits = NextSBitOffset - SBitOffset; 660 if (SizeInBits & (SizeInBits - 1)) 661 report_fatal_error("Unsupported field expression for llvm.bpf.preserve.field.info"); 662 return SizeInBits >> 3; 663 } 664 } 665 666 if (InfoKind == BPFCoreSharedInfo::FIELD_SIGNEDNESS) { 667 const DIType *BaseTy; 668 if (Tag == dwarf::DW_TAG_array_type) { 669 // Signedness only checked when final array elements are accessed. 670 if (CTy->getElements().size() != 1) 671 report_fatal_error("Invalid array expression for llvm.bpf.preserve.field.info"); 672 BaseTy = stripQualifiers(CTy->getBaseType()); 673 } else { 674 auto *MemberTy = cast<DIDerivedType>(CTy->getElements()[AccessIndex]); 675 BaseTy = stripQualifiers(MemberTy->getBaseType()); 676 } 677 678 // Only basic types and enum types have signedness. 679 const auto *BTy = dyn_cast<DIBasicType>(BaseTy); 680 while (!BTy) { 681 const auto *CompTy = dyn_cast<DICompositeType>(BaseTy); 682 // Report an error if the field expression does not have signedness. 683 if (!CompTy || CompTy->getTag() != dwarf::DW_TAG_enumeration_type) 684 report_fatal_error("Invalid field expression for llvm.bpf.preserve.field.info"); 685 BaseTy = stripQualifiers(CompTy->getBaseType()); 686 BTy = dyn_cast<DIBasicType>(BaseTy); 687 } 688 uint32_t Encoding = BTy->getEncoding(); 689 return (Encoding == dwarf::DW_ATE_signed || Encoding == dwarf::DW_ATE_signed_char); 690 } 691 692 if (InfoKind == BPFCoreSharedInfo::FIELD_LSHIFT_U64) { 693 // The value is loaded into a value with FIELD_BYTE_SIZE size, 694 // and then zero or sign extended to U64. 695 // FIELD_LSHIFT_U64 and FIELD_RSHIFT_U64 are operations 696 // to extract the original value. 697 const Triple &Triple = TM->getTargetTriple(); 698 DIDerivedType *MemberTy = nullptr; 699 bool IsBitField = false; 700 uint32_t SizeInBits; 701 702 if (Tag == dwarf::DW_TAG_array_type) { 703 auto *EltTy = stripQualifiers(CTy->getBaseType()); 704 SizeInBits = calcArraySize(CTy, 1) * EltTy->getSizeInBits(); 705 } else { 706 MemberTy = cast<DIDerivedType>(CTy->getElements()[AccessIndex]); 707 SizeInBits = MemberTy->getSizeInBits(); 708 IsBitField = MemberTy->isBitField(); 709 } 710 711 if (!IsBitField) { 712 if (SizeInBits > 64) 713 report_fatal_error("too big field size for llvm.bpf.preserve.field.info"); 714 return 64 - SizeInBits; 715 } 716 717 unsigned SBitOffset, NextSBitOffset; 718 GetStorageBitRange(MemberTy, *RecordAlignment, SBitOffset, NextSBitOffset); 719 if (NextSBitOffset - SBitOffset > 64) 720 report_fatal_error("too big field size for llvm.bpf.preserve.field.info"); 721 722 unsigned OffsetInBits = MemberTy->getOffsetInBits(); 723 if (Triple.getArch() == Triple::bpfel) 724 return SBitOffset + 64 - OffsetInBits - SizeInBits; 725 else 726 return OffsetInBits + 64 - NextSBitOffset; 727 } 728 729 if (InfoKind == BPFCoreSharedInfo::FIELD_RSHIFT_U64) { 730 DIDerivedType *MemberTy = nullptr; 731 bool IsBitField = false; 732 uint32_t SizeInBits; 733 if (Tag == dwarf::DW_TAG_array_type) { 734 auto *EltTy = stripQualifiers(CTy->getBaseType()); 735 SizeInBits = calcArraySize(CTy, 1) * EltTy->getSizeInBits(); 736 } else { 737 MemberTy = cast<DIDerivedType>(CTy->getElements()[AccessIndex]); 738 SizeInBits = MemberTy->getSizeInBits(); 739 IsBitField = MemberTy->isBitField(); 740 } 741 742 if (!IsBitField) { 743 if (SizeInBits > 64) 744 report_fatal_error("too big field size for llvm.bpf.preserve.field.info"); 745 return 64 - SizeInBits; 746 } 747 748 unsigned SBitOffset, NextSBitOffset; 749 GetStorageBitRange(MemberTy, *RecordAlignment, SBitOffset, NextSBitOffset); 750 if (NextSBitOffset - SBitOffset > 64) 751 report_fatal_error("too big field size for llvm.bpf.preserve.field.info"); 752 753 return 64 - SizeInBits; 754 } 755 756 llvm_unreachable("Unknown llvm.bpf.preserve.field.info info kind"); 757 } 758 759 bool BPFAbstractMemberAccess::HasPreserveFieldInfoCall(CallInfoStack &CallStack) { 760 // This is called in error return path, no need to maintain CallStack. 761 while (CallStack.size()) { 762 auto StackElem = CallStack.top(); 763 if (StackElem.second.Kind == BPFPreserveFieldInfoAI) 764 return true; 765 CallStack.pop(); 766 } 767 return false; 768 } 769 770 /// Compute the base of the whole preserve_* intrinsics chains, i.e., the base 771 /// pointer of the first preserve_*_access_index call, and construct the access 772 /// string, which will be the name of a global variable. 773 Value *BPFAbstractMemberAccess::computeBaseAndAccessKey(CallInst *Call, 774 CallInfo &CInfo, 775 std::string &AccessKey, 776 MDNode *&TypeMeta) { 777 Value *Base = nullptr; 778 std::string TypeName; 779 CallInfoStack CallStack; 780 781 // Put the access chain into a stack with the top as the head of the chain. 782 while (Call) { 783 CallStack.push(std::make_pair(Call, CInfo)); 784 CInfo = AIChain[Call].second; 785 Call = AIChain[Call].first; 786 } 787 788 // The access offset from the base of the head of chain is also 789 // calculated here as all debuginfo types are available. 790 791 // Get type name and calculate the first index. 792 // We only want to get type name from typedef, structure or union. 793 // If user wants a relocation like 794 // int *p; ... __builtin_preserve_access_index(&p[4]) ... 795 // or 796 // int a[10][20]; ... __builtin_preserve_access_index(&a[2][3]) ... 797 // we will skip them. 798 uint32_t FirstIndex = 0; 799 uint32_t PatchImm = 0; // AccessOffset or the requested field info 800 uint32_t InfoKind = BPFCoreSharedInfo::FIELD_BYTE_OFFSET; 801 while (CallStack.size()) { 802 auto StackElem = CallStack.top(); 803 Call = StackElem.first; 804 CInfo = StackElem.second; 805 806 if (!Base) 807 Base = CInfo.Base; 808 809 DIType *PossibleTypeDef = stripQualifiers(cast<DIType>(CInfo.Metadata), 810 false); 811 DIType *Ty = stripQualifiers(PossibleTypeDef); 812 if (CInfo.Kind == BPFPreserveUnionAI || 813 CInfo.Kind == BPFPreserveStructAI) { 814 // struct or union type. If the typedef is in the metadata, always 815 // use the typedef. 816 TypeName = std::string(PossibleTypeDef->getName()); 817 TypeMeta = PossibleTypeDef; 818 PatchImm += FirstIndex * (Ty->getSizeInBits() >> 3); 819 break; 820 } 821 822 assert(CInfo.Kind == BPFPreserveArrayAI); 823 824 // Array entries will always be consumed for accumulative initial index. 825 CallStack.pop(); 826 827 // BPFPreserveArrayAI 828 uint64_t AccessIndex = CInfo.AccessIndex; 829 830 DIType *BaseTy = nullptr; 831 bool CheckElemType = false; 832 if (const auto *CTy = dyn_cast<DICompositeType>(Ty)) { 833 // array type 834 assert(CTy->getTag() == dwarf::DW_TAG_array_type); 835 836 837 FirstIndex += AccessIndex * calcArraySize(CTy, 1); 838 BaseTy = stripQualifiers(CTy->getBaseType()); 839 CheckElemType = CTy->getElements().size() == 1; 840 } else { 841 // pointer type 842 auto *DTy = cast<DIDerivedType>(Ty); 843 assert(DTy->getTag() == dwarf::DW_TAG_pointer_type); 844 845 BaseTy = stripQualifiers(DTy->getBaseType()); 846 CTy = dyn_cast<DICompositeType>(BaseTy); 847 if (!CTy) { 848 CheckElemType = true; 849 } else if (CTy->getTag() != dwarf::DW_TAG_array_type) { 850 FirstIndex += AccessIndex; 851 CheckElemType = true; 852 } else { 853 FirstIndex += AccessIndex * calcArraySize(CTy, 0); 854 } 855 } 856 857 if (CheckElemType) { 858 auto *CTy = dyn_cast<DICompositeType>(BaseTy); 859 if (!CTy) { 860 if (HasPreserveFieldInfoCall(CallStack)) 861 report_fatal_error("Invalid field access for llvm.preserve.field.info intrinsic"); 862 return nullptr; 863 } 864 865 unsigned CTag = CTy->getTag(); 866 if (CTag == dwarf::DW_TAG_structure_type || CTag == dwarf::DW_TAG_union_type) { 867 TypeName = std::string(CTy->getName()); 868 } else { 869 if (HasPreserveFieldInfoCall(CallStack)) 870 report_fatal_error("Invalid field access for llvm.preserve.field.info intrinsic"); 871 return nullptr; 872 } 873 TypeMeta = CTy; 874 PatchImm += FirstIndex * (CTy->getSizeInBits() >> 3); 875 break; 876 } 877 } 878 assert(TypeName.size()); 879 AccessKey += std::to_string(FirstIndex); 880 881 // Traverse the rest of access chain to complete offset calculation 882 // and access key construction. 883 while (CallStack.size()) { 884 auto StackElem = CallStack.top(); 885 CInfo = StackElem.second; 886 CallStack.pop(); 887 888 if (CInfo.Kind == BPFPreserveFieldInfoAI) { 889 InfoKind = CInfo.AccessIndex; 890 if (InfoKind == BPFCoreSharedInfo::FIELD_EXISTENCE) 891 PatchImm = 1; 892 break; 893 } 894 895 // If the next Call (the top of the stack) is a BPFPreserveFieldInfoAI, 896 // the action will be extracting field info. 897 if (CallStack.size()) { 898 auto StackElem2 = CallStack.top(); 899 CallInfo CInfo2 = StackElem2.second; 900 if (CInfo2.Kind == BPFPreserveFieldInfoAI) { 901 InfoKind = CInfo2.AccessIndex; 902 assert(CallStack.size() == 1); 903 } 904 } 905 906 // Access Index 907 uint64_t AccessIndex = CInfo.AccessIndex; 908 AccessKey += ":" + std::to_string(AccessIndex); 909 910 MDNode *MDN = CInfo.Metadata; 911 // At this stage, it cannot be pointer type. 912 auto *CTy = cast<DICompositeType>(stripQualifiers(cast<DIType>(MDN))); 913 PatchImm = GetFieldInfo(InfoKind, CTy, AccessIndex, PatchImm, 914 CInfo.RecordAlignment); 915 } 916 917 // Access key is the 918 // "llvm." + type name + ":" + reloc type + ":" + patched imm + "$" + 919 // access string, 920 // uniquely identifying one relocation. 921 // The prefix "llvm." indicates this is a temporary global, which should 922 // not be emitted to ELF file. 923 AccessKey = "llvm." + TypeName + ":" + std::to_string(InfoKind) + ":" + 924 std::to_string(PatchImm) + "$" + AccessKey; 925 926 return Base; 927 } 928 929 MDNode *BPFAbstractMemberAccess::computeAccessKey(CallInst *Call, 930 CallInfo &CInfo, 931 std::string &AccessKey, 932 bool &IsInt32Ret) { 933 DIType *Ty = stripQualifiers(cast<DIType>(CInfo.Metadata), false); 934 assert(!Ty->getName().empty()); 935 936 int64_t PatchImm; 937 std::string AccessStr("0"); 938 if (CInfo.AccessIndex == BPFCoreSharedInfo::TYPE_EXISTENCE || 939 CInfo.AccessIndex == BPFCoreSharedInfo::TYPE_MATCH) { 940 PatchImm = 1; 941 } else if (CInfo.AccessIndex == BPFCoreSharedInfo::TYPE_SIZE) { 942 // typedef debuginfo type has size 0, get the eventual base type. 943 DIType *BaseTy = stripQualifiers(Ty, true); 944 PatchImm = BaseTy->getSizeInBits() / 8; 945 } else { 946 // ENUM_VALUE_EXISTENCE and ENUM_VALUE 947 IsInt32Ret = false; 948 949 // The argument could be a global variable or a getelementptr with base to 950 // a global variable depending on whether the clang option `opaque-options` 951 // is set or not. 952 const GlobalVariable *GV = 953 cast<GlobalVariable>(Call->getArgOperand(1)->stripPointerCasts()); 954 assert(GV->hasInitializer()); 955 const ConstantDataArray *DA = cast<ConstantDataArray>(GV->getInitializer()); 956 assert(DA->isString()); 957 StringRef ValueStr = DA->getAsString(); 958 959 // ValueStr format: <EnumeratorStr>:<Value> 960 size_t Separator = ValueStr.find_first_of(':'); 961 StringRef EnumeratorStr = ValueStr.substr(0, Separator); 962 963 // Find enumerator index in the debuginfo 964 DIType *BaseTy = stripQualifiers(Ty, true); 965 const auto *CTy = cast<DICompositeType>(BaseTy); 966 assert(CTy->getTag() == dwarf::DW_TAG_enumeration_type); 967 int EnumIndex = 0; 968 for (const auto Element : CTy->getElements()) { 969 const auto *Enum = cast<DIEnumerator>(Element); 970 if (Enum->getName() == EnumeratorStr) { 971 AccessStr = std::to_string(EnumIndex); 972 break; 973 } 974 EnumIndex++; 975 } 976 977 if (CInfo.AccessIndex == BPFCoreSharedInfo::ENUM_VALUE) { 978 StringRef EValueStr = ValueStr.substr(Separator + 1); 979 PatchImm = std::stoll(std::string(EValueStr)); 980 } else { 981 PatchImm = 1; 982 } 983 } 984 985 AccessKey = "llvm." + Ty->getName().str() + ":" + 986 std::to_string(CInfo.AccessIndex) + std::string(":") + 987 std::to_string(PatchImm) + std::string("$") + AccessStr; 988 989 return Ty; 990 } 991 992 /// Call/Kind is the base preserve_*_access_index() call. Attempts to do 993 /// transformation to a chain of relocable GEPs. 994 bool BPFAbstractMemberAccess::transformGEPChain(CallInst *Call, 995 CallInfo &CInfo) { 996 std::string AccessKey; 997 MDNode *TypeMeta; 998 Value *Base = nullptr; 999 bool IsInt32Ret; 1000 1001 IsInt32Ret = CInfo.Kind == BPFPreserveFieldInfoAI; 1002 if (CInfo.Kind == BPFPreserveFieldInfoAI && CInfo.Metadata) { 1003 TypeMeta = computeAccessKey(Call, CInfo, AccessKey, IsInt32Ret); 1004 } else { 1005 Base = computeBaseAndAccessKey(Call, CInfo, AccessKey, TypeMeta); 1006 if (!Base) 1007 return false; 1008 } 1009 1010 BasicBlock *BB = Call->getParent(); 1011 GlobalVariable *GV; 1012 1013 if (GEPGlobals.find(AccessKey) == GEPGlobals.end()) { 1014 IntegerType *VarType; 1015 if (IsInt32Ret) 1016 VarType = Type::getInt32Ty(BB->getContext()); // 32bit return value 1017 else 1018 VarType = Type::getInt64Ty(BB->getContext()); // 64bit ptr or enum value 1019 1020 GV = new GlobalVariable(*M, VarType, false, GlobalVariable::ExternalLinkage, 1021 nullptr, AccessKey); 1022 GV->addAttribute(BPFCoreSharedInfo::AmaAttr); 1023 GV->setMetadata(LLVMContext::MD_preserve_access_index, TypeMeta); 1024 GEPGlobals[AccessKey] = GV; 1025 } else { 1026 GV = GEPGlobals[AccessKey]; 1027 } 1028 1029 if (CInfo.Kind == BPFPreserveFieldInfoAI) { 1030 // Load the global variable which represents the returned field info. 1031 LoadInst *LDInst; 1032 if (IsInt32Ret) 1033 LDInst = new LoadInst(Type::getInt32Ty(BB->getContext()), GV, "", Call); 1034 else 1035 LDInst = new LoadInst(Type::getInt64Ty(BB->getContext()), GV, "", Call); 1036 1037 Instruction *PassThroughInst = 1038 BPFCoreSharedInfo::insertPassThrough(M, BB, LDInst, Call); 1039 Call->replaceAllUsesWith(PassThroughInst); 1040 Call->eraseFromParent(); 1041 return true; 1042 } 1043 1044 // For any original GEP Call and Base %2 like 1045 // %4 = bitcast %struct.net_device** %dev1 to i64* 1046 // it is transformed to: 1047 // %6 = load llvm.sk_buff:0:50$0:0:0:2:0 1048 // %7 = bitcast %struct.sk_buff* %2 to i8* 1049 // %8 = getelementptr i8, i8* %7, %6 1050 // %9 = bitcast i8* %8 to i64* 1051 // using %9 instead of %4 1052 // The original Call inst is removed. 1053 1054 // Load the global variable. 1055 auto *LDInst = new LoadInst(Type::getInt64Ty(BB->getContext()), GV, "", Call); 1056 1057 // Generate a BitCast 1058 auto *BCInst = new BitCastInst(Base, Type::getInt8PtrTy(BB->getContext())); 1059 BB->getInstList().insert(Call->getIterator(), BCInst); 1060 1061 // Generate a GetElementPtr 1062 auto *GEP = GetElementPtrInst::Create(Type::getInt8Ty(BB->getContext()), 1063 BCInst, LDInst); 1064 BB->getInstList().insert(Call->getIterator(), GEP); 1065 1066 // Generate a BitCast 1067 auto *BCInst2 = new BitCastInst(GEP, Call->getType()); 1068 BB->getInstList().insert(Call->getIterator(), BCInst2); 1069 1070 // For the following code, 1071 // Block0: 1072 // ... 1073 // if (...) goto Block1 else ... 1074 // Block1: 1075 // %6 = load llvm.sk_buff:0:50$0:0:0:2:0 1076 // %7 = bitcast %struct.sk_buff* %2 to i8* 1077 // %8 = getelementptr i8, i8* %7, %6 1078 // ... 1079 // goto CommonExit 1080 // Block2: 1081 // ... 1082 // if (...) goto Block3 else ... 1083 // Block3: 1084 // %6 = load llvm.bpf_map:0:40$0:0:0:2:0 1085 // %7 = bitcast %struct.sk_buff* %2 to i8* 1086 // %8 = getelementptr i8, i8* %7, %6 1087 // ... 1088 // goto CommonExit 1089 // CommonExit 1090 // SimplifyCFG may generate: 1091 // Block0: 1092 // ... 1093 // if (...) goto Block_Common else ... 1094 // Block2: 1095 // ... 1096 // if (...) goto Block_Common else ... 1097 // Block_Common: 1098 // PHI = [llvm.sk_buff:0:50$0:0:0:2:0, llvm.bpf_map:0:40$0:0:0:2:0] 1099 // %6 = load PHI 1100 // %7 = bitcast %struct.sk_buff* %2 to i8* 1101 // %8 = getelementptr i8, i8* %7, %6 1102 // ... 1103 // goto CommonExit 1104 // For the above code, we cannot perform proper relocation since 1105 // "load PHI" has two possible relocations. 1106 // 1107 // To prevent above tail merging, we use __builtin_bpf_passthrough() 1108 // where one of its parameters is a seq_num. Since two 1109 // __builtin_bpf_passthrough() funcs will always have different seq_num, 1110 // tail merging cannot happen. The __builtin_bpf_passthrough() will be 1111 // removed in the beginning of Target IR passes. 1112 // 1113 // This approach is also used in other places when global var 1114 // representing a relocation is used. 1115 Instruction *PassThroughInst = 1116 BPFCoreSharedInfo::insertPassThrough(M, BB, BCInst2, Call); 1117 Call->replaceAllUsesWith(PassThroughInst); 1118 Call->eraseFromParent(); 1119 1120 return true; 1121 } 1122 1123 bool BPFAbstractMemberAccess::doTransformation(Function &F) { 1124 bool Transformed = false; 1125 1126 // Collect PreserveDIAccessIndex Intrinsic call chains. 1127 // The call chains will be used to generate the access 1128 // patterns similar to GEP. 1129 collectAICallChains(F); 1130 1131 for (auto &C : BaseAICalls) 1132 Transformed = transformGEPChain(C.first, C.second) || Transformed; 1133 1134 return removePreserveAccessIndexIntrinsic(F) || Transformed; 1135 } 1136 1137 PreservedAnalyses 1138 BPFAbstractMemberAccessPass::run(Function &F, FunctionAnalysisManager &AM) { 1139 return BPFAbstractMemberAccess(TM).run(F) ? PreservedAnalyses::none() 1140 : PreservedAnalyses::all(); 1141 } 1142