Coverage for /Syzygy/instrument/transforms/entry_thunk_transform_unittest.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%2202200.C++test

Line-by-line coverage:

   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    :  // Unittests for iteration primitives.
  16    :  
  17    :  #include "syzygy/instrument/transforms/entry_thunk_transform.h"
  18    :  
  19    :  #include <vector>
  20    :  
  21    :  #include "gmock/gmock.h"
  22    :  #include "gtest/gtest.h"
  23    :  #include "syzygy/block_graph/typed_block.h"
  24    :  #include "syzygy/pe/pe_utils.h"
  25    :  
  26    :  namespace instrument {
  27    :  namespace transforms {
  28    :  
  29    :  namespace {
  30    :  
  31    :  using block_graph::BlockGraph;
  32    :  using block_graph::ConstBlockVector;
  33    :  using block_graph::TypedBlock;
  34    :  using core::AbsoluteAddress;
  35    :  using testing::_;
  36    :  using testing::Return;
  37    :  
  38    :  // Expose protected members for testing.
  39    :  class TestEntryThunkTransform : public EntryThunkTransform {
  40    :   public:
  41    :    using EntryThunkTransform::Thunk;
  42    :  };
  43    :  
  44    :  class EntryThunkTransformTest : public testing::Test {
  45    :   public:
  46    :    EntryThunkTransformTest()
  47    :        : dos_header_block_(NULL),
  48    :          nt_headers_block_(NULL),
  49    :          foo_(NULL),
  50    :          bar_(NULL),
  51  E :          array_(NULL) {
  52  E :    }
  53    :  
  54  E :    virtual void SetUp() {
  55    :      // TODO(siggi): We have a lot of code that does this sort of thing, maybe
  56    :      //     it should be concentrated in a test fixture in pe someplace.
  57    :      // Create the DOS/NT headers.
  58    :      dos_header_block_ = bg_.AddBlock(BlockGraph::DATA_BLOCK,
  59    :                                       sizeof(IMAGE_DOS_HEADER),
  60  E :                                       "DOS Header");
  61  E :      ASSERT_TRUE(
  62    :          dos_header_block_->AllocateData(dos_header_block_->size()) != NULL);
  63    :  
  64    :      nt_headers_block_ = bg_.AddBlock(BlockGraph::DATA_BLOCK,
  65    :                                       sizeof(IMAGE_NT_HEADERS),
  66  E :                                       "NT Headers");
  67    :  
  68  E :      ASSERT_TRUE(
  69    :          nt_headers_block_->AllocateData(nt_headers_block_->size()) != NULL);
  70  E :      TypedBlock<IMAGE_NT_HEADERS> nt_headers;
  71  E :      ASSERT_TRUE(nt_headers.Init(0, nt_headers_block_));
  72  E :      nt_headers->Signature = IMAGE_NT_SIGNATURE;
  73  E :      nt_headers->FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
  74  E :      nt_headers->OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
  75    :  
  76  E :      TypedBlock<IMAGE_DOS_HEADER> dos_header;
  77  E :      ASSERT_TRUE(dos_header.Init(0, dos_header_block_));
  78  E :      ASSERT_TRUE(dos_header.SetReference(BlockGraph::RELATIVE_REF,
  79    :                                          dos_header->e_lfanew,
  80    :                                          nt_headers));
  81    :  
  82    :      // Make the DOS header valid just for giggles.
  83  E :      ASSERT_TRUE(pe::UpdateDosHeader(dos_header_block_));
  84    :  
  85    :      // Get the .text section.
  86    :      BlockGraph::Section* text =
  87  E :          bg_.FindOrAddSection(pe::kCodeSectionName, pe::kCodeCharacteristics);
  88    :  
  89    :      // Create a couple of code blocks for "functions".
  90  E :      foo_ = bg_.AddBlock(BlockGraph::CODE_BLOCK, 20, "foo");
  91  E :      foo_->set_section(text->id());
  92    :      foo_->source_ranges().Push(BlockGraph::Block::DataRange(0, 20),
  93  E :          BlockGraph::Block::SourceRange(core::RelativeAddress(0x1000), 20));
  94    :  
  95  E :      bar_ = bg_.AddBlock(BlockGraph::CODE_BLOCK, 20, "bar");
  96  E :      bar_->set_section(text->id());
  97    :      bar_->source_ranges().Push(BlockGraph::Block::DataRange(0, 20),
  98  E :          BlockGraph::Block::SourceRange(core::RelativeAddress(0x1020), 20));
  99    :  
 100    :      // Get the .rdata section.
 101    :      BlockGraph::Section* rdata =
 102    :          bg_.FindOrAddSection(pe::kReadOnlyDataSectionName,
 103  E :                               pe::kReadOnlyDataCharacteristics);
 104    :  
 105    :      // Create a data array block.
 106    :      array_ = bg_.AddBlock(BlockGraph::DATA_BLOCK,
 107    :                            30 * sizeof(AbsoluteAddress),
 108  E :                            "array");
 109  E :      array_->set_section(rdata->id());
 110    :  
 111    :      // foo() refers to the start of bar() with a PC-relative reference.
 112    :      foo_->SetReference(5, BlockGraph::Reference(BlockGraph::PC_RELATIVE_REF,
 113    :                                                  sizeof(AbsoluteAddress),
 114    :                                                  bar_,
 115  E :                                                  0, 0));
 116    :      // foo() is self-referential.
 117    :      foo_->SetReference(10, BlockGraph::Reference(BlockGraph::PC_RELATIVE_REF,
 118    :                                                   sizeof(AbsoluteAddress),
 119    :                                                   foo_,
 120  E :                                                   0, 0));
 121    :  
 122    :      // bar() refers to foo() five bytes in.
 123    :      bar_->SetReference(5, BlockGraph::Reference(BlockGraph::PC_RELATIVE_REF,
 124    :                                                  sizeof(AbsoluteAddress),
 125    :                                                  foo_,
 126  E :                                                  5, 5));
 127    :  
 128    :      // The array refers to the start of both foo() and bar().
 129    :      array_->SetReference(0, BlockGraph::Reference(BlockGraph::ABSOLUTE_REF,
 130    :                                                    sizeof(AbsoluteAddress),
 131    :                                                    foo_,
 132  E :                                                    0, 0));
 133    :  
 134    :      array_->SetReference(4, BlockGraph::Reference(BlockGraph::ABSOLUTE_REF,
 135    :                                                    sizeof(AbsoluteAddress),
 136    :                                                    bar_,
 137  E :                                                    0, 0));
 138    :  
 139    :      // And the array refers 5 bytes into foo().
 140    :      array_->SetReference(8, BlockGraph::Reference(BlockGraph::ABSOLUTE_REF,
 141    :                                                    sizeof(AbsoluteAddress),
 142    :                                                    foo_,
 143  E :                                                    5, 5));
 144    :  
 145  E :      num_sections_pre_transform_ = bg_.sections().size();
 146    :  
 147    :      // No thunks so far.
 148  E :      ASSERT_NO_FATAL_FAILURE(VerifyThunks(0, 0, 0));
 149  E :    }
 150    :  
 151    :    // Retrieves the thunks.
 152  E :    void FindThunks(ConstBlockVector* ret) {
 153  E :      ASSERT_TRUE(ret != NULL);
 154  E :      EXPECT_TRUE(ret->empty());
 155  E :      BlockGraph::Section* thunk_section = bg_.FindSection(".thunks");
 156  E :      if (thunk_section == NULL)
 157  E :        return;
 158    :  
 159  E :      BlockGraph::BlockMap::const_iterator it = bg_.blocks().begin();
 160  E :      for (; it != bg_.blocks().end(); ++it) {
 161  E :        const BlockGraph::Block& block = it->second;
 162  E :        if (block.section() == thunk_section->id()) {
 163  E :          EXPECT_EQ(BlockGraph::CODE_BLOCK, block.type());
 164  E :          EXPECT_EQ(2, block.references().size());
 165    :  
 166    :          // It's a thunk.
 167  E :          ret->push_back(&block);
 168    :        }
 169  E :      }
 170  E :    }
 171    :  
 172  E :    size_t CountDestinations(const ConstBlockVector& blocks) {
 173    :      typedef std::set<std::pair<BlockGraph::Block*, BlockGraph::Offset>>
 174    :          ReferenceMap;
 175  E :      ReferenceMap destinations;
 176  E :      for (size_t i = 0; i < blocks.size(); ++i) {
 177    :        // Lookup and record the destination.
 178  E :        BlockGraph::Reference ref;
 179  E :        EXPECT_TRUE(blocks[i]->GetReference(
 180    :            offsetof(TestEntryThunkTransform::Thunk, func_addr), &ref));
 181  E :        EXPECT_EQ(BlockGraph::ABSOLUTE_REF, ref.type());
 182  E :        destinations.insert(std::make_pair(ref.referenced(), ref.offset()));
 183  E :      }
 184  E :      return destinations.size();
 185  E :    }
 186    :  
 187  E :    size_t CountEntryPoints(const ConstBlockVector& blocks) {
 188    :      typedef std::set<std::pair<BlockGraph::Block*, BlockGraph::Offset>>
 189    :          ReferenceMap;
 190  E :      ReferenceMap entrypoints;
 191  E :      for (size_t i = 0; i < blocks.size(); ++i) {
 192    :        // Lookup and record the entrypoint.
 193  E :        BlockGraph::Reference ref;
 194  E :        EXPECT_TRUE(blocks[i]->GetReference(
 195    :            offsetof(TestEntryThunkTransform::Thunk, hook_addr), &ref));
 196  E :        EXPECT_EQ(BlockGraph::ABSOLUTE_REF, ref.type());
 197  E :        entrypoints.insert(std::make_pair(ref.referenced(), ref.offset()));
 198  E :      }
 199  E :      return entrypoints.size();
 200  E :    }
 201    :  
 202  E :    void VerifySourceRanges(const ConstBlockVector& thunks) {
 203  E :      for (size_t i = 0; i < thunks.size(); ++i) {
 204    :        // Test the source ranges on the thunk.
 205  E :        ASSERT_EQ(1, thunks[i]->source_ranges().size());
 206    :        BlockGraph::Block::SourceRanges::RangePair r =
 207  E :            thunks[i]->source_ranges().range_pairs()[0];
 208  E :        ASSERT_EQ(0, r.first.start());
 209  E :        ASSERT_EQ(sizeof(TestEntryThunkTransform::Thunk), r.first.size());
 210    :  
 211  E :        BlockGraph::Reference ref;
 212  E :        EXPECT_TRUE(thunks[i]->GetReference(
 213    :            offsetof(TestEntryThunkTransform::Thunk, func_addr), &ref));
 214    :  
 215    :        // Retrieve the referenced block's source ranges to calculate
 216    :        // the destination start address.
 217  E :        EXPECT_EQ(1, ref.referenced()->source_ranges().size());
 218    :        BlockGraph::Block::SourceRanges::RangePair o =
 219  E :            ref.referenced()->source_ranges().range_pairs()[0];
 220    :  
 221    :        // The thunk's destination should be the block's start, plus the
 222    :        // reference offset.
 223  E :        EXPECT_EQ(o.second.start() + ref.offset(), r.second.start());
 224  E :        EXPECT_EQ(sizeof(TestEntryThunkTransform::Thunk), r.second.size());
 225  E :      }
 226  E :    }
 227    :  
 228    :    // Verifies that there are num_thunks thunks in the image, and that they
 229    :    // have the expected properties.
 230    :    void VerifyThunks(size_t expected_thunks,
 231    :                      size_t expected_destinations,
 232  E :                      size_t expected_entrypoints) {
 233  E :      ConstBlockVector thunks;
 234  E :      ASSERT_NO_FATAL_FAILURE(FindThunks(&thunks));
 235    :  
 236  E :      EXPECT_EQ(expected_thunks, thunks.size());
 237  E :      EXPECT_EQ(expected_destinations, CountDestinations(thunks));
 238  E :      EXPECT_EQ(expected_entrypoints, CountEntryPoints(thunks));
 239  E :    }
 240    :  
 241    :    enum ImageType {
 242    :      DLL_IMAGE,
 243    :      EXE_IMAGE,
 244    :    };
 245    :  
 246  E :    void SetEmptyDllEntryPoint() {
 247  E :      TypedBlock<IMAGE_NT_HEADERS> nt_headers;
 248  E :      ASSERT_TRUE(nt_headers.Init(0, nt_headers_block_));
 249  E :      nt_headers->FileHeader.Characteristics |= IMAGE_FILE_DLL;
 250  E :    }
 251    :  
 252    :    // Sets the image entrypoint and sets or clears the DLL flag
 253    :    // in the NT headers.
 254  E :    void SetEntryPoint(BlockGraph::Block* entrypoint, ImageType image_type) {
 255    :      // Set the image entrypoint.
 256  E :      TypedBlock<IMAGE_NT_HEADERS> nt_headers;
 257  E :      ASSERT_TRUE(nt_headers.Init(0, nt_headers_block_));
 258  E :      ASSERT_TRUE(
 259    :          nt_headers.SetReference(
 260    :              BlockGraph::RELATIVE_REF,
 261    :              nt_headers->OptionalHeader.AddressOfEntryPoint,
 262    :              entrypoint,
 263    :              0, 0));
 264    :  
 265    :      // Set or clear the DLL flag.
 266  E :      if (image_type == DLL_IMAGE)
 267  E :        nt_headers->FileHeader.Characteristics |= IMAGE_FILE_DLL;
 268  E :      else
 269  E :        nt_headers->FileHeader.Characteristics &= ~IMAGE_FILE_DLL;
 270  E :    }
 271    :  
 272    :    // Creates a TLS directory with the given block for entrypoint, and sets or
 273    :    // clears the DLL flag in the NT headers.
 274  E :    void SetTLSEntryPoint(BlockGraph::Block* entrypoint, ImageType image_type) {
 275    :      // Set the image entrypoint.
 276  E :      TypedBlock<IMAGE_NT_HEADERS> nt_headers;
 277  E :      ASSERT_TRUE(nt_headers.Init(0, nt_headers_block_));
 278    :      IMAGE_DATA_DIRECTORY& data_dir =
 279  E :          nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS];
 280  E :      ASSERT_EQ(0, data_dir.Size);
 281    :  
 282    :      // Create the TLS directory block.
 283    :      BlockGraph::Block* tls_dir_block = bg_.AddBlock(BlockGraph::DATA_BLOCK,
 284    :                                                      sizeof(IMAGE_TLS_DIRECTORY),
 285  E :                                                      "TLS Directory");
 286  E :      ASSERT_TRUE(tls_dir_block != NULL);
 287  E :      ASSERT_TRUE(tls_dir_block->AllocateData(tls_dir_block->size()));
 288    :  
 289    :      // Hook the TLS dir up to the NT headers.
 290  E :      ASSERT_TRUE(nt_headers.SetReference(BlockGraph::ABSOLUTE_REF,
 291    :                                          data_dir.VirtualAddress,
 292    :                                          tls_dir_block,
 293    :                                          0, 0));
 294  E :      data_dir.Size = tls_dir_block->size();
 295    :  
 296  E :      TypedBlock<IMAGE_TLS_DIRECTORY> tls_dir;
 297  E :      ASSERT_TRUE(tls_dir.Init(0, tls_dir_block));
 298    :  
 299    :      BlockGraph::Block* tls_callbacks = bg_.AddBlock(BlockGraph::DATA_BLOCK,
 300    :                                                      2 * sizeof(AbsoluteAddress),
 301  E :                                                      "TLS Callbacks");
 302  E :      ASSERT_TRUE(tls_callbacks != NULL);
 303  E :      ASSERT_TRUE(tls_callbacks->AllocateData(tls_callbacks->size()) != NULL);
 304  E :      ASSERT_TRUE(tls_dir.SetReference(BlockGraph::ABSOLUTE_REF,
 305    :                                       tls_dir->AddressOfCallBacks,
 306    :                                       tls_callbacks,
 307    :                                       0, 0));
 308    :  
 309  E :      ASSERT_TRUE(tls_callbacks->SetReference(0,
 310    :                      BlockGraph::Reference(BlockGraph::ABSOLUTE_REF,
 311    :                                            sizeof(AbsoluteAddress),
 312    :                                            entrypoint,
 313    :                                            0, 0)));
 314    :  
 315    :      // Set or clear the DLL flag.
 316  E :      if (image_type == DLL_IMAGE)
 317  E :        nt_headers->FileHeader.Characteristics |= IMAGE_FILE_DLL;
 318  E :      else
 319  E :        nt_headers->FileHeader.Characteristics &= ~IMAGE_FILE_DLL;
 320  E :    }
 321    :  
 322    :   protected:
 323    :    size_t num_sections_pre_transform_;
 324    :  
 325    :    BlockGraph bg_;
 326    :    BlockGraph::Block* dos_header_block_;
 327    :    BlockGraph::Block* nt_headers_block_;
 328    :  
 329    :    BlockGraph::Block* foo_;
 330    :    BlockGraph::Block* bar_;
 331    :    BlockGraph::Block* array_;
 332    :  };
 333    :  
 334    :  }  // namespace
 335    :  
 336  E :  TEST_F(EntryThunkTransformTest, InstrumentAll) {
 337  E :    EntryThunkTransform transform;
 338  E :    ASSERT_NO_FATAL_FAILURE(SetEmptyDllEntryPoint());
 339    :  
 340  E :    ASSERT_TRUE(ApplyBlockGraphTransform(&transform, &bg_, dos_header_block_));
 341    :  
 342    :    // We should have three thunks - one each for the start of foo() and bar(),
 343    :    // and one for the middle of foo().
 344  E :    ASSERT_NO_FATAL_FAILURE(VerifyThunks(3, 3, 1));
 345    :  
 346    :    // The .thunks section should have been added.
 347  E :    EXPECT_EQ(num_sections_pre_transform_ + 1, bg_.sections().size());
 348  E :  }
 349    :  
 350  E :  TEST_F(EntryThunkTransformTest, InstrumentModuleEntriesOnlyNone) {
 351  E :    EntryThunkTransform transform;
 352  E :    ASSERT_NO_FATAL_FAILURE(SetEmptyDllEntryPoint());
 353  E :    transform.set_only_instrument_module_entry(true);
 354    :  
 355  E :    ASSERT_TRUE(ApplyBlockGraphTransform(&transform, &bg_, dos_header_block_));
 356    :  
 357    :    // We should have no thunks.
 358  E :    ASSERT_NO_FATAL_FAILURE(VerifyThunks(0, 0, 0));
 359    :  
 360    :    // The .thunks section should not have been added, as there are no hooks
 361    :    // added.
 362  E :    EXPECT_EQ(num_sections_pre_transform_, bg_.sections().size());
 363  E :  }
 364    :  
 365  E :  TEST_F(EntryThunkTransformTest, InstrumentModuleEntriesOnlyDllMainOnly) {
 366  E :    EntryThunkTransform transform;
 367  E :    ASSERT_NO_FATAL_FAILURE(SetEntryPoint(foo_, DLL_IMAGE));
 368  E :    transform.set_only_instrument_module_entry(true);
 369    :  
 370  E :    ASSERT_TRUE(ApplyBlockGraphTransform(&transform, &bg_, dos_header_block_));
 371    :  
 372    :    // We should have one thunk, for the DLL main entry point to the start of
 373    :    // foo_.
 374  E :    ASSERT_NO_FATAL_FAILURE(VerifyThunks(1, 1, 1));
 375    :  
 376    :    // The .thunks section should have been added.
 377  E :    EXPECT_EQ(num_sections_pre_transform_ + 1, bg_.sections().size());
 378  E :  }
 379    :  
 380  E :  TEST_F(EntryThunkTransformTest, InstrumentModuleEntriesOnlyDllMainAndTls) {
 381  E :    EntryThunkTransform transform;
 382  E :    ASSERT_NO_FATAL_FAILURE(SetEntryPoint(foo_, DLL_IMAGE));
 383  E :    ASSERT_NO_FATAL_FAILURE(SetTLSEntryPoint(bar_, DLL_IMAGE));
 384  E :    transform.set_only_instrument_module_entry(true);
 385    :  
 386  E :    ASSERT_TRUE(ApplyBlockGraphTransform(&transform, &bg_, dos_header_block_));
 387    :  
 388    :    // We should have two thunk, for the DLL main entry point and another for the
 389    :    // TLS. One is to foo_ and one is to bar_.
 390  E :    ASSERT_NO_FATAL_FAILURE(VerifyThunks(2, 2, 1));
 391    :  
 392    :    // The .thunks section should have been added.
 393  E :    EXPECT_EQ(num_sections_pre_transform_ + 1, bg_.sections().size());
 394  E :  }
 395    :  
 396  E :  TEST_F(EntryThunkTransformTest, InstrumentModuleEntriesOnlyExeMainAndTls) {
 397  E :    EntryThunkTransform transform;
 398  E :    ASSERT_NO_FATAL_FAILURE(SetEntryPoint(foo_, EXE_IMAGE));
 399  E :    ASSERT_NO_FATAL_FAILURE(SetTLSEntryPoint(bar_, EXE_IMAGE));
 400  E :    transform.set_only_instrument_module_entry(true);
 401    :  
 402  E :    ASSERT_TRUE(ApplyBlockGraphTransform(&transform, &bg_, dos_header_block_));
 403    :  
 404    :    // We should have one TLS thunk and an EXE entry thunk.
 405  E :    ASSERT_NO_FATAL_FAILURE(VerifyThunks(2, 2, 2));
 406    :  
 407    :    // The .thunks section should have been added.
 408  E :    EXPECT_EQ(num_sections_pre_transform_ + 1, bg_.sections().size());
 409  E :  }
 410    :  
 411  E :  TEST_F(EntryThunkTransformTest, InstrumentAllDebugFriendly) {
 412  E :    EntryThunkTransform transform;
 413  E :    ASSERT_NO_FATAL_FAILURE(SetEntryPoint(foo_, EXE_IMAGE));
 414  E :    transform.set_src_ranges_for_thunks(true);
 415    :  
 416  E :    ASSERT_TRUE(ApplyBlockGraphTransform(&transform, &bg_, dos_header_block_));
 417    :  
 418    :    // Verify the source ranges on the thunks.
 419  E :    ConstBlockVector thunks;
 420  E :    ASSERT_NO_FATAL_FAILURE(FindThunks(&thunks));
 421  E :    VerifySourceRanges(thunks);
 422  E :  }
 423    :  
 424  E :  TEST_F(EntryThunkTransformTest, InstrumentNoUnsafe) {
 425  E :    EntryThunkTransform transform;
 426  E :    ASSERT_NO_FATAL_FAILURE(SetEmptyDllEntryPoint());
 427    :  
 428    :    // No unsafe reference instrumentation.
 429  E :    transform.set_instrument_unsafe_references(false);
 430    :  
 431    :    // Tag both foo and bar with unsafe attributes.
 432  E :    foo_->set_attribute(BlockGraph::HAS_INLINE_ASSEMBLY);
 433  E :    bar_->set_attribute(BlockGraph::BUILT_BY_UNSUPPORTED_COMPILER);
 434    :  
 435  E :    ASSERT_TRUE(ApplyBlockGraphTransform(&transform, &bg_, dos_header_block_));
 436    :  
 437    :    // We should have two thunks - one each for the start of foo() and bar().
 438  E :    ASSERT_NO_FATAL_FAILURE(VerifyThunks(2, 2, 1));
 439    :  
 440    :    // The foo->bar reference should not have been thunked.
 441  E :    BlockGraph::Reference ref;
 442  E :    ASSERT_TRUE(foo_->GetReference(5, &ref));
 443  E :    ASSERT_EQ(bar_, ref.referenced());
 444    :  
 445    :    // The .thunks section should have been added.
 446  E :    EXPECT_EQ(num_sections_pre_transform_ + 1, bg_.sections().size());
 447  E :  }
 448    :  
 449  E :  TEST_F(EntryThunkTransformTest, InstrumentDllEntrypoint) {
 450  E :    EntryThunkTransform transform;
 451  E :    ASSERT_NO_FATAL_FAILURE(SetEntryPoint(foo_, DLL_IMAGE));
 452    :  
 453  E :    ASSERT_TRUE(ApplyBlockGraphTransform(&transform, &bg_, dos_header_block_));
 454    :  
 455    :    // We should have three thunks - one each for the start of foo() and bar().
 456    :    // One of the thunks should use the DllMain entrypoint.
 457  E :    ASSERT_NO_FATAL_FAILURE(VerifyThunks(3, 3, 2));
 458    :  
 459    :    // The .thunks section should have been added.
 460  E :    EXPECT_EQ(num_sections_pre_transform_ + 1, bg_.sections().size());
 461  E :  }
 462    :  
 463  E :  TEST_F(EntryThunkTransformTest, InstrumentExeEntrypoint) {
 464  E :    EntryThunkTransform transform;
 465  E :    ASSERT_NO_FATAL_FAILURE(SetEntryPoint(foo_, EXE_IMAGE));
 466    :  
 467  E :    ASSERT_TRUE(ApplyBlockGraphTransform(&transform, &bg_, dos_header_block_));
 468    :  
 469    :    // We should have three thunks - one each for the start of foo() and bar().
 470  E :    ASSERT_NO_FATAL_FAILURE(VerifyThunks(3, 3, 2));
 471    :  
 472    :    // The .thunks section should have been added.
 473  E :    EXPECT_EQ(num_sections_pre_transform_ + 1, bg_.sections().size());
 474  E :  }
 475    :  
 476  E :  TEST_F(EntryThunkTransformTest, InstrumentDllTLSEntrypoint) {
 477  E :    EntryThunkTransform transform;
 478  E :    ASSERT_NO_FATAL_FAILURE(SetEntryPoint(foo_, DLL_IMAGE));
 479  E :    ASSERT_NO_FATAL_FAILURE(SetTLSEntryPoint(bar_, DLL_IMAGE));
 480    :  
 481  E :    ASSERT_TRUE(ApplyBlockGraphTransform(&transform, &bg_, dos_header_block_));
 482    :  
 483    :    // We should have three thunks - one each for the start of foo() and bar().
 484    :    // One of the thunks should use the DllMain entrypoint.
 485  E :    ASSERT_NO_FATAL_FAILURE(VerifyThunks(3, 3, 2));
 486    :  
 487    :    // The .thunks section should have been added.
 488  E :    EXPECT_EQ(num_sections_pre_transform_ + 1, bg_.sections().size());
 489  E :  }
 490    :  
 491  E :  TEST_F(EntryThunkTransformTest, InstrumentExeTLSEntrypoint) {
 492  E :    EntryThunkTransform transform;
 493  E :    ASSERT_NO_FATAL_FAILURE(SetEntryPoint(foo_, EXE_IMAGE));
 494  E :    ASSERT_NO_FATAL_FAILURE(SetTLSEntryPoint(bar_, EXE_IMAGE));
 495    :  
 496  E :    ASSERT_TRUE(ApplyBlockGraphTransform(&transform, &bg_, dos_header_block_));
 497    :  
 498    :    // We should have three thunks - one each for the start of foo() and bar().
 499  E :    ASSERT_NO_FATAL_FAILURE(VerifyThunks(3, 3, 3));
 500    :  
 501    :    // The .thunks section should have been added.
 502  E :    EXPECT_EQ(num_sections_pre_transform_ + 1, bg_.sections().size());
 503  E :  }
 504    :  
 505    :  }  // namespace transforms
 506    :  }  // namespace instrument

Coverage information generated Thu Sep 06 11:30:46 2012.