xref: /llvm-project/llvm/lib/CodeGen/SanitizerBinaryMetadata.cpp (revision 586ecdf205aa8b3d162da6f955170a6736656615)
1dbe8c2c3SDmitry Vyukov //===- SanitizerBinaryMetadata.cpp
2dbe8c2c3SDmitry Vyukov //----------------------------------------------===//
3dbe8c2c3SDmitry Vyukov //
4dbe8c2c3SDmitry Vyukov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5dbe8c2c3SDmitry Vyukov // See https://llvm.org/LICENSE.txt for license information.
6dbe8c2c3SDmitry Vyukov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7dbe8c2c3SDmitry Vyukov //
8dbe8c2c3SDmitry Vyukov //===----------------------------------------------------------------------===//
9dbe8c2c3SDmitry Vyukov //
10dbe8c2c3SDmitry Vyukov // This file is a part of SanitizerBinaryMetadata.
11dbe8c2c3SDmitry Vyukov //
12dbe8c2c3SDmitry Vyukov //===----------------------------------------------------------------------===//
13dbe8c2c3SDmitry Vyukov 
14dbe8c2c3SDmitry Vyukov #include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"
15dbe8c2c3SDmitry Vyukov #include "llvm/CodeGen/MachineFrameInfo.h"
16dbe8c2c3SDmitry Vyukov #include "llvm/CodeGen/MachineFunction.h"
17dbe8c2c3SDmitry Vyukov #include "llvm/CodeGen/MachineFunctionPass.h"
18dbe8c2c3SDmitry Vyukov #include "llvm/CodeGen/Passes.h"
19dbe8c2c3SDmitry Vyukov #include "llvm/IR/IRBuilder.h"
20dbe8c2c3SDmitry Vyukov #include "llvm/IR/MDBuilder.h"
21dbe8c2c3SDmitry Vyukov #include "llvm/InitializePasses.h"
22dbe8c2c3SDmitry Vyukov #include "llvm/Pass.h"
23dbe8c2c3SDmitry Vyukov #include <algorithm>
24dbe8c2c3SDmitry Vyukov 
25dbe8c2c3SDmitry Vyukov using namespace llvm;
26dbe8c2c3SDmitry Vyukov 
27b6942a28SBenjamin Kramer namespace {
28dbe8c2c3SDmitry Vyukov class MachineSanitizerBinaryMetadata : public MachineFunctionPass {
29dbe8c2c3SDmitry Vyukov public:
30dbe8c2c3SDmitry Vyukov   static char ID;
31dbe8c2c3SDmitry Vyukov 
32dbe8c2c3SDmitry Vyukov   MachineSanitizerBinaryMetadata();
33dbe8c2c3SDmitry Vyukov   bool runOnMachineFunction(MachineFunction &F) override;
34dbe8c2c3SDmitry Vyukov };
35b6942a28SBenjamin Kramer } // namespace
36dbe8c2c3SDmitry Vyukov 
37dbe8c2c3SDmitry Vyukov INITIALIZE_PASS(MachineSanitizerBinaryMetadata, "machine-sanmd",
38dbe8c2c3SDmitry Vyukov                 "Machine Sanitizer Binary Metadata", false, false)
39dbe8c2c3SDmitry Vyukov 
40dbe8c2c3SDmitry Vyukov char MachineSanitizerBinaryMetadata::ID = 0;
41dbe8c2c3SDmitry Vyukov char &llvm::MachineSanitizerBinaryMetadataID =
42dbe8c2c3SDmitry Vyukov     MachineSanitizerBinaryMetadata::ID;
43dbe8c2c3SDmitry Vyukov 
MachineSanitizerBinaryMetadata()44dbe8c2c3SDmitry Vyukov MachineSanitizerBinaryMetadata::MachineSanitizerBinaryMetadata()
45dbe8c2c3SDmitry Vyukov     : MachineFunctionPass(ID) {
46dbe8c2c3SDmitry Vyukov   initializeMachineSanitizerBinaryMetadataPass(
47dbe8c2c3SDmitry Vyukov       *PassRegistry::getPassRegistry());
48dbe8c2c3SDmitry Vyukov }
49dbe8c2c3SDmitry Vyukov 
runOnMachineFunction(MachineFunction & MF)50dbe8c2c3SDmitry Vyukov bool MachineSanitizerBinaryMetadata::runOnMachineFunction(MachineFunction &MF) {
51dbe8c2c3SDmitry Vyukov   MDNode *MD = MF.getFunction().getMetadata(LLVMContext::MD_pcsections);
52dbe8c2c3SDmitry Vyukov   if (!MD)
53dbe8c2c3SDmitry Vyukov     return false;
54dbe8c2c3SDmitry Vyukov   const auto &Section = *cast<MDString>(MD->getOperand(0));
55*586ecdf2SKazu Hirata   if (!Section.getString().starts_with(kSanitizerBinaryMetadataCoveredSection))
56dbe8c2c3SDmitry Vyukov     return false;
57dbe8c2c3SDmitry Vyukov   auto &AuxMDs = *cast<MDTuple>(MD->getOperand(1));
58dbe8c2c3SDmitry Vyukov   // Assume it currently only has features.
59dbe8c2c3SDmitry Vyukov   assert(AuxMDs.getNumOperands() == 1);
603d53b527SMarco Elver   Constant *Features =
613d53b527SMarco Elver       cast<ConstantAsMetadata>(AuxMDs.getOperand(0))->getValue();
62dbe8c2c3SDmitry Vyukov   if (!Features->getUniqueInteger()[kSanitizerBinaryMetadataUARBit])
63dbe8c2c3SDmitry Vyukov     return false;
64dbe8c2c3SDmitry Vyukov   // Calculate size of stack args for the function.
65dbe8c2c3SDmitry Vyukov   int64_t Size = 0;
66dbe8c2c3SDmitry Vyukov   uint64_t Align = 0;
67dbe8c2c3SDmitry Vyukov   const MachineFrameInfo &MFI = MF.getFrameInfo();
68dbe8c2c3SDmitry Vyukov   for (int i = -1; i >= (int)-MFI.getNumFixedObjects(); --i) {
69dbe8c2c3SDmitry Vyukov     Size = std::max(Size, MFI.getObjectOffset(i) + MFI.getObjectSize(i));
70dbe8c2c3SDmitry Vyukov     Align = std::max(Align, MFI.getObjectAlign(i).value());
71dbe8c2c3SDmitry Vyukov   }
72dbe8c2c3SDmitry Vyukov   Size = (Size + Align - 1) & ~(Align - 1);
733d53b527SMarco Elver   if (!Size)
743d53b527SMarco Elver     return false;
753d53b527SMarco Elver   // Non-zero size, update metadata.
76dbe8c2c3SDmitry Vyukov   auto &F = MF.getFunction();
77dbe8c2c3SDmitry Vyukov   IRBuilder<> IRB(F.getContext());
78dbe8c2c3SDmitry Vyukov   MDBuilder MDB(F.getContext());
79dbe8c2c3SDmitry Vyukov   // Keep the features and append size of stack args to the metadata.
803d53b527SMarco Elver   APInt NewFeatures = Features->getUniqueInteger();
813d53b527SMarco Elver   NewFeatures.setBit(kSanitizerBinaryMetadataUARHasSizeBit);
823d53b527SMarco Elver   F.setMetadata(
833d53b527SMarco Elver       LLVMContext::MD_pcsections,
843d53b527SMarco Elver       MDB.createPCSections({{Section.getString(),
853d53b527SMarco Elver                              {IRB.getInt(NewFeatures), IRB.getInt32(Size)}}}));
86dbe8c2c3SDmitry Vyukov   return false;
87dbe8c2c3SDmitry Vyukov }
88