1 : // Copyright 2012 Google Inc.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include <windows.h> // NOLINT
16 : #include <objbase.h> // NOLINT
17 : #include <winnt.h> // NOLINT
18 :
19 : #include <math.h>
20 : #include <stdio.h>
21 : #include <time.h>
22 :
23 : #include <cstdlib>
24 :
25 : // A handful of TLS variables, to cause TLS fixups to appear.
26 m : __declspec(thread) int tls_int = 42;
27 m : __declspec(thread) int tls_array[64] = { 0 };
28 m : __declspec(thread) char tls_string_buffer[512] = { 0 };
29 m : __declspec(thread) double tls_double = 3.5;
30 :
31 : // A dummy TLS Initialization callback handler.
32 m : VOID NTAPI MyTlsCallback(PVOID instance, DWORD reason, PVOID reserved) {
33 m : ::time(NULL);
34 m : }
35 :
36 : // Declare a TLS initializer callback to the linker.
37 : #pragma section(".CRT$XLY",long,read)
38 m : extern "C" __declspec(allocate(".CRT$XLY"))
39 m : PIMAGE_TLS_CALLBACK _xl_y1 = MyTlsCallback;
40 :
41 m : extern "C" __declspec(allocate(".CRT$XLY"))
42 m : PIMAGE_TLS_CALLBACK _xl_y2 = MyTlsCallback;
43 :
44 m : extern int function1();
45 m : extern int function2();
46 m : extern int function3();
47 :
48 : #pragma auto_inline(off)
49 :
50 m : DWORD WINAPI TestExport(size_t buf_len, char* buf) {
51 m : static const char kTestString[] =
52 m : "The quick brown fox jumped over the lazy dog";
53 :
54 m : ::strncpy(buf, kTestString, buf_len);
55 :
56 m : return 0;
57 m : }
58 :
59 m : DWORD WINAPI BringInOle32DelayLib() {
60 : // Reference this from Ole32 to pull in something.
61 m : ::CoInitialize(NULL);
62 :
63 m : return 0;
64 m : }
65 :
66 m : const char* BoolToString(bool value) {
67 m : return value ? "true" : "false";
68 m : }
69 :
70 m : int FunctionWithInlineAssembly() {
71 m : static int datum = 0;
72 m : __asm {
73 m : mov eax, [datum];
74 m : add eax, 1;
75 m : mov [datum], eax;
76 m : }
77 m : return datum;
78 m : }
79 :
80 : #pragma auto_inline()
81 :
82 m : BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) {
83 : // The goal of the following weird code is to thwart any optimizations
84 : // that the compiler might try.
85 :
86 : // Put a series of calls in order. In general, expect they'll show up in
87 : // the same order when we search for references.
88 m : function1();
89 m : function1();
90 m : function3();
91 m : function2();
92 m : function2();
93 m : function3();
94 m : function1();
95 m : function1();
96 :
97 m : int foo = FunctionWithInlineAssembly();
98 :
99 : // The following odd code and switch statement are to outsmart the
100 : // optimizer and coerce it to generate a case and jump table pair.
101 : // On decomposition, we expect to find and label the case and jump
102 : // tables individually.
103 m : wchar_t c = rand() % static_cast<wchar_t>(-1);
104 m : bool is_whitespace = false;
105 m : bool is_qwerty = false;
106 m : bool is_asdfgh = false;
107 m : bool is_upper_case = false;
108 m : bool is_other = false;
109 :
110 : // Switch over the UTF16 character space.
111 m : switch (c) {
112 m : case L'Q':
113 m : case L'W':
114 m : case L'E':
115 m : case L'R':
116 m : case L'T':
117 m : case L'Y':
118 m : is_qwerty = true;
119 m : is_upper_case = true;
120 m : break;
121 :
122 m : case L'q':
123 m : case L'w':
124 m : case L'e':
125 m : case L'r':
126 m : case L't':
127 m : case L'y':
128 m : is_qwerty = true;
129 m : is_upper_case = false;
130 m : break;
131 :
132 m : case L'A':
133 m : case L'S':
134 m : case L'D':
135 m : case L'F':
136 m : case L'G':
137 m : case L'H':
138 m : is_asdfgh = true;
139 m : is_upper_case = true;
140 m : break;
141 :
142 m : case L'a':
143 m : case L's':
144 m : case L'd':
145 m : case L'f':
146 m : case L'g':
147 m : case L'h':
148 m : is_asdfgh = true;
149 m : is_upper_case = false;
150 m : break;
151 :
152 m : case ' ':
153 m : case '\t':
154 m : case '\r':
155 m : case '\n':
156 m : is_whitespace = true;
157 m : break;
158 :
159 m : default:
160 m : is_other = true;
161 m : break;
162 m : }
163 :
164 m : char buffer[1024] = {'\0'};
165 m : ::memset(buffer, 0, sizeof(buffer));
166 m : ::_snprintf(buffer,
167 m : sizeof(buffer) - 1,
168 m : "is_qwerty=%s\nis_asdfgh=%s\nis_upper_case=%s\nis_whitespace=%s\n"
169 m : "is_other=%s",
170 m : BoolToString(is_qwerty),
171 m : BoolToString(is_asdfgh),
172 m : BoolToString(is_upper_case),
173 m : BoolToString(is_whitespace),
174 m : BoolToString(is_other));
175 :
176 m : TestExport(sizeof(buffer), buffer);
177 :
178 : // The following odd code and switch statement are to outsmart the
179 : // optimizer and coerce it to generate another case and jump table
180 : // pair. On decomposition, we expect to find and label the case
181 : // and jump tables individually.
182 m : int n = rand();
183 :
184 : // Access the TLS data so that some TLS FIXUPs are produced.
185 m : n += tls_int;
186 m : n += tls_array[0];
187 m : n += tls_string_buffer[0];
188 m : n += static_cast<int>(tls_double);
189 :
190 : // The case table is a 20X expanded switch on n mod 7.
191 m : switch (n % 140) {
192 m : case 0:
193 m : case 7:
194 m : case 14:
195 m : case 21:
196 m : case 28:
197 m : case 35:
198 m : case 42:
199 m : case 49:
200 m : case 56:
201 m : case 63:
202 m : case 70:
203 m : case 77:
204 m : case 84:
205 m : case 91:
206 m : case 98:
207 m : case 105:
208 m : case 112:
209 m : case 119:
210 m : case 126:
211 m : case 133:
212 m : return reinterpret_cast<BOOL>(
213 m : function1() + strstr("hello world", "hello"));
214 :
215 m : case 1:
216 m : case 8:
217 m : case 15:
218 m : case 22:
219 m : case 29:
220 m : case 36:
221 m : case 43:
222 m : case 50:
223 m : case 57:
224 m : case 64:
225 m : case 71:
226 m : case 78:
227 m : case 85:
228 m : case 92:
229 m : case 99:
230 m : case 106:
231 m : case 113:
232 m : case 120:
233 m : case 127:
234 m : case 134:
235 m : return static_cast<BOOL>(function2() + strlen("foobar"));
236 :
237 m : case 2:
238 m : case 9:
239 m : case 16:
240 m : case 23:
241 m : case 30:
242 m : case 37:
243 m : case 44:
244 m : case 51:
245 m : case 58:
246 m : case 65:
247 m : case 72:
248 m : case 79:
249 m : case 86:
250 m : case 93:
251 m : case 100:
252 m : case 107:
253 m : case 114:
254 m : case 121:
255 m : case 128:
256 m : case 135:
257 m : return static_cast<BOOL>(function3() + clock());
258 :
259 m : case 3:
260 m : case 10:
261 m : case 17:
262 m : case 24:
263 m : case 31:
264 m : case 38:
265 m : case 45:
266 m : case 52:
267 m : case 59:
268 m : case 66:
269 m : case 73:
270 m : case 80:
271 m : case 87:
272 m : case 94:
273 m : case 101:
274 m : case 108:
275 m : case 115:
276 m : case 122:
277 m : case 129:
278 m : case 136:
279 m : return static_cast<BOOL>(function1() + function2() +
280 m : reinterpret_cast<int>(memchr("hello", 'e', 5)));
281 :
282 m : case 4:
283 m : case 11:
284 m : case 18:
285 m : case 25:
286 m : case 32:
287 m : case 39:
288 m : case 46:
289 m : case 53:
290 m : case 60:
291 m : case 67:
292 m : case 74:
293 m : case 81:
294 m : case 88:
295 m : case 95:
296 m : case 102:
297 m : case 109:
298 m : case 116:
299 m : case 123:
300 m : case 130:
301 m : case 137:
302 m : return static_cast<BOOL>(function1() + function3() + abs(-3));
303 :
304 m : case 5:
305 m : case 12:
306 m : case 19:
307 m : case 26:
308 m : case 33:
309 m : case 40:
310 m : case 47:
311 m : case 54:
312 m : case 61:
313 m : case 68:
314 m : case 75:
315 m : case 82:
316 m : case 89:
317 m : case 96:
318 m : case 103:
319 m : case 110:
320 m : case 117:
321 m : case 124:
322 m : case 131:
323 m : case 138:
324 m : return static_cast<BOOL>(
325 m : function2() + function3() + static_cast<int>(floor(1.3)));
326 :
327 m : case 6:
328 m : case 13:
329 m : case 20:
330 m : case 27:
331 m : case 34:
332 m : case 41:
333 m : case 48:
334 m : case 55:
335 m : case 62:
336 m : case 69:
337 m : case 76:
338 m : case 83:
339 m : case 90:
340 m : case 97:
341 m : case 104:
342 m : case 111:
343 m : case 118:
344 m : case 125:
345 m : case 132:
346 m : case 139:
347 m : return static_cast<BOOL>(
348 m : function1() + function2() + function3() + atoi("7"));
349 m : }
350 m : }
351 :
352 m : void used_operation() {
353 m : function1();
354 m : function2();
355 m : function3();
356 m : }
357 :
358 : // This won't be called.
359 m : void unused_operation() {
360 m : char dummy[512];
361 m : TestExport(sizeof(dummy), dummy);
362 m : }
363 :
364 m : class Used {
365 m : public:
366 m : Used() {}
367 m : virtual ~Used() {}
368 m : virtual void M() {
369 m : used_operation();
370 m : }
371 m : };
372 :
373 : // Unused::M() won't be called.
374 m : class Unused : public Used {
375 m : public:
376 m : virtual void M() {
377 m : unused_operation();
378 m : }
379 m : };
380 :
381 m : void CALLBACK TestUnusedFuncs(HWND unused_window,
382 m : HINSTANCE unused_instance,
383 m : LPSTR unused_cmd_line,
384 m : int unused_show) {
385 m : bool call_it = time(NULL) > 10000; // true unless you play with the clock.
386 :
387 m : (call_it ? used_operation : unused_operation)();
388 :
389 m : Used a;
390 m : Unused b;
391 m : (call_it ? &a : &b)->M();
392 m : }
|