Index: test/tools/llvm-cfi-verify/X86/function_only_check.s =================================================================== --- /dev/null +++ test/tools/llvm-cfi-verify/X86/function_only_check.s @@ -0,0 +1,8 @@ +# RUN: llvm-cfi-verify -trap-function=__cfi_slowpath@plt %S/Inputs/function-only-check.o | FileCheck %s + +# CHECK-LABEL: {{^Instruction: .* \(PROTECTED\)}} + +# CHECK: Expected Protected: 1 (100.00%) +# CHECK: Unexpected Protected: 0 (0.00%) +# CHECK: Expected Unprotected: 0 (0.00%) +# CHECK: Unexpected Unprotected (BAD): 0 (0.00%) Index: tools/llvm-cfi-verify/lib/FileAnalysis.cpp =================================================================== --- tools/llvm-cfi-verify/lib/FileAnalysis.cpp +++ tools/llvm-cfi-verify/lib/FileAnalysis.cpp @@ -452,6 +452,11 @@ if (!(object::ELFSectionRef(Section).getFlags() & ELF::SHF_EXECINSTR)) continue; + // Avoid checking the PLT since it produces spurious failures on AArch64. + StringRef SectionName; + if (!Section.getName(SectionName) && SectionName == ".plt") + continue; + StringRef SectionContents; if (Section.getContents(SectionContents)) return make_error("Failed to retrieve section contents", Index: tools/llvm-cfi-verify/lib/GraphBuilder.cpp =================================================================== --- tools/llvm-cfi-verify/lib/GraphBuilder.cpp +++ tools/llvm-cfi-verify/lib/GraphBuilder.cpp @@ -311,6 +311,24 @@ Result.ConditionalBranchNodes.push_back(BranchNode); } + // When using cross-DSO, some indirect calls are not guarded by a branch to a + // trap but instead follow a call to __cfi_slowpath. For example: + // if (!InlinedFastCheck(f)) + // call *f + // else { + // __cfi_slowpath(CallSiteTypeId, f); + // call *f + // } + // To mark the second call as protected, we recognize indirect calls that + // directly follow calls to the trap function. + if (CFCrossRefs.empty()) { + const Instr *PrevInstr = Analysis.getPrevInstructionSequential(ChildMeta); + if (PrevInstr && Analysis.isTrapCall(*PrevInstr)) { + Result.IntermediateNodes[PrevInstr->VMAddress] = Address; + HasValidCrossRef = true; + } + } + if (!HasValidCrossRef) Result.OrphanedNodes.push_back(Address);