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