mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[SanitizeCoverage] Add support for NoSanitizeCoverage function attribute
We really ought to support no_sanitize("coverage") in line with other sanitizers. This came up again in discussions on the Linux-kernel mailing lists, because we currently do workarounds using objtool to remove coverage instrumentation. Since that support is only on x86, to continue support coverage instrumentation on other architectures, we must support selectively disabling coverage instrumentation via function attributes. Unfortunately, for SanitizeCoverage, it has not been implemented as a sanitizer via fsanitize= and associated options in Sanitizers.def, but rolls its own option fsanitize-coverage. This meant that we never got "automatic" no_sanitize attribute support. Implement no_sanitize attribute support by special-casing the string "coverage" in the NoSanitizeAttr implementation. To keep the feature as unintrusive to existing IR generation as possible, define a new negative function attribute NoSanitizeCoverage to propagate the information through to the instrumentation pass. Fixes: https://bugs.llvm.org/show_bug.cgi?id=49035 Reviewed By: vitalybuka, morehouse Differential Revision: https://reviews.llvm.org/D102772
This commit is contained in:
parent
91c3ce1475
commit
b835b9cf36
@ -69,6 +69,7 @@ func TestAttributes(t *testing.T) {
|
||||
"noredzone",
|
||||
"noreturn",
|
||||
"nounwind",
|
||||
"nosanitize_coverage",
|
||||
"optnone",
|
||||
"optsize",
|
||||
"readnone",
|
||||
|
@ -1073,6 +1073,8 @@ The integer codes are mapped to well-known attributes as follows.
|
||||
* code 69: ``byref``
|
||||
* code 70: ``mustprogress``
|
||||
* code 74: ``vscale_range(<Min>[, <Max>])``
|
||||
* code 75: ``swiftasync``
|
||||
* code 76: ``nosanitize_coverage``
|
||||
|
||||
.. note::
|
||||
The ``allocsize`` attribute has a special encoding for its arguments. Its two
|
||||
|
@ -1691,6 +1691,9 @@ example:
|
||||
trap or generate asynchronous exceptions. Exception handling schemes
|
||||
that are recognized by LLVM to handle asynchronous exceptions, such
|
||||
as SEH, will still provide their implementation defined semantics.
|
||||
``nosanitize_coverage``
|
||||
This attribute indicates that SanitizerCoverage instrumentation is disabled
|
||||
for this function.
|
||||
``null_pointer_is_valid``
|
||||
If ``null_pointer_is_valid`` is set, then the ``null`` address
|
||||
in address-space 0 is considered to be a valid address for memory loads and
|
||||
|
@ -217,6 +217,7 @@ enum Kind {
|
||||
kw_nosync,
|
||||
kw_nocf_check,
|
||||
kw_nounwind,
|
||||
kw_nosanitize_coverage,
|
||||
kw_null_pointer_is_valid,
|
||||
kw_optforfuzzing,
|
||||
kw_optnone,
|
||||
|
@ -666,6 +666,7 @@ enum AttributeKindCodes {
|
||||
ATTR_KIND_NO_PROFILE = 73,
|
||||
ATTR_KIND_VSCALE_RANGE = 74,
|
||||
ATTR_KIND_SWIFT_ASYNC = 75,
|
||||
ATTR_KIND_NO_SANITIZE_COVERAGE = 76,
|
||||
};
|
||||
|
||||
enum ComdatSelectionKindCodes {
|
||||
|
@ -154,6 +154,9 @@ def NoProfile : EnumAttr<"noprofile">;
|
||||
/// Function doesn't unwind stack.
|
||||
def NoUnwind : EnumAttr<"nounwind">;
|
||||
|
||||
/// No SanitizeCoverage instrumentation.
|
||||
def NoSanitizeCoverage : EnumAttr<"nosanitize_coverage">;
|
||||
|
||||
/// Null pointer in address space zero is valid.
|
||||
def NullPointerIsValid : EnumAttr<"null_pointer_is_valid">;
|
||||
|
||||
|
@ -671,6 +671,7 @@ lltok::Kind LLLexer::LexIdentifier() {
|
||||
KEYWORD(nocf_check);
|
||||
KEYWORD(noundef);
|
||||
KEYWORD(nounwind);
|
||||
KEYWORD(nosanitize_coverage);
|
||||
KEYWORD(null_pointer_is_valid);
|
||||
KEYWORD(optforfuzzing);
|
||||
KEYWORD(optnone);
|
||||
|
@ -1398,6 +1398,9 @@ bool LLParser::parseFnAttributeValuePairs(AttrBuilder &B,
|
||||
case lltok::kw_noprofile: B.addAttribute(Attribute::NoProfile); break;
|
||||
case lltok::kw_norecurse: B.addAttribute(Attribute::NoRecurse); break;
|
||||
case lltok::kw_nounwind: B.addAttribute(Attribute::NoUnwind); break;
|
||||
case lltok::kw_nosanitize_coverage:
|
||||
B.addAttribute(Attribute::NoSanitizeCoverage);
|
||||
break;
|
||||
case lltok::kw_null_pointer_is_valid:
|
||||
B.addAttribute(Attribute::NullPointerIsValid); break;
|
||||
case lltok::kw_optforfuzzing:
|
||||
@ -1825,6 +1828,7 @@ bool LLParser::parseOptionalParamAttrs(AttrBuilder &B) {
|
||||
case lltok::kw_noreturn:
|
||||
case lltok::kw_nocf_check:
|
||||
case lltok::kw_nounwind:
|
||||
case lltok::kw_nosanitize_coverage:
|
||||
case lltok::kw_optforfuzzing:
|
||||
case lltok::kw_optnone:
|
||||
case lltok::kw_optsize:
|
||||
@ -1936,6 +1940,7 @@ bool LLParser::parseOptionalReturnAttrs(AttrBuilder &B) {
|
||||
case lltok::kw_noreturn:
|
||||
case lltok::kw_nocf_check:
|
||||
case lltok::kw_nounwind:
|
||||
case lltok::kw_nosanitize_coverage:
|
||||
case lltok::kw_optforfuzzing:
|
||||
case lltok::kw_optnone:
|
||||
case lltok::kw_optsize:
|
||||
|
@ -1474,6 +1474,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) {
|
||||
return Attribute::NoCfCheck;
|
||||
case bitc::ATTR_KIND_NO_UNWIND:
|
||||
return Attribute::NoUnwind;
|
||||
case bitc::ATTR_KIND_NO_SANITIZE_COVERAGE:
|
||||
return Attribute::NoSanitizeCoverage;
|
||||
case bitc::ATTR_KIND_NULL_POINTER_IS_VALID:
|
||||
return Attribute::NullPointerIsValid;
|
||||
case bitc::ATTR_KIND_OPT_FOR_FUZZING:
|
||||
|
@ -686,6 +686,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) {
|
||||
return bitc::ATTR_KIND_NO_PROFILE;
|
||||
case Attribute::NoUnwind:
|
||||
return bitc::ATTR_KIND_NO_UNWIND;
|
||||
case Attribute::NoSanitizeCoverage:
|
||||
return bitc::ATTR_KIND_NO_SANITIZE_COVERAGE;
|
||||
case Attribute::NullPointerIsValid:
|
||||
return bitc::ATTR_KIND_NULL_POINTER_IS_VALID;
|
||||
case Attribute::OptForFuzzing:
|
||||
|
@ -442,6 +442,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
|
||||
return "noprofile";
|
||||
if (hasAttribute(Attribute::NoUnwind))
|
||||
return "nounwind";
|
||||
if (hasAttribute(Attribute::NoSanitizeCoverage))
|
||||
return "nosanitize_coverage";
|
||||
if (hasAttribute(Attribute::OptForFuzzing))
|
||||
return "optforfuzzing";
|
||||
if (hasAttribute(Attribute::OptimizeNone))
|
||||
|
@ -1661,6 +1661,7 @@ static bool isFuncOnlyAttr(Attribute::AttrKind Kind) {
|
||||
case Attribute::NoCfCheck:
|
||||
case Attribute::NoUnwind:
|
||||
case Attribute::NoInline:
|
||||
case Attribute::NoSanitizeCoverage:
|
||||
case Attribute::AlwaysInline:
|
||||
case Attribute::OptimizeForSize:
|
||||
case Attribute::StackProtect:
|
||||
|
@ -53,6 +53,7 @@ static Attribute::AttrKind parseAttrKind(StringRef Kind) {
|
||||
.Case("nocf_check", Attribute::NoCfCheck)
|
||||
.Case("norecurse", Attribute::NoRecurse)
|
||||
.Case("nounwind", Attribute::NoUnwind)
|
||||
.Case("nosanitize_coverage", Attribute::NoSanitizeCoverage)
|
||||
.Case("optforfuzzing", Attribute::OptForFuzzing)
|
||||
.Case("optnone", Attribute::OptimizeNone)
|
||||
.Case("optsize", Attribute::OptimizeForSize)
|
||||
|
@ -621,6 +621,8 @@ void ModuleSanitizerCoverage::instrumentFunction(
|
||||
return;
|
||||
if (Blocklist && Blocklist->inSection("coverage", "fun", F.getName()))
|
||||
return;
|
||||
if (F.hasFnAttribute(Attribute::NoSanitizeCoverage))
|
||||
return;
|
||||
if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge)
|
||||
SplitAllCriticalEdges(F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests());
|
||||
SmallVector<Instruction *, 8> IndirCalls;
|
||||
|
@ -954,6 +954,7 @@ Function *CodeExtractor::constructFunction(const ValueSet &inputs,
|
||||
case Attribute::NonLazyBind:
|
||||
case Attribute::NoRedZone:
|
||||
case Attribute::NoUnwind:
|
||||
case Attribute::NoSanitizeCoverage:
|
||||
case Attribute::NullPointerIsValid:
|
||||
case Attribute::OptForFuzzing:
|
||||
case Attribute::OptimizeNone:
|
||||
|
@ -453,6 +453,12 @@ define void @f76(i8* swiftasync %0)
|
||||
ret void;
|
||||
}
|
||||
|
||||
; CHECK: define void @f77() #48
|
||||
define void @f77() nosanitize_coverage
|
||||
{
|
||||
ret void;
|
||||
}
|
||||
|
||||
; CHECK: attributes #0 = { noreturn }
|
||||
; CHECK: attributes #1 = { nounwind }
|
||||
; CHECK: attributes #2 = { readnone }
|
||||
@ -501,4 +507,5 @@ define void @f76(i8* swiftasync %0)
|
||||
; CHECK: attributes #45 = { vscale_range(8,8) }
|
||||
; CHECK: attributes #46 = { vscale_range(1,8) }
|
||||
; CHECK: attributes #47 = { vscale_range(1,0) }
|
||||
; CHECK: attributes #48 = { nosanitize_coverage }
|
||||
; CHECK: attributes #[[NOBUILTIN]] = { nobuiltin }
|
||||
|
@ -1510,7 +1510,7 @@ exit:
|
||||
; CHECK: select <2 x i1> <i1 true, i1 false>, <2 x i8> <i8 2, i8 3>, <2 x i8> <i8 3, i8 2>
|
||||
|
||||
call void @f.nobuiltin() builtin
|
||||
; CHECK: call void @f.nobuiltin() #44
|
||||
; CHECK: call void @f.nobuiltin() #45
|
||||
|
||||
call fastcc noalias i32* @f.noalias() noinline
|
||||
; CHECK: call fastcc noalias i32* @f.noalias() #12
|
||||
@ -1904,6 +1904,9 @@ define void @instructions.strictfp() strictfp {
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @f.nosanitize_coverage() nosanitize_coverage
|
||||
; CHECK: declare void @f.nosanitize_coverage() #44
|
||||
|
||||
; immarg attribute
|
||||
declare void @llvm.test.immarg.intrinsic(i32 immarg)
|
||||
; CHECK: declare void @llvm.test.immarg.intrinsic(i32 immarg)
|
||||
@ -1961,7 +1964,8 @@ declare void @byval_named_type(%named_type* byval(%named_type))
|
||||
; CHECK: attributes #41 = { writeonly }
|
||||
; CHECK: attributes #42 = { speculatable }
|
||||
; CHECK: attributes #43 = { strictfp }
|
||||
; CHECK: attributes #44 = { builtin }
|
||||
; CHECK: attributes #44 = { nosanitize_coverage }
|
||||
; CHECK: attributes #45 = { builtin }
|
||||
|
||||
;; Metadata
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
'("alwaysinline" "argmemonly" "allocsize" "builtin" "cold" "convergent" "dereferenceable" "dereferenceable_or_null" "hot" "inaccessiblememonly"
|
||||
"inaccessiblemem_or_argmemonly" "inalloca" "inlinehint" "jumptable" "minsize" "mustprogress" "naked" "nobuiltin" "nonnull"
|
||||
"nocallback" "nocf_check" "noduplicate" "nofree" "noimplicitfloat" "noinline" "nomerge" "nonlazybind" "noprofile" "noredzone" "noreturn"
|
||||
"norecurse" "nosync" "noundef" "nounwind" "null_pointer_is_valid" "optforfuzzing" "optnone" "optsize" "preallocated" "readnone" "readonly" "returned" "returns_twice"
|
||||
"norecurse" "nosync" "noundef" "nounwind" "nosanitize_coverage" "null_pointer_is_valid" "optforfuzzing" "optnone" "optsize" "preallocated" "readnone" "readonly" "returned" "returns_twice"
|
||||
"shadowcallstack" "speculatable" "speculative_load_hardening" "ssp" "sspreq" "sspstrong" "safestack" "sanitize_address" "sanitize_hwaddress" "sanitize_memtag"
|
||||
"sanitize_thread" "sanitize_memory" "strictfp" "swifterror" "uwtable" "vscale_range" "willreturn" "writeonly" "immarg") 'symbols) . font-lock-constant-face)
|
||||
;; Variables
|
||||
|
@ -176,6 +176,7 @@ FuncAttr ::= noreturn
|
||||
| sanitize_thread
|
||||
| sanitize_memory
|
||||
| mustprogress
|
||||
| nosanitize_coverage
|
||||
;
|
||||
|
||||
OptFuncAttrs ::= + _ | OptFuncAttrs FuncAttr ;
|
||||
|
@ -138,6 +138,7 @@ syn keyword llvmKeyword
|
||||
\ nosync
|
||||
\ noundef
|
||||
\ nounwind
|
||||
\ nosanitize_coverage
|
||||
\ null_pointer_is_valid
|
||||
\ optforfuzzing
|
||||
\ optnone
|
||||
|
@ -237,6 +237,7 @@ patterns:
|
||||
\\bnosync\\b|\
|
||||
\\bnoundef\\b|\
|
||||
\\bnounwind\\b|\
|
||||
\\bnosanitize_coverage\\b|\
|
||||
\\bnull_pointer_is_valid\\b|\
|
||||
\\boptforfuzzing\\b|\
|
||||
\\boptnone\\b|\
|
||||
|
Loading…
x
Reference in New Issue
Block a user