2015-12-27 16:13:45 +08:00
|
|
|
//===- ForceFunctionAttrs.cpp - Force function attrs for debugging --------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// 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
|
2015-12-27 16:13:45 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
|
|
|
|
#include "llvm/ADT/StringSwitch.h"
|
|
|
|
#include "llvm/IR/Function.h"
|
|
|
|
#include "llvm/IR/LLVMContext.h"
|
|
|
|
#include "llvm/IR/Module.h"
|
|
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
#define DEBUG_TYPE "forceattrs"
|
|
|
|
|
|
|
|
static cl::list<std::string>
|
|
|
|
ForceAttributes("force-attribute", cl::Hidden,
|
|
|
|
cl::desc("Add an attribute to a function. This should be a "
|
|
|
|
"pair of 'function-name:attribute-name', for "
|
2016-01-07 02:18:16 +08:00
|
|
|
"example -force-attribute=foo:noinline. This "
|
2015-12-27 16:13:45 +08:00
|
|
|
"option can be specified multiple times."));
|
|
|
|
|
|
|
|
static Attribute::AttrKind parseAttrKind(StringRef Kind) {
|
|
|
|
return StringSwitch<Attribute::AttrKind>(Kind)
|
|
|
|
.Case("alwaysinline", Attribute::AlwaysInline)
|
|
|
|
.Case("builtin", Attribute::Builtin)
|
|
|
|
.Case("cold", Attribute::Cold)
|
|
|
|
.Case("convergent", Attribute::Convergent)
|
|
|
|
.Case("inlinehint", Attribute::InlineHint)
|
|
|
|
.Case("jumptable", Attribute::JumpTable)
|
|
|
|
.Case("minsize", Attribute::MinSize)
|
|
|
|
.Case("naked", Attribute::Naked)
|
|
|
|
.Case("nobuiltin", Attribute::NoBuiltin)
|
|
|
|
.Case("noduplicate", Attribute::NoDuplicate)
|
|
|
|
.Case("noimplicitfloat", Attribute::NoImplicitFloat)
|
|
|
|
.Case("noinline", Attribute::NoInline)
|
|
|
|
.Case("nonlazybind", Attribute::NonLazyBind)
|
|
|
|
.Case("noredzone", Attribute::NoRedZone)
|
|
|
|
.Case("noreturn", Attribute::NoReturn)
|
2018-03-17 21:29:46 +08:00
|
|
|
.Case("nocf_check", Attribute::NoCfCheck)
|
2015-12-27 16:13:45 +08:00
|
|
|
.Case("norecurse", Attribute::NoRecurse)
|
|
|
|
.Case("nounwind", Attribute::NoUnwind)
|
[SimplifyCFG] Create attribute for fuzzing-specific optimizations.
Summary:
When building with libFuzzer, converting control flow to selects or
obscuring the original operands of CMPs reduces the effectiveness of
libFuzzer's heuristics.
This patch provides an attribute to disable or modify certain optimizations
for optimal fuzzing signal.
Provides a less aggressive alternative to https://reviews.llvm.org/D44057.
Reviewers: vitalybuka, davide, arsenm, hfinkel
Reviewed By: vitalybuka
Subscribers: junbuml, mehdi_amini, wdng, javed.absar, hiraditya, llvm-commits, kcc
Differential Revision: https://reviews.llvm.org/D44232
llvm-svn: 328214
2018-03-23 01:07:51 +08:00
|
|
|
.Case("optforfuzzing", Attribute::OptForFuzzing)
|
2015-12-27 16:13:45 +08:00
|
|
|
.Case("optnone", Attribute::OptimizeNone)
|
|
|
|
.Case("optsize", Attribute::OptimizeForSize)
|
|
|
|
.Case("readnone", Attribute::ReadNone)
|
|
|
|
.Case("readonly", Attribute::ReadOnly)
|
|
|
|
.Case("argmemonly", Attribute::ArgMemOnly)
|
|
|
|
.Case("returns_twice", Attribute::ReturnsTwice)
|
|
|
|
.Case("safestack", Attribute::SafeStack)
|
2018-04-04 05:40:27 +08:00
|
|
|
.Case("shadowcallstack", Attribute::ShadowCallStack)
|
2015-12-27 16:13:45 +08:00
|
|
|
.Case("sanitize_address", Attribute::SanitizeAddress)
|
2017-12-09 08:21:41 +08:00
|
|
|
.Case("sanitize_hwaddress", Attribute::SanitizeHWAddress)
|
2015-12-27 16:13:45 +08:00
|
|
|
.Case("sanitize_memory", Attribute::SanitizeMemory)
|
|
|
|
.Case("sanitize_thread", Attribute::SanitizeThread)
|
ARM MTE stack sanitizer.
Add "memtag" sanitizer that detects and mitigates stack memory issues
using armv8.5 Memory Tagging Extension.
It is similar in principle to HWASan, which is a software implementation
of the same idea, but there are enough differencies to warrant a new
sanitizer type IMHO. It is also expected to have very different
performance properties.
The new sanitizer does not have a runtime library (it may grow one
later, along with a "debugging" mode). Similar to SafeStack and
StackProtector, the instrumentation pass (in a follow up change) will be
inserted in all cases, but will only affect functions marked with the
new sanitize_memtag attribute.
Reviewers: pcc, hctim, vitalybuka, ostannard
Subscribers: srhines, mehdi_amini, javed.absar, kristof.beyls, hiraditya, cryptoad, steven_wu, dexonsmith, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D64169
llvm-svn: 366123
2019-07-16 04:02:23 +08:00
|
|
|
.Case("sanitize_memtag", Attribute::SanitizeMemTag)
|
2018-09-04 20:38:00 +08:00
|
|
|
.Case("speculative_load_hardening", Attribute::SpeculativeLoadHardening)
|
2015-12-27 16:13:45 +08:00
|
|
|
.Case("ssp", Attribute::StackProtect)
|
|
|
|
.Case("sspreq", Attribute::StackProtectReq)
|
|
|
|
.Case("sspstrong", Attribute::StackProtectStrong)
|
2017-08-15 05:15:13 +08:00
|
|
|
.Case("strictfp", Attribute::StrictFP)
|
2015-12-27 16:13:45 +08:00
|
|
|
.Case("uwtable", Attribute::UWTable)
|
|
|
|
.Default(Attribute::None);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// If F has any forced attributes given on the command line, add them.
|
|
|
|
static void addForcedAttributes(Function &F) {
|
|
|
|
for (auto &S : ForceAttributes) {
|
|
|
|
auto KV = StringRef(S).split(':');
|
|
|
|
if (KV.first != F.getName())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
auto Kind = parseAttrKind(KV.second);
|
|
|
|
if (Kind == Attribute::None) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "ForcedAttribute: " << KV.second
|
|
|
|
<< " unknown or not handled!\n");
|
2015-12-27 16:13:45 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (F.hasFnAttribute(Kind))
|
|
|
|
continue;
|
|
|
|
F.addFnAttr(Kind);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-17 08:11:01 +08:00
|
|
|
PreservedAnalyses ForceFunctionAttrsPass::run(Module &M,
|
|
|
|
ModuleAnalysisManager &) {
|
2015-12-27 16:13:45 +08:00
|
|
|
if (ForceAttributes.empty())
|
|
|
|
return PreservedAnalyses::all();
|
|
|
|
|
|
|
|
for (Function &F : M.functions())
|
|
|
|
addForcedAttributes(F);
|
|
|
|
|
|
|
|
// Just conservatively invalidate analyses, this isn't likely to be important.
|
|
|
|
return PreservedAnalyses::none();
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
struct ForceFunctionAttrsLegacyPass : public ModulePass {
|
|
|
|
static char ID; // Pass identification, replacement for typeid
|
|
|
|
ForceFunctionAttrsLegacyPass() : ModulePass(ID) {
|
|
|
|
initializeForceFunctionAttrsLegacyPassPass(
|
|
|
|
*PassRegistry::getPassRegistry());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool runOnModule(Module &M) override {
|
|
|
|
if (ForceAttributes.empty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (Function &F : M.functions())
|
|
|
|
addForcedAttributes(F);
|
|
|
|
|
|
|
|
// Conservatively assume we changed something.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
char ForceFunctionAttrsLegacyPass::ID = 0;
|
|
|
|
INITIALIZE_PASS(ForceFunctionAttrsLegacyPass, "forceattrs",
|
|
|
|
"Force set function attributes", false, false)
|
|
|
|
|
|
|
|
Pass *llvm::createForceFunctionAttrsLegacyPass() {
|
|
|
|
return new ForceFunctionAttrsLegacyPass();
|
|
|
|
}
|