blob: 6135aca58493bccbe933e23b15f3be18e359a137 [file] [log] [blame]
[email protected]43a9e242011-04-06 17:42:451// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]04ca1bc2009-05-08 23:00:292// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
mostynb1007a4a2016-04-11 23:18:065#include <memory>
huangs88451332017-05-18 19:50:346#include <sstream>
[email protected]04ca1bc2009-05-08 23:00:297#include <string>
huangs8d5be252016-01-29 22:14:188#include <utility>
huangsc8037632016-05-19 18:16:409#include <vector>
[email protected]04ca1bc2009-05-08 23:00:2910
huangs7b221a52016-11-09 22:28:2311#include "base/bind.h"
huangs85636222017-01-13 18:09:1312#include "base/memory/ptr_util.h"
[email protected]04ca1bc2009-05-08 23:00:2913#include "courgette/assembly_program.h"
14#include "courgette/courgette.h"
huangs8d5be252016-01-29 22:14:1815#include "courgette/encoded_program.h"
huangsc8037632016-05-19 18:16:4016#include "courgette/image_utils.h"
[email protected]04ca1bc2009-05-08 23:00:2917#include "courgette/streams.h"
18
19#include "testing/gtest/include/gtest/gtest.h"
20
huangs7b221a52016-11-09 22:28:2321namespace courgette {
22
23namespace {
24
[email protected]04ca1bc2009-05-08 23:00:2925class AdjustmentMethodTest : public testing::Test {
26 public:
27 void Test1() const;
28
29 private:
30 void SetUp() {
31 }
32
33 void TearDown() {
34 }
35
huangs8d5be252016-01-29 22:14:1836 // Returns one of two similar simple programs. These differ only in Label
37 // assignment, so it is possible to make them look identical.
huangs7b221a52016-11-09 22:28:2338 std::unique_ptr<AssemblyProgram> MakeProgram(int kind) const {
Jeremy Roman42e81a62018-03-01 19:08:5939 auto prog = std::make_unique<AssemblyProgram>(EXE_WIN_32_X86, 0x00400000);
[email protected]04ca1bc2009-05-08 23:00:2940
huangs7b221a52016-11-09 22:28:2341 RVA kRvaA = 0x00410000;
42 RVA kRvaB = 0x00410004;
huangsc8037632016-05-19 18:16:4043
huangs7b221a52016-11-09 22:28:2344 std::vector<RVA> abs32_rvas;
huangsc8037632016-05-19 18:16:4045 abs32_rvas.push_back(kRvaA);
46 abs32_rvas.push_back(kRvaB);
huangs7b221a52016-11-09 22:28:2347 std::vector<RVA> rel32_rvas; // Stub.
huangsc8037632016-05-19 18:16:4048
huangs7b221a52016-11-09 22:28:2349 TrivialRvaVisitor abs32_visitor(abs32_rvas);
50 TrivialRvaVisitor rel32_visitor(rel32_rvas);
huangsc8037632016-05-19 18:16:4051 prog->PrecomputeLabels(&abs32_visitor, &rel32_visitor);
52
huangs7b221a52016-11-09 22:28:2353 Label* labelA = prog->FindAbs32Label(kRvaA);
54 Label* labelB = prog->FindAbs32Label(kRvaB);
[email protected]04ca1bc2009-05-08 23:00:2955
tzik0881a4002018-03-08 06:19:4956 InstructionGenerator gen = base::BindRepeating(
huangs257f9fb02017-03-23 23:17:5057 [](Label* labelA, Label* labelB,
huangs7b221a52016-11-09 22:28:2358 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
huangs88451332017-05-18 19:50:3469 EXPECT_TRUE(prog->AnnotateLabels(gen));
huangsc4155eb62017-04-13 20:47:0770 EXPECT_EQ(6U, prog->abs32_label_annotations().size());
71 EXPECT_EQ(0U, prog->rel32_label_annotations().size());
[email protected]04ca1bc2009-05-08 23:00:2972
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
huangs7b221a52016-11-09 22:28:2385 std::unique_ptr<AssemblyProgram> MakeProgramA() const {
huangs8d5be252016-01-29 22:14:1886 return MakeProgram(0);
87 }
huangs7b221a52016-11-09 22:28:2388 std::unique_ptr<AssemblyProgram> MakeProgramB() const {
huangs8d5be252016-01-29 22:14:1889 return MakeProgram(1);
90 }
[email protected]04ca1bc2009-05-08 23:00:2991
huangs88451332017-05-18 19:50:3492 // 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]04ca1bc2009-05-08 23:00:29100
huangs88451332017-05-18 19:50:34101 EXPECT_GT(oss.str().length(), 1U); // Ensure results are non-trivial.
102 return oss.str();
[email protected]04ca1bc2009-05-08 23:00:29103 }
104};
105
[email protected]04ca1bc2009-05-08 23:00:29106void AdjustmentMethodTest::Test1() const {
huangs7b221a52016-11-09 22:28:23107 std::unique_ptr<AssemblyProgram> prog1 = MakeProgramA();
108 std::unique_ptr<AssemblyProgram> prog2 = MakeProgramB();
huangs88451332017-05-18 19:50:34109 std::string s1 = Serialize(prog1.get());
110 std::string s2 = Serialize(prog2.get());
[email protected]04ca1bc2009-05-08 23:00:29111
112 // Don't use EXPECT_EQ because strings are unprintable.
113 EXPECT_FALSE(s1 == s2); // Unadjusted A and B differ.
114
huangs7b221a52016-11-09 22:28:23115 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);
huangs88451332017-05-18 19:50:34119 std::string s5 = Serialize(prog5.get());
120 std::string s6 = Serialize(prog6.get());
[email protected]04ca1bc2009-05-08 23:00:29121
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]04ca1bc2009-05-08 23:00:29126TEST_F(AdjustmentMethodTest, All) {
127 Test1();
128}
huangs7b221a52016-11-09 22:28:23129
130} // namespace
131
132} // namespace courgette