llvm-project/llvm/lib/CodeGen/SanitizerBinaryMetadata.cpp
Marco Elver bf9814b705 [SanitizerBinaryMetadata] Emit constants as ULEB128
Emit all constant integers produced by SanitizerBinaryMetadata as
ULEB128 to further reduce binary space used. Increasing the version is
not necessary given this change depends on (and will land) along with
the bump to v2.

To support this, the !pcsections metadata format is extended to allow
for per-section options, encoded in the first MD operator which must
always be a string and contain the section: "<section>!<options>".

Reviewed By: dvyukov

Differential Revision: https://reviews.llvm.org/D143484
2023-02-08 13:12:34 +01:00

88 lines
3.1 KiB
C++

//===- SanitizerBinaryMetadata.cpp
//----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file is a part of SanitizerBinaryMetadata.
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include <algorithm>
using namespace llvm;
namespace {
class MachineSanitizerBinaryMetadata : public MachineFunctionPass {
public:
static char ID;
MachineSanitizerBinaryMetadata();
bool runOnMachineFunction(MachineFunction &F) override;
};
} // namespace
INITIALIZE_PASS(MachineSanitizerBinaryMetadata, "machine-sanmd",
"Machine Sanitizer Binary Metadata", false, false)
char MachineSanitizerBinaryMetadata::ID = 0;
char &llvm::MachineSanitizerBinaryMetadataID =
MachineSanitizerBinaryMetadata::ID;
MachineSanitizerBinaryMetadata::MachineSanitizerBinaryMetadata()
: MachineFunctionPass(ID) {
initializeMachineSanitizerBinaryMetadataPass(
*PassRegistry::getPassRegistry());
}
bool MachineSanitizerBinaryMetadata::runOnMachineFunction(MachineFunction &MF) {
MDNode *MD = MF.getFunction().getMetadata(LLVMContext::MD_pcsections);
if (!MD)
return false;
const auto &Section = *cast<MDString>(MD->getOperand(0));
if (!Section.getString().startswith(kSanitizerBinaryMetadataCoveredSection))
return false;
auto &AuxMDs = *cast<MDTuple>(MD->getOperand(1));
// Assume it currently only has features.
assert(AuxMDs.getNumOperands() == 1);
Constant *Features =
cast<ConstantAsMetadata>(AuxMDs.getOperand(0))->getValue();
if (!Features->getUniqueInteger()[kSanitizerBinaryMetadataUARBit])
return false;
// Calculate size of stack args for the function.
int64_t Size = 0;
uint64_t Align = 0;
const MachineFrameInfo &MFI = MF.getFrameInfo();
for (int i = -1; i >= (int)-MFI.getNumFixedObjects(); --i) {
Size = std::max(Size, MFI.getObjectOffset(i) + MFI.getObjectSize(i));
Align = std::max(Align, MFI.getObjectAlign(i).value());
}
Size = (Size + Align - 1) & ~(Align - 1);
if (!Size)
return false;
// Non-zero size, update metadata.
auto &F = MF.getFunction();
IRBuilder<> IRB(F.getContext());
MDBuilder MDB(F.getContext());
// Keep the features and append size of stack args to the metadata.
APInt NewFeatures = Features->getUniqueInteger();
NewFeatures.setBit(kSanitizerBinaryMetadataUARHasSizeBit);
F.setMetadata(
LLVMContext::MD_pcsections,
MDB.createPCSections({{Section.getString(),
{IRB.getInt(NewFeatures), IRB.getInt32(Size)}}}));
return false;
}