-
Notifications
You must be signed in to change notification settings - Fork 13.7k
[LLVM][rtsan] Add RealtimeSanitizer transform pass #101232
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
2a3929d
6c67a4b
44ee4bd
8faf8c4
40f8769
6be30bb
06ce2d2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
//===- RealtimeSanitizer.h - RealtimeSanitizer instrumentation --*- C++ -*-===// | ||
// | ||
// 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 the RealtimeSanitizer, an LLVM transformation for | ||
// detecting and reporting realtime safety violations. | ||
// | ||
// The instrumentation pass inserts calls to __rtsan_realtime_enter and | ||
// __rtsan_realtime_exit at the entry and exit points of functions that are | ||
// marked with the appropriate attribute. | ||
// | ||
// See also: llvm-project/compiler-rt/lib/rtsan/ | ||
// | ||
//===----------------------------------------------------------------------===// | ||
#ifndef LLVM_TRANSFORMS_INSTRUMENTATION_REALTIMESANITIZER_H | ||
#define LLVM_TRANSFORMS_INSTRUMENTATION_REALTIMESANITIZER_H | ||
|
||
#include "llvm/IR/PassManager.h" | ||
|
||
namespace llvm { | ||
|
||
struct RealtimeSanitizerOptions {}; | ||
|
||
class RealtimeSanitizerPass : public PassInfoMixin<RealtimeSanitizerPass> { | ||
public: | ||
RealtimeSanitizerPass(const RealtimeSanitizerOptions &Options); | ||
PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM); | ||
|
||
static bool isRequired() { return true; } | ||
|
||
private: | ||
RealtimeSanitizerOptions Options{}; | ||
}; | ||
|
||
} // namespace llvm | ||
|
||
#endif // LLVM_TRANSFORMS_INSTRUMENTATION_REALTIMESANITIZER_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
//===- RealtimeSanitizer.cpp - RealtimeSanitizer instrumentation *- C++ -*-===// | ||
// | ||
// 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 the RealtimeSanitizer, an LLVM transformation for | ||
// detecting and reporting realtime safety violations. | ||
// | ||
// See also: llvm-project/compiler-rt/lib/rtsan/ | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "llvm/IR/Analysis.h" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs a file header There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in latest! |
||
#include "llvm/IR/IRBuilder.h" | ||
#include "llvm/IR/Module.h" | ||
|
||
#include "llvm/Transforms/Instrumentation/RealtimeSanitizer.h" | ||
|
||
using namespace llvm; | ||
|
||
static void insertCallBeforeInstruction(Function &Fn, Instruction &Instruction, | ||
const char *FunctionName) { | ||
LLVMContext &Context = Fn.getContext(); | ||
FunctionType *FuncType = FunctionType::get(Type::getVoidTy(Context), false); | ||
FunctionCallee Func = | ||
Fn.getParent()->getOrInsertFunction(FunctionName, FuncType); | ||
IRBuilder<> Builder{&Instruction}; | ||
Builder.CreateCall(Func, {}); | ||
} | ||
|
||
static void insertCallAtFunctionEntryPoint(Function &Fn, | ||
const char *InsertFnName) { | ||
|
||
insertCallBeforeInstruction(Fn, Fn.front().front(), InsertFnName); | ||
} | ||
|
||
static void insertCallAtAllFunctionExitPoints(Function &Fn, | ||
const char *InsertFnName) { | ||
for (auto &BB : Fn) | ||
for (auto &I : BB) | ||
if (auto *RI = dyn_cast<ReturnInst>(&I)) | ||
insertCallBeforeInstruction(Fn, I, InsertFnName); | ||
} | ||
|
||
RealtimeSanitizerPass::RealtimeSanitizerPass( | ||
const RealtimeSanitizerOptions &Options) | ||
: Options{Options} {} | ||
|
||
PreservedAnalyses RealtimeSanitizerPass::run(Function &F, | ||
AnalysisManager<Function> &AM) { | ||
if (F.hasFnAttribute(Attribute::SanitizeRealtime)) { | ||
insertCallAtFunctionEntryPoint(F, "__rtsan_realtime_enter"); | ||
insertCallAtAllFunctionExitPoints(F, "__rtsan_realtime_exit"); | ||
return PreservedAnalyses::none(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not super important, but this could There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks! I can fix this in a follow up. Do you know where I can find more info on what this means? I was pattern matching other transforms and don't have a deep knowledge of what these "preserved analyses" actually do for the pass. Any additional info greatly appreciated! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It means whether the analysis has to be re-evalulated after the pass (if needed by a pass afterwards), or whether the pass has not changed the result (or, for some analyses, it is possible to incrementally change them, in which case it could also have done that). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, if I can rephrase what you're saying for my own education: "If a pass has changed the code in some way, we need to alert the analysis that it has been changed so it can be re-evaluated. In my original code, I basically said the maximal 'this has changed EVERYTHING, please re-run EVERYTHING (preserve nothing)'. Where if I was being more judicious, I would have only said 'I changed the code, but the Control Flow Analysis is still valid, you do not have to re-run that portion, it is preserved' Is my understanding correct? Sincerely appreciate the information here, this area of the project is brand new to me and I will take any knowledge I can get. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that sounds correct. |
||
} | ||
|
||
return PreservedAnalyses::all(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
; RUN: opt < %s -passes=rtsan -S | FileCheck %s | ||
|
||
define void @violation() #0 { | ||
%1 = alloca ptr, align 8 | ||
%2 = call ptr @malloc(i64 noundef 2) #3 | ||
store ptr %2, ptr %1, align 8 | ||
ret void | ||
} | ||
|
||
declare ptr @malloc(i64 noundef) #1 | ||
|
||
define noundef i32 @main() #2 { | ||
%1 = alloca i32, align 4 | ||
store i32 0, ptr %1, align 4 | ||
call void @violation() #4 | ||
ret i32 0 | ||
} | ||
|
||
attributes #0 = { mustprogress noinline sanitize_realtime optnone ssp uwtable(sync) } | ||
|
||
; RealtimeSanitizer pass should insert __rtsan_realtime_enter right after function definition | ||
; CHECK-LABEL: @violation() | ||
; CHECK-NEXT: call{{.*}}@__rtsan_realtime_enter | ||
|
||
; RealtimeSanitizer pass should insert __rtsan_realtime_exit right before function return | ||
; CHECK: call{{.*}}@__rtsan_realtime_exit | ||
; CHECK-NEXT: ret{{.*}}void |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
; RUN: opt < %s -passes=rtsan -S | FileCheck %s | ||
|
||
define i32 @example(i32 %x) #0 { | ||
entry: | ||
%retval = alloca i32 | ||
%cmp = icmp sgt i32 %x, 10 | ||
br i1 %cmp, label %then, label %else | ||
|
||
then: | ||
ret i32 1 | ||
|
||
else: | ||
ret i32 0 | ||
} | ||
|
||
attributes #0 = { mustprogress noinline sanitize_realtime optnone ssp uwtable(sync) } | ||
|
||
; RealtimeSanitizer pass should insert __rtsan_realtime_enter right after function definition | ||
cjappl marked this conversation as resolved.
Show resolved
Hide resolved
|
||
; CHECK-LABEL: @example( | ||
; CHECK-NEXT: entry: | ||
; CHECK-NEXT: call{{.*}}@__rtsan_realtime_enter | ||
|
||
; RealtimeSanitizer pass should insert the call at both function returns | ||
; CHECK-LABEL: then: | ||
; CHECK-NEXT: call{{.*}}@__rtsan_realtime_exit | ||
; CHECK-NEXT: ret i32 1 | ||
|
||
; CHECK-LABEL: else: | ||
; CHECK-NEXT: call{{.*}}@__rtsan_realtime_exit | ||
; CHECK-NEXT: ret i32 0 |
Uh oh!
There was an error while loading. Please reload this page.