1 //===- SanitizerBinaryMetadata.cpp 2 //----------------------------------------------===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file is a part of SanitizerBinaryMetadata. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/CodeGen/SanitizerBinaryMetadata.h" 15 #include "llvm/CodeGen/MachineFrameInfo.h" 16 #include "llvm/CodeGen/MachineFunction.h" 17 #include "llvm/CodeGen/MachineFunctionPass.h" 18 #include "llvm/CodeGen/Passes.h" 19 #include "llvm/IR/IRBuilder.h" 20 #include "llvm/IR/MDBuilder.h" 21 #include "llvm/InitializePasses.h" 22 #include "llvm/Pass.h" 23 #include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h" 24 #include <algorithm> 25 26 using namespace llvm; 27 28 namespace { 29 // FIXME: This pass modifies Function metadata, which is not to be done in 30 // MachineFunctionPass. It should probably be moved to a FunctionPass. 31 class MachineSanitizerBinaryMetadataLegacy : public MachineFunctionPass { 32 public: 33 static char ID; 34 35 MachineSanitizerBinaryMetadataLegacy(); 36 bool runOnMachineFunction(MachineFunction &F) override; 37 }; 38 39 struct MachineSanitizerBinaryMetadata { 40 bool run(MachineFunction &MF); 41 }; 42 43 } // namespace 44 45 INITIALIZE_PASS(MachineSanitizerBinaryMetadataLegacy, "machine-sanmd", 46 "Machine Sanitizer Binary Metadata", false, false) 47 48 char MachineSanitizerBinaryMetadataLegacy::ID = 0; 49 char &llvm::MachineSanitizerBinaryMetadataID = 50 MachineSanitizerBinaryMetadataLegacy::ID; 51 52 MachineSanitizerBinaryMetadataLegacy::MachineSanitizerBinaryMetadataLegacy() 53 : MachineFunctionPass(ID) { 54 initializeMachineSanitizerBinaryMetadataLegacyPass( 55 *PassRegistry::getPassRegistry()); 56 } 57 58 bool MachineSanitizerBinaryMetadataLegacy::runOnMachineFunction( 59 MachineFunction &MF) { 60 return MachineSanitizerBinaryMetadata().run(MF); 61 } 62 63 PreservedAnalyses 64 MachineSanitizerBinaryMetadataPass::run(MachineFunction &MF, 65 MachineFunctionAnalysisManager &MFAM) { 66 if (!MachineSanitizerBinaryMetadata().run(MF)) 67 return PreservedAnalyses::all(); 68 69 return getMachineFunctionPassPreservedAnalyses(); 70 } 71 72 bool MachineSanitizerBinaryMetadata::run(MachineFunction &MF) { 73 MDNode *MD = MF.getFunction().getMetadata(LLVMContext::MD_pcsections); 74 if (!MD) 75 return false; 76 const auto &Section = *cast<MDString>(MD->getOperand(0)); 77 if (!Section.getString().starts_with(kSanitizerBinaryMetadataCoveredSection)) 78 return false; 79 auto &AuxMDs = *cast<MDTuple>(MD->getOperand(1)); 80 // Assume it currently only has features. 81 assert(AuxMDs.getNumOperands() == 1); 82 Constant *Features = 83 cast<ConstantAsMetadata>(AuxMDs.getOperand(0))->getValue(); 84 if (!Features->getUniqueInteger()[kSanitizerBinaryMetadataUARBit]) 85 return false; 86 // Calculate size of stack args for the function. 87 int64_t Size = 0; 88 uint64_t Align = 0; 89 const MachineFrameInfo &MFI = MF.getFrameInfo(); 90 for (int i = -1; i >= (int)-MFI.getNumFixedObjects(); --i) { 91 Size = std::max(Size, MFI.getObjectOffset(i) + MFI.getObjectSize(i)); 92 Align = std::max(Align, MFI.getObjectAlign(i).value()); 93 } 94 Size = (Size + Align - 1) & ~(Align - 1); 95 if (!Size) 96 return false; 97 // Non-zero size, update metadata. 98 auto &F = MF.getFunction(); 99 IRBuilder<> IRB(F.getContext()); 100 MDBuilder MDB(F.getContext()); 101 // Keep the features and append size of stack args to the metadata. 102 APInt NewFeatures = Features->getUniqueInteger(); 103 NewFeatures.setBit(kSanitizerBinaryMetadataUARHasSizeBit); 104 F.setMetadata( 105 LLVMContext::MD_pcsections, 106 MDB.createPCSections({{Section.getString(), 107 {IRB.getInt(NewFeatures), IRB.getInt32(Size)}}})); 108 return false; 109 } 110