mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 17:36:05 +00:00

Functions created with createWithDefaultAttr() need to have the correct target-{cpu,features} attributes to avoid miscompilations such as using the wrong relocation type to access globals (missing tagged-globals feature), clobbering registers specified via -ffixed-* (missing reserve-* feature), and so on. There's already a number of attributes copied from the module flags onto functions created by createWithDefaultAttr(). I don't think module flags are the right choice for the target attributes because we don't need the conflict resolution logic between modules with different target attributes, nor does it seem sensible to add it: there's no unambiguously "correct" set of target attributes when merging two modules with different attributes, and nor should there be; it's perfectly valid for two modules to be compiled with different target attributes, that's the whole reason why they are per-function. This also implies that it's unnecessary to serialize the attributes in bitcode, which implies that they shouldn't be stored on the module. We can also observe that for the most part, createWithDefaultAttr() is called from compiler passes such as sanitizers, coverage and profiling passes that are part of the compile time pipeline, not the LTO pipeline. This hints at a solution: we need to store the attributes in a non-serialized location associated with the ambient compilation context. Therefore in this patch I elected to store the attributes on the LLVMContext. There are calls to createWithDefaultAttr() in the NVPTX and AMDGPU backends, and those calls would happen at LTO time. For those callers, the bug still potentially exists and it would be necessary to refactor them to create the functions at compile time if this issue is relevant on those platforms. Fixes #93633. Reviewers: fmayer, MaskRay, eugenis Reviewed By: MaskRay Pull Request: https://github.com/llvm/llvm-project/pull/96721
91 lines
4.9 KiB
C++
91 lines
4.9 KiB
C++
// RUN: echo "int extra_global;" > %t.extra-source.cpp
|
|
// RUN: echo "global:*ignorelisted_global*" > %t.ignorelist
|
|
// RUN: %clang_cc1 -include %t.extra-source.cpp -fsanitize=address -fsanitize-ignorelist=%t.ignorelist -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,GLOBS,ASAN
|
|
// RUN: %clang_cc1 -include %t.extra-source.cpp -fsanitize=kernel-address -fsanitize-ignorelist=%t.ignorelist -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,GLOBS,KASAN
|
|
// The ignorelist file uses regexps, so Windows path backslashes.
|
|
// RUN: echo "src:%s" | sed -e 's/\\/\\\\/g' > %t.ignorelist-src
|
|
// RUN: %clang_cc1 -include %t.extra-source.cpp -fsanitize=address -fsanitize-ignorelist=%t.ignorelist-src -emit-llvm -o - %s | FileCheck %s --check-prefix=IGNORELIST-SRC
|
|
// RUN: %clang_cc1 -include %t.extra-source.cpp -fsanitize=kernel-address -fsanitize-ignorelist=%t.ignorelist-src -emit-llvm -o - %s | FileCheck %s --check-prefix=IGNORELIST-SRC
|
|
|
|
int global;
|
|
int dyn_init_global = global;
|
|
int __attribute__((no_sanitize("address"))) attributed_global;
|
|
int __attribute__((disable_sanitizer_instrumentation)) disable_instrumentation_global;
|
|
int ignorelisted_global;
|
|
extern int __attribute__((no_sanitize("address"))) external_global;
|
|
|
|
int __attribute__((section("__DATA, __common"))) sectioned_global; // KASAN - ignore globals in a section
|
|
extern "C" {
|
|
int __special_global; // KASAN - ignore globals with __-prefix
|
|
}
|
|
|
|
void func() {
|
|
static int static_var = 0;
|
|
const char *literal = "Hello, world!";
|
|
external_global = 1;
|
|
}
|
|
|
|
// GLOBS: @{{.*}}extra_global{{.*}} ={{.*}} global
|
|
// GLOBS-NOT: no_sanitize_address
|
|
// GLOBS: @{{.*}}global{{.*}} ={{.*}} global
|
|
// GLOBS-NOT: no_sanitize_address
|
|
// GLOBS: @{{.*}}dyn_init_global{{.*}} ={{.*}} global {{.*}}, sanitize_address_dyninit
|
|
// GLOBS-NOT: no_sanitize_address
|
|
|
|
// GLOBS: @{{.*}}attributed_global{{.*}} ={{.*}} global {{.*}} no_sanitize_address
|
|
// GLOBS: @{{.*}}disable_instrumentation_global{{.*}} ={{.*}} global {{.*}} no_sanitize_address
|
|
// GLOBS: @{{.*}}ignorelisted_global{{.*}} ={{.*}} global {{.*}} no_sanitize_address
|
|
|
|
// ASAN: @{{.*}}sectioned_global{{.*}} ={{.*}} global { i32, [28 x i8] }{{.*}}, align 32
|
|
// ASAN-NOT: no_sanitize_address
|
|
// ASAN: @{{.*}}__special_global{{.*}} ={{.*}} global { i32, [28 x i8] }{{.*}}, align 32
|
|
// ASAN-NOT: no_sanitize_address
|
|
|
|
/// Note: No attribute is added by the IR pass, but the type didn't change, so
|
|
/// that checks our assertions that the globals didn't get instrumented.
|
|
// KASAN: @{{.*}}sectioned_global{{.*}} ={{.*}} global i32 {{.*}}
|
|
// KASAN: @{{.*}}__special_global{{.*}} ={{.*}} global i32 {{.*}}
|
|
|
|
// GLOBS: @{{[^ ]*}}static_var{{[^ ]*}} ={{.*}} global {{.*}}
|
|
// GLOBS-NOT: no_sanitize_address
|
|
// GLOBS: @{{.*}} = {{.*}}c"Hello, world!\00"
|
|
// GLOBS-NOT: no_sanitize_address
|
|
|
|
// GLOBS: @{{.*}}external_global{{.*}} ={{.*}} no_sanitize_address
|
|
|
|
/// Without -fasynchronous-unwind-tables, ctor and dtor get the uwtable attribute.
|
|
// CHECK-LABEL: define internal void @asan.module_ctor() #[[#ATTR:]] {
|
|
// ASAN-NEXT: call void @__asan_init
|
|
// ASAN-NEXT: call void @__asan_version_mismatch_check
|
|
// KASAN-NOT: call void @__asan_init
|
|
// KASAN-NOT: call void @__asan_version_mismatch_check
|
|
// ASAN-NEXT: call void @__asan_register_globals({{.*}}, i{{32|64}} 7)
|
|
// KASAN-NEXT: call void @__asan_register_globals({{.*}}, i{{32|64}} 5)
|
|
// CHECK-NEXT: ret void
|
|
|
|
// CHECK: define internal void @asan.module_dtor() #[[#ATTR]] {
|
|
// CHECK-NEXT: call void @__asan_unregister_globals
|
|
// CHECK-NEXT: ret void
|
|
|
|
// CHECK: attributes #[[#ATTR]] = { nounwind
|
|
|
|
/// If -fasynchronous-unwind-tables, set the module flag "uwtable". ctor/dtor
|
|
/// will thus get the uwtable attribute.
|
|
// RUN: %clang_cc1 -emit-llvm -fsanitize=address -funwind-tables=2 -o - %s | FileCheck %s --check-prefixes=UWTABLE
|
|
// UWTABLE: define internal void @asan.module_dtor() #[[#ATTR:]] {
|
|
// UWTABLE: attributes #[[#ATTR]] = { nounwind uwtable
|
|
// UWTABLE: ![[#]] = !{i32 7, !"uwtable", i32 2}
|
|
|
|
// IGNORELIST-SRC: @{{.*}}extra_global{{.*}} ={{.*}} global
|
|
// IGNORELIST-SRC-NOT: no_sanitize_address
|
|
// IGNORELIST-SRC: @{{.*}}global{{.*}} ={{.*}} global {{.*}} no_sanitize_address
|
|
// IGNORELIST-SRC: @{{.*}}dyn_init_global{{.*}} ={{.*}} global {{.*}} no_sanitize_address
|
|
// IGNORELIST-SRC: @{{.*}}attributed_global{{.*}} ={{.*}} global {{.*}} no_sanitize_address
|
|
// IGNORELIST-SRC: @{{.*}}disable_instrumentation_global{{.*}} ={{.*}} global {{.*}} no_sanitize_address
|
|
// IGNORELIST-SRC: @{{.*}}ignorelisted_global{{.*}} ={{.*}} global {{.*}} no_sanitize_address
|
|
// IGNORELIST-SRC: @{{.*}}sectioned_global{{.*}} ={{.*}} global {{.*}} no_sanitize_address
|
|
// IGNORELIST-SRC: @{{.*}}__special_global{{.*}} ={{.*}} global {{.*}} no_sanitize_address
|
|
// IGNORELIST-SRC: @{{.*}}static_var{{.*}} ={{.*}} global {{.*}} no_sanitize_address
|
|
// IGNORELIST-SRC: @{{.*}} ={{.*}} c"Hello, world!\00"{{.*}} no_sanitize_address
|
|
// IGNORELIST-SRC: @{{.*}}external_global{{.*}} ={{.*}} no_sanitize_address
|