Coverage for /Syzygy/pe/test_dll.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
0.0%00328.C++source

Line-by-line coverage:

   1    :  // Copyright 2012 Google Inc. All Rights Reserved.
   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    :  // Bring in a data import from export_dll.dll. This will cause a global data
  26    :  // symbol to be emitted pointing to the import entry, but with the type we give
  27    :  // here. If the type is bigger than the entire import table then the data
  28    :  // symbol will be bigger than the block it resolves to. The data must be
  29    :  // explicitly marked dllimport otherwise the linker will treat it as a code
  30    :  // symbol and create a thunk for it.
  31  m :  __declspec(dllimport) extern int kExportedData[1024];
  32    :  
  33    :  // A handful of TLS variables, to cause TLS fixups to appear.
  34  m :  __declspec(thread) int tls_int = 42;
  35  m :  __declspec(thread) int tls_array[64] = { 0 };
  36  m :  __declspec(thread) char tls_string_buffer[512] = { 0 };
  37  m :  __declspec(thread) double tls_double = 3.5;
  38    :  
  39    :  // A dummy TLS Initialization callback handler.
  40  m :  VOID NTAPI MyTlsCallback(PVOID instance, DWORD reason, PVOID reserved) {
  41  m :    ::time(NULL);
  42  m :  }
  43    :  
  44    :  // Declare a TLS initializer callback to the linker.
  45    :  #pragma section(".CRT$XLY",long,read)
  46  m :  extern "C" __declspec(allocate(".CRT$XLY"))
  47  m :    PIMAGE_TLS_CALLBACK _xl_y1  = MyTlsCallback;
  48    :  
  49  m :  extern "C" __declspec(allocate(".CRT$XLY"))
  50  m :    PIMAGE_TLS_CALLBACK _xl_y2  = MyTlsCallback;
  51    :  
  52    :  // Use both mechanisms for importing functions (explicitly hinted with
  53    :  // 'dllimport' and not) so that both code generation mechanisms are present
  54    :  // in the final binary and subsequently tested by our decomposer.
  55  m :  __declspec(dllimport) extern int function1();
  56  m :  extern int function2();
  57  m :  extern int function3();
  58    :  
  59    :  #pragma auto_inline(off)
  60    :  
  61  m :  DWORD WINAPI TestExport(size_t buf_len, char* buf) {
  62  m :    static const char kTestString[] =
  63  m :        "The quick brown fox jumped over the lazy dog";
  64    :  
  65  m :    ::strncpy(buf, kTestString, buf_len);
  66    :  
  67  m :    return 0;
  68  m :  }
  69    :  
  70  m :  DWORD WINAPI BringInOle32DelayLib() {
  71    :    // Reference this from Ole32 to pull in something.
  72  m :    ::CoInitialize(NULL);
  73    :  
  74  m :    return 0;
  75  m :  }
  76    :  
  77  m :  const char* BoolToString(bool value) {
  78  m :    return value ? "true" : "false";
  79  m :  }
  80    :  
  81  m :  int FunctionWithInlineAssembly() {
  82  m :    static int datum = 0;
  83  m :    __asm {
  84  m :      mov eax, [datum];
  85  m :      add eax, 1;
  86  m :      mov [datum], eax;
  87  m :    }
  88  m :    return datum;
  89  m :  }
  90    :  
  91    :  #pragma auto_inline()
  92    :  
  93  m :  BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) {
  94    :    // The goal of the following weird code is to thwart any optimizations
  95    :    // that the compiler might try.
  96    :  
  97    :    // Put a series of calls in order. In general, expect they'll show up in
  98    :    // the same order when we search for references.
  99  m :    function1();
 100  m :    function1();
 101  m :    function3();
 102  m :    function2();
 103  m :    function2();
 104  m :    function3();
 105  m :    function1();
 106  m :    function1();
 107    :  
 108  m :    int foo = FunctionWithInlineAssembly();
 109  m :    foo += kExportedData[0];
 110    :  
 111    :    // We modify the exported data. If imports are improperly thunked this will
 112    :    // cause us to write junk all over any created thunks and should hopefully
 113    :    // cause the instrumented test_dll to explode.
 114  m :    for (size_t i = 0; i < sizeof(kExportedData) / sizeof(kExportedData[0]); ++i)
 115  m :      kExportedData[i] = i;
 116    :  
 117    :    // The following odd code and switch statement are to outsmart the
 118    :    // optimizer and coerce it to generate a case and jump table pair.
 119    :    // On decomposition, we expect to find and label the case and jump
 120    :    // tables individually.
 121  m :    wchar_t c = rand() % static_cast<wchar_t>(-1);
 122    :  
 123    :    // We also need to coerce the optimizer into keeping around kExportedData and
 124    :    // FunctionWithInlineAssembly.
 125  m :    c ^= static_cast<wchar_t>(foo);
 126    :  
 127  m :    bool is_whitespace = false;
 128  m :    bool is_qwerty = false;
 129  m :    bool is_asdfgh = false;
 130  m :    bool is_upper_case = false;
 131  m :    bool is_other = false;
 132    :  
 133    :    // Switch over the UTF16 character space.
 134  m :    switch (c) {
 135  m :     case L'Q':
 136  m :     case L'W':
 137  m :     case L'E':
 138  m :     case L'R':
 139  m :     case L'T':
 140  m :     case L'Y':
 141  m :      is_qwerty = true;
 142  m :      is_upper_case = true;
 143  m :      break;
 144    :  
 145  m :     case L'q':
 146  m :     case L'w':
 147  m :     case L'e':
 148  m :     case L'r':
 149  m :     case L't':
 150  m :     case L'y':
 151  m :      is_qwerty = true;
 152  m :      is_upper_case = false;
 153  m :      break;
 154    :  
 155  m :     case L'A':
 156  m :     case L'S':
 157  m :     case L'D':
 158  m :     case L'F':
 159  m :     case L'G':
 160  m :     case L'H':
 161  m :      is_asdfgh = true;
 162  m :      is_upper_case = true;
 163  m :      break;
 164    :  
 165  m :     case L'a':
 166  m :     case L's':
 167  m :     case L'd':
 168  m :     case L'f':
 169  m :     case L'g':
 170  m :     case L'h':
 171  m :      is_asdfgh = true;
 172  m :      is_upper_case = false;
 173  m :      break;
 174    :  
 175  m :     case ' ':
 176  m :     case '\t':
 177  m :     case '\r':
 178  m :     case '\n':
 179  m :      is_whitespace = true;
 180  m :      break;
 181    :  
 182  m :     default:
 183  m :      is_other = true;
 184  m :      break;
 185  m :    }
 186    :  
 187  m :    char buffer[1024] = {'\0'};
 188  m :    ::memset(buffer, 0, sizeof(buffer));
 189  m :    ::_snprintf(buffer,
 190  m :                sizeof(buffer) - 1,
 191  m :                "is_qwerty=%s\nis_asdfgh=%s\nis_upper_case=%s\nis_whitespace=%s\n"
 192  m :                "is_other=%s",
 193  m :                BoolToString(is_qwerty),
 194  m :                BoolToString(is_asdfgh),
 195  m :                BoolToString(is_upper_case),
 196  m :                BoolToString(is_whitespace),
 197  m :                BoolToString(is_other));
 198    :  
 199  m :    TestExport(sizeof(buffer), buffer);
 200    :  
 201    :    // This code generates a simple jump table with no case table following it.
 202    :  
 203  m :    int n = rand();
 204    :  
 205  m :    switch (n % 3) {
 206  m :      case 0:
 207  m :        n += function1();
 208  m :        break;
 209  m :      case 1:
 210  m :        n += function2();
 211  m :        break;
 212  m :      case 2:
 213  m :        n += function3();
 214  m :        break;
 215  m :      case 3:
 216  m :        n -= function1();
 217  m :        break;
 218  m :      case 4:
 219  m :        n -= function2();
 220  m :        break;
 221  m :      case 5:
 222  m :        n -= function3();
 223  m :        break;
 224  m :    }
 225    :  
 226    :    // The following odd code and switch statement are to outsmart the
 227    :    // optimizer and coerce it to generate another case and jump table
 228    :    // pair. On decomposition, we expect to find and label the case
 229    :    // and jump tables individually.
 230    :  
 231    :    // Access the TLS data so that some TLS FIXUPs are produced.
 232  m :    n += tls_int;
 233  m :    n += tls_array[0];
 234  m :    n += tls_string_buffer[0];
 235  m :    n += static_cast<int>(tls_double);
 236    :  
 237    :    // The case table is a 20X expanded switch on n mod 7.
 238  m :    switch (n % 140) {
 239  m :      case 0:
 240  m :      case 7:
 241  m :      case 14:
 242  m :      case 21:
 243  m :      case 28:
 244  m :      case 35:
 245  m :      case 42:
 246  m :      case 49:
 247  m :      case 56:
 248  m :      case 63:
 249  m :      case 70:
 250  m :      case 77:
 251  m :      case 84:
 252  m :      case 91:
 253  m :      case 98:
 254  m :      case 105:
 255  m :      case 112:
 256  m :      case 119:
 257  m :      case 126:
 258  m :      case 133:
 259  m :        return reinterpret_cast<BOOL>(
 260  m :            function1() + strstr("hello world", "hello"));
 261    :  
 262  m :      case 1:
 263  m :      case 8:
 264  m :      case 15:
 265  m :      case 22:
 266  m :      case 29:
 267  m :      case 36:
 268  m :      case 43:
 269  m :      case 50:
 270  m :      case 57:
 271  m :      case 64:
 272  m :      case 71:
 273  m :      case 78:
 274  m :      case 85:
 275  m :      case 92:
 276  m :      case 99:
 277  m :      case 106:
 278  m :      case 113:
 279  m :      case 120:
 280  m :      case 127:
 281  m :      case 134:
 282  m :        return static_cast<BOOL>(function2() + strlen("foobar"));
 283    :  
 284  m :      case 2:
 285  m :      case 9:
 286  m :      case 16:
 287  m :      case 23:
 288  m :      case 30:
 289  m :      case 37:
 290  m :      case 44:
 291  m :      case 51:
 292  m :      case 58:
 293  m :      case 65:
 294  m :      case 72:
 295  m :      case 79:
 296  m :      case 86:
 297  m :      case 93:
 298  m :      case 100:
 299  m :      case 107:
 300  m :      case 114:
 301  m :      case 121:
 302  m :      case 128:
 303  m :      case 135:
 304  m :        return static_cast<BOOL>(function3() + clock());
 305    :  
 306  m :      case 3:
 307  m :      case 10:
 308  m :      case 17:
 309  m :      case 24:
 310  m :      case 31:
 311  m :      case 38:
 312  m :      case 45:
 313  m :      case 52:
 314  m :      case 59:
 315  m :      case 66:
 316  m :      case 73:
 317  m :      case 80:
 318  m :      case 87:
 319  m :      case 94:
 320  m :      case 101:
 321  m :      case 108:
 322  m :      case 115:
 323  m :      case 122:
 324  m :      case 129:
 325  m :      case 136:
 326  m :        return static_cast<BOOL>(function1() + function2() +
 327  m :            reinterpret_cast<int>(memchr("hello", 'e', 5)));
 328    :  
 329  m :      case 4:
 330  m :      case 11:
 331  m :      case 18:
 332  m :      case 25:
 333  m :      case 32:
 334  m :      case 39:
 335  m :      case 46:
 336  m :      case 53:
 337  m :      case 60:
 338  m :      case 67:
 339  m :      case 74:
 340  m :      case 81:
 341  m :      case 88:
 342  m :      case 95:
 343  m :      case 102:
 344  m :      case 109:
 345  m :      case 116:
 346  m :      case 123:
 347  m :      case 130:
 348  m :      case 137:
 349  m :        return static_cast<BOOL>(function1() + function3() + abs(-3));
 350    :  
 351  m :      case 5:
 352  m :      case 12:
 353  m :      case 19:
 354  m :      case 26:
 355  m :      case 33:
 356  m :      case 40:
 357  m :      case 47:
 358  m :      case 54:
 359  m :      case 61:
 360  m :      case 68:
 361  m :      case 75:
 362  m :      case 82:
 363  m :      case 89:
 364  m :      case 96:
 365  m :      case 103:
 366  m :      case 110:
 367  m :      case 117:
 368  m :      case 124:
 369  m :      case 131:
 370  m :      case 138:
 371  m :        return static_cast<BOOL>(
 372  m :            function2() + function3() + static_cast<int>(floor(1.3)));
 373    :  
 374  m :      case 6:
 375  m :      case 13:
 376  m :      case 20:
 377  m :      case 27:
 378  m :      case 34:
 379  m :      case 41:
 380  m :      case 48:
 381  m :      case 55:
 382  m :      case 62:
 383  m :      case 69:
 384  m :      case 76:
 385  m :      case 83:
 386  m :      case 90:
 387  m :      case 97:
 388  m :      case 104:
 389  m :      case 111:
 390  m :      case 118:
 391  m :      case 125:
 392  m :      case 132:
 393  m :      case 139:
 394  m :        return static_cast<BOOL>(
 395  m :            function1() + function2() + function3() + atoi("7"));
 396  m :    }
 397  m :  }
 398    :  
 399  m :  void used_operation() {
 400  m :    function1();
 401  m :    function2();
 402  m :    function3();
 403  m :  }
 404    :  
 405    :  // This won't be called.
 406  m :  void unused_operation() {
 407  m :    char dummy[512];
 408  m :    TestExport(sizeof(dummy), dummy);
 409  m :  }
 410    :  
 411  m :  class Used {
 412  m :   public:
 413  m :    Used() {}
 414  m :    virtual ~Used() {}
 415  m :    virtual void M() {
 416  m :      used_operation();
 417  m :    }
 418  m :  };
 419    :  
 420    :  // Unused::M() won't be called.
 421  m :  class Unused : public Used {
 422  m :   public:
 423  m :    virtual void M() {
 424  m :      unused_operation();
 425  m :    }
 426  m :  };
 427    :  
 428  m :  void CALLBACK TestUnusedFuncs(HWND unused_window,
 429  m :                                HINSTANCE unused_instance,
 430  m :                                LPSTR unused_cmd_line,
 431  m :                                int unused_show) {
 432  m :    bool call_it = time(NULL) > 10000;  // true unless you play with the clock.
 433    :  
 434  m :    (call_it ? used_operation : unused_operation)();
 435    :  
 436  m :    Used a;
 437  m :    Unused b;
 438  m :    (call_it ? &a : &b)->M();
 439  m :  }

Coverage information generated Thu Mar 14 11:53:36 2013.