llvm-project/clang/test/CodeGen/X86/ms-secure-hotpatch-globals.c
sivadeilra 7aeb1a1fd8
Fix Solaris buildbot (#145737)
#145565 broke the Solaris buildbot, due to a subtlety in how
command-lines are parsed, which is different between Windows and
non-Windows platforms. The fix is to use `--` to force passing the rest
of args without interpretation. This is similar to existing tests for
`%clang_cl`, such as
`clang/test/CodeGen/debug-info-codeview-buildinfo.c`.

Currently, CI jobs for PRs do not detect this problem. Fixing that is
tracked in issue #145713.
2025-06-25 12:08:37 -07:00

136 lines
3.4 KiB
C

// REQUIRES: x86-registered-target
// This verifies that global variable redirection works correctly when using hotpatching.
//
// RUN: %clang_cl -c --target=x86_64-windows-msvc -O2 /Z7 \
// RUN: -fms-secure-hotpatch-functions-list=hp1,hp2,hp3,hp4,hp5_phi_ptr_mixed,hp_phi_ptr_both,hp_const_ptr_sub \
// RUN: /clang:-S /clang:-o- -- %s | FileCheck %s
#ifdef __clang__
#define NO_TAIL __attribute__((disable_tail_calls))
#else
#define NO_TAIL
#endif
extern int g_data[10];
struct SomeData {
int x;
int y;
};
const struct SomeData g_this_is_const = { 100, 200 };
struct HasPointers {
int* ptr;
int x;
};
extern struct HasPointers g_has_pointers;
void take_data(const void* p);
void do_side_effects();
void do_other_side_effects();
void hp1() NO_TAIL {
take_data(&g_data[5]);
}
// CHECK: hp1:
// CHECK: mov rcx, qword ptr [rip + __ref_g_data]
// CHECK: add rcx, 20
// CHECK: call take_data
// CHECK: .seh_endproc
void hp2() NO_TAIL {
// We do not expect string literals to be redirected.
take_data("hello, world!");
}
// CHECK: hp2:
// CHECK: lea rcx, [rip + "??_C@_0O@KJBLMJCB@hello?0?5world?$CB?$AA@"]
// CHECK: call take_data
// CHECK: .seh_endproc
void hp3() NO_TAIL {
// We do not expect g_this_is_const to be redirected because it is const
// and contains no pointers.
take_data(&g_this_is_const);
}
// CHECK: hp3:
// CHECK: lea rcx, [rip + g_this_is_const]
// CHECK: call take_data
// CHECK-NOT: __ref_g_this_is_const
// CHECK: .seh_endproc
void hp4() NO_TAIL {
take_data(&g_has_pointers);
// We expect &g_has_pointers to be redirected.
}
// CHECK: hp4:
// CHECK: mov rcx, qword ptr [rip + __ref_g_has_pointers]
// CHECK: call take_data
// CHECK: .seh_endproc
// This case checks that global variable redirection interacts correctly with PHI nodes.
// The IR for this generates a "phi ptr g_has_pointers, g_this_is_const" node.
// We expect g_has_pointers to be redirected, but not g_this_is_const.
void hp5_phi_ptr_mixed(int x) NO_TAIL {
const void* y;
if (x) {
y = &g_has_pointers;
do_side_effects();
} else {
y = &g_this_is_const;
do_other_side_effects();
}
take_data(y);
}
// CHECK: hp5_phi_ptr_mixed
// CHECK: .seh_endprologue
// CHECK: test ecx, ecx
// CHECK: mov rsi, qword ptr [rip + __ref_g_has_pointers]
// CHECK: call do_side_effects
// CHECK: jmp
// CHECK: call do_other_side_effects
// CHECK: lea rsi, [rip + g_this_is_const]
// CHECK: mov rcx, rsi
// CHECK: call take_data
// CHECK: .seh_endproc
// This case tests that global variable redirection interacts correctly with PHI nodes,
// where two (all) operands of a given PHI node are globabl variables that redirect.
void hp_phi_ptr_both(int x) NO_TAIL {
const void* y;
if (x) {
y = &g_has_pointers;
do_side_effects();
} else {
y = &g_data[5];
do_other_side_effects();
}
take_data(y);
}
// CHECK: hp_phi_ptr_both:
// CHECK: .seh_endprologue
// CHECK: test ecx, ecx
// CHECK: mov rsi, qword ptr [rip + __ref_g_has_pointers]
// CHECK: mov rsi, qword ptr [rip + __ref_g_data]
// CHECK: take_data
// CHECK: .seh_endproc
// Test a constant expression which references global variable addresses.
size_t hp_const_ptr_sub() NO_TAIL {
return (unsigned char*)&g_has_pointers - (unsigned char*)&g_data;
}
// CHECK: hp_const_ptr_sub:
// CHECK: mov rax, qword ptr [rip + __ref_g_has_pointers]
// CHECK: sub rax, qword ptr [rip + __ref_g_data]
// CHECK: ret