OLD | NEW |
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" | 5 #include "courgette/rel32_finder_win32_x86.h" |
6 | 6 |
| 7 #include <stddef.h> |
| 8 #include <stdint.h> |
| 9 |
7 #include <algorithm> | 10 #include <algorithm> |
8 #include <sstream> | 11 #include <sstream> |
9 #include <string> | 12 #include <string> |
10 | 13 |
11 #include "base/macros.h" | 14 #include "base/macros.h" |
12 #include "courgette/base_test_unittest.h" | 15 #include "courgette/base_test_unittest.h" |
13 #include "courgette/image_utils.h" | 16 #include "courgette/image_utils.h" |
14 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
15 | 18 |
16 namespace courgette { | 19 namespace courgette { |
(...skipping 23 matching lines...) Expand all Loading... |
40 EXPECT_EQ(expected_rel32_locations_, rel32_locations) | 43 EXPECT_EQ(expected_rel32_locations_, rel32_locations) |
41 << "From test case " << name << " (addresses are in hex)"; | 44 << "From test case " << name << " (addresses are in hex)"; |
42 } | 45 } |
43 | 46 |
44 private: | 47 private: |
45 RVA text_start_rva_; | 48 RVA text_start_rva_; |
46 RVA text_end_rva_; | 49 RVA text_end_rva_; |
47 RVA relocs_start_rva_; | 50 RVA relocs_start_rva_; |
48 RVA relocs_end_rva_; | 51 RVA relocs_end_rva_; |
49 RVA image_end_rva_; | 52 RVA image_end_rva_; |
50 std::vector<uint8> text_data_; | 53 std::vector<uint8_t> text_data_; |
51 std::vector<RVA> abs32_locations_; | 54 std::vector<RVA> abs32_locations_; |
52 std::vector<RVA> expected_rel32_locations_; | 55 std::vector<RVA> expected_rel32_locations_; |
53 | 56 |
54 // Scans |iss| for the next non-empty line, after removing "#"-style comments | 57 // Scans |iss| for the next non-empty line, after removing "#"-style comments |
55 // and stripping trailing spaces. On success, returns true and writes the | 58 // and stripping trailing spaces. On success, returns true and writes the |
56 // result to |line_out|. Otherwise returns false. | 59 // result to |line_out|. Otherwise returns false. |
57 bool ReadNonEmptyLine(std::istringstream& iss, std::string* line_out) { | 60 bool ReadNonEmptyLine(std::istringstream& iss, std::string* line_out) { |
58 std::string line; | 61 std::string line; |
59 while (std::getline(iss, line)) { | 62 while (std::getline(iss, line)) { |
60 // Trim comments and trailing spaces. | 63 // Trim comments and trailing spaces. |
61 size_t end_pos = std::min(line.find("#"), line.length()); | 64 size_t end_pos = std::min(line.find("#"), line.length()); |
62 while (end_pos > 0 && line[end_pos] == ' ') | 65 while (end_pos > 0 && line[end_pos] == ' ') |
63 --end_pos; | 66 --end_pos; |
64 line.resize(end_pos); | 67 line.resize(end_pos); |
65 if (!line.empty()) | 68 if (!line.empty()) |
66 break; | 69 break; |
67 } | 70 } |
68 if (line.empty()) | 71 if (line.empty()) |
69 return false; | 72 return false; |
70 line_out->swap(line); | 73 line_out->swap(line); |
71 return true; | 74 return true; |
72 } | 75 } |
73 | 76 |
74 // Scans |iss| for the next non-empty line, and reads (hex) uint32 into |v|. | 77 // Scans |iss| for the next non-empty line, and reads (hex) uint32_t into |v|. |
75 // Returns true iff successful. | 78 // Returns true iff successful. |
76 bool ReadHexUInt32(std::istringstream& iss, uint32* v) { | 79 bool ReadHexUInt32(std::istringstream& iss, uint32_t* v) { |
77 std::string line; | 80 std::string line; |
78 if (!ReadNonEmptyLine(iss, &line)) | 81 if (!ReadNonEmptyLine(iss, &line)) |
79 return false; | 82 return false; |
80 return sscanf(line.c_str(), "%X", v) == 1; | 83 return sscanf(line.c_str(), "%X", v) == 1; |
81 } | 84 } |
82 | 85 |
83 // Initializes the test case by parsing the multi-line string |test_data| | 86 // Initializes the test case by parsing the multi-line string |test_data| |
84 // to extract Rel32FinderWin32X86 parameters, and read expected values. | 87 // to extract Rel32FinderWin32X86 parameters, and read expected values. |
85 void LoadTestFromString(const std::string& test_data) { | 88 void LoadTestFromString(const std::string& test_data) { |
86 // The first lines (ignoring empty ones) specify RVA bounds. | 89 // The first lines (ignoring empty ones) specify RVA bounds. |
87 std::istringstream iss(test_data); | 90 std::istringstream iss(test_data); |
88 ASSERT_TRUE(ReadHexUInt32(iss, &text_start_rva_)); | 91 ASSERT_TRUE(ReadHexUInt32(iss, &text_start_rva_)); |
89 ASSERT_TRUE(ReadHexUInt32(iss, &text_end_rva_)); | 92 ASSERT_TRUE(ReadHexUInt32(iss, &text_end_rva_)); |
90 ASSERT_TRUE(ReadHexUInt32(iss, &relocs_start_rva_)); | 93 ASSERT_TRUE(ReadHexUInt32(iss, &relocs_start_rva_)); |
91 ASSERT_TRUE(ReadHexUInt32(iss, &relocs_end_rva_)); | 94 ASSERT_TRUE(ReadHexUInt32(iss, &relocs_end_rva_)); |
92 ASSERT_TRUE(ReadHexUInt32(iss, &image_end_rva_)); | 95 ASSERT_TRUE(ReadHexUInt32(iss, &image_end_rva_)); |
93 | 96 |
94 std::string line; | 97 std::string line; |
95 // The Program section specifies instruction bytes. We require lines to be | 98 // The Program section specifies instruction bytes. We require lines to be |
96 // formatted in "DUMPBIN /DISASM" style, i.e., | 99 // formatted in "DUMPBIN /DISASM" style, i.e., |
97 // "00401003: E8 00 00 00 00 call 00401008" | 100 // "00401003: E8 00 00 00 00 call 00401008" |
98 // ^ ^ ^ ^ ^ ^ | 101 // ^ ^ ^ ^ ^ ^ |
99 // We extract up to 6 bytes per line. The remaining are ignored. | 102 // We extract up to 6 bytes per line. The remaining are ignored. |
100 const int kBytesBegin = 12; | 103 const int kBytesBegin = 12; |
101 const int kBytesEnd = 17; | 104 const int kBytesEnd = 17; |
102 ReadNonEmptyLine(iss, &line); | 105 ReadNonEmptyLine(iss, &line); |
103 ASSERT_EQ("Program:", line); | 106 ASSERT_EQ("Program:", line); |
104 while (ReadNonEmptyLine(iss, &line) && line != "Abs32:") { | 107 while (ReadNonEmptyLine(iss, &line) && line != "Abs32:") { |
105 std::string toks = line.substr(kBytesBegin, kBytesEnd); | 108 std::string toks = line.substr(kBytesBegin, kBytesEnd); |
106 uint32 vals[6]; | 109 uint32_t vals[6]; |
107 int num_read = sscanf(toks.c_str(), "%X %X %X %X %X %X", &vals[0], | 110 int num_read = sscanf(toks.c_str(), "%X %X %X %X %X %X", &vals[0], |
108 &vals[1], &vals[2], &vals[3], &vals[4], &vals[5]); | 111 &vals[1], &vals[2], &vals[3], &vals[4], &vals[5]); |
109 for (int i = 0; i < num_read; ++i) | 112 for (int i = 0; i < num_read; ++i) |
110 text_data_.push_back(static_cast<uint8>(vals[i] & 0xFF)); | 113 text_data_.push_back(static_cast<uint8_t>(vals[i] & 0xFF)); |
111 } | 114 } |
112 ASSERT_FALSE(text_data_.empty()); | 115 ASSERT_FALSE(text_data_.empty()); |
113 | 116 |
114 // The Abs32 section specifies hex RVAs, one per line. | 117 // The Abs32 section specifies hex RVAs, one per line. |
115 ASSERT_EQ("Abs32:", line); | 118 ASSERT_EQ("Abs32:", line); |
116 while (ReadNonEmptyLine(iss, &line) && line != "Expected:") { | 119 while (ReadNonEmptyLine(iss, &line) && line != "Expected:") { |
117 RVA abs32_location; | 120 RVA abs32_location; |
118 ASSERT_EQ(1, sscanf(line.c_str(), "%X", &abs32_location)); | 121 ASSERT_EQ(1, sscanf(line.c_str(), "%X", &abs32_location)); |
119 abs32_locations_.push_back(abs32_location); | 122 abs32_locations_.push_back(abs32_location); |
120 } | 123 } |
(...skipping 19 matching lines...) Expand all Loading... |
140 TEST_F(Rel32FinderWin32X86Test, TestBasic) { | 143 TEST_F(Rel32FinderWin32X86Test, TestBasic) { |
141 RunTest("rel32_win32_x86_01.txt"); | 144 RunTest("rel32_win32_x86_01.txt"); |
142 RunTest("rel32_win32_x86_02.txt"); | 145 RunTest("rel32_win32_x86_02.txt"); |
143 RunTest("rel32_win32_x86_03.txt"); | 146 RunTest("rel32_win32_x86_03.txt"); |
144 RunTest("rel32_win32_x86_04.txt"); | 147 RunTest("rel32_win32_x86_04.txt"); |
145 } | 148 } |
146 | 149 |
147 } // namespace | 150 } // namespace |
148 | 151 |
149 } // namespace courgette | 152 } // namespace courgette |
OLD | NEW |