[email protected] | 43a9e24 | 2011-04-06 17:42:45 | [diff] [blame] | 1 | // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
[email protected] | 04ca1bc | 2009-05-08 23:00:29 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
mostynb | 1007a4a | 2016-04-11 23:18:06 | [diff] [blame] | 5 | #include <memory> |
huangs | 8845133 | 2017-05-18 19:50:34 | [diff] [blame] | 6 | #include <sstream> |
[email protected] | 04ca1bc | 2009-05-08 23:00:29 | [diff] [blame] | 7 | #include <string> |
huangs | 8d5be25 | 2016-01-29 22:14:18 | [diff] [blame] | 8 | #include <utility> |
huangs | c803763 | 2016-05-19 18:16:40 | [diff] [blame] | 9 | #include <vector> |
[email protected] | 04ca1bc | 2009-05-08 23:00:29 | [diff] [blame] | 10 | |
huangs | 7b221a5 | 2016-11-09 22:28:23 | [diff] [blame] | 11 | #include "base/bind.h" |
huangs | 8563622 | 2017-01-13 18:09:13 | [diff] [blame] | 12 | #include "base/memory/ptr_util.h" |
[email protected] | 04ca1bc | 2009-05-08 23:00:29 | [diff] [blame] | 13 | #include "courgette/assembly_program.h" |
| 14 | #include "courgette/courgette.h" |
huangs | 8d5be25 | 2016-01-29 22:14:18 | [diff] [blame] | 15 | #include "courgette/encoded_program.h" |
huangs | c803763 | 2016-05-19 18:16:40 | [diff] [blame] | 16 | #include "courgette/image_utils.h" |
[email protected] | 04ca1bc | 2009-05-08 23:00:29 | [diff] [blame] | 17 | #include "courgette/streams.h" |
| 18 | |
| 19 | #include "testing/gtest/include/gtest/gtest.h" |
| 20 | |
huangs | 7b221a5 | 2016-11-09 22:28:23 | [diff] [blame] | 21 | namespace courgette { |
| 22 | |
| 23 | namespace { |
| 24 | |
[email protected] | 04ca1bc | 2009-05-08 23:00:29 | [diff] [blame] | 25 | class AdjustmentMethodTest : public testing::Test { |
| 26 | public: |
| 27 | void Test1() const; |
| 28 | |
| 29 | private: |
| 30 | void SetUp() { |
| 31 | } |
| 32 | |
| 33 | void TearDown() { |
| 34 | } |
| 35 | |
huangs | 8d5be25 | 2016-01-29 22:14:18 | [diff] [blame] | 36 | // Returns one of two similar simple programs. These differ only in Label |
| 37 | // assignment, so it is possible to make them look identical. |
huangs | 7b221a5 | 2016-11-09 22:28:23 | [diff] [blame] | 38 | std::unique_ptr<AssemblyProgram> MakeProgram(int kind) const { |
Jeremy Roman | 42e81a6 | 2018-03-01 19:08:59 | [diff] [blame] | 39 | auto prog = std::make_unique<AssemblyProgram>(EXE_WIN_32_X86, 0x00400000); |
[email protected] | 04ca1bc | 2009-05-08 23:00:29 | [diff] [blame] | 40 | |
huangs | 7b221a5 | 2016-11-09 22:28:23 | [diff] [blame] | 41 | RVA kRvaA = 0x00410000; |
| 42 | RVA kRvaB = 0x00410004; |
huangs | c803763 | 2016-05-19 18:16:40 | [diff] [blame] | 43 | |
huangs | 7b221a5 | 2016-11-09 22:28:23 | [diff] [blame] | 44 | std::vector<RVA> abs32_rvas; |
huangs | c803763 | 2016-05-19 18:16:40 | [diff] [blame] | 45 | abs32_rvas.push_back(kRvaA); |
| 46 | abs32_rvas.push_back(kRvaB); |
huangs | 7b221a5 | 2016-11-09 22:28:23 | [diff] [blame] | 47 | std::vector<RVA> rel32_rvas; // Stub. |
huangs | c803763 | 2016-05-19 18:16:40 | [diff] [blame] | 48 | |
huangs | 7b221a5 | 2016-11-09 22:28:23 | [diff] [blame] | 49 | TrivialRvaVisitor abs32_visitor(abs32_rvas); |
| 50 | TrivialRvaVisitor rel32_visitor(rel32_rvas); |
huangs | c803763 | 2016-05-19 18:16:40 | [diff] [blame] | 51 | prog->PrecomputeLabels(&abs32_visitor, &rel32_visitor); |
| 52 | |
huangs | 7b221a5 | 2016-11-09 22:28:23 | [diff] [blame] | 53 | Label* labelA = prog->FindAbs32Label(kRvaA); |
| 54 | Label* labelB = prog->FindAbs32Label(kRvaB); |
[email protected] | 04ca1bc | 2009-05-08 23:00:29 | [diff] [blame] | 55 | |
tzik | 0881a400 | 2018-03-08 06:19:49 | [diff] [blame] | 56 | InstructionGenerator gen = base::BindRepeating( |
huangs | 257f9fb0 | 2017-03-23 23:17:50 | [diff] [blame] | 57 | [](Label* labelA, Label* labelB, |
huangs | 7b221a5 | 2016-11-09 22:28:23 | [diff] [blame] | 58 | InstructionReceptor* receptor) -> CheckBool { |
| 59 | EXPECT_TRUE(receptor->EmitAbs32(labelA)); |
| 60 | EXPECT_TRUE(receptor->EmitAbs32(labelA)); |
| 61 | EXPECT_TRUE(receptor->EmitAbs32(labelB)); |
| 62 | EXPECT_TRUE(receptor->EmitAbs32(labelA)); |
| 63 | EXPECT_TRUE(receptor->EmitAbs32(labelA)); |
| 64 | EXPECT_TRUE(receptor->EmitAbs32(labelB)); |
| 65 | return true; |
| 66 | }, |
| 67 | labelA, labelB); |
| 68 | |
huangs | 8845133 | 2017-05-18 19:50:34 | [diff] [blame] | 69 | EXPECT_TRUE(prog->AnnotateLabels(gen)); |
huangs | c4155eb6 | 2017-04-13 20:47:07 | [diff] [blame] | 70 | EXPECT_EQ(6U, prog->abs32_label_annotations().size()); |
| 71 | EXPECT_EQ(0U, prog->rel32_label_annotations().size()); |
[email protected] | 04ca1bc | 2009-05-08 23:00:29 | [diff] [blame] | 72 | |
| 73 | if (kind == 0) { |
| 74 | labelA->index_ = 0; |
| 75 | labelB->index_ = 1; |
| 76 | } else { |
| 77 | labelA->index_ = 1; |
| 78 | labelB->index_ = 0; |
| 79 | } |
| 80 | prog->AssignRemainingIndexes(); |
| 81 | |
| 82 | return prog; |
| 83 | } |
| 84 | |
huangs | 7b221a5 | 2016-11-09 22:28:23 | [diff] [blame] | 85 | std::unique_ptr<AssemblyProgram> MakeProgramA() const { |
huangs | 8d5be25 | 2016-01-29 22:14:18 | [diff] [blame] | 86 | return MakeProgram(0); |
| 87 | } |
huangs | 7b221a5 | 2016-11-09 22:28:23 | [diff] [blame] | 88 | std::unique_ptr<AssemblyProgram> MakeProgramB() const { |
huangs | 8d5be25 | 2016-01-29 22:14:18 | [diff] [blame] | 89 | return MakeProgram(1); |
| 90 | } |
[email protected] | 04ca1bc | 2009-05-08 23:00:29 | [diff] [blame] | 91 | |
huangs | 8845133 | 2017-05-18 19:50:34 | [diff] [blame] | 92 | // Returns a string that is the serialized version of |program| annotations. |
| 93 | std::string Serialize(AssemblyProgram* program) const { |
| 94 | std::ostringstream oss; |
| 95 | for (const Label* label : program->abs32_label_annotations()) |
| 96 | oss << "(" << label->rva_ << "," << label->index_ << ")"; |
| 97 | oss << ";"; |
| 98 | for (const Label* label : program->rel32_label_annotations()) |
| 99 | oss << "(" << label->rva_ << "," << label->index_ << ")"; |
[email protected] | 04ca1bc | 2009-05-08 23:00:29 | [diff] [blame] | 100 | |
huangs | 8845133 | 2017-05-18 19:50:34 | [diff] [blame] | 101 | EXPECT_GT(oss.str().length(), 1U); // Ensure results are non-trivial. |
| 102 | return oss.str(); |
[email protected] | 04ca1bc | 2009-05-08 23:00:29 | [diff] [blame] | 103 | } |
| 104 | }; |
| 105 | |
[email protected] | 04ca1bc | 2009-05-08 23:00:29 | [diff] [blame] | 106 | void AdjustmentMethodTest::Test1() const { |
huangs | 7b221a5 | 2016-11-09 22:28:23 | [diff] [blame] | 107 | std::unique_ptr<AssemblyProgram> prog1 = MakeProgramA(); |
| 108 | std::unique_ptr<AssemblyProgram> prog2 = MakeProgramB(); |
huangs | 8845133 | 2017-05-18 19:50:34 | [diff] [blame] | 109 | std::string s1 = Serialize(prog1.get()); |
| 110 | std::string s2 = Serialize(prog2.get()); |
[email protected] | 04ca1bc | 2009-05-08 23:00:29 | [diff] [blame] | 111 | |
| 112 | // Don't use EXPECT_EQ because strings are unprintable. |
| 113 | EXPECT_FALSE(s1 == s2); // Unadjusted A and B differ. |
| 114 | |
huangs | 7b221a5 | 2016-11-09 22:28:23 | [diff] [blame] | 115 | std::unique_ptr<AssemblyProgram> prog5 = MakeProgramA(); |
| 116 | std::unique_ptr<AssemblyProgram> prog6 = MakeProgramB(); |
| 117 | Status can_adjust = Adjust(*prog5, prog6.get()); |
| 118 | EXPECT_EQ(C_OK, can_adjust); |
huangs | 8845133 | 2017-05-18 19:50:34 | [diff] [blame] | 119 | std::string s5 = Serialize(prog5.get()); |
| 120 | std::string s6 = Serialize(prog6.get()); |
[email protected] | 04ca1bc | 2009-05-08 23:00:29 | [diff] [blame] | 121 | |
| 122 | EXPECT_TRUE(s1 == s5); // Adjustment did not change A (prog5) |
| 123 | EXPECT_TRUE(s5 == s6); // Adjustment did change B into A |
| 124 | } |
| 125 | |
[email protected] | 04ca1bc | 2009-05-08 23:00:29 | [diff] [blame] | 126 | TEST_F(AdjustmentMethodTest, All) { |
| 127 | Test1(); |
| 128 | } |
huangs | 7b221a5 | 2016-11-09 22:28:23 | [diff] [blame] | 129 | |
| 130 | } // namespace |
| 131 | |
| 132 | } // namespace courgette |