• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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