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