1 /*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "gtest/gtest.h"
18
19 #include <cstdint>
20
21 #include "berberis/assembler/machine_code.h"
22
23 namespace berberis {
24
25 namespace {
26
TEST(MachineCodeTest,Add)27 TEST(MachineCodeTest, Add) {
28 MachineCode mc;
29
30 mc.AddU8(0x00);
31 mc.Add<uint16_t>(0x0201);
32 mc.Add<uint32_t>(0x06050403);
33 mc.AddU8(0x07);
34
35 uint8_t out[128]{};
36
37 ASSERT_GT(sizeof(out), mc.install_size());
38 mc.InstallUnsafe(out, nullptr);
39
40 EXPECT_EQ(0x00, out[0]);
41 EXPECT_EQ(0x01, out[1]);
42 EXPECT_EQ(0x02, out[2]);
43 EXPECT_EQ(0x03, out[3]);
44 EXPECT_EQ(0x04, out[4]);
45 EXPECT_EQ(0x05, out[5]);
46 EXPECT_EQ(0x06, out[6]);
47 EXPECT_EQ(0x07, out[7]);
48 }
49
TEST(MachineCodeTest,RelocRecoveryPoint)50 TEST(MachineCodeTest, RelocRecoveryPoint) {
51 MachineCode mc;
52
53 mc.AddU8(0xde);
54 mc.AddU8(0xad);
55 mc.AddU8(0xbe);
56 mc.AddU8(0xef);
57
58 mc.AddRelocation(0, RelocationType::RelocRecoveryPoint, 1, 3);
59
60 uint8_t out[128]{};
61 RecoveryMap rec;
62
63 ASSERT_GT(sizeof(out), mc.install_size());
64 mc.InstallUnsafe(out, &rec);
65
66 EXPECT_EQ(0xad, out[1]);
67 EXPECT_EQ(0xef, out[3]);
68
69 auto fault_addr = reinterpret_cast<uintptr_t>(&out[1]);
70 auto recovery_addr = reinterpret_cast<uintptr_t>(&out[3]);
71
72 EXPECT_EQ(recovery_addr, rec[fault_addr]);
73 }
74
TEST(MachineCodeTest,RelocAbsToDisp32)75 TEST(MachineCodeTest, RelocAbsToDisp32) {
76 MachineCode mc;
77
78 mc.AddU8(0xf1);
79 mc.Add<uint32_t>(0xcccccccc);
80 mc.AddU8(0xf6);
81 mc.Add<uint32_t>(0xcccccccc);
82 mc.AddU8(0xfb);
83
84 // Relocate absolute addresses from 'out' to ensure displacement limit.
85 uint8_t out[128]{};
86
87 mc.AddRelocation(
88 1, RelocationType::RelocAbsToDisp32, 0, reinterpret_cast<intptr_t>(out) + 128); // 128 (0x80)
89 mc.AddRelocation(
90 6, RelocationType::RelocAbsToDisp32, 6, reinterpret_cast<intptr_t>(out)); // -6 (0xfa)
91
92 ASSERT_GT(sizeof(out), mc.install_size());
93 mc.InstallUnsafe(out, nullptr);
94
95 EXPECT_EQ(0xf1, out[0]);
96 EXPECT_EQ(0x80, out[1]);
97 EXPECT_EQ(0x00, out[2]);
98 EXPECT_EQ(0x00, out[3]);
99 EXPECT_EQ(0x00, out[4]);
100 EXPECT_EQ(0xf6, out[5]);
101 EXPECT_EQ(0xfa, out[6]);
102 EXPECT_EQ(0xff, out[7]);
103 EXPECT_EQ(0xff, out[8]);
104 EXPECT_EQ(0xff, out[9]);
105 EXPECT_EQ(0xfb, out[10]);
106 }
107
108 } // namespace
109
110 } // namespace berberis
111