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 : #ifndef SYZYGY_PE_UNITTEST_UTIL_H_
16 : #define SYZYGY_PE_UNITTEST_UTIL_H_
17 :
18 : #include <windows.h>
19 :
20 : #include "base/files/file_path.h"
21 : #include "base/files/file_util.h"
22 : #include "gtest/gtest.h"
23 : #include "syzygy/block_graph/block_graph.h"
24 : #include "syzygy/block_graph/orderer.h"
25 : #include "syzygy/block_graph/unittest_util.h"
26 : #include "syzygy/common/unittest_util.h"
27 : #include "syzygy/core/unittest_util.h"
28 : #include "syzygy/pe/coff_file.h"
29 : #include "syzygy/pe/image_layout.h"
30 : #include "syzygy/pe/pe_file.h"
31 :
32 : namespace testing {
33 :
34 : // Name of the test DLLs and PDBs. These exist in the output directory, and
35 : // again in the test_data directory.
36 : extern const wchar_t kTestDllName[];
37 : extern const wchar_t kTestDllPdbName[];
38 : extern const wchar_t kTestDllName64[];
39 : extern const wchar_t kTestDllPdbName64[];
40 :
41 : // Name of the integrations tests DLLs and PDBs.
42 : extern const wchar_t kIntegrationTestsDllName[];
43 : extern const wchar_t kIntegrationTestsDllPdbName[];
44 :
45 : // Name of the DLL containing an empty exports directory.
46 : extern const wchar_t kNoExportsDllName[];
47 : extern const wchar_t kNoExportsDllPdbName[];
48 :
49 : // Name of the test DLL object files and the PDB files where their type
50 : // information has been emitted, relative to the test_data directory.
51 : // The two object files are guaranteed to be in the specified format.
52 : extern const wchar_t kTestDllCoffObjName[];
53 : extern const wchar_t kTestDllLtcgObjName[];
54 : extern const wchar_t kTestDllCoffObjPdbName[];
55 : extern const wchar_t kTestDllLtcgObjPdbName[];
56 :
57 : // Statically checked in object files that explore some of the boundary cases
58 : // of COFF files. These are also relative to the test data directory. These live
59 : // in syzygy\pe\test_data, thus should be referred to using GetSrcRelativePath.
60 : extern const wchar_t kCodeView2Name[];
61 : extern const wchar_t kEmptyStringTableCoffName[];
62 :
63 : // Name of the various test DLLs generated by the test_data project.
64 : // These are placed in $(OutputDir)\test_data, so use
65 : // GetExeTestDataRelativePath to build paths to them.
66 : extern const wchar_t kAsanInstrumentedTestDllName[];
67 : extern const wchar_t kAsanInstrumentedTestDllPdbName[];
68 : extern const wchar_t kBBEntryInstrumentedTestDllName[];
69 : extern const wchar_t kBBEntryInstrumentedTestDllPdbName[];
70 : extern const wchar_t kCallTraceInstrumentedTestDllName[];
71 : extern const wchar_t kCallTraceInstrumentedTestDllPdbName[];
72 : extern const wchar_t kCoverageInstrumentedTestDllName[];
73 : extern const wchar_t kCoverageInstrumentedTestDllPdbName[];
74 : extern const wchar_t kProfileInstrumentedTestDllName[];
75 : extern const wchar_t kProfileInstrumentedTestDllPdbName[];
76 : extern const wchar_t kRandomizedTestDllName[];
77 : extern const wchar_t kRandomizedTestDllPdbName[];
78 : extern const wchar_t kSignedTestDllName[];
79 :
80 : // Name of the various trace files.
81 : extern const wchar_t *kBBEntryTraceFiles[4];
82 : extern const wchar_t *kBranchTraceFiles[4];
83 : extern const wchar_t *kCallTraceTraceFiles[4];
84 : extern const wchar_t *kCoverageTraceFiles[4];
85 : extern const wchar_t kMemProfTraceFile[];
86 : extern const wchar_t *kProfileTraceFiles[4];
87 :
88 : // This class wraps an HMODULE and ensures that ::FreeLibrary is called when it
89 : // goes out of scope.
90 : class ScopedHMODULE {
91 : public:
92 : ScopedHMODULE();
93 : explicit ScopedHMODULE(HMODULE v);
94 : ~ScopedHMODULE();
95 :
96 : void Reset(HMODULE v);
97 : void Release();
98 :
99 E : operator HMODULE() const {
100 E : return value_;
101 E : }
102 :
103 : private:
104 : HMODULE value_;
105 : };
106 :
107 : // Given a block-graph that represents a decomposed PE image this reaches in
108 : // and modifies the GUID and path values in place. This prevents any written
109 : // images from matching the same symbol file. If this is not done it is possible
110 : // for the debugger to cause an exception to be raised while loading a symbol
111 : // file whose signature does match, but whose contents don't match, a
112 : // transformed PE file.
113 : // @param dos_header_block The DOS header block.
114 : // @note Meant to be called from within an ASSERT_NO_FATAL_FAILURE block.
115 : void TwiddlePdbGuidAndPath(block_graph::BlockGraph::Block* dos_header_block);
116 :
117 : class PELibUnitTest : public testing::ApplicationTestBase {
118 : public:
119 : // Decomposes test_dll, populating the given PE file and image layout.
120 : static void DecomposeTestDll(pe::PEFile* pe_file,
121 : pe::ImageLayout* image_layout);
122 :
123 : // Performs a series of assertions on the test DLL's integrity.
124 : static void CheckTestDll(const base::FilePath& path);
125 :
126 : // Loads the test DLL and returns its module handle.
127 : static void LoadTestDll(const base::FilePath& path, ScopedHMODULE* module);
128 : };
129 :
130 : class CoffUnitTest : public testing::PELibUnitTest {
131 : public:
132 E : CoffUnitTest() : image_layout_(&block_graph_) {
133 E : }
134 :
135 : virtual void SetUp() override;
136 :
137 : // Decompose test_dll.coff_obj.
138 : void DecomposeOriginal();
139 :
140 : // Reorder and lay out test_dll.coff_obj into a new object file, located
141 : // at new_test_dll_obj_path_.
142 : void LayoutAndWriteNew(block_graph::BlockGraphOrdererInterface* orderer);
143 :
144 : // Writes and redecomposes the COFF file, and ensures that all symbols have
145 : // made it through the process.
146 : void TestRoundTrip();
147 :
148 : base::FilePath test_dll_obj_path_;
149 : base::FilePath new_test_dll_obj_path_;
150 : base::FilePath temp_dir_path_;
151 :
152 : // Original image details.
153 : testing::DummyTransformPolicy policy_;
154 : pe::CoffFile image_file_;
155 : block_graph::BlockGraph block_graph_;
156 : pe::ImageLayout image_layout_;
157 : block_graph::BlockGraph::Block* headers_block_;
158 : };
159 :
160 : } // namespace testing
161 :
162 : #endif // SYZYGY_PE_UNITTEST_UTIL_H_
|