• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "exidx_entry_parser.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<DfxMemory> memory = std::make_shared<DfxMemory>(UNWIND_TYPE_LOCAL);
65     ExidxEntryParser exidx(memory);
66     uint32_t values[] = {0x1, 0x1};
67     uintptr_t entryOffset = (uintptr_t)(&values[0]);
68     // cant unwind
69     ASSERT_FALSE(exidx.ExtractEntryData(entryOffset));
70     ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_CANT_UNWIND);
71     GTEST_LOG_(INFO) << "ArmExidxTest001: end.";
72 }
73 /**
74  * @tc.name: ArmExidxTest002
75  * @tc.desc: test ExtractEntryData inline compact model
76  * @tc.type: FUNC
77  */
78 HWTEST_F(ArmExidxTest, ArmExidxTest002, TestSize.Level0)
79 {
80     GTEST_LOG_(INFO) << "ArmExidxTest002: start.";
81     std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(UNWIND_TYPE_LOCAL);
82     ExidxEntryParser exidx(memory);
83     // inline compact model
84     uint32_t values[] = {0x7fff2340, 0x80c0c0c0};
85     uintptr_t entryOffset = (uintptr_t)(&values[0]);
86     ASSERT_TRUE(exidx.ExtractEntryData(entryOffset));
87     std::deque<uint8_t> data = exidx.ops_;
88     ASSERT_EQ(data.size(), 4U);
89     ASSERT_EQ(data[0], 0xc0U);
90     ASSERT_EQ(data[1], 0xc0U);
91     ASSERT_EQ(data[2], 0xc0U);
92     ASSERT_EQ(data[3], 0xb0U);
93     GTEST_LOG_(INFO) << "ArmExidxTest002: end.";
94 }
95 /**
96  * @tc.name: ArmExidxTest003
97  * @tc.desc: test ExtractEntryData highest bit is zero, point to .ARM.extab data
98  * @tc.type: FUNC
99  */
100 HWTEST_F(ArmExidxTest, ArmExidxTest003, TestSize.Level2)
101 {
102     GTEST_LOG_(INFO) << "ArmExidxTest003: start.";
103     std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(UNWIND_TYPE_LOCAL);
104     ExidxEntryParser exidx(memory);
105 
106     //personality 0
107     uint32_t values0[] = {0x7fff2340, 0x00001111, 0x80c0c0c0};
108     uintptr_t entryOffset = (uintptr_t)(&values0[0]);
109     ASSERT_TRUE(exidx.ExtractEntryData(entryOffset));
110     std::deque<uint8_t> data = exidx.ops_;
111     ASSERT_EQ(data.size(), 4U);
112     ASSERT_EQ(data[0], 0xc0U);
113     ASSERT_EQ(data[1], 0xc0U);
114     ASSERT_EQ(data[2], 0xc0U);
115     ASSERT_EQ(data[3], 0xb0U);
116 
117     //personality 1
118     uint32_t values1[] = {0x7fff2340, 0x00001111, 0x8100c0c0};
119     entryOffset = (uintptr_t)(&values1[0]);
120     ASSERT_TRUE(exidx.ExtractEntryData(entryOffset));
121     data = exidx.ops_;
122     ASSERT_EQ(data.size(), 3U);
123     ASSERT_EQ(data[0], 0xc0U);
124     ASSERT_EQ(data[1], 0xc0U);
125     ASSERT_EQ(data[2], 0xb0U);
126 
127     //personality 2 MOREWORD 0
128     uint32_t values2[] = {0x7fff2340, 0x00001111, 0x8200c0c0};
129     entryOffset = (uintptr_t)(&values2[0]);
130     ASSERT_TRUE(exidx.ExtractEntryData(entryOffset));
131     data = exidx.ops_;
132     ASSERT_EQ(data.size(), 3U);
133     ASSERT_EQ(data[0], 0xc0U);
134     ASSERT_EQ(data[1], 0xc0U);
135     ASSERT_EQ(data[2], 0xb0U);
136 
137     //personality 2 MOREWORD 1
138     uint32_t values2m[] = {0x7fff2340, 0x00001111, 0x8201c0c0, 0xd0e0f0b0};
139     entryOffset = (uintptr_t)(&values2m[0]);
140     ASSERT_TRUE(exidx.ExtractEntryData(entryOffset));
141     data = exidx.ops_;
142     ASSERT_EQ(data.size(), 6U);
143     ASSERT_EQ(data[0], 0xc0U);
144     ASSERT_EQ(data[1], 0xc0U);
145     ASSERT_EQ(data[2], 0xd0U);
146     ASSERT_EQ(data[3], 0xe0U);
147     ASSERT_EQ(data[4], 0xf0U);
148     ASSERT_EQ(data[5], 0xb0U);
149     GTEST_LOG_(INFO) << "ArmExidxTest003: end.";
150 }
151 /**
152  * @tc.name: ArmExidxTest004
153  * @tc.desc: test Eval
154  * @tc.type: FUNC
155  */
156 HWTEST_F(ArmExidxTest, ArmExidxTest004, TestSize.Level2)
157 {
158     // 00xxxxxx: vsp = vsp + (xxxxxx << 2) + 4
159     GTEST_LOG_(INFO) << "ArmExidxTest004: start.";
160     std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(UNWIND_TYPE_LOCAL);
161     ExidxEntryParser exidx(memory);
162     uint32_t values[] = {0x7fff2340, 0x00001111, 0x810010b0};
163     uintptr_t entryOffset = (uintptr_t)(&values[0]);
164     exidx.rsState_ = std::make_shared<RegLocState>();
165     ASSERT_TRUE(exidx.Eval(entryOffset));
166     exidx.FlushInstr();
167     ASSERT_EQ(exidx.rsState_->cfaRegOffset, 0x44);
168     GTEST_LOG_(INFO) << "ArmExidxTest004: end.";
169 }
170 
171 /**
172  * @tc.name: ArmExidxTest005
173  * @tc.desc: test Eval
174  * @tc.type: FUNC
175  */
176 HWTEST_F(ArmExidxTest, ArmExidxTest005, TestSize.Level2)
177 {
178     // 01xxxxxx: vsp = vsp - (xxxxxx << 2) - 4
179     GTEST_LOG_(INFO) << "ArmExidxTest005: start.";
180     std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(UNWIND_TYPE_LOCAL);
181     ExidxEntryParser exidx(memory);
182     uint32_t values[] = {0x7fff2340, 0x00001111, 0x810041b0};
183     uintptr_t entryOffset = (uintptr_t)(&values[0]);
184     exidx.rsState_ = std::make_shared<RegLocState>();
185     ASSERT_TRUE(exidx.Eval(entryOffset));
186     exidx.FlushInstr();
187     ASSERT_EQ(exidx.rsState_->cfaRegOffset, -8);
188     GTEST_LOG_(INFO) << "ArmExidxTest005: end.";
189 }
190 
191 /**
192  * @tc.name: ArmExidxTest006
193  * @tc.desc: test Eval
194  * @tc.type: FUNC
195  */
196 HWTEST_F(ArmExidxTest, ArmExidxTest006, TestSize.Level2)
197 {
198     // 10000000 00000000: Refuse to unwind
199     GTEST_LOG_(INFO) << "ArmExidxTest006: start.";
200     std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(UNWIND_TYPE_LOCAL);
201     ExidxEntryParser exidx(memory);
202     uint32_t values[] = {0x7fff2340, 0x00001111, 0x81008000};
203     uintptr_t entryOffset = (uintptr_t)(&values[0]);
204     ASSERT_TRUE(exidx.Eval(entryOffset));
205     ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_CANT_UNWIND);
206     GTEST_LOG_(INFO) << "ArmExidxTest006: end.";
207 }
208 
209 /**
210  * @tc.name: ArmExidxTest007
211  * @tc.desc: test Eval
212  * @tc.type: FUNC
213  */
214 HWTEST_F(ArmExidxTest, ArmExidxTest007, TestSize.Level2)
215 {
216     // 1000iiii iiiiiiii (i not all 0)
217     GTEST_LOG_(INFO) << "ArmExidxTest007: start.";
218     std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(UNWIND_TYPE_LOCAL);
219     ExidxEntryParser exidx(memory);
220     uint32_t values[] = {0x7fff2340, 0x00001111, 0x81008811};
221     uintptr_t entryOffset = (uintptr_t)(&values[0]);
222     exidx.rsState_ = std::make_shared<RegLocState>();
223     ASSERT_TRUE(exidx.Eval(entryOffset));
224     exidx.FlushInstr();
225     ASSERT_EQ(exidx.rsState_->cfaReg, REG_SP);
226     ASSERT_EQ(exidx.rsState_->cfaRegOffset, 12);
227     ASSERT_EQ(exidx.rsState_->locs[3].type, REG_LOC_MEM_OFFSET);
228     ASSERT_EQ(exidx.rsState_->locs[3].val, -4);
229     GTEST_LOG_(INFO) << "ArmExidxTest007: end.";
230 }
231 
232 /**
233  * @tc.name: ArmExidxTest008
234  * @tc.desc: test Eval
235  * @tc.type: FUNC
236  */
237 HWTEST_F(ArmExidxTest, ArmExidxTest008, TestSize.Level2)
238 {
239     // 10011101 || 10011111
240     GTEST_LOG_(INFO) << "ArmExidxTest008: start.";
241     std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(UNWIND_TYPE_LOCAL);
242     ExidxEntryParser exidx(memory);
243     uint32_t values[] = {0x7fff2340, 0x00001111, 0x81009db0};
244     uintptr_t entryOffset = (uintptr_t)(&values[0]);
245     ASSERT_TRUE(exidx.Eval(entryOffset));
246     ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_RESERVED_VALUE);
247 
248     values[2] = 0x81009fb0;
249     ASSERT_TRUE(exidx.Eval(entryOffset));
250     ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_RESERVED_VALUE);
251     GTEST_LOG_(INFO) << "ArmExidxTest008: end.";
252 }
253 
254 /**
255  * @tc.name: ArmExidxTest009
256  * @tc.desc: test Eval
257  * @tc.type: FUNC
258  */
259 HWTEST_F(ArmExidxTest, ArmExidxTest009, TestSize.Level2)
260 {
261     GTEST_LOG_(INFO) << "ArmExidxTest009: start.";
262     std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(UNWIND_TYPE_LOCAL);
263     ExidxEntryParser exidx(memory);
264     uint32_t values[] = {0x7fff2340, 0x00001111, 0x81009bb0};
265     uintptr_t entryOffset = (uintptr_t)(&values[0]);
266     exidx.rsState_ = std::make_shared<RegLocState>();
267     ASSERT_TRUE(exidx.Eval(entryOffset));
268     exidx.FlushInstr();
269     // 1001nnnn(nnnn != 13, 15)
270     ASSERT_EQ(exidx.rsState_->cfaReg, 11U);
271     ASSERT_EQ(exidx.rsState_->cfaRegOffset, 0);
272     GTEST_LOG_(INFO) << "ArmExidxTest009: end.";
273 }
274 
275 /**
276  * @tc.name: ArmExidxTest010
277  * @tc.desc: test Eval
278  * @tc.type: FUNC
279  */
280 HWTEST_F(ArmExidxTest, ArmExidxTest010, TestSize.Level2)
281 {
282     //10100nnn Pop r4-r[4+nnn]
283     GTEST_LOG_(INFO) << "ArmExidxTest010: start.";
284     std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(UNWIND_TYPE_LOCAL);
285     ExidxEntryParser exidx(memory);
286     uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100a7b0};
287     uintptr_t entryOffset = (uintptr_t)(&values[0]);
288     exidx.rsState_ = std::make_shared<RegLocState>();
289     ASSERT_TRUE(exidx.Eval(entryOffset));
290     exidx.FlushInstr();
291     ASSERT_EQ(exidx.rsState_->cfaReg, REG_SP);
292     ASSERT_EQ(exidx.rsState_->cfaRegOffset, 32);
293     ASSERT_EQ(exidx.rsState_->locs[0].type, REG_LOC_MEM_OFFSET);
294     ASSERT_EQ(exidx.rsState_->locs[0].val, -20);
295     ASSERT_EQ(exidx.rsState_->locs[1].type, REG_LOC_MEM_OFFSET);
296     ASSERT_EQ(exidx.rsState_->locs[1].val, -4);
297     GTEST_LOG_(INFO) << "ArmExidxTest010: end.";
298 }
299 
300 /**
301  * @tc.name: ArmExidxTest011
302  * @tc.desc: test Eval
303  * @tc.type: FUNC
304  */
305 HWTEST_F(ArmExidxTest, ArmExidxTest011, TestSize.Level2)
306 {
307     // 10101nnn Pop r4-r[4+nnn], r14
308     GTEST_LOG_(INFO) << "ArmExidxTest011: start.";
309     std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(UNWIND_TYPE_LOCAL);
310     ExidxEntryParser exidx(memory);
311 
312     uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100afb0};
313     uintptr_t entryOffset = (uintptr_t)(&values[0]);
314     exidx.rsState_ = std::make_shared<RegLocState>();
315     ASSERT_TRUE(exidx.Eval(entryOffset));
316     exidx.FlushInstr();
317     ASSERT_EQ(exidx.rsState_->cfaReg, REG_SP);
318     ASSERT_EQ(exidx.rsState_->cfaRegOffset, 36);
319     ASSERT_EQ(exidx.rsState_->locs[0].type, REG_LOC_MEM_OFFSET);
320     ASSERT_EQ(exidx.rsState_->locs[0].val, -24);
321     ASSERT_EQ(exidx.rsState_->locs[1].type, REG_LOC_MEM_OFFSET);
322     ASSERT_EQ(exidx.rsState_->locs[1].val, -8);
323     ASSERT_EQ(exidx.rsState_->locs[4].type, REG_LOC_MEM_OFFSET);
324     ASSERT_EQ(exidx.rsState_->locs[4].val, -4);
325     GTEST_LOG_(INFO) << "ArmExidxTest011: end.";
326 }
327 
328 /**
329  * @tc.name: ArmExidxTest012
330  * @tc.desc: test Eval
331  * @tc.type: FUNC
332  */
333 HWTEST_F(ArmExidxTest, ArmExidxTest012, TestSize.Level2)
334 {
335     // 10110000 Finish
336     GTEST_LOG_(INFO) << "ArmExidxTest012: start.";
337     std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(UNWIND_TYPE_LOCAL);
338     ExidxEntryParser exidx(memory);
339 
340     uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100b0b0};
341     uintptr_t entryOffset = (uintptr_t)(&values[0]);
342     exidx.rsState_ = std::make_shared<RegLocState>();
343     ASSERT_TRUE(exidx.Eval(entryOffset));
344     exidx.FlushInstr();
345     ASSERT_EQ(exidx.rsState_->cfaReg, REG_SP);
346     ASSERT_EQ(exidx.rsState_->cfaRegOffset, 0);
347     ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_ARM_EXIDX_FINISH);
348     GTEST_LOG_(INFO) << "ArmExidxTest012: end.";
349 }
350 
351 /**
352  * @tc.name: ArmExidxTest013
353  * @tc.desc: test Eval
354  * @tc.type: FUNC
355  */
356 HWTEST_F(ArmExidxTest, ArmExidxTest013, TestSize.Level2)
357 {
358     // 10110001 00000000: Spare
359     GTEST_LOG_(INFO) << "ArmExidxTest013: start.";
360     std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(UNWIND_TYPE_LOCAL);
361     ExidxEntryParser exidx(memory);
362 
363     uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100b100};
364     uintptr_t entryOffset = (uintptr_t)(&values[0]);
365     exidx.rsState_ = std::make_shared<RegLocState>();
366     ASSERT_TRUE(exidx.Eval(entryOffset));
367     exidx.FlushInstr();
368     ASSERT_EQ(exidx.rsState_->cfaReg, REG_SP);
369     ASSERT_EQ(exidx.rsState_->cfaRegOffset, 0);
370     ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_ARM_EXIDX_SPARE);
371 
372     // 10110001 xxxxyyyy spare
373 
374     GTEST_LOG_(INFO) << "ArmExidxTest013: end.";
375 }
376 
377 /**
378  * @tc.name: ArmExidxTest014
379  * @tc.desc: test Eval
380  * @tc.type: FUNC
381  */
382 HWTEST_F(ArmExidxTest, ArmExidxTest014, TestSize.Level2)
383 {
384     // 10110001 0000iiii(i not all 0) Pop integer registers under mask{r3, r2,r1,r0}
385     GTEST_LOG_(INFO) << "ArmExidxTest014: start.";
386     std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(UNWIND_TYPE_LOCAL);
387     ExidxEntryParser exidx(memory);
388 
389     uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100b108};
390     uintptr_t entryOffset = (uintptr_t)(&values[0]);
391     exidx.rsState_ = std::make_shared<RegLocState>();
392     ASSERT_TRUE(exidx.Eval(entryOffset));
393     exidx.FlushInstr();
394     ASSERT_EQ(exidx.rsState_->cfaReg, REG_SP);
395     ASSERT_EQ(exidx.rsState_->cfaRegOffset, 4);
396     GTEST_LOG_(INFO) << "ArmExidxTest014: end.";
397 }
398 
399 /**
400  * @tc.name: ArmExidxTest015
401  * @tc.desc: test Eval
402  * @tc.type: FUNC
403  */
404 HWTEST_F(ArmExidxTest, ArmExidxTest015, TestSize.Level2)
405 {
406     // 10110010 uleb128 vsp = vsp + 0x204 + (uleb128 << 2)
407     GTEST_LOG_(INFO) << "ArmExidxTest015: start.";
408     std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(UNWIND_TYPE_LOCAL);
409     ExidxEntryParser exidx(memory);
410 
411     uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100b208};
412     uintptr_t entryOffset = (uintptr_t)(&values[0]);
413     exidx.rsState_ = std::make_shared<RegLocState>();
414     ASSERT_TRUE(exidx.Eval(entryOffset));
415     exidx.FlushInstr();
416     ASSERT_EQ(exidx.rsState_->cfaReg, REG_SP);
417     ASSERT_EQ(exidx.rsState_->cfaRegOffset, 0x224);
418     GTEST_LOG_(INFO) << "ArmExidxTest015: end.";
419 }
420 
421 /**
422  * @tc.name: ArmExidxTest016
423  * @tc.desc: test Eval
424  * @tc.type: FUNC
425  */
426 HWTEST_F(ArmExidxTest, ArmExidxTest016, TestSize.Level2)
427 {
428     // 10110011 sssscccc: Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved by FSTMFDX
429     GTEST_LOG_(INFO) << "ArmExidxTest016: start.";
430     std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(UNWIND_TYPE_LOCAL);
431     ExidxEntryParser exidx(memory);
432 
433     uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100b302};
434     uintptr_t entryOffset = (uintptr_t)(&values[0]);
435     exidx.rsState_ = std::make_shared<RegLocState>();
436     ASSERT_TRUE(exidx.Eval(entryOffset));
437     exidx.FlushInstr();
438     ASSERT_EQ(exidx.rsState_->cfaReg, REG_SP);
439     ASSERT_EQ(exidx.rsState_->cfaRegOffset, 0x1c);
440     GTEST_LOG_(INFO) << "ArmExidxTest016: end.";
441 }
442 
443 
444 /**
445  * @tc.name: ArmExidxTest017
446  * @tc.desc: test Eval
447  * @tc.type: FUNC
448  */
449 HWTEST_F(ArmExidxTest, ArmExidxTest017, TestSize.Level2)
450 {
451     // 10111nnn:  VFP double-precision registers D[8]-D[8+nnn] saved by FSTMFDX
452     GTEST_LOG_(INFO) << "ArmExidxTest016: start.";
453     std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(UNWIND_TYPE_LOCAL);
454     ExidxEntryParser exidx(memory);
455 
456     uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100b9b0};
457     uintptr_t entryOffset = (uintptr_t)(&values[0]);
458     exidx.rsState_ = std::make_shared<RegLocState>();
459     ASSERT_TRUE(exidx.Eval(entryOffset));
460     exidx.FlushInstr();
461     ASSERT_EQ(exidx.rsState_->cfaReg, REG_SP);
462     ASSERT_EQ(exidx.rsState_->cfaRegOffset, 0x14);
463     GTEST_LOG_(INFO) << "ArmExidxTest016: end.";
464 }
465 
466 /**
467  * @tc.name: ArmExidxTest018
468  * @tc.desc: test Eval
469  * @tc.type: FUNC
470  */
471 HWTEST_F(ArmExidxTest, ArmExidxTest018, TestSize.Level2)
472 {
473     /* 11000nnn (nnn != 6,7) : Intel Wireless MMX pop wR[10]-wR[10+nnn]
474     *  11000110 sssscccc : Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc]
475     *  11000111 00000000 : spare
476     *  11000111 0000iiii : Intel Wireless MMX pop wCGR register under mask {wCGR3,2,1,0}
477     *  11000111 xxxxyyyy (xxxx!=0000): spare
478     */
479     GTEST_LOG_(INFO) << "ArmExidxTest018: start.";
480     std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(UNWIND_TYPE_LOCAL);
481     ExidxEntryParser exidx(memory);
482     // 11000nnn (nnn != 6,7)
483     uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100c1b0};
484     uintptr_t entryOffset = (uintptr_t)(&values[0]);
485     exidx.rsState_ = std::make_shared<RegLocState>();
486     ASSERT_TRUE(exidx.Eval(entryOffset));
487     exidx.FlushInstr();
488     ASSERT_EQ(exidx.rsState_->cfaReg, REG_SP);
489     ASSERT_EQ(exidx.rsState_->cfaRegOffset, 0x10);
490 
491     // 11000110 sssscccc
492     values[2] = 0x8100c602;
493     ASSERT_TRUE(exidx.Eval(entryOffset));
494     exidx.FlushInstr();
495     ASSERT_EQ(exidx.rsState_->cfaReg, REG_SP);
496     ASSERT_EQ(exidx.rsState_->cfaRegOffset, 0x18);
497 
498     // 11000111 00000000 : spare
499     values[2] = 0x8100c700;
500     ASSERT_TRUE(exidx.Eval(entryOffset));
501     exidx.FlushInstr();
502     ASSERT_EQ(exidx.rsState_->cfaReg, REG_SP);
503     ASSERT_EQ(exidx.rsState_->cfaRegOffset, 0);
504     ASSERT_EQ(exidx.GetLastErrorCode(), UNW_ERROR_ARM_EXIDX_SPARE);
505 
506     // 11000111 0000iiii : Intel Wireless MMX pop wCGR register under mask {wCGR3,2,1,0}
507     values[2] = 0x8100c70f;
508     ASSERT_TRUE(exidx.Eval(entryOffset));
509     exidx.FlushInstr();
510     ASSERT_EQ(exidx.rsState_->cfaReg, REG_SP);
511     ASSERT_EQ(exidx.rsState_->cfaRegOffset, 0x10);
512 
513     //11000111 xxxxyyyy (xxxx!=0000): spare
514     values[2] = 0x8100c71f;
515     ASSERT_TRUE(exidx.Eval(entryOffset));
516     exidx.FlushInstr();
517     ASSERT_EQ(exidx.rsState_->cfaReg, REG_SP);
518     ASSERT_EQ(exidx.rsState_->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 Eval
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<DfxMemory> memory = std::make_shared<DfxMemory>(UNWIND_TYPE_LOCAL);
538     ExidxEntryParser exidx(memory);
539     // 11001000 sssscccc
540     uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100c801};
541     uintptr_t entryOffset = (uintptr_t)(&values[0]);
542     exidx.rsState_ = std::make_shared<RegLocState>();
543     ASSERT_TRUE(exidx.Eval(entryOffset));
544     exidx.FlushInstr();
545     ASSERT_EQ(exidx.rsState_->cfaReg, REG_SP);
546     ASSERT_EQ(exidx.rsState_->cfaRegOffset, 0x10);
547 
548     // 11001001 sssscccc
549     values[2] = 0x8100c902;
550     ASSERT_TRUE(exidx.Eval(entryOffset));
551     exidx.FlushInstr();
552     ASSERT_EQ(exidx.rsState_->cfaReg, REG_SP);
553     ASSERT_EQ(exidx.rsState_->cfaRegOffset, 0x18);
554 
555     // 11001yyy(yyy != 000, 001) Spare
556     values[2] = 0x8100cbb0;
557     ASSERT_TRUE(exidx.Eval(entryOffset));
558     exidx.FlushInstr();
559     ASSERT_EQ(exidx.rsState_->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 Eval
567  * @tc.type: FUNC
568  */
569 HWTEST_F(ArmExidxTest, ArmExidxTest020, TestSize.Level2)
570 {
571     GTEST_LOG_(INFO) << "ArmExidxTest020: start.";
572     std::shared_ptr<DfxMemory> memory = std::make_shared<DfxMemory>(UNWIND_TYPE_LOCAL);
573     ExidxEntryParser exidx(memory);
574     // 11010nnn Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by VPUSH (seeremark d)
575     uint32_t values[] = {0x7fff2340, 0x00001111, 0x8100d1b0};
576     uintptr_t entryOffset = (uintptr_t)(&values[0]);
577     exidx.rsState_ = std::make_shared<RegLocState>();
578     ASSERT_TRUE(exidx.Eval(entryOffset));
579     exidx.FlushInstr();
580     ASSERT_EQ(exidx.rsState_->cfaReg, REG_SP);
581     ASSERT_EQ(exidx.rsState_->cfaRegOffset, 0x10);
582 
583     // 11xxxyyy: Spare (xxx != 000, 001, 010)
584     values[2] = 0x8100f8b0;
585     ASSERT_TRUE(exidx.Eval(entryOffset));
586     exidx.FlushInstr();
587     ASSERT_EQ(exidx.rsState_->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