Skip to content
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

[SanitizerBinaryMetadata] Fix multi-version sanitizer metadata #97848

Merged
merged 1 commit into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions clang/test/CodeGen/sanitize-metadata-ignorelist.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,6 @@ void bar() {
__atomic_fetch_add(&y, 2, __ATOMIC_RELAXED);
}

// ALLOW: __sanitizer_metadata_covered.module_ctor
// FUN: __sanitizer_metadata_covered.module_ctor
// SRC-NOT: __sanitizer_metadata_covered.module_ctor
// ALLOW: __sanitizer_metadata_covered2.module_ctor
// FUN: __sanitizer_metadata_covered2.module_ctor
// SRC-NOT: __sanitizer_metadata_covered{{.*}}.module_ctor
22 changes: 11 additions & 11 deletions clang/test/CodeGen/sanitize-metadata-nosanitize.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
// RUN: %clang_cc1 -O -fexperimental-sanitize-metadata=covered -fexperimental-sanitize-metadata=atomics -fexperimental-sanitize-metadata=uar -triple x86_64-gnu-linux -x c -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK

//.
// CHECK: @__start_sanmd_covered = extern_weak hidden global ptr
// CHECK: @__stop_sanmd_covered = extern_weak hidden global ptr
// CHECK: @__start_sanmd_atomics = extern_weak hidden global ptr
// CHECK: @__stop_sanmd_atomics = extern_weak hidden global ptr
// CHECK: @llvm.used = appending global [4 x ptr] [ptr @__sanitizer_metadata_covered.module_ctor, ptr @__sanitizer_metadata_covered.module_dtor, ptr @__sanitizer_metadata_atomics.module_ctor, ptr @__sanitizer_metadata_atomics.module_dtor], section "llvm.metadata"
// CHECK: @llvm.global_ctors = appending global [2 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 2, ptr @__sanitizer_metadata_covered.module_ctor, ptr @__sanitizer_metadata_covered.module_ctor }, { i32, ptr, ptr } { i32 2, ptr @__sanitizer_metadata_atomics.module_ctor, ptr @__sanitizer_metadata_atomics.module_ctor }]
// CHECK: @llvm.global_dtors = appending global [2 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 2, ptr @__sanitizer_metadata_covered.module_dtor, ptr @__sanitizer_metadata_covered.module_dtor }, { i32, ptr, ptr } { i32 2, ptr @__sanitizer_metadata_atomics.module_dtor, ptr @__sanitizer_metadata_atomics.module_dtor }]
// CHECK: @__start_sanmd_covered2 = extern_weak hidden global ptr
// CHECK: @__stop_sanmd_covered2 = extern_weak hidden global ptr
// CHECK: @__start_sanmd_atomics2 = extern_weak hidden global ptr
// CHECK: @__stop_sanmd_atomics2 = extern_weak hidden global ptr
// CHECK: @llvm.used = appending global [4 x ptr] [ptr @__sanitizer_metadata_covered2.module_ctor, ptr @__sanitizer_metadata_covered2.module_dtor, ptr @__sanitizer_metadata_atomics2.module_ctor, ptr @__sanitizer_metadata_atomics2.module_dtor], section "llvm.metadata"
// CHECK: @llvm.global_ctors = appending global [2 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 2, ptr @__sanitizer_metadata_covered2.module_ctor, ptr @__sanitizer_metadata_covered2.module_ctor }, { i32, ptr, ptr } { i32 2, ptr @__sanitizer_metadata_atomics2.module_ctor, ptr @__sanitizer_metadata_atomics2.module_ctor }]
// CHECK: @llvm.global_dtors = appending global [2 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 2, ptr @__sanitizer_metadata_covered2.module_dtor, ptr @__sanitizer_metadata_covered2.module_dtor }, { i32, ptr, ptr } { i32 2, ptr @__sanitizer_metadata_atomics2.module_dtor, ptr @__sanitizer_metadata_atomics2.module_dtor }]
//.
// CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(write, argmem: none, inaccessiblemem: none)
// CHECK-LABEL: define dso_local void @escape
Expand Down Expand Up @@ -95,17 +95,17 @@ __attribute__((no_sanitize("all"))) int test_no_sanitize_all(int *x, int *y) {
// CHECK: attributes #3 = { mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none) "min-legal-vector-width"="0" "no-trapping-math"="true" "no_sanitize_thread" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
// CHECK: attributes #4 = { nounwind "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
//.
// CHECK: !2 = !{!"sanmd_covered!C", !3}
// CHECK: !2 = !{!"sanmd_covered2!C", !3}
// CHECK: !3 = !{i64 0}
// CHECK: !4 = !{!"sanmd_covered!C", !5}
// CHECK: !4 = !{!"sanmd_covered2!C", !5}
// CHECK: !5 = !{i64 3}
// CHECK: !6 = !{!7, !7, i64 0}
// CHECK: !7 = !{!"any pointer", !8, i64 0}
// CHECK: !8 = !{!"omnipotent char", !9, i64 0}
// CHECK: !9 = !{!"Simple C/C++ TBAA"}
// CHECK: !10 = !{!"sanmd_atomics!C"}
// CHECK: !10 = !{!"sanmd_atomics2!C"}
// CHECK: !11 = !{!12, !12, i64 0}
// CHECK: !12 = !{!"int", !8, i64 0}
// CHECK: !13 = !{!"sanmd_covered!C", !14}
// CHECK: !13 = !{!"sanmd_covered2!C", !14}
// CHECK: !14 = !{i64 2}
//.
28 changes: 14 additions & 14 deletions clang/test/CodeGen/sanitize-metadata.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// RUN: %clang_cc1 -O -fexperimental-sanitize-metadata=atomics -triple x86_64-gnu-linux -x c -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,ATOMICS
// RUN: %clang_cc1 -O -fexperimental-sanitize-metadata=atomics -triple aarch64-gnu-linux -x c -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,ATOMICS

// CHECK: @__start_sanmd_atomics = extern_weak hidden global ptr
// CHECK: @__stop_sanmd_atomics = extern_weak hidden global ptr
// CHECK: @__start_sanmd_covered = extern_weak hidden global ptr
// CHECK: @__stop_sanmd_covered = extern_weak hidden global ptr
// CHECK: @__start_sanmd_atomics2 = extern_weak hidden global ptr
// CHECK: @__stop_sanmd_atomics2 = extern_weak hidden global ptr
// CHECK: @__start_sanmd_covered2 = extern_weak hidden global ptr
// CHECK: @__stop_sanmd_covered2 = extern_weak hidden global ptr

int x, y;

Expand All @@ -21,16 +21,16 @@ int atomics() {
__atomic_fetch_add(&x, 1, __ATOMIC_RELAXED);
return y;
}
// ATOMICS-LABEL: __sanitizer_metadata_atomics.module_ctor
// ATOMICS: call void @__sanitizer_metadata_atomics_add(i32 2, ptr @__start_sanmd_atomics, ptr @__stop_sanmd_atomics)
// ATOMICS-LABEL: __sanitizer_metadata_atomics.module_dtor
// ATOMICS: call void @__sanitizer_metadata_atomics_del(i32 2, ptr @__start_sanmd_atomics, ptr @__stop_sanmd_atomics)
// ATOMICS-LABEL: __sanitizer_metadata_atomics2.module_ctor
// ATOMICS: call void @__sanitizer_metadata_atomics_add(i32 2, ptr @__start_sanmd_atomics2, ptr @__stop_sanmd_atomics2)
// ATOMICS-LABEL: __sanitizer_metadata_atomics2.module_dtor
// ATOMICS: call void @__sanitizer_metadata_atomics_del(i32 2, ptr @__start_sanmd_atomics2, ptr @__stop_sanmd_atomics2)

// CHECK-LABEL: __sanitizer_metadata_covered.module_ctor
// CHECK: call void @__sanitizer_metadata_covered_add(i32 2, ptr @__start_sanmd_covered, ptr @__stop_sanmd_covered)
// CHECK-LABEL: __sanitizer_metadata_covered.module_dtor
// CHECK: call void @__sanitizer_metadata_covered_del(i32 2, ptr @__start_sanmd_covered, ptr @__stop_sanmd_covered)
// CHECK-LABEL: __sanitizer_metadata_covered2.module_ctor
// CHECK: call void @__sanitizer_metadata_covered_add(i32 2, ptr @__start_sanmd_covered2, ptr @__stop_sanmd_covered2)
// CHECK-LABEL: __sanitizer_metadata_covered2.module_dtor
// CHECK: call void @__sanitizer_metadata_covered_del(i32 2, ptr @__start_sanmd_covered2, ptr @__stop_sanmd_covered2)

// ATOMICS: ![[ATOMICS_COVERED]] = !{!"sanmd_covered!C", ![[ATOMICS_COVERED_AUX:[0-9]+]]}
// ATOMICS: ![[ATOMICS_COVERED]] = !{!"sanmd_covered2!C", ![[ATOMICS_COVERED_AUX:[0-9]+]]}
// ATOMICS: ![[ATOMICS_COVERED_AUX]] = !{i64 1}
// ATOMICS: ![[ATOMIC_OP]] = !{!"sanmd_atomics!C"}
// ATOMICS: ![[ATOMIC_OP]] = !{!"sanmd_atomics2!C"}
32 changes: 22 additions & 10 deletions llvm/lib/Transforms/Instrumentation/SanitizerBinaryMetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Analysis/CaptureTracking.h"
Expand Down Expand Up @@ -130,7 +131,7 @@ class SanitizerBinaryMetadata {
std::unique_ptr<SpecialCaseList> Ignorelist)
: Mod(M), Options(transformOptionsFromCl(std::move(Opts))),
Ignorelist(std::move(Ignorelist)), TargetTriple(M.getTargetTriple()),
IRB(M.getContext()) {
VersionStr(utostr(getVersion())), IRB(M.getContext()) {
// FIXME: Make it work with other formats.
assert(TargetTriple.isOSBinFormatELF() && "ELF only");
assert(!(TargetTriple.isNVPTX() || TargetTriple.isAMDGPU()) &&
Expand Down Expand Up @@ -167,10 +168,10 @@ class SanitizerBinaryMetadata {
StringRef getSectionName(StringRef SectionSuffix);

// Returns the section start marker name.
Twine getSectionStart(StringRef SectionSuffix);
StringRef getSectionStart(StringRef SectionSuffix);

// Returns the section end marker name.
Twine getSectionEnd(StringRef SectionSuffix);
StringRef getSectionEnd(StringRef SectionSuffix);

// Returns true if the access to the address should be considered "atomic".
bool pretendAtomicAccess(const Value *Addr);
Expand All @@ -179,6 +180,7 @@ class SanitizerBinaryMetadata {
const SanitizerBinaryMetadataOptions Options;
std::unique_ptr<SpecialCaseList> Ignorelist;
const Triple TargetTriple;
const std::string VersionStr;
IRBuilder<> IRB;
BumpPtrAllocator Alloc;
UniqueStringSaver StringPool{Alloc};
Expand Down Expand Up @@ -209,19 +211,25 @@ bool SanitizerBinaryMetadata::run() {
getSectionMarker(getSectionStart(MI->SectionSuffix), PtrTy),
getSectionMarker(getSectionEnd(MI->SectionSuffix), PtrTy),
};

// Calls to the initialization functions with different versions cannot be
// merged. Give the structors unique names based on the version, which will
// also be used as the COMDAT key.
const std::string StructorPrefix = (MI->FunctionPrefix + VersionStr).str();

// We declare the _add and _del functions as weak, and only call them if
// there is a valid symbol linked. This allows building binaries with
// semantic metadata, but without having callbacks. When a tool that wants
// the metadata is linked which provides the callbacks, they will be called.
Function *Ctor =
createSanitizerCtorAndInitFunctions(
Mod, (MI->FunctionPrefix + ".module_ctor").str(),
Mod, StructorPrefix + ".module_ctor",
(MI->FunctionPrefix + "_add").str(), InitTypes, InitArgs,
/*VersionCheckName=*/StringRef(), /*Weak=*/ClWeakCallbacks)
.first;
Function *Dtor =
createSanitizerCtorAndInitFunctions(
Mod, (MI->FunctionPrefix + ".module_dtor").str(),
Mod, StructorPrefix + ".module_dtor",
(MI->FunctionPrefix + "_del").str(), InitTypes, InitArgs,
/*VersionCheckName=*/StringRef(), /*Weak=*/ClWeakCallbacks)
.first;
Expand Down Expand Up @@ -454,15 +462,19 @@ SanitizerBinaryMetadata::getSectionMarker(const Twine &MarkerName, Type *Ty) {
StringRef SanitizerBinaryMetadata::getSectionName(StringRef SectionSuffix) {
// FIXME: Other TargetTriples.
// Request ULEB128 encoding for all integer constants.
return StringPool.save(SectionSuffix + "!C");
return StringPool.save(SectionSuffix + VersionStr + "!C");
}

Twine SanitizerBinaryMetadata::getSectionStart(StringRef SectionSuffix) {
return "__start_" + SectionSuffix;
StringRef SanitizerBinaryMetadata::getSectionStart(StringRef SectionSuffix) {
// Twine only concatenates 2 strings; with >2 strings, concatenating them
// creates Twine temporaries, and returning the final Twine no longer works
// because we'd end up with a stack-use-after-return. So here we also use the
// StringPool to store the new string.
return StringPool.save("__start_" + SectionSuffix + VersionStr);
}

Twine SanitizerBinaryMetadata::getSectionEnd(StringRef SectionSuffix) {
return "__stop_" + SectionSuffix;
StringRef SanitizerBinaryMetadata::getSectionEnd(StringRef SectionSuffix) {
return StringPool.save("__stop_" + SectionSuffix + VersionStr);
}

} // namespace
Expand Down
28 changes: 14 additions & 14 deletions llvm/test/Instrumentation/SanitizerBinaryMetadata/atomics.ll
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

; Check that atomic memory operations receive PC sections metadata.

; CHECK: @__start_sanmd_atomics = extern_weak hidden global ptr
; CHECK: @__stop_sanmd_atomics = extern_weak hidden global ptr
; CHECK: @__start_sanmd_covered = extern_weak hidden global ptr
; CHECK: @__stop_sanmd_covered = extern_weak hidden global ptr
; CHECK: @__start_sanmd_atomics2 = extern_weak hidden global ptr
; CHECK: @__stop_sanmd_atomics2 = extern_weak hidden global ptr
; CHECK: @__start_sanmd_covered2 = extern_weak hidden global ptr
; CHECK: @__stop_sanmd_covered2 = extern_weak hidden global ptr

target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"

Expand Down Expand Up @@ -2035,46 +2035,46 @@ entry:

; Check that callbacks are emitted.

; CHECK-LABEL: __sanitizer_metadata_atomics.module_ctor
; CHECK-LABEL: __sanitizer_metadata_atomics2.module_ctor
; CHECK-DAG: entry:
; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr @__sanitizer_metadata_atomics_add, null
; CHECK-NEXT: br i1 [[CMP]], label %callfunc, label %ret
; CHECK-DAG: callfunc:
; CHECK-NEXT: call void @__sanitizer_metadata_atomics_add(i32 2, ptr @__start_sanmd_atomics, ptr @__stop_sanmd_atomics)
; CHECK-NEXT: call void @__sanitizer_metadata_atomics_add(i32 2, ptr @__start_sanmd_atomics2, ptr @__stop_sanmd_atomics2)
; CHECK-NEXT: br label %ret
; CHECK-DAG: ret:
; CHECK-NEXT: ret void

; CHECK-LABEL: __sanitizer_metadata_atomics.module_dtor
; CHECK-LABEL: __sanitizer_metadata_atomics2.module_dtor
; CHECK-DAG: entry:
; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr @__sanitizer_metadata_atomics_del, null
; CHECK-NEXT: br i1 [[CMP]], label %callfunc, label %ret
; CHECK-DAG: callfunc:
; CHECK-NEXT: call void @__sanitizer_metadata_atomics_del(i32 2, ptr @__start_sanmd_atomics, ptr @__stop_sanmd_atomics)
; CHECK-NEXT: call void @__sanitizer_metadata_atomics_del(i32 2, ptr @__start_sanmd_atomics2, ptr @__stop_sanmd_atomics2)
; CHECK-NEXT: br label %ret
; CHECK-DAG: ret:
; CHECK-NEXT: ret void

; CHECK-LABEL: __sanitizer_metadata_covered.module_ctor
; CHECK-LABEL: __sanitizer_metadata_covered2.module_ctor
; CHECK-DAG: entry:
; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr @__sanitizer_metadata_covered_add, null
; CHECK-NEXT: br i1 [[CMP]], label %callfunc, label %ret
; CHECK-DAG: callfunc:
; CHECK-NEXT: call void @__sanitizer_metadata_covered_add(i32 2, ptr @__start_sanmd_covered, ptr @__stop_sanmd_covered)
; CHECK-NEXT: call void @__sanitizer_metadata_covered_add(i32 2, ptr @__start_sanmd_covered2, ptr @__stop_sanmd_covered2)
; CHECK-NEXT: br label %ret
; CHECK-DAG: ret:
; CHECK-NEXT: ret void

; CHECK-LABEL: __sanitizer_metadata_covered.module_dtor
; CHECK-LABEL: __sanitizer_metadata_covered2.module_dtor
; CHECK-DAG: entry:
; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr @__sanitizer_metadata_covered_del, null
; CHECK-NEXT: br i1 [[CMP]], label %callfunc, label %ret
; CHECK-DAG: callfunc:
; CHECK-NEXT: call void @__sanitizer_metadata_covered_del(i32 2, ptr @__start_sanmd_covered, ptr @__stop_sanmd_covered)
; CHECK-NEXT: call void @__sanitizer_metadata_covered_del(i32 2, ptr @__start_sanmd_covered2, ptr @__stop_sanmd_covered2)
; CHECK-NEXT: br label %ret
; CHECK-DAG: ret:
; CHECK-NEXT: ret void

; CHECK: !0 = !{!"sanmd_covered!C", !1}
; CHECK: !0 = !{!"sanmd_covered2!C", !1}
; CHECK: !1 = !{i64 1}
; CHECK: !2 = !{!"sanmd_atomics!C"}
; CHECK: !2 = !{!"sanmd_atomics2!C"}
18 changes: 9 additions & 9 deletions llvm/test/Instrumentation/SanitizerBinaryMetadata/ctor.ll
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
; RUN: opt < %s -passes='module(sanmd-module)' -sanitizer-metadata-atomics -S | FileCheck %s

; CHECK: $__sanitizer_metadata_atomics.module_ctor = comdat any
; CHECK: $__sanitizer_metadata_atomics.module_dtor = comdat any
; CHECK: $__sanitizer_metadata_covered.module_ctor = comdat any
; CHECK: $__sanitizer_metadata_covered.module_dtor = comdat any
; CHECK: $__sanitizer_metadata_atomics2.module_ctor = comdat any
; CHECK: $__sanitizer_metadata_atomics2.module_dtor = comdat any
; CHECK: $__sanitizer_metadata_covered2.module_ctor = comdat any
; CHECK: $__sanitizer_metadata_covered2.module_dtor = comdat any

; CHECK: @llvm.used = appending global [4 x ptr] [ptr @__sanitizer_metadata_atomics.module_ctor, ptr @__sanitizer_metadata_atomics.module_dtor, ptr @__sanitizer_metadata_covered.module_ctor, ptr @__sanitizer_metadata_covered.module_dtor], section "llvm.metadata"
; CHECK: @llvm.global_ctors = appending global [2 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 2, ptr @__sanitizer_metadata_atomics.module_ctor, ptr @__sanitizer_metadata_atomics.module_ctor }, { i32, ptr, ptr } { i32 2, ptr @__sanitizer_metadata_covered.module_ctor, ptr @__sanitizer_metadata_covered.module_ctor }]
; CHECK: @llvm.global_dtors = appending global [2 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 2, ptr @__sanitizer_metadata_atomics.module_dtor, ptr @__sanitizer_metadata_atomics.module_dtor }, { i32, ptr, ptr } { i32 2, ptr @__sanitizer_metadata_covered.module_dtor, ptr @__sanitizer_metadata_covered.module_dtor }]
; CHECK: @llvm.used = appending global [4 x ptr] [ptr @__sanitizer_metadata_atomics2.module_ctor, ptr @__sanitizer_metadata_atomics2.module_dtor, ptr @__sanitizer_metadata_covered2.module_ctor, ptr @__sanitizer_metadata_covered2.module_dtor], section "llvm.metadata"
; CHECK: @llvm.global_ctors = appending global [2 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 2, ptr @__sanitizer_metadata_atomics2.module_ctor, ptr @__sanitizer_metadata_atomics2.module_ctor }, { i32, ptr, ptr } { i32 2, ptr @__sanitizer_metadata_covered2.module_ctor, ptr @__sanitizer_metadata_covered2.module_ctor }]
; CHECK: @llvm.global_dtors = appending global [2 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 2, ptr @__sanitizer_metadata_atomics2.module_dtor, ptr @__sanitizer_metadata_atomics2.module_dtor }, { i32, ptr, ptr } { i32 2, ptr @__sanitizer_metadata_covered2.module_dtor, ptr @__sanitizer_metadata_covered2.module_dtor }]

; CHECK: define hidden void @__sanitizer_metadata_covered.module_ctor() #1 comdat {
; CHECK: define hidden void @__sanitizer_metadata_covered.module_dtor() #1 comdat {
; CHECK: define hidden void @__sanitizer_metadata_covered2.module_ctor() #1 comdat {
; CHECK: define hidden void @__sanitizer_metadata_covered2.module_dtor() #1 comdat {

target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
Expand Down
Loading