1 /*
2 * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <gtest/gtest.h>
17
18 #include <string>
19 #include <thread>
20 #include <vector>
21
22 #include <unistd.h>
23
24 #include "dfx_define.h"
25 #define private public
26 #define protected public
27 #include "arm_exidx.h"
28 #undef private
29 #undef protected
30 #include "dfx_memory.h"
31 using namespace testing;
32 using namespace testing::ext;
33 #if defined(__arm__)
34 namespace OHOS {
35 namespace HiviewDFX {
36 class ArmExidxTest : public testing::Test {
37 public:
38 static void SetUpTestCase();
39 static void TearDownTestCase();
40 void SetUp();
41 void TearDown();
42 };
43
SetUpTestCase()44 void ArmExidxTest::SetUpTestCase()
45 {}
46
TearDownTestCase()47 void ArmExidxTest::TearDownTestCase()
48 {}
49
SetUp()50 void ArmExidxTest::SetUp()
51 {}
52
TearDown()53 void ArmExidxTest::TearDown()
54 {}
55
56 /**
57 * @tc.name: ArmExidxTest001
58 * @tc.desc: test ExtractEntryData
59 * @tc.type: FUNC
60 */
61 HWTEST_F(ArmExidxTest, ArmExidxTest001, TestSize.Level2)
62 {
63 GTEST_LOG_(INFO) << "ArmExidxTest001: start.";
64 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
65 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
66 ArmExidx exidx(memory);
67 uint32_t values[] = {0x1, 0x1};
68 uintptr_t entryOffset = (uintptr_t)(&values[0]);
69 // cant unwind
70 ASSERT_FALSE(exidx.ExtractEntryData(entryOffset));
71 ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_CANT_UNWIND);
72 GTEST_LOG_(INFO) << "ArmExidxTest001: end.";
73 }
74 /**
75 * @tc.name: ArmExidxTest002
76 * @tc.desc: test ExtractEntryData inline compact model
77 * @tc.type: FUNC
78 */
79 HWTEST_F(ArmExidxTest, ArmExidxTest002, TestSize.Level2)
80 {
81 GTEST_LOG_(INFO) << "ArmExidxTest002: start.";
82 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
83 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
84 ArmExidx exidx(memory);
85 // inline compact model
86 uint32_t values[] = {0x7fff2340, 0x80c0c0c0};
87 uintptr_t entryOffset = (uintptr_t)(&values[0]);
88 ASSERT_TRUE(exidx.ExtractEntryData(entryOffset));
89 std::deque<uint8_t> data = exidx.ops_;
90 ASSERT_EQ(data.size(), 4U);
91 ASSERT_EQ(data[0], 0xc0U);
92 ASSERT_EQ(data[1], 0xc0U);
93 ASSERT_EQ(data[2], 0xc0U);
94 ASSERT_EQ(data[3], 0xb0U);
95 GTEST_LOG_(INFO) << "ArmExidxTest002: end.";
96 }
97 /**
98 * @tc.name: ArmExidxTest003
99 * @tc.desc: test ExtractEntryData highest bit is zero, point to .ARM.extab data
100 * @tc.type: FUNC
101 */
102 HWTEST_F(ArmExidxTest, ArmExidxTest003, TestSize.Level2)
103 {
104 GTEST_LOG_(INFO) << "ArmExidxTest003: start.";
105 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
106 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
107 ArmExidx exidx(memory);
108
109 //personality 0
110 uint32_t values0[] = {0x7fff2340, 0x00001111, 0x80c0c0c0};
111 uintptr_t entryOffset = (uintptr_t)(&values0[0]);
112 ASSERT_TRUE(exidx.ExtractEntryData(entryOffset));
113 std::deque<uint8_t> data = exidx.ops_;
114 ASSERT_EQ(data.size(), 4U);
115 ASSERT_EQ(data[0], 0xc0U);
116 ASSERT_EQ(data[1], 0xc0U);
117 ASSERT_EQ(data[2], 0xc0U);
118 ASSERT_EQ(data[3], 0xb0U);
119
120 //personality 1
121 uint32_t values1[] = {0x7fff2340, 0x00001111, 0x8100c0c0};
122 entryOffset = (uintptr_t)(&values1[0]);
123 ASSERT_TRUE(exidx.ExtractEntryData(entryOffset));
124 data = exidx.ops_;
125 ASSERT_EQ(data.size(), 3U);
126 ASSERT_EQ(data[0], 0xc0U);
127 ASSERT_EQ(data[1], 0xc0U);
128 ASSERT_EQ(data[2], 0xb0U);
129
130 //personality 2 MOREWORD 0
131 uint32_t values2[] = {0x7fff2340, 0x00001111, 0x8200c0c0};
132 entryOffset = (uintptr_t)(&values2[0]);
133 ASSERT_TRUE(exidx.ExtractEntryData(entryOffset));
134 data = exidx.ops_;
135 ASSERT_EQ(data.size(), 3U);
136 ASSERT_EQ(data[0], 0xc0U);
137 ASSERT_EQ(data[1], 0xc0U);
138 ASSERT_EQ(data[2], 0xb0U);
139
140 //personality 2 MOREWORD 1
141 uint32_t values2m[] = {0x7fff2340, 0x00001111, 0x8201c0c0, 0xd0e0f0b0};
142 entryOffset = (uintptr_t)(&values2m[0]);
143 ASSERT_TRUE(exidx.ExtractEntryData(entryOffset));
144 data = exidx.ops_;
145 ASSERT_EQ(data.size(), 6U);
146 ASSERT_EQ(data[0], 0xc0U);
147 ASSERT_EQ(data[1], 0xc0U);
148 ASSERT_EQ(data[2], 0xd0U);
149 ASSERT_EQ(data[3], 0xe0U);
150 ASSERT_EQ(data[4], 0xf0U);
151 ASSERT_EQ(data[5], 0xb0U);
152 GTEST_LOG_(INFO) << "ArmExidxTest003: end.";
153 }
154 /**
155 * @tc.name: ArmExidxTest004
156 * @tc.desc: test Step
157 * @tc.type: FUNC
158 */
159 HWTEST_F(ArmExidxTest, ArmExidxTest004, TestSize.Level2)
160 {
161 // 00xxxxxx: vsp = vsp + (xxxxxx << 2) + 4
162 GTEST_LOG_(INFO) << "ArmExidxTest004: start.";
163 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
164 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
165 ArmExidx exidx(memory);
166 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
167 uint32_t values[] = {0x7fff2340, 0x00001111, 0x810010b0};
168 uintptr_t entryOffset = (uintptr_t)(&values[0]);
169 ASSERT_TRUE(exidx.Step(entryOffset, rs));
170 ASSERT_EQ(rs->cfaRegOffset, 0x44);
171 GTEST_LOG_(INFO) << "ArmExidxTest004: end.";
172 }
173
174 /**
175 * @tc.name: ArmExidxTest005
176 * @tc.desc: test Step
177 * @tc.type: FUNC
178 */
179 HWTEST_F(ArmExidxTest, ArmExidxTest005, TestSize.Level2)
180 {
181 // 01xxxxxx: vsp = vsp - (xxxxxx << 2) - 4
182 GTEST_LOG_(INFO) << "ArmExidxTest005: start.";
183 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
184 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
185 ArmExidx exidx(memory);
186 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
187 uint32_t values[] = {0x7fff2340, 0x00001111, 0x810041b0};
188 uintptr_t entryOffset = (uintptr_t)(&values[0]);
189 ASSERT_TRUE(exidx.Step(entryOffset, rs));
190 ASSERT_EQ(rs->cfaRegOffset, -8);
191 GTEST_LOG_(INFO) << "ArmExidxTest005: end.";
192 }
193
194 /**
195 * @tc.name: ArmExidxTest006
196 * @tc.desc: test Step
197 * @tc.type: FUNC
198 */
199 HWTEST_F(ArmExidxTest, ArmExidxTest006, TestSize.Level2)
200 {
201 // 10000000 00000000: Refuse to unwind
202 GTEST_LOG_(INFO) << "ArmExidxTest006: start.";
203 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
204 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
205 ArmExidx exidx(memory);
206 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
207 uint32_t values[] = {0x7fff2340, 0x00001111, 0x81008000};
208 uintptr_t entryOffset = (uintptr_t)(&values[0]);
209
210 ASSERT_TRUE(exidx.Step(entryOffset, rs));
211 ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_CANT_UNWIND);
212 GTEST_LOG_(INFO) << "ArmExidxTest006: end.";
213 }
214
215 /**
216 * @tc.name: ArmExidxTest007
217 * @tc.desc: test Step
218 * @tc.type: FUNC
219 */
220 HWTEST_F(ArmExidxTest, ArmExidxTest007, TestSize.Level2)
221 {
222 // 1000iiii iiiiiiii (i not all 0)
223 GTEST_LOG_(INFO) << "ArmExidxTest007: start.";
224 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
225 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
226 ArmExidx exidx(memory);
227 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
228 uint32_t values[] = {0x7fff2340, 0x00001111, 0x81008811};
229 uintptr_t entryOffset = (uintptr_t)(&values[0]);
230 ASSERT_TRUE(exidx.Step(entryOffset, rs));
231 ASSERT_EQ(rs->cfaReg, REG_SP);
232 ASSERT_EQ(rs->cfaRegOffset, 12);
233 ASSERT_EQ(rs->locs[3].type, REG_LOC_MEM_OFFSET);
234 ASSERT_EQ(rs->locs[3].val, -4);
235 GTEST_LOG_(INFO) << "ArmExidxTest007: end.";
236 }
237
238 /**
239 * @tc.name: ArmExidxTest008
240 * @tc.desc: test Step
241 * @tc.type: FUNC
242 */
243 HWTEST_F(ArmExidxTest, ArmExidxTest008, TestSize.Level2)
244 {
245 // 10011101 || 10011111
246 GTEST_LOG_(INFO) << "ArmExidxTest008: start.";
247 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
248 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
249 ArmExidx exidx(memory);
250 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
251 uint32_t values[] = {0x7fff2340, 0x00001111, 0x81009db0};
252 uintptr_t entryOffset = (uintptr_t)(&values[0]);
253 ASSERT_TRUE(exidx.Step(entryOffset, rs));
254 ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_RESERVED_VALUE);
255
256 values[2] = 0x81009fb0;
257 ASSERT_TRUE(exidx.Step(entryOffset, rs));
258 ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_RESERVED_VALUE);
259 GTEST_LOG_(INFO) << "ArmExidxTest008: end.";
260 }
261
262 /**
263 * @tc.name: ArmExidxTest009
264 * @tc.desc: test Step
265 * @tc.type: FUNC
266 */
267 HWTEST_F(ArmExidxTest, ArmExidxTest009, TestSize.Level2)
268 {
269 GTEST_LOG_(INFO) << "ArmExidxTest009: start.";
270 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
271 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
272 ArmExidx exidx(memory);
273 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
274 uint32_t values[] = {0x7fff2340, 0x00001111, 0x81009bb0};
275 uintptr_t entryOffset = (uintptr_t)(&values[0]);
276 ASSERT_TRUE(exidx.Step(entryOffset, rs));
277
278 // 1001nnnn(nnnn != 13, 15)
279 ASSERT_EQ(rs->cfaReg, 11U);
280 ASSERT_EQ(rs->cfaRegOffset, 0);
281 GTEST_LOG_(INFO) << "ArmExidxTest009: end.";
282 }
283
284 /**
285 * @tc.name: ArmExidxTest010
286 * @tc.desc: test Step
287 * @tc.type: FUNC
288 */
289 HWTEST_F(ArmExidxTest, ArmExidxTest010, TestSize.Level2)
290 {
291 //10100nnn Pop r4-r[4+nnn]
292 GTEST_LOG_(INFO) << "ArmExidxTest010: start.";
293 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
294 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
295 ArmExidx exidx(memory);
296 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
297 uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100a7b0};
298 uintptr_t entryOffset = (uintptr_t)(&values[0]);
299 ASSERT_TRUE(exidx.Step(entryOffset, rs));
300 ASSERT_EQ(rs->cfaReg, REG_SP);
301 ASSERT_EQ(rs->cfaRegOffset, 32);
302 ASSERT_EQ(rs->locs[0].type, REG_LOC_MEM_OFFSET);
303 ASSERT_EQ(rs->locs[0].val, -20);
304 ASSERT_EQ(rs->locs[1].type, REG_LOC_MEM_OFFSET);
305 ASSERT_EQ(rs->locs[1].val, -4);
306 GTEST_LOG_(INFO) << "ArmExidxTest010: end.";
307 }
308
309 /**
310 * @tc.name: ArmExidxTest011
311 * @tc.desc: test Step
312 * @tc.type: FUNC
313 */
314 HWTEST_F(ArmExidxTest, ArmExidxTest011, TestSize.Level2)
315 {
316 // 10101nnn Pop r4-r[4+nnn], r14
317 GTEST_LOG_(INFO) << "ArmExidxTest011: start.";
318 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
319 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
320 ArmExidx exidx(memory);
321 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
322 uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100afb0};
323 uintptr_t entryOffset = (uintptr_t)(&values[0]);
324 ASSERT_TRUE(exidx.Step(entryOffset, rs));
325 ASSERT_EQ(rs->cfaReg, REG_SP);
326 ASSERT_EQ(rs->cfaRegOffset, 36);
327 ASSERT_EQ(rs->locs[0].type, REG_LOC_MEM_OFFSET);
328 ASSERT_EQ(rs->locs[0].val, -24);
329 ASSERT_EQ(rs->locs[1].type, REG_LOC_MEM_OFFSET);
330 ASSERT_EQ(rs->locs[1].val, -8);
331 ASSERT_EQ(rs->locs[4].type, REG_LOC_MEM_OFFSET);
332 ASSERT_EQ(rs->locs[4].val, -4);
333 GTEST_LOG_(INFO) << "ArmExidxTest011: end.";
334 }
335
336 /**
337 * @tc.name: ArmExidxTest012
338 * @tc.desc: test Step
339 * @tc.type: FUNC
340 */
341 HWTEST_F(ArmExidxTest, ArmExidxTest012, TestSize.Level2)
342 {
343 // 10110000 Finish
344 GTEST_LOG_(INFO) << "ArmExidxTest012: start.";
345 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
346 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
347 ArmExidx exidx(memory);
348 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
349 uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100b0b0};
350 uintptr_t entryOffset = (uintptr_t)(&values[0]);
351 ASSERT_TRUE(exidx.Step(entryOffset, rs));
352 ASSERT_EQ(rs->cfaReg, REG_SP);
353 ASSERT_EQ(rs->cfaRegOffset, 0);
354 ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_ARM_EXIDX_FINISH);
355 GTEST_LOG_(INFO) << "ArmExidxTest012: end.";
356 }
357
358 /**
359 * @tc.name: ArmExidxTest013
360 * @tc.desc: test Step
361 * @tc.type: FUNC
362 */
363 HWTEST_F(ArmExidxTest, ArmExidxTest013, TestSize.Level2)
364 {
365 // 10110001 00000000: Spare
366 GTEST_LOG_(INFO) << "ArmExidxTest013: start.";
367 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
368 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
369 ArmExidx exidx(memory);
370 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
371 uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100b100};
372 uintptr_t entryOffset = (uintptr_t)(&values[0]);
373 ASSERT_TRUE(exidx.Step(entryOffset, rs));
374 ASSERT_EQ(rs->cfaReg, REG_SP);
375 ASSERT_EQ(rs->cfaRegOffset, 0);
376 ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_ARM_EXIDX_SPARE);
377
378 // 10110001 xxxxyyyy spare
379
380 GTEST_LOG_(INFO) << "ArmExidxTest013: end.";
381 }
382
383 /**
384 * @tc.name: ArmExidxTest014
385 * @tc.desc: test Step
386 * @tc.type: FUNC
387 */
388 HWTEST_F(ArmExidxTest, ArmExidxTest014, TestSize.Level2)
389 {
390 // 10110001 0000iiii(i not all 0) Pop integer registers under mask{r3, r2,r1,r0}
391 GTEST_LOG_(INFO) << "ArmExidxTest014: start.";
392 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
393 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
394 ArmExidx exidx(memory);
395 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
396 uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100b108};
397 uintptr_t entryOffset = (uintptr_t)(&values[0]);
398 ASSERT_TRUE(exidx.Step(entryOffset, rs));
399 ASSERT_EQ(rs->cfaReg, REG_SP);
400 ASSERT_EQ(rs->cfaRegOffset, 4);
401 GTEST_LOG_(INFO) << "ArmExidxTest014: end.";
402 }
403
404 /**
405 * @tc.name: ArmExidxTest015
406 * @tc.desc: test Step
407 * @tc.type: FUNC
408 */
409 HWTEST_F(ArmExidxTest, ArmExidxTest015, TestSize.Level2)
410 {
411 // 10110010 uleb128 vsp = vsp + 0x204 + (uleb128 << 2)
412 GTEST_LOG_(INFO) << "ArmExidxTest015: start.";
413 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
414 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
415 ArmExidx exidx(memory);
416 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
417 uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100b208};
418 uintptr_t entryOffset = (uintptr_t)(&values[0]);
419 ASSERT_TRUE(exidx.Step(entryOffset, rs));
420 ASSERT_EQ(rs->cfaReg, REG_SP);
421 ASSERT_EQ(rs->cfaRegOffset, 0x224);
422 GTEST_LOG_(INFO) << "ArmExidxTest015: end.";
423 }
424
425 /**
426 * @tc.name: ArmExidxTest016
427 * @tc.desc: test Step
428 * @tc.type: FUNC
429 */
430 HWTEST_F(ArmExidxTest, ArmExidxTest016, TestSize.Level2)
431 {
432 // 10110011 sssscccc: Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved by FSTMFDX
433 GTEST_LOG_(INFO) << "ArmExidxTest016: start.";
434 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
435 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
436 ArmExidx exidx(memory);
437 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
438 uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100b302};
439 uintptr_t entryOffset = (uintptr_t)(&values[0]);
440 ASSERT_TRUE(exidx.Step(entryOffset, rs));
441 ASSERT_EQ(rs->cfaReg, REG_SP);
442 ASSERT_EQ(rs->cfaRegOffset, 0x1c);
443 GTEST_LOG_(INFO) << "ArmExidxTest016: end.";
444 }
445
446
447 /**
448 * @tc.name: ArmExidxTest017
449 * @tc.desc: test Step
450 * @tc.type: FUNC
451 */
452 HWTEST_F(ArmExidxTest, ArmExidxTest017, TestSize.Level2)
453 {
454 // 10111nnn: VFP double-precision registers D[8]-D[8+nnn] saved by FSTMFDX
455 GTEST_LOG_(INFO) << "ArmExidxTest016: start.";
456 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
457 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
458 ArmExidx exidx(memory);
459 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
460 uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100b9b0};
461 uintptr_t entryOffset = (uintptr_t)(&values[0]);
462 ASSERT_TRUE(exidx.Step(entryOffset, rs));
463 ASSERT_EQ(rs->cfaReg, REG_SP);
464 ASSERT_EQ(rs->cfaRegOffset, 0x14);
465 GTEST_LOG_(INFO) << "ArmExidxTest016: end.";
466 }
467
468 /**
469 * @tc.name: ArmExidxTest018
470 * @tc.desc: test Step
471 * @tc.type: FUNC
472 */
473 HWTEST_F(ArmExidxTest, ArmExidxTest018, TestSize.Level2)
474 {
475 /* 11000nnn (nnn != 6,7) : Intel Wireless MMX pop wR[10]-wR[10+nnn]
476 * 11000110 sssscccc : Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc]
477 * 11000111 00000000 : spare
478 * 11000111 0000iiii : Intel Wireless MMX pop wCGR register under mask {wCGR3,2,1,0}
479 * 11000111 xxxxyyyy (xxxx!=0000): spare
480 */
481 GTEST_LOG_(INFO) << "ArmExidxTest018: start.";
482 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
483 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
484 ArmExidx exidx(memory);
485 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
486
487
488 // 11000nnn (nnn != 6,7)
489 uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100c1b0};
490 uintptr_t entryOffset = (uintptr_t)(&values[0]);
491 ASSERT_TRUE(exidx.Step(entryOffset, rs));
492 ASSERT_EQ(rs->cfaReg, REG_SP);
493 ASSERT_EQ(rs->cfaRegOffset, 0x10);
494
495 // 11000110 sssscccc
496 values[2] = 0x8100c602;
497 ASSERT_TRUE(exidx.Step(entryOffset, rs));
498 ASSERT_EQ(rs->cfaReg, REG_SP);
499 ASSERT_EQ(rs->cfaRegOffset, 0x18);
500
501 // 11000111 00000000 : spare
502 values[2] = 0x8100c700;
503 ASSERT_TRUE(exidx.Step(entryOffset, rs));
504 ASSERT_EQ(rs->cfaReg, REG_SP);
505 ASSERT_EQ(rs->cfaRegOffset, 0);
506 ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_ARM_EXIDX_SPARE);
507
508 // 11000111 0000iiii : Intel Wireless MMX pop wCGR register under mask {wCGR3,2,1,0}
509 values[2] = 0x8100c70f;
510 ASSERT_TRUE(exidx.Step(entryOffset, rs));
511 ASSERT_EQ(rs->cfaReg, REG_SP);
512 ASSERT_EQ(rs->cfaRegOffset, 0x10);
513
514 //11000111 xxxxyyyy (xxxx!=0000): spare
515 values[2] = 0x8100c71f;
516 ASSERT_TRUE(exidx.Step(entryOffset, rs));
517 ASSERT_EQ(rs->cfaReg, REG_SP);
518 ASSERT_EQ(rs->cfaRegOffset, 0);
519 ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_ARM_EXIDX_SPARE);
520 GTEST_LOG_(INFO) << "ArmExidxTest018: end.";
521 }
522
523 /**
524 * @tc.name: ArmExidxTest019
525 * @tc.desc: test Step
526 * @tc.type: FUNC
527 */
528 HWTEST_F(ArmExidxTest, ArmExidxTest019, TestSize.Level2)
529 {
530 /**
531 * 11001000 sssscccc Pop VFP double precision registers
532 * D[16+ssss]-D[16+ssss+cccc] saved (as if) by VPUSH (see remarks d,e)
533 * 11001001 sssscccc Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved (as if) by VPUSH (see remark d)
534 * 11001yyy(yyy != 000, 001) Spare
535 */
536 GTEST_LOG_(INFO) << "ArmExidxTest019: start.";
537 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
538 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
539 ArmExidx exidx(memory);
540 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
541
542 // 11001000 sssscccc
543 uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100c801};
544 uintptr_t entryOffset = (uintptr_t)(&values[0]);
545 ASSERT_TRUE(exidx.Step(entryOffset, rs));
546 ASSERT_EQ(rs->cfaReg, REG_SP);
547 ASSERT_EQ(rs->cfaRegOffset, 0x10);
548
549 // 11001001 sssscccc
550 values[2] = 0x8100c902;
551 ASSERT_TRUE(exidx.Step(entryOffset, rs));
552 ASSERT_EQ(rs->cfaReg, REG_SP);
553 ASSERT_EQ(rs->cfaRegOffset, 0x18);
554
555 // 11001yyy(yyy != 000, 001) Spare
556 values[2] = 0x8100cbb0;
557 ASSERT_TRUE(exidx.Step(entryOffset, rs));
558 ASSERT_EQ(rs->cfaReg, REG_SP);
559 ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_ARM_EXIDX_SPARE);
560 GTEST_LOG_(INFO) << "ArmExidxTest019: end.";
561 }
562
563 /**
564 * @tc.name: ArmExidxTest020
565 * @tc.desc: test Step
566 * @tc.type: FUNC
567 */
568 HWTEST_F(ArmExidxTest, ArmExidxTest020, TestSize.Level2)
569 {
570 GTEST_LOG_(INFO) << "ArmExidxTest020: start.";
571 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
572 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
573 ArmExidx exidx(memory);
574 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
575
576 // 11010nnn Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by VPUSH (seeremark d)
577 uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100d1b0};
578 uintptr_t entryOffset = (uintptr_t)(&values[0]);
579 ASSERT_TRUE(exidx.Step(entryOffset, rs));
580 ASSERT_EQ(rs->cfaReg, REG_SP);
581 ASSERT_EQ(rs->cfaRegOffset, 0x10);
582
583 // 11xxxyyy: Spare (xxx != 000, 001, 010)
584 values[2] = 0x8100f8b0;
585 ASSERT_TRUE(exidx.Step(entryOffset, rs));
586 ASSERT_EQ(rs->cfaReg, REG_SP);
587 ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_ARM_EXIDX_SPARE);
588 GTEST_LOG_(INFO) << "ArmExidxTest020: end.";
589 }
590 } // namespace HiviewDFX
591 } // namepsace OHOS
592 #endif
593