1
0
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:
Marco Elver 2021-05-25 12:29:00 +02:00
parent 91c3ce1475
commit b835b9cf36
21 changed files with 45 additions and 3 deletions

View File

@ -69,6 +69,7 @@ func TestAttributes(t *testing.T) {
"noredzone", "noredzone",
"noreturn", "noreturn",
"nounwind", "nounwind",
"nosanitize_coverage",
"optnone", "optnone",
"optsize", "optsize",
"readnone", "readnone",

View File

@ -1073,6 +1073,8 @@ The integer codes are mapped to well-known attributes as follows.
* code 69: ``byref`` * code 69: ``byref``
* code 70: ``mustprogress`` * code 70: ``mustprogress``
* code 74: ``vscale_range(<Min>[, <Max>])`` * code 74: ``vscale_range(<Min>[, <Max>])``
* code 75: ``swiftasync``
* code 76: ``nosanitize_coverage``
.. note:: .. note::
The ``allocsize`` attribute has a special encoding for its arguments. Its two The ``allocsize`` attribute has a special encoding for its arguments. Its two

View File

@ -1691,6 +1691,9 @@ example:
trap or generate asynchronous exceptions. Exception handling schemes trap or generate asynchronous exceptions. Exception handling schemes
that are recognized by LLVM to handle asynchronous exceptions, such that are recognized by LLVM to handle asynchronous exceptions, such
as SEH, will still provide their implementation defined semantics. 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`` ``null_pointer_is_valid``
If ``null_pointer_is_valid`` is set, then the ``null`` address 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 in address-space 0 is considered to be a valid address for memory loads and

View File

@ -217,6 +217,7 @@ enum Kind {
kw_nosync, kw_nosync,
kw_nocf_check, kw_nocf_check,
kw_nounwind, kw_nounwind,
kw_nosanitize_coverage,
kw_null_pointer_is_valid, kw_null_pointer_is_valid,
kw_optforfuzzing, kw_optforfuzzing,
kw_optnone, kw_optnone,

View File

@ -666,6 +666,7 @@ enum AttributeKindCodes {
ATTR_KIND_NO_PROFILE = 73, ATTR_KIND_NO_PROFILE = 73,
ATTR_KIND_VSCALE_RANGE = 74, ATTR_KIND_VSCALE_RANGE = 74,
ATTR_KIND_SWIFT_ASYNC = 75, ATTR_KIND_SWIFT_ASYNC = 75,
ATTR_KIND_NO_SANITIZE_COVERAGE = 76,
}; };
enum ComdatSelectionKindCodes { enum ComdatSelectionKindCodes {

View File

@ -154,6 +154,9 @@ def NoProfile : EnumAttr<"noprofile">;
/// Function doesn't unwind stack. /// Function doesn't unwind stack.
def NoUnwind : EnumAttr<"nounwind">; def NoUnwind : EnumAttr<"nounwind">;
/// No SanitizeCoverage instrumentation.
def NoSanitizeCoverage : EnumAttr<"nosanitize_coverage">;
/// Null pointer in address space zero is valid. /// Null pointer in address space zero is valid.
def NullPointerIsValid : EnumAttr<"null_pointer_is_valid">; def NullPointerIsValid : EnumAttr<"null_pointer_is_valid">;

View File

@ -671,6 +671,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(nocf_check); KEYWORD(nocf_check);
KEYWORD(noundef); KEYWORD(noundef);
KEYWORD(nounwind); KEYWORD(nounwind);
KEYWORD(nosanitize_coverage);
KEYWORD(null_pointer_is_valid); KEYWORD(null_pointer_is_valid);
KEYWORD(optforfuzzing); KEYWORD(optforfuzzing);
KEYWORD(optnone); KEYWORD(optnone);

View File

@ -1398,6 +1398,9 @@ bool LLParser::parseFnAttributeValuePairs(AttrBuilder &B,
case lltok::kw_noprofile: B.addAttribute(Attribute::NoProfile); break; case lltok::kw_noprofile: B.addAttribute(Attribute::NoProfile); break;
case lltok::kw_norecurse: B.addAttribute(Attribute::NoRecurse); break; case lltok::kw_norecurse: B.addAttribute(Attribute::NoRecurse); break;
case lltok::kw_nounwind: B.addAttribute(Attribute::NoUnwind); 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: case lltok::kw_null_pointer_is_valid:
B.addAttribute(Attribute::NullPointerIsValid); break; B.addAttribute(Attribute::NullPointerIsValid); break;
case lltok::kw_optforfuzzing: case lltok::kw_optforfuzzing:
@ -1825,6 +1828,7 @@ bool LLParser::parseOptionalParamAttrs(AttrBuilder &B) {
case lltok::kw_noreturn: case lltok::kw_noreturn:
case lltok::kw_nocf_check: case lltok::kw_nocf_check:
case lltok::kw_nounwind: case lltok::kw_nounwind:
case lltok::kw_nosanitize_coverage:
case lltok::kw_optforfuzzing: case lltok::kw_optforfuzzing:
case lltok::kw_optnone: case lltok::kw_optnone:
case lltok::kw_optsize: case lltok::kw_optsize:
@ -1936,6 +1940,7 @@ bool LLParser::parseOptionalReturnAttrs(AttrBuilder &B) {
case lltok::kw_noreturn: case lltok::kw_noreturn:
case lltok::kw_nocf_check: case lltok::kw_nocf_check:
case lltok::kw_nounwind: case lltok::kw_nounwind:
case lltok::kw_nosanitize_coverage:
case lltok::kw_optforfuzzing: case lltok::kw_optforfuzzing:
case lltok::kw_optnone: case lltok::kw_optnone:
case lltok::kw_optsize: case lltok::kw_optsize:

View File

@ -1474,6 +1474,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) {
return Attribute::NoCfCheck; return Attribute::NoCfCheck;
case bitc::ATTR_KIND_NO_UNWIND: case bitc::ATTR_KIND_NO_UNWIND:
return Attribute::NoUnwind; return Attribute::NoUnwind;
case bitc::ATTR_KIND_NO_SANITIZE_COVERAGE:
return Attribute::NoSanitizeCoverage;
case bitc::ATTR_KIND_NULL_POINTER_IS_VALID: case bitc::ATTR_KIND_NULL_POINTER_IS_VALID:
return Attribute::NullPointerIsValid; return Attribute::NullPointerIsValid;
case bitc::ATTR_KIND_OPT_FOR_FUZZING: case bitc::ATTR_KIND_OPT_FOR_FUZZING:

View File

@ -686,6 +686,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) {
return bitc::ATTR_KIND_NO_PROFILE; return bitc::ATTR_KIND_NO_PROFILE;
case Attribute::NoUnwind: case Attribute::NoUnwind:
return bitc::ATTR_KIND_NO_UNWIND; return bitc::ATTR_KIND_NO_UNWIND;
case Attribute::NoSanitizeCoverage:
return bitc::ATTR_KIND_NO_SANITIZE_COVERAGE;
case Attribute::NullPointerIsValid: case Attribute::NullPointerIsValid:
return bitc::ATTR_KIND_NULL_POINTER_IS_VALID; return bitc::ATTR_KIND_NULL_POINTER_IS_VALID;
case Attribute::OptForFuzzing: case Attribute::OptForFuzzing:

View File

@ -442,6 +442,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
return "noprofile"; return "noprofile";
if (hasAttribute(Attribute::NoUnwind)) if (hasAttribute(Attribute::NoUnwind))
return "nounwind"; return "nounwind";
if (hasAttribute(Attribute::NoSanitizeCoverage))
return "nosanitize_coverage";
if (hasAttribute(Attribute::OptForFuzzing)) if (hasAttribute(Attribute::OptForFuzzing))
return "optforfuzzing"; return "optforfuzzing";
if (hasAttribute(Attribute::OptimizeNone)) if (hasAttribute(Attribute::OptimizeNone))

View File

@ -1661,6 +1661,7 @@ static bool isFuncOnlyAttr(Attribute::AttrKind Kind) {
case Attribute::NoCfCheck: case Attribute::NoCfCheck:
case Attribute::NoUnwind: case Attribute::NoUnwind:
case Attribute::NoInline: case Attribute::NoInline:
case Attribute::NoSanitizeCoverage:
case Attribute::AlwaysInline: case Attribute::AlwaysInline:
case Attribute::OptimizeForSize: case Attribute::OptimizeForSize:
case Attribute::StackProtect: case Attribute::StackProtect:

View File

@ -53,6 +53,7 @@ static Attribute::AttrKind parseAttrKind(StringRef Kind) {
.Case("nocf_check", Attribute::NoCfCheck) .Case("nocf_check", Attribute::NoCfCheck)
.Case("norecurse", Attribute::NoRecurse) .Case("norecurse", Attribute::NoRecurse)
.Case("nounwind", Attribute::NoUnwind) .Case("nounwind", Attribute::NoUnwind)
.Case("nosanitize_coverage", Attribute::NoSanitizeCoverage)
.Case("optforfuzzing", Attribute::OptForFuzzing) .Case("optforfuzzing", Attribute::OptForFuzzing)
.Case("optnone", Attribute::OptimizeNone) .Case("optnone", Attribute::OptimizeNone)
.Case("optsize", Attribute::OptimizeForSize) .Case("optsize", Attribute::OptimizeForSize)

View File

@ -621,6 +621,8 @@ void ModuleSanitizerCoverage::instrumentFunction(
return; return;
if (Blocklist && Blocklist->inSection("coverage", "fun", F.getName())) if (Blocklist && Blocklist->inSection("coverage", "fun", F.getName()))
return; return;
if (F.hasFnAttribute(Attribute::NoSanitizeCoverage))
return;
if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge) if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge)
SplitAllCriticalEdges(F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests()); SplitAllCriticalEdges(F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests());
SmallVector<Instruction *, 8> IndirCalls; SmallVector<Instruction *, 8> IndirCalls;

View File

@ -954,6 +954,7 @@ Function *CodeExtractor::constructFunction(const ValueSet &inputs,
case Attribute::NonLazyBind: case Attribute::NonLazyBind:
case Attribute::NoRedZone: case Attribute::NoRedZone:
case Attribute::NoUnwind: case Attribute::NoUnwind:
case Attribute::NoSanitizeCoverage:
case Attribute::NullPointerIsValid: case Attribute::NullPointerIsValid:
case Attribute::OptForFuzzing: case Attribute::OptForFuzzing:
case Attribute::OptimizeNone: case Attribute::OptimizeNone:

View File

@ -453,6 +453,12 @@ define void @f76(i8* swiftasync %0)
ret void; ret void;
} }
; CHECK: define void @f77() #48
define void @f77() nosanitize_coverage
{
ret void;
}
; CHECK: attributes #0 = { noreturn } ; CHECK: attributes #0 = { noreturn }
; CHECK: attributes #1 = { nounwind } ; CHECK: attributes #1 = { nounwind }
; CHECK: attributes #2 = { readnone } ; CHECK: attributes #2 = { readnone }
@ -501,4 +507,5 @@ define void @f76(i8* swiftasync %0)
; CHECK: attributes #45 = { vscale_range(8,8) } ; CHECK: attributes #45 = { vscale_range(8,8) }
; CHECK: attributes #46 = { vscale_range(1,8) } ; CHECK: attributes #46 = { vscale_range(1,8) }
; CHECK: attributes #47 = { vscale_range(1,0) } ; CHECK: attributes #47 = { vscale_range(1,0) }
; CHECK: attributes #48 = { nosanitize_coverage }
; CHECK: attributes #[[NOBUILTIN]] = { nobuiltin } ; CHECK: attributes #[[NOBUILTIN]] = { nobuiltin }

View File

@ -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> ; 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 call void @f.nobuiltin() builtin
; CHECK: call void @f.nobuiltin() #44 ; CHECK: call void @f.nobuiltin() #45
call fastcc noalias i32* @f.noalias() noinline call fastcc noalias i32* @f.noalias() noinline
; CHECK: call fastcc noalias i32* @f.noalias() #12 ; CHECK: call fastcc noalias i32* @f.noalias() #12
@ -1904,6 +1904,9 @@ define void @instructions.strictfp() strictfp {
ret void ret void
} }
declare void @f.nosanitize_coverage() nosanitize_coverage
; CHECK: declare void @f.nosanitize_coverage() #44
; immarg attribute ; immarg attribute
declare void @llvm.test.immarg.intrinsic(i32 immarg) declare void @llvm.test.immarg.intrinsic(i32 immarg)
; CHECK: 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 #41 = { writeonly }
; CHECK: attributes #42 = { speculatable } ; CHECK: attributes #42 = { speculatable }
; CHECK: attributes #43 = { strictfp } ; CHECK: attributes #43 = { strictfp }
; CHECK: attributes #44 = { builtin } ; CHECK: attributes #44 = { nosanitize_coverage }
; CHECK: attributes #45 = { builtin }
;; Metadata ;; Metadata

View File

@ -25,7 +25,7 @@
'("alwaysinline" "argmemonly" "allocsize" "builtin" "cold" "convergent" "dereferenceable" "dereferenceable_or_null" "hot" "inaccessiblememonly" '("alwaysinline" "argmemonly" "allocsize" "builtin" "cold" "convergent" "dereferenceable" "dereferenceable_or_null" "hot" "inaccessiblememonly"
"inaccessiblemem_or_argmemonly" "inalloca" "inlinehint" "jumptable" "minsize" "mustprogress" "naked" "nobuiltin" "nonnull" "inaccessiblemem_or_argmemonly" "inalloca" "inlinehint" "jumptable" "minsize" "mustprogress" "naked" "nobuiltin" "nonnull"
"nocallback" "nocf_check" "noduplicate" "nofree" "noimplicitfloat" "noinline" "nomerge" "nonlazybind" "noprofile" "noredzone" "noreturn" "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" "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) "sanitize_thread" "sanitize_memory" "strictfp" "swifterror" "uwtable" "vscale_range" "willreturn" "writeonly" "immarg") 'symbols) . font-lock-constant-face)
;; Variables ;; Variables

View File

@ -176,6 +176,7 @@ FuncAttr ::= noreturn
| sanitize_thread | sanitize_thread
| sanitize_memory | sanitize_memory
| mustprogress | mustprogress
| nosanitize_coverage
; ;
OptFuncAttrs ::= + _ | OptFuncAttrs FuncAttr ; OptFuncAttrs ::= + _ | OptFuncAttrs FuncAttr ;

View File

@ -138,6 +138,7 @@ syn keyword llvmKeyword
\ nosync \ nosync
\ noundef \ noundef
\ nounwind \ nounwind
\ nosanitize_coverage
\ null_pointer_is_valid \ null_pointer_is_valid
\ optforfuzzing \ optforfuzzing
\ optnone \ optnone

View File

@ -237,6 +237,7 @@ patterns:
\\bnosync\\b|\ \\bnosync\\b|\
\\bnoundef\\b|\ \\bnoundef\\b|\
\\bnounwind\\b|\ \\bnounwind\\b|\
\\bnosanitize_coverage\\b|\
\\bnull_pointer_is_valid\\b|\ \\bnull_pointer_is_valid\\b|\
\\boptforfuzzing\\b|\ \\boptforfuzzing\\b|\
\\boptnone\\b|\ \\boptnone\\b|\