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