1
2 /*
3 * Copyright (c) 2021 Huawei Device Co., Ltd.
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 <iostream>
18 #include <string>
19
20 #include <gtest/gtest.h>
21 #include "disassembler.h"
22
23 using namespace panda::disasm;
24
25 std::string g_bin_path_abs {};
26
TEST(instructions_test,test_language_panda_assembly)27 TEST(instructions_test, test_language_panda_assembly)
28 {
29 Disassembler d {};
30
31 std::stringstream ss {};
32 d.Disassemble(g_bin_path_abs + "empty_record.bc");
33 d.Serialize(ss);
34
35 EXPECT_TRUE(ss.str().find(".language PandaAssembly") != std::string::npos);
36 }
37
TEST(instructions_test,test_ins)38 TEST(instructions_test, test_ins)
39 {
40 Disassembler d {};
41
42 std::stringstream ss {};
43 d.Disassemble(g_bin_path_abs + "instructions.bc");
44 d.Serialize(ss);
45
46 size_t beg_g = ss.str().find("g_u1_() <static> {");
47 size_t end_g = ss.str().find('}', beg_g);
48
49 ASSERT_TRUE(beg_g != std::string::npos && end_g != std::string::npos) << "function g not found";
50
51 std::string body_g = ss.str().substr(beg_g + strlen("g() {"), end_g - (beg_g + strlen("g() {")));
52
53 EXPECT_TRUE(body_g.find("\tmov v0, v1") != std::string::npos);
54 EXPECT_TRUE(body_g.find("\tmov.64 v2, v3") != std::string::npos);
55 EXPECT_TRUE(body_g.find("\tmov.obj v4, v5") != std::string::npos);
56
57 EXPECT_TRUE(body_g.find("\tmovi v0, 0xffffffffffffffff") != std::string::npos);
58 EXPECT_TRUE(body_g.find("\tmovi.64 v0, 0x2") != std::string::npos);
59 EXPECT_TRUE(body_g.find("\tfmovi.64 v0, 0x4008147ae147ae14") != std::string::npos);
60
61 EXPECT_TRUE(body_g.find("\tlda v1") != std::string::npos);
62 EXPECT_TRUE(body_g.find("\tlda.64 v0") != std::string::npos);
63 EXPECT_TRUE(body_g.find("\tlda.obj v1") != std::string::npos);
64
65 EXPECT_TRUE(body_g.find("\tldai 0x1") != std::string::npos);
66 EXPECT_TRUE(body_g.find("\tldai.64 0x2") != std::string::npos);
67 EXPECT_TRUE(body_g.find("\tfldai.64 0x4008147ae147ae14") != std::string::npos);
68 EXPECT_TRUE(body_g.find("\tlda.str \"kek\"") != std::string::npos);
69 EXPECT_TRUE(body_g.find("\tlda.type A") != std::string::npos);
70 EXPECT_TRUE(body_g.find("\tlda.null") != std::string::npos);
71
72 EXPECT_TRUE(body_g.find("\tsta v0") != std::string::npos);
73 EXPECT_TRUE(body_g.find("\tsta.64 v1") != std::string::npos);
74 EXPECT_TRUE(body_g.find("\tsta.obj v2") != std::string::npos);
75
76 EXPECT_TRUE(body_g.find("\tjump_label_0: jmp jump_label_0") != std::string::npos);
77 EXPECT_TRUE(body_g.find("\tjeq v1, jump_label_1") != std::string::npos);
78 EXPECT_TRUE(body_g.find("\tldai 0x1") != std::string::npos);
79 EXPECT_TRUE(body_g.find("\tjmp jump_label_2") != std::string::npos);
80 EXPECT_TRUE(body_g.find("\tjump_label_1: ldai 0x0") != std::string::npos);
81 EXPECT_TRUE(body_g.find("\tjump_label_2: cmp.64 v1") != std::string::npos);
82 EXPECT_TRUE(body_g.find("\tucmp v2") != std::string::npos);
83 EXPECT_TRUE(body_g.find("\tucmp.64 v3") != std::string::npos);
84
85 EXPECT_TRUE(body_g.find("\tfcmpl.64 v1") != std::string::npos);
86 EXPECT_TRUE(body_g.find("\tfcmpg.64 v1") != std::string::npos);
87
88 EXPECT_TRUE(body_g.find("\tjeqz jump_label_0") != std::string::npos);
89 EXPECT_TRUE(body_g.find("\tjnez jump_label_0") != std::string::npos);
90 EXPECT_TRUE(body_g.find("\tjltz jump_label_0") != std::string::npos);
91 EXPECT_TRUE(body_g.find("\tjgtz jump_label_0") != std::string::npos);
92 EXPECT_TRUE(body_g.find("\tjlez jump_label_0") != std::string::npos);
93 EXPECT_TRUE(body_g.find("\tjgez jump_label_0") != std::string::npos);
94
95 EXPECT_TRUE(body_g.find("\tjeq v2, jump_label_0") != std::string::npos);
96 EXPECT_TRUE(body_g.find("\tjne v2, jump_label_0") != std::string::npos);
97 EXPECT_TRUE(body_g.find("\tjlt v2, jump_label_0") != std::string::npos);
98 EXPECT_TRUE(body_g.find("\tjgt v2, jump_label_0") != std::string::npos);
99 EXPECT_TRUE(body_g.find("\tjle v2, jump_label_0") != std::string::npos);
100 EXPECT_TRUE(body_g.find("\tjge v2, jump_label_0") != std::string::npos);
101
102 EXPECT_TRUE(body_g.find("\tfadd2.64 v1") != std::string::npos);
103 EXPECT_TRUE(body_g.find("\tfsub2.64 v1") != std::string::npos);
104 EXPECT_TRUE(body_g.find("\tfmul2.64 v1") != std::string::npos);
105 EXPECT_TRUE(body_g.find("\tfdiv2.64 v1") != std::string::npos);
106 EXPECT_TRUE(body_g.find("\tfmod2.64 v1") != std::string::npos);
107
108 EXPECT_TRUE(body_g.find("\tadd2 v2") != std::string::npos);
109 EXPECT_TRUE(body_g.find("\tadd2.64 v2") != std::string::npos);
110 EXPECT_TRUE(body_g.find("\tsub2 v2") != std::string::npos);
111 EXPECT_TRUE(body_g.find("\tsub2.64 v2") != std::string::npos);
112 EXPECT_TRUE(body_g.find("\tmul2 v2") != std::string::npos);
113 EXPECT_TRUE(body_g.find("\tmul2.64 v2") != std::string::npos);
114 EXPECT_TRUE(body_g.find("\tand2 v2") != std::string::npos);
115 EXPECT_TRUE(body_g.find("\tand2.64 v2") != std::string::npos);
116 EXPECT_TRUE(body_g.find("\tor2 v2") != std::string::npos);
117 EXPECT_TRUE(body_g.find("\tor2.64 v2") != std::string::npos);
118 EXPECT_TRUE(body_g.find("\txor2 v2") != std::string::npos);
119 EXPECT_TRUE(body_g.find("\txor2.64 v2") != std::string::npos);
120 EXPECT_TRUE(body_g.find("\tshl2 v2") != std::string::npos);
121 EXPECT_TRUE(body_g.find("\tshl2.64 v2") != std::string::npos);
122 EXPECT_TRUE(body_g.find("\tshr2 v2") != std::string::npos);
123 EXPECT_TRUE(body_g.find("\tshr2.64 v2") != std::string::npos);
124 EXPECT_TRUE(body_g.find("\tashr2 v2") != std::string::npos);
125 EXPECT_TRUE(body_g.find("\tashr2.64 v2") != std::string::npos);
126 EXPECT_TRUE(body_g.find("\tdiv2 v2") != std::string::npos);
127 EXPECT_TRUE(body_g.find("\tdiv2.64 v2") != std::string::npos);
128 EXPECT_TRUE(body_g.find("\tmod2 v2") != std::string::npos);
129 EXPECT_TRUE(body_g.find("\tmod2.64 v2") != std::string::npos);
130 EXPECT_TRUE(body_g.find("\tdivu2 v2") != std::string::npos);
131 EXPECT_TRUE(body_g.find("\tdivu2.64 v2") != std::string::npos);
132 EXPECT_TRUE(body_g.find("\tmodu2 v2") != std::string::npos);
133 EXPECT_TRUE(body_g.find("\tmodu2.64 v2") != std::string::npos);
134
135 EXPECT_TRUE(body_g.find("\tadd v1, v2") != std::string::npos);
136 EXPECT_TRUE(body_g.find("\tsub v1, v2") != std::string::npos);
137 EXPECT_TRUE(body_g.find("\tmul v1, v2") != std::string::npos);
138 EXPECT_TRUE(body_g.find("\tand v1, v2") != std::string::npos);
139 EXPECT_TRUE(body_g.find("\tor v1, v2") != std::string::npos);
140 EXPECT_TRUE(body_g.find("\txor v1, v2") != std::string::npos);
141 EXPECT_TRUE(body_g.find("\tshl v1, v2") != std::string::npos);
142 EXPECT_TRUE(body_g.find("\tshr v1, v2") != std::string::npos);
143 EXPECT_TRUE(body_g.find("\tashr v1, v2") != std::string::npos);
144 EXPECT_TRUE(body_g.find("\tdiv v1, v2") != std::string::npos);
145 EXPECT_TRUE(body_g.find("\tmod v1, v2") != std::string::npos);
146
147 EXPECT_TRUE(body_g.find("\taddi 0x1") != std::string::npos);
148 EXPECT_TRUE(body_g.find("\tsubi 0x1") != std::string::npos);
149 EXPECT_TRUE(body_g.find("\tmuli 0x1") != std::string::npos);
150 EXPECT_TRUE(body_g.find("\tandi 0x1") != std::string::npos);
151 EXPECT_TRUE(body_g.find("\tori 0x1") != std::string::npos);
152 EXPECT_TRUE(body_g.find("\txori 0x1") != std::string::npos);
153 EXPECT_TRUE(body_g.find("\tshli 0x1") != std::string::npos);
154 EXPECT_TRUE(body_g.find("\tshri 0x1") != std::string::npos);
155 EXPECT_TRUE(body_g.find("\tashri 0x1") != std::string::npos);
156 EXPECT_TRUE(body_g.find("\tdivi 0x1") != std::string::npos);
157 EXPECT_TRUE(body_g.find("\tmodi 0x1") != std::string::npos);
158
159 EXPECT_TRUE(body_g.find("\tneg") != std::string::npos);
160 EXPECT_TRUE(body_g.find("\tneg.64") != std::string::npos);
161 EXPECT_TRUE(body_g.find("\tnot") != std::string::npos);
162 EXPECT_TRUE(body_g.find("\tnot.64") != std::string::npos);
163
164 EXPECT_TRUE(body_g.find("\ti32tof64") != std::string::npos);
165 EXPECT_TRUE(body_g.find("\tu32tof64") != std::string::npos);
166 EXPECT_TRUE(body_g.find("\ti64tof64") != std::string::npos);
167 EXPECT_TRUE(body_g.find("\tu64tof64") != std::string::npos);
168 EXPECT_TRUE(body_g.find("\tf64toi32") != std::string::npos);
169 EXPECT_TRUE(body_g.find("\tf64toi64") != std::string::npos);
170 EXPECT_TRUE(body_g.find("\tf64tou32") != std::string::npos);
171 EXPECT_TRUE(body_g.find("\tf64tou64") != std::string::npos);
172 EXPECT_TRUE(body_g.find("\ti32toi64") != std::string::npos);
173 EXPECT_TRUE(body_g.find("\ti64toi32") != std::string::npos);
174 EXPECT_TRUE(body_g.find("\tu32toi64") != std::string::npos);
175
176 EXPECT_TRUE(body_g.find("\tldarr.8 v1") != std::string::npos);
177 EXPECT_TRUE(body_g.find("\tldarru.8 v2") != std::string::npos);
178 EXPECT_TRUE(body_g.find("\tldarr.16 v1") != std::string::npos);
179 EXPECT_TRUE(body_g.find("\tldarru.16 v1") != std::string::npos);
180 EXPECT_TRUE(body_g.find("\tldarr v1") != std::string::npos);
181 EXPECT_TRUE(body_g.find("\tldarr.64 v1") != std::string::npos);
182 EXPECT_TRUE(body_g.find("\tfldarr.32 v1") != std::string::npos);
183 EXPECT_TRUE(body_g.find("\tfldarr.64 v1") != std::string::npos);
184 EXPECT_TRUE(body_g.find("\tldarr.obj v1") != std::string::npos);
185
186 EXPECT_TRUE(body_g.find("\tstarr.8 v1, v2") != std::string::npos);
187 EXPECT_TRUE(body_g.find("\tstarr.16 v1, v2") != std::string::npos);
188 EXPECT_TRUE(body_g.find("\tstarr v1, v2") != std::string::npos);
189 EXPECT_TRUE(body_g.find("\tstarr.64 v1, v2") != std::string::npos);
190 EXPECT_TRUE(body_g.find("\tfstarr.32 v1, v2") != std::string::npos);
191 EXPECT_TRUE(body_g.find("\tfstarr.64 v1, v2") != std::string::npos);
192 EXPECT_TRUE(body_g.find("\tstarr.obj v1, v2") != std::string::npos);
193
194 EXPECT_TRUE(body_g.find("\tnewobj v6, A") != std::string::npos);
195
196 EXPECT_TRUE(body_g.find("\tinitobj A.init_") != std::string::npos);
197
198 EXPECT_TRUE(body_g.find("\tldobj v0, A.kek") != std::string::npos);
199 EXPECT_TRUE(body_g.find("\tldobj.64 v0, A.kek") != std::string::npos);
200 EXPECT_TRUE(body_g.find("\tldobj.obj v0, A.kek") != std::string::npos);
201
202 EXPECT_TRUE(body_g.find("\tstobj v1, A.kek") != std::string::npos);
203 EXPECT_TRUE(body_g.find("\tstobj.64 v1, A.kek") != std::string::npos);
204 EXPECT_TRUE(body_g.find("\tstobj.obj v1, A.kek") != std::string::npos);
205
206 EXPECT_TRUE(body_g.find("\tldstatic A.kek") != std::string::npos);
207 EXPECT_TRUE(body_g.find("\tldstatic.64 A.kek") != std::string::npos);
208 EXPECT_TRUE(body_g.find("\tldstatic.obj A.kek") != std::string::npos);
209
210 EXPECT_TRUE(body_g.find("\tststatic A.kek") != std::string::npos);
211 EXPECT_TRUE(body_g.find("\tststatic.64 A.kek") != std::string::npos);
212 EXPECT_TRUE(body_g.find("\tststatic.obj A.kek") != std::string::npos);
213
214 EXPECT_TRUE(body_g.find("\tcheckcast A") != std::string::npos);
215 EXPECT_TRUE(body_g.find("\tisinstance A") != std::string::npos);
216 }
217
TEST(instructions_test,test_calls)218 TEST(instructions_test, test_calls)
219 {
220 Disassembler d {};
221
222 std::stringstream ss {};
223 d.Disassemble(g_bin_path_abs + "calls.bc");
224 d.Serialize(ss);
225
226 size_t beg_g = ss.str().find("g_u1_u1_(u1 a0) <static> {");
227 size_t end_g = ss.str().find('}', beg_g);
228
229 ASSERT_TRUE(beg_g != std::string::npos && end_g != std::string::npos) << "function g not found";
230
231 std::string body_g = ss.str().substr(beg_g + strlen("g_u1_u1_(u1 a0) <static> {"),
232 end_g - (beg_g + strlen("g_u1_u1_(u1 a0) <static> {")));
233
234 EXPECT_TRUE(body_g.find("\tcall.virt.short B.Bhandler_unspec_B_u8_, v4") != std::string::npos);
235 EXPECT_TRUE(body_g.find("\tcall.virt.short B.Bhandler_short_B_u1_u8_, v4, v1") != std::string::npos);
236 EXPECT_TRUE(body_g.find("\tcall.virt B.Bhandler_short2_B_u1_i64_u8_, v4, v1, v2") != std::string::npos);
237 EXPECT_TRUE(body_g.find("\tcall.virt B.Bhandler_long_B_i8_i16_i32_u16_, v4, v0, v1, v2") != std::string::npos);
238 EXPECT_TRUE(body_g.find("\tcall.virt.range B.Bhandler_range_B_i8_i16_i32_i8_i16_i32_u16_, v4") !=
239 std::string::npos);
240
241 EXPECT_TRUE(body_g.find("\tcall.short handler_unspec_u8_") != std::string::npos);
242 EXPECT_TRUE(body_g.find("\tcall.short handler_short_u1_u8_, v1") != std::string::npos);
243 EXPECT_TRUE(body_g.find("\tcall.short handler_short2_u1_i64_u8_, v1, v2") != std::string::npos);
244 EXPECT_TRUE(body_g.find("\tcall handler_long_i8_i16_i32_u16_, v0, v1, v2") != std::string::npos);
245 EXPECT_TRUE(body_g.find("\tcall handler_long2_i8_i16_i32_f64_u16_, v0, v1, v2, v3") != std::string::npos);
246 EXPECT_TRUE(body_g.find("\tcall.range handler_range_i8_i16_i32_i8_i16_i32_u16_, v0") != std::string::npos);
247
248 EXPECT_TRUE(body_g.find("\tinitobj B.Bhandler_unspec_B_u8_") != std::string::npos);
249 EXPECT_TRUE(body_g.find("\tinitobj.short B.Bhandler_short_B_u1_u8_, v1") != std::string::npos);
250 EXPECT_TRUE(body_g.find("\tinitobj.short B.Bhandler_short2_B_u1_i64_u8_, v1, v2") != std::string::npos);
251 EXPECT_TRUE(body_g.find("\tinitobj B.Bhandler_long_B_i8_i16_i32_u16_, v0, v1, v2") != std::string::npos);
252 EXPECT_TRUE(body_g.find("\tinitobj B.Bhandler_long2_B_i8_i16_i32_i64_u16_, v0, v1, v2, v3") != std::string::npos);
253 EXPECT_TRUE(body_g.find("\tinitobj.range B.Bhandler_range_B_i8_i16_i32_i8_i16_i32_u16_, v0") != std::string::npos);
254
255 EXPECT_TRUE(body_g.find("\tcall.acc.short handler_short_u1_u8_, v0, 0x0") != std::string::npos);
256 EXPECT_TRUE(body_g.find("\tcall.acc.short handler_short2_u1_i64_u8_, a0, 0x1") != std::string::npos);
257
258 EXPECT_TRUE(ss.str().find(".function u16 long_function_i8_i16_i32_i8_i16_i32_i64_f32_u16_(i8 a0, i16 a1, i32 a2, "
259 "i8 a3, i16 a4, i32 a5, i64 a6, f32 a7)") != std::string::npos);
260
261 EXPECT_TRUE(body_g.find("\tcalli.dyn.short 0x1, v0") != std::string::npos);
262 }
263
TEST(instructions_test,test_returns)264 TEST(instructions_test, test_returns)
265 {
266 Disassembler d {};
267
268 std::stringstream ss {};
269 d.Disassemble(g_bin_path_abs + "returns.bc");
270 d.Serialize(ss);
271
272 size_t beg_g = ss.str().find("g_u1_() <static> {");
273 size_t end_g = ss.str().find('}', beg_g);
274
275 ASSERT_TRUE(beg_g != std::string::npos && end_g != std::string::npos) << "function g not found";
276
277 std::string body_g = ss.str().substr(beg_g + strlen("g() {"), end_g - (beg_g + strlen("g() {")));
278
279 EXPECT_TRUE(body_g.find("\treturn") != std::string::npos);
280 EXPECT_TRUE(body_g.find("\treturn.64") != std::string::npos);
281 EXPECT_TRUE(body_g.find("\treturn.obj") != std::string::npos);
282 EXPECT_TRUE(body_g.find("\treturn.void") != std::string::npos);
283 }
284
TEST(instructions_test,test_newarr)285 TEST(instructions_test, test_newarr)
286 {
287 Disassembler d {};
288
289 std::stringstream ss {};
290 d.Disassemble(g_bin_path_abs + "newarrs.bc");
291 d.Serialize(ss);
292
293 size_t beg_g = ss.str().find("g_u1_u1_(u1 a0) <static> {");
294 size_t end_g = ss.str().find('}', beg_g);
295
296 ASSERT_TRUE(beg_g != std::string::npos && end_g != std::string::npos) << "function g not found";
297
298 std::string body_g = ss.str().substr(beg_g + strlen("g() {"), end_g - (beg_g + strlen("g() {")));
299
300 EXPECT_TRUE(body_g.find("\tnewarr v0, a0, u1[]") != std::string::npos);
301 EXPECT_TRUE(body_g.find("\tnewarr v0, a0, i8[]") != std::string::npos);
302 EXPECT_TRUE(body_g.find("\tnewarr v0, a0, u8[]") != std::string::npos);
303 EXPECT_TRUE(body_g.find("\tnewarr v0, a0, i16[]") != std::string::npos);
304 EXPECT_TRUE(body_g.find("\tnewarr v0, a0, u16[]") != std::string::npos);
305 EXPECT_TRUE(body_g.find("\tnewarr v0, a0, i32[]") != std::string::npos);
306 EXPECT_TRUE(body_g.find("\tnewarr v0, a0, u32[]") != std::string::npos);
307 EXPECT_TRUE(body_g.find("\tnewarr v0, a0, f32[]") != std::string::npos);
308 EXPECT_TRUE(body_g.find("\tnewarr v0, a0, f64[]") != std::string::npos);
309 EXPECT_TRUE(body_g.find("\tnewarr v0, a0, i64[]") != std::string::npos);
310 EXPECT_TRUE(body_g.find("\tnewarr v0, a0, u64[]") != std::string::npos);
311 }
312
main(int argc,char ** argv)313 int main(int argc, char **argv)
314 {
315 std::string dir_basename {};
316 std::string glob_argv0 = argv[0];
317
318 size_t last_slash_idx = glob_argv0.rfind('/');
319
320 if (std::string::npos != last_slash_idx) {
321 dir_basename = glob_argv0.substr(0, last_slash_idx + 1);
322 }
323
324 g_bin_path_abs = dir_basename + "../disassembler/bin/";
325
326 ::testing::InitGoogleTest(&argc, argv);
327 return RUN_ALL_TESTS();
328 }
329