136 lines · c
1// REQUIRES: x86-registered-target2 3// This verifies that global variable redirection works correctly when using hotpatching.4//5// RUN: %clang_cl -c --target=x86_64-windows-msvc -O2 /Z7 \6// RUN: -fms-secure-hotpatch-functions-list=hp1,hp2,hp3,hp4,hp5_phi_ptr_mixed,hp_phi_ptr_both,hp_const_ptr_sub \7// RUN: /clang:-S /clang:-o- -- %s | FileCheck %s8 9#ifdef __clang__10#define NO_TAIL __attribute__((disable_tail_calls))11#else12#define NO_TAIL13#endif14 15extern int g_data[10];16 17struct SomeData {18 int x;19 int y;20};21 22const struct SomeData g_this_is_const = { 100, 200 };23 24struct HasPointers {25 int* ptr;26 int x;27};28 29extern struct HasPointers g_has_pointers;30 31void take_data(const void* p);32 33void do_side_effects();34void do_other_side_effects();35 36void hp1() NO_TAIL {37 take_data(&g_data[5]);38}39 40// CHECK: hp1:41// CHECK: mov rcx, qword ptr [rip + __ref_g_data]42// CHECK: add rcx, 2043// CHECK: call take_data44// CHECK: .seh_endproc45 46void hp2() NO_TAIL {47 // We do not expect string literals to be redirected.48 take_data("hello, world!");49}50 51// CHECK: hp2:52// CHECK: lea rcx, [rip + "??_C@_0O@KJBLMJCB@hello?0?5world?$CB?$AA@"]53// CHECK: call take_data54// CHECK: .seh_endproc55 56void hp3() NO_TAIL {57 // We do not expect g_this_is_const to be redirected because it is const58 // and contains no pointers.59 take_data(&g_this_is_const);60}61 62// CHECK: hp3:63// CHECK: lea rcx, [rip + g_this_is_const]64// CHECK: call take_data65// CHECK-NOT: __ref_g_this_is_const66// CHECK: .seh_endproc67 68void hp4() NO_TAIL {69 take_data(&g_has_pointers);70 // We expect &g_has_pointers to be redirected.71}72 73// CHECK: hp4:74// CHECK: mov rcx, qword ptr [rip + __ref_g_has_pointers]75// CHECK: call take_data76// CHECK: .seh_endproc77 78// This case checks that global variable redirection interacts correctly with PHI nodes.79// The IR for this generates a "phi ptr g_has_pointers, g_this_is_const" node.80// We expect g_has_pointers to be redirected, but not g_this_is_const.81void hp5_phi_ptr_mixed(int x) NO_TAIL {82 const void* y;83 if (x) {84 y = &g_has_pointers;85 do_side_effects();86 } else {87 y = &g_this_is_const;88 do_other_side_effects();89 }90 take_data(y);91}92 93// CHECK: hp5_phi_ptr_mixed94// CHECK: .seh_endprologue95// CHECK: test ecx, ecx96// CHECK: mov rsi, qword ptr [rip + __ref_g_has_pointers]97// CHECK: call do_side_effects98// CHECK: jmp99// CHECK: call do_other_side_effects100// CHECK: lea rsi, [rip + g_this_is_const]101// CHECK: mov rcx, rsi102// CHECK: call take_data103// CHECK: .seh_endproc104 105// This case tests that global variable redirection interacts correctly with PHI nodes,106// where two (all) operands of a given PHI node are globabl variables that redirect.107void hp_phi_ptr_both(int x) NO_TAIL {108 const void* y;109 if (x) {110 y = &g_has_pointers;111 do_side_effects();112 } else {113 y = &g_data[5];114 do_other_side_effects();115 }116 take_data(y);117}118 119// CHECK: hp_phi_ptr_both:120// CHECK: .seh_endprologue121// CHECK: test ecx, ecx122// CHECK: mov rsi, qword ptr [rip + __ref_g_has_pointers]123// CHECK: mov rsi, qword ptr [rip + __ref_g_data]124// CHECK: take_data125// CHECK: .seh_endproc126 127// Test a constant expression which references global variable addresses.128size_t hp_const_ptr_sub() NO_TAIL {129 return (unsigned char*)&g_has_pointers - (unsigned char*)&g_data;130}131 132// CHECK: hp_const_ptr_sub:133// CHECK: mov rax, qword ptr [rip + __ref_g_has_pointers]134// CHECK: sub rax, qword ptr [rip + __ref_g_data]135// CHECK: ret136