File: ms-secure-hotpatch-globals.c

package info (click to toggle)
llvm-toolchain-21 1%3A21.1.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 2,235,796 kB
  • sloc: cpp: 7,617,614; ansic: 1,433,901; asm: 1,058,726; python: 252,096; f90: 94,671; objc: 70,753; lisp: 42,813; pascal: 18,401; sh: 10,032; ml: 5,111; perl: 4,720; awk: 3,523; makefile: 3,401; javascript: 2,272; xml: 892; fortran: 770
file content (135 lines) | stat: -rw-r--r-- 3,497 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// 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