1 /*
2 * Copyright (c) 2023 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_TRUE(exidx.rsState_->isPcSet);
232 ASSERT_EQ(rs->cfaReg, REG_SP);
233 ASSERT_EQ(rs->cfaRegOffset, 12);
234 ASSERT_EQ(rs->locs[3].type, REG_LOC_MEM_OFFSET);
235 ASSERT_EQ(rs->locs[3].val, -4);
236 GTEST_LOG_(INFO) << "ArmExidxTest007: end.";
237 }
238
239 /**
240 * @tc.name: ArmExidxTest008
241 * @tc.desc: test Step
242 * @tc.type: FUNC
243 */
244 HWTEST_F(ArmExidxTest, ArmExidxTest008, TestSize.Level2)
245 {
246 // 10011101 || 10011111
247 GTEST_LOG_(INFO) << "ArmExidxTest008: start.";
248 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
249 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
250 ArmExidx exidx(memory);
251 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
252 uint32_t values[] = {0x7fff2340, 0x00001111, 0x81009db0};
253 uintptr_t entryOffset = (uintptr_t)(&values[0]);
254 ASSERT_TRUE(exidx.Step(entryOffset, rs));
255 ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_RESERVED_VALUE);
256
257 values[2] = 0x81009fb0;
258 ASSERT_TRUE(exidx.Step(entryOffset, rs));
259 ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_RESERVED_VALUE);
260 GTEST_LOG_(INFO) << "ArmExidxTest008: end.";
261 }
262
263 /**
264 * @tc.name: ArmExidxTest009
265 * @tc.desc: test Step
266 * @tc.type: FUNC
267 */
268 HWTEST_F(ArmExidxTest, ArmExidxTest009, TestSize.Level2)
269 {
270 GTEST_LOG_(INFO) << "ArmExidxTest009: start.";
271 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
272 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
273 ArmExidx exidx(memory);
274 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
275 uint32_t values[] = {0x7fff2340, 0x00001111, 0x81009bb0};
276 uintptr_t entryOffset = (uintptr_t)(&values[0]);
277 ASSERT_TRUE(exidx.Step(entryOffset, rs));
278
279 // 1001nnnn(nnnn != 13, 15)
280 ASSERT_EQ(rs->cfaReg, 11U);
281 ASSERT_EQ(rs->cfaRegOffset, 0);
282 GTEST_LOG_(INFO) << "ArmExidxTest009: end.";
283 }
284
285 /**
286 * @tc.name: ArmExidxTest010
287 * @tc.desc: test Step
288 * @tc.type: FUNC
289 */
290 HWTEST_F(ArmExidxTest, ArmExidxTest010, TestSize.Level2)
291 {
292 //10100nnn Pop r4-r[4+nnn]
293 GTEST_LOG_(INFO) << "ArmExidxTest010: start.";
294 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
295 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
296 ArmExidx exidx(memory);
297 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
298 uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100a7b0};
299 uintptr_t entryOffset = (uintptr_t)(&values[0]);
300 ASSERT_TRUE(exidx.Step(entryOffset, rs));
301 ASSERT_EQ(rs->cfaReg, REG_SP);
302 ASSERT_EQ(rs->cfaRegOffset, 32);
303 ASSERT_EQ(rs->locs[0].type, REG_LOC_MEM_OFFSET);
304 ASSERT_EQ(rs->locs[0].val, -20);
305 ASSERT_EQ(rs->locs[1].type, REG_LOC_MEM_OFFSET);
306 ASSERT_EQ(rs->locs[1].val, -4);
307 GTEST_LOG_(INFO) << "ArmExidxTest010: end.";
308 }
309
310 /**
311 * @tc.name: ArmExidxTest011
312 * @tc.desc: test Step
313 * @tc.type: FUNC
314 */
315 HWTEST_F(ArmExidxTest, ArmExidxTest011, TestSize.Level2)
316 {
317 // 10101nnn Pop r4-r[4+nnn], r14
318 GTEST_LOG_(INFO) << "ArmExidxTest011: start.";
319 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
320 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
321 ArmExidx exidx(memory);
322 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
323 uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100afb0};
324 uintptr_t entryOffset = (uintptr_t)(&values[0]);
325 ASSERT_TRUE(exidx.Step(entryOffset, rs));
326 ASSERT_EQ(rs->cfaReg, REG_SP);
327 ASSERT_EQ(rs->cfaRegOffset, 36);
328 ASSERT_EQ(rs->locs[0].type, REG_LOC_MEM_OFFSET);
329 ASSERT_EQ(rs->locs[0].val, -24);
330 ASSERT_EQ(rs->locs[1].type, REG_LOC_MEM_OFFSET);
331 ASSERT_EQ(rs->locs[1].val, -8);
332 ASSERT_EQ(rs->locs[4].type, REG_LOC_MEM_OFFSET);
333 ASSERT_EQ(rs->locs[4].val, -4);
334 GTEST_LOG_(INFO) << "ArmExidxTest011: end.";
335 }
336
337 /**
338 * @tc.name: ArmExidxTest012
339 * @tc.desc: test Step
340 * @tc.type: FUNC
341 */
342 HWTEST_F(ArmExidxTest, ArmExidxTest012, TestSize.Level2)
343 {
344 // 10110000 Finish
345 GTEST_LOG_(INFO) << "ArmExidxTest012: start.";
346 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
347 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
348 ArmExidx exidx(memory);
349 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
350 uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100b0b0};
351 uintptr_t entryOffset = (uintptr_t)(&values[0]);
352 ASSERT_TRUE(exidx.Step(entryOffset, rs));
353 ASSERT_EQ(rs->cfaReg, REG_SP);
354 ASSERT_EQ(rs->cfaRegOffset, 0);
355 ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_ARM_EXIDX_FINISH);
356 GTEST_LOG_(INFO) << "ArmExidxTest012: end.";
357 }
358
359 /**
360 * @tc.name: ArmExidxTest013
361 * @tc.desc: test Step
362 * @tc.type: FUNC
363 */
364 HWTEST_F(ArmExidxTest, ArmExidxTest013, TestSize.Level2)
365 {
366 // 10110001 00000000: Spare
367 GTEST_LOG_(INFO) << "ArmExidxTest013: start.";
368 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
369 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
370 ArmExidx exidx(memory);
371 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
372 uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100b100};
373 uintptr_t entryOffset = (uintptr_t)(&values[0]);
374 ASSERT_TRUE(exidx.Step(entryOffset, rs));
375 ASSERT_EQ(rs->cfaReg, REG_SP);
376 ASSERT_EQ(rs->cfaRegOffset, 0);
377 ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_ARM_EXIDX_SPARE);
378
379 // 10110001 xxxxyyyy spare
380
381 GTEST_LOG_(INFO) << "ArmExidxTest013: end.";
382 }
383
384 /**
385 * @tc.name: ArmExidxTest014
386 * @tc.desc: test Step
387 * @tc.type: FUNC
388 */
389 HWTEST_F(ArmExidxTest, ArmExidxTest014, TestSize.Level2)
390 {
391 // 10110001 0000iiii(i not all 0) Pop integer registers under mask{r3, r2,r1,r0}
392 GTEST_LOG_(INFO) << "ArmExidxTest014: start.";
393 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
394 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
395 ArmExidx exidx(memory);
396 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
397 uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100b108};
398 uintptr_t entryOffset = (uintptr_t)(&values[0]);
399 ASSERT_TRUE(exidx.Step(entryOffset, rs));
400 ASSERT_EQ(rs->cfaReg, REG_SP);
401 ASSERT_EQ(rs->cfaRegOffset, 4);
402 GTEST_LOG_(INFO) << "ArmExidxTest014: end.";
403 }
404
405 /**
406 * @tc.name: ArmExidxTest015
407 * @tc.desc: test Step
408 * @tc.type: FUNC
409 */
410 HWTEST_F(ArmExidxTest, ArmExidxTest015, TestSize.Level2)
411 {
412 // 10110010 uleb128 vsp = vsp + 0x204 + (uleb128 << 2)
413 GTEST_LOG_(INFO) << "ArmExidxTest015: start.";
414 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
415 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
416 ArmExidx exidx(memory);
417 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
418 uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100b208};
419 uintptr_t entryOffset = (uintptr_t)(&values[0]);
420 ASSERT_TRUE(exidx.Step(entryOffset, rs));
421 ASSERT_EQ(rs->cfaReg, REG_SP);
422 ASSERT_EQ(rs->cfaRegOffset, 0x224);
423 GTEST_LOG_(INFO) << "ArmExidxTest015: end.";
424 }
425
426 /**
427 * @tc.name: ArmExidxTest016
428 * @tc.desc: test Step
429 * @tc.type: FUNC
430 */
431 HWTEST_F(ArmExidxTest, ArmExidxTest016, TestSize.Level2)
432 {
433 // 10110011 sssscccc: Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved by FSTMFDX
434 GTEST_LOG_(INFO) << "ArmExidxTest016: start.";
435 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
436 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
437 ArmExidx exidx(memory);
438 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
439 uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100b302};
440 uintptr_t entryOffset = (uintptr_t)(&values[0]);
441 ASSERT_TRUE(exidx.Step(entryOffset, rs));
442 ASSERT_EQ(rs->cfaReg, REG_SP);
443 ASSERT_EQ(rs->cfaRegOffset, 0x1c);
444 GTEST_LOG_(INFO) << "ArmExidxTest016: end.";
445 }
446
447
448 /**
449 * @tc.name: ArmExidxTest017
450 * @tc.desc: test Step
451 * @tc.type: FUNC
452 */
453 HWTEST_F(ArmExidxTest, ArmExidxTest017, TestSize.Level2)
454 {
455 // 10111nnn: VFP double-precision registers D[8]-D[8+nnn] saved by FSTMFDX
456 GTEST_LOG_(INFO) << "ArmExidxTest016: start.";
457 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
458 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
459 ArmExidx exidx(memory);
460 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
461 uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100b9b0};
462 uintptr_t entryOffset = (uintptr_t)(&values[0]);
463 ASSERT_TRUE(exidx.Step(entryOffset, rs));
464 ASSERT_EQ(rs->cfaReg, REG_SP);
465 ASSERT_EQ(rs->cfaRegOffset, 0x14);
466 GTEST_LOG_(INFO) << "ArmExidxTest016: end.";
467 }
468
469 /**
470 * @tc.name: ArmExidxTest018
471 * @tc.desc: test Step
472 * @tc.type: FUNC
473 */
474 HWTEST_F(ArmExidxTest, ArmExidxTest018, TestSize.Level2)
475 {
476 /* 11000nnn (nnn != 6,7) : Intel Wireless MMX pop wR[10]-wR[10+nnn]
477 * 11000110 sssscccc : Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc]
478 * 11000111 00000000 : spare
479 * 11000111 0000iiii : Intel Wireless MMX pop wCGR register under mask {wCGR3,2,1,0}
480 * 11000111 xxxxyyyy (xxxx!=0000): spare
481 */
482 GTEST_LOG_(INFO) << "ArmExidxTest018: start.";
483 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
484 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
485 ArmExidx exidx(memory);
486 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
487
488
489 // 11000nnn (nnn != 6,7)
490 uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100c1b0};
491 uintptr_t entryOffset = (uintptr_t)(&values[0]);
492 ASSERT_TRUE(exidx.Step(entryOffset, rs));
493 ASSERT_EQ(rs->cfaReg, REG_SP);
494 ASSERT_EQ(rs->cfaRegOffset, 0x10);
495
496 // 11000110 sssscccc
497 values[2] = 0x8100c602;
498 ASSERT_TRUE(exidx.Step(entryOffset, rs));
499 ASSERT_EQ(rs->cfaReg, REG_SP);
500 ASSERT_EQ(rs->cfaRegOffset, 0x18);
501
502 // 11000111 00000000 : spare
503 values[2] = 0x8100c700;
504 ASSERT_TRUE(exidx.Step(entryOffset, rs));
505 ASSERT_EQ(rs->cfaReg, REG_SP);
506 ASSERT_EQ(rs->cfaRegOffset, 0);
507 ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_ARM_EXIDX_SPARE);
508
509 // 11000111 0000iiii : Intel Wireless MMX pop wCGR register under mask {wCGR3,2,1,0}
510 values[2] = 0x8100c70f;
511 ASSERT_TRUE(exidx.Step(entryOffset, rs));
512 ASSERT_EQ(rs->cfaReg, REG_SP);
513 ASSERT_EQ(rs->cfaRegOffset, 0x10);
514
515 //11000111 xxxxyyyy (xxxx!=0000): spare
516 values[2] = 0x8100c71f;
517 ASSERT_TRUE(exidx.Step(entryOffset, rs));
518 ASSERT_EQ(rs->cfaReg, REG_SP);
519 ASSERT_EQ(rs->cfaRegOffset, 0);
520 ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_ARM_EXIDX_SPARE);
521 GTEST_LOG_(INFO) << "ArmExidxTest018: end.";
522 }
523
524 /**
525 * @tc.name: ArmExidxTest019
526 * @tc.desc: test Step
527 * @tc.type: FUNC
528 */
529 HWTEST_F(ArmExidxTest, ArmExidxTest019, TestSize.Level2)
530 {
531 /**
532 * 11001000 sssscccc Pop VFP double precision registers
533 * D[16+ssss]-D[16+ssss+cccc] saved (as if) by VPUSH (see remarks d,e)
534 * 11001001 sssscccc Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved (as if) by VPUSH (see remark d)
535 * 11001yyy(yyy != 000, 001) Spare
536 */
537 GTEST_LOG_(INFO) << "ArmExidxTest019: start.";
538 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
539 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
540 ArmExidx exidx(memory);
541 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
542
543 // 11001000 sssscccc
544 uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100c801};
545 uintptr_t entryOffset = (uintptr_t)(&values[0]);
546 ASSERT_TRUE(exidx.Step(entryOffset, rs));
547 ASSERT_EQ(rs->cfaReg, REG_SP);
548 ASSERT_EQ(rs->cfaRegOffset, 0x10);
549
550 // 11001001 sssscccc
551 values[2] = 0x8100c902;
552 ASSERT_TRUE(exidx.Step(entryOffset, rs));
553 ASSERT_EQ(rs->cfaReg, REG_SP);
554 ASSERT_EQ(rs->cfaRegOffset, 0x18);
555
556 // 11001yyy(yyy != 000, 001) Spare
557 values[2] = 0x8100cbb0;
558 ASSERT_TRUE(exidx.Step(entryOffset, rs));
559 ASSERT_EQ(rs->cfaReg, REG_SP);
560 ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_ARM_EXIDX_SPARE);
561 GTEST_LOG_(INFO) << "ArmExidxTest019: end.";
562 }
563
564 /**
565 * @tc.name: ArmExidxTest020
566 * @tc.desc: test Step
567 * @tc.type: FUNC
568 */
569 HWTEST_F(ArmExidxTest, ArmExidxTest020, TestSize.Level2)
570 {
571 GTEST_LOG_(INFO) << "ArmExidxTest020: start.";
572 std::shared_ptr<DfxAccessorsLocal> acc = std::make_shared<DfxAccessorsLocal>();
573 std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(acc);
574 ArmExidx exidx(memory);
575 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>();
576
577 // 11010nnn Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by VPUSH (seeremark d)
578 uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100d1b0};
579 uintptr_t entryOffset = (uintptr_t)(&values[0]);
580 ASSERT_TRUE(exidx.Step(entryOffset, rs));
581 ASSERT_EQ(rs->cfaReg, REG_SP);
582 ASSERT_EQ(rs->cfaRegOffset, 0x10);
583
584 // 11xxxyyy: Spare (xxx != 000, 001, 010)
585 values[2] = 0x8100f8b0;
586 ASSERT_TRUE(exidx.Step(entryOffset, rs));
587 ASSERT_EQ(rs->cfaReg, REG_SP);
588 ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_ARM_EXIDX_SPARE);
589 GTEST_LOG_(INFO) << "ArmExidxTest020: end.";
590 }
591 } // namespace HiviewDFX
592 } // namepsace OHOS
593 #endif
594