Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(338)

Side by Side Diff: courgette/rel32_finder_unittest.cc

Issue 2008253004: Refactor rel32 searching process for x64 to make it more similar to x86. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Correct far away ptr in rel32_x64_03.txt test case Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « courgette/rel32_finder.cc ('k') | courgette/rel32_finder_win32_x86.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "courgette/rel32_finder_win32_x86.h"
6
7 #include <stddef.h> 5 #include <stddef.h>
8 #include <stdint.h> 6 #include <stdint.h>
9 7
10 #include <algorithm> 8 #include <algorithm>
9 #include <memory>
11 #include <sstream> 10 #include <sstream>
12 #include <string> 11 #include <string>
13 12
14 #include "base/macros.h" 13 #include "base/macros.h"
15 #include "courgette/base_test_unittest.h" 14 #include "courgette/base_test_unittest.h"
16 #include "courgette/image_utils.h" 15 #include "courgette/image_utils.h"
16 #include "courgette/rel32_finder_x64.h"
17 #include "courgette/rel32_finder_x86.h"
17 #include "testing/gtest/include/gtest/gtest.h" 18 #include "testing/gtest/include/gtest/gtest.h"
18 19
19 namespace courgette { 20 namespace courgette {
20 21
21 namespace { 22 namespace {
22 23
23 // Helper class to load and execute a Rel32FinderWin32X86 test case. 24 // Helper class to load and execute a Rel32Finder test case.
24 class Rel32FinderWin32X86TestCase { 25 class Rel32FinderTestCase {
25 public: 26 public:
26 Rel32FinderWin32X86TestCase(const std::string& test_data) 27 Rel32FinderTestCase(const std::string& test_data)
27 : text_start_rva_(0), 28 : text_start_rva_(0),
28 text_end_rva_(0), 29 text_end_rva_(0),
29 relocs_start_rva_(0), 30 relocs_start_rva_(0),
30 relocs_end_rva_(0), 31 relocs_end_rva_(0),
31 image_end_rva_(0) { 32 image_end_rva_(0) {
32 LoadTestFromString(test_data); 33 LoadTestFromString(test_data);
33 } 34 }
34 35
35 void RunTestBasic(std::string name) { 36 void RunTestBasic(std::string name) {
36 Rel32FinderWin32X86_Basic finder(relocs_start_rva_, relocs_end_rva_);
37 ASSERT_FALSE(text_data_.empty()); 37 ASSERT_FALSE(text_data_.empty());
38 finder.Find(&text_data_[0], &text_data_[0] + text_data_.size(), 38 finder_->Find(&text_data_[0], &text_data_[0] + text_data_.size(),
39 text_start_rva_, text_end_rva_, abs32_locations_); 39 text_start_rva_, text_end_rva_, abs32_locations_);
40 std::vector<RVA> rel32_locations; 40 std::vector<RVA> rel32_locations;
41 finder.SwapRel32Locations(&rel32_locations); 41 finder_->SwapRel32Locations(&rel32_locations);
42 EXPECT_EQ(expected_rel32_locations_, rel32_locations) 42 EXPECT_EQ(expected_rel32_locations_, rel32_locations)
43 << "From test case " << name << " (addresses are in hex)"; 43 << "From test case " << name << " (addresses are in hex)";
44 } 44 }
45 45
46 void CreateFinder(const std::string& processor_type) {
47 if (processor_type == "x64") {
48 finder_ = std::unique_ptr<Rel32Finder>(new Rel32FinderX64(
49 relocs_start_rva_, relocs_end_rva_, image_end_rva_));
50 } else if (processor_type == "x86") {
51 finder_ = std::unique_ptr<Rel32Finder>(
52 new Rel32FinderX86(relocs_start_rva_, relocs_end_rva_));
53 } else {
54 NOTREACHED();
55 }
56 }
57
46 private: 58 private:
59 std::unique_ptr<Rel32Finder> finder_;
47 RVA text_start_rva_; 60 RVA text_start_rva_;
48 RVA text_end_rva_; 61 RVA text_end_rva_;
49 RVA relocs_start_rva_; 62 RVA relocs_start_rva_;
50 RVA relocs_end_rva_; 63 RVA relocs_end_rva_;
51 RVA image_end_rva_; 64 RVA image_end_rva_;
52 std::vector<uint8_t> text_data_; 65 std::vector<uint8_t> text_data_;
53 std::vector<RVA> abs32_locations_; 66 std::vector<RVA> abs32_locations_;
54 std::vector<RVA> expected_rel32_locations_; 67 std::vector<RVA> expected_rel32_locations_;
55 68
56 // Scans |iss| for the next non-empty line, after removing "#"-style comments 69 // Scans |iss| for the next non-empty line, after removing "#"-style comments
57 // and stripping trailing spaces. On success, returns true and writes the 70 // and stripping trailing spaces. On success, returns true and writes the
58 // result to |line_out|. Otherwise returns false. 71 // result to |line_out|. Otherwise returns false.
59 bool ReadNonEmptyLine(std::istringstream& iss, std::string* line_out) { 72 bool ReadNonEmptyLine(std::istringstream& iss, std::string* line_out) {
60 std::string line; 73 std::string line;
61 while (std::getline(iss, line)) { 74 while (std::getline(iss, line)) {
62 // Trim comments and trailing spaces. 75 // Trim comments and trailing spaces.
63 size_t end_pos = std::min(line.find("#"), line.length()); 76 size_t end_pos = std::min(line.find("#"), line.length());
64 while (end_pos > 0 && line[end_pos] == ' ') 77 while (end_pos > 0 && line[end_pos - 1] == ' ')
65 --end_pos; 78 --end_pos;
66 line.resize(end_pos); 79 line.resize(end_pos);
67 if (!line.empty()) 80 if (!line.empty())
68 break; 81 break;
69 } 82 }
70 if (line.empty()) 83 if (line.empty())
71 return false; 84 return false;
72 line_out->swap(line); 85 line_out->swap(line);
73 return true; 86 return true;
74 } 87 }
75 88
76 // Scans |iss| for the next non-empty line, and reads (hex) uint32_t into |v|. 89 // Scans |iss| for the next non-empty line, and reads (hex) uint32_t into |v|.
77 // Returns true iff successful. 90 // Returns true iff successful.
78 bool ReadHexUInt32(std::istringstream& iss, uint32_t* v) { 91 bool ReadHexUInt32(std::istringstream& iss, uint32_t* v) {
79 std::string line; 92 std::string line;
80 if (!ReadNonEmptyLine(iss, &line)) 93 if (!ReadNonEmptyLine(iss, &line))
81 return false; 94 return false;
82 return sscanf(line.c_str(), "%X", v) == 1; 95 return sscanf(line.c_str(), "%X", v) == 1;
83 } 96 }
84 97
85 // Initializes the test case by parsing the multi-line string |test_data| 98 // Initializes the test case by parsing the multi-line string |test_data|
86 // to extract Rel32FinderWin32X86 parameters, and read expected values. 99 // to extract Rel32Finder parameters, and read expected values.
87 void LoadTestFromString(const std::string& test_data) { 100 void LoadTestFromString(const std::string& test_data) {
88 // The first lines (ignoring empty ones) specify RVA bounds. 101 // The first lines (ignoring empty ones) specify RVA bounds.
89 std::istringstream iss(test_data); 102 std::istringstream iss(test_data);
103 std::string processor_type;
104 ASSERT_TRUE(ReadNonEmptyLine(iss, &processor_type));
90 ASSERT_TRUE(ReadHexUInt32(iss, &text_start_rva_)); 105 ASSERT_TRUE(ReadHexUInt32(iss, &text_start_rva_));
91 ASSERT_TRUE(ReadHexUInt32(iss, &text_end_rva_)); 106 ASSERT_TRUE(ReadHexUInt32(iss, &text_end_rva_));
92 ASSERT_TRUE(ReadHexUInt32(iss, &relocs_start_rva_)); 107 ASSERT_TRUE(ReadHexUInt32(iss, &relocs_start_rva_));
93 ASSERT_TRUE(ReadHexUInt32(iss, &relocs_end_rva_)); 108 ASSERT_TRUE(ReadHexUInt32(iss, &relocs_end_rva_));
94 ASSERT_TRUE(ReadHexUInt32(iss, &image_end_rva_)); 109 ASSERT_TRUE(ReadHexUInt32(iss, &image_end_rva_));
95 110
96 std::string line; 111 std::string line;
97 // The Program section specifies instruction bytes. We require lines to be 112 // The Program section specifies instruction bytes. We require lines to be
98 // formatted in "DUMPBIN /DISASM" style, i.e., 113 // formatted in "DUMPBIN /DISASM" style, i.e.,
99 // "00401003: E8 00 00 00 00 call 00401008" 114 // "00401003: E8 00 00 00 00 call 00401008"
100 // ^ ^ ^ ^ ^ ^ 115 // ^ ^ ^ ^ ^ ^
101 // We extract up to 6 bytes per line. The remaining are ignored. 116 // We extract up to 6 bytes per line. The remaining are ignored.
102 const int kBytesBegin = 12; 117 const int kBytesBegin = 12;
103 const int kBytesEnd = 17; 118 const int kBytesEnd = 17;
104 ReadNonEmptyLine(iss, &line); 119 ReadNonEmptyLine(iss, &line);
105 ASSERT_EQ("Program:", line); 120 ASSERT_EQ("Program:", line);
106 while (ReadNonEmptyLine(iss, &line) && line != "Abs32:") { 121 while (ReadNonEmptyLine(iss, &line) && line != "Abs32:") {
107 std::string toks = line.substr(kBytesBegin, kBytesEnd); 122 std::string toks = line.substr(kBytesBegin, kBytesEnd);
108 uint32_t vals[6]; 123 uint32_t vals[6];
109 int num_read = sscanf(toks.c_str(), "%X %X %X %X %X %X", &vals[0], 124 int num_read = sscanf(toks.c_str(), "%X %X %X %X %X %X", &vals[0],
110 &vals[1], &vals[2], &vals[3], &vals[4], &vals[5]); 125 &vals[1], &vals[2], &vals[3], &vals[4], &vals[5]);
111 for (int i = 0; i < num_read; ++i) 126 for (int i = 0; i < num_read; ++i)
112 text_data_.push_back(static_cast<uint8_t>(vals[i] & 0xFF)); 127 text_data_.push_back(static_cast<uint8_t>(vals[i] & 0xFF));
113 } 128 }
114 ASSERT_FALSE(text_data_.empty()); 129 ASSERT_FALSE(text_data_.empty());
115 130
116 // The Abs32 section specifies hex RVAs, one per line. 131 // The Abs32 section specifies hex RVAs, one per line.
117 ASSERT_EQ("Abs32:", line); 132 ASSERT_EQ("Abs32:", line);
118 while (ReadNonEmptyLine(iss, &line) && line != "Expected:") { 133 while (ReadNonEmptyLine(iss, &line) && line != "Expected:") {
119 RVA abs32_location; 134 RVA abs32_location;
120 ASSERT_EQ(1, sscanf(line.c_str(), "%X", &abs32_location)); 135 ASSERT_EQ(1, sscanf(line.c_str(), "%X", &abs32_location));
121 abs32_locations_.push_back(abs32_location); 136 abs32_locations_.push_back(abs32_location);
122 } 137 }
123 138
124 // The Expected section specifies hex Rel32 RVAs, one per line. 139 // The Expected section specifies hex Rel32 RVAs, one per line.
125 ASSERT_EQ("Expected:", line); 140 ASSERT_EQ("Expected:", line);
126 while (ReadNonEmptyLine(iss, &line)) { 141 while (ReadNonEmptyLine(iss, &line)) {
127 RVA rel32_location; 142 RVA rel32_location;
128 ASSERT_EQ(1, sscanf(line.c_str(), "%X", &rel32_location)); 143 ASSERT_EQ(1, sscanf(line.c_str(), "%X", &rel32_location));
129 expected_rel32_locations_.push_back(rel32_location); 144 expected_rel32_locations_.push_back(rel32_location);
130 } 145 }
146 CreateFinder(processor_type);
131 } 147 }
132 }; 148 };
133 149
134 class Rel32FinderWin32X86Test : public BaseTest { 150 class Rel32FinderTest : public BaseTest {
135 public: 151 public:
136 void RunTest(const char* test_case_file) { 152 void RunTest(const char* test_case_file) {
137 Rel32FinderWin32X86TestCase test_case(FileContents(test_case_file)); 153 Rel32FinderTestCase test_case(FileContents(test_case_file));
138 test_case.RunTestBasic(test_case_file); 154 test_case.RunTestBasic(test_case_file);
139 } 155 }
140 }; 156 };
141 157
142 TEST_F(Rel32FinderWin32X86Test, TestBasic) { 158 TEST_F(Rel32FinderTest, TestBasic) {
143 RunTest("rel32_win32_x86_01.txt"); 159 RunTest("rel32_x86_01.txt");
144 RunTest("rel32_win32_x86_02.txt"); 160 RunTest("rel32_x86_02.txt");
145 RunTest("rel32_win32_x86_03.txt"); 161 RunTest("rel32_x86_03.txt");
146 RunTest("rel32_win32_x86_04.txt"); 162 RunTest("rel32_x86_04.txt");
163
164 RunTest("rel32_x64_01.txt");
165 RunTest("rel32_x64_02.txt");
166 RunTest("rel32_x64_03.txt");
147 } 167 }
148 168
149 } // namespace 169 } // namespace
150 170
151 } // namespace courgette 171 } // namespace courgette
OLDNEW
« no previous file with comments | « courgette/rel32_finder.cc ('k') | courgette/rel32_finder_win32_x86.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698