1 /*
2 * Copyright (c) 2023-2025 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 <dlfcn.h>
19 #include <securec.h>
20
21 #include <ctime>
22 #include <cstdio>
23 #include <fstream>
24 #include <memory>
25 #include <string>
26 #include <vector>
27
28 #include <fcntl.h>
29 #include <unistd.h>
30
31 #include <sys/stat.h>
32 #include <sys/types.h>
33
34 #include "string_ex.h"
35
36 #include "dfx_define.h"
37 #include "dfx_instructions.h"
38 #include "dfx_log.h"
39 #include "dfx_memory.h"
40 #include "dfx_regs.h"
41 #include "dwarf_cfa_instructions.h"
42 #include "dwarf_define.h"
43 #include "dwarf_op.h"
44 #include "dwarf_entry_parser.h"
45 #include "elf_factory.h"
46 #include "thread_context.h"
47 #include "unwind_arm64_define.h"
48 #include "unwind_context.h"
49
50 using namespace OHOS::HiviewDFX;
51 using namespace testing::ext;
52 using namespace std;
53 #define HEX 16
54 #define STACK_VALUE (-8)
55
56 namespace OHOS {
57 namespace HiviewDFX {
58 class DwarfTest : public testing::Test {
59 public:
TearDownTestCase(void)60 static void TearDownTestCase(void) {}
SetUp()61 void SetUp() {}
TearDown()62 void TearDown() {}
63 };
64
65 class DwarfEntryParserTest : public DwarfEntryParser {
66 public:
DwarfEntryParserTest(std::shared_ptr<DfxMemory> memory)67 explicit DwarfEntryParserTest(std::shared_ptr<DfxMemory> memory) : DwarfEntryParser(memory) {};
~DwarfEntryParserTest()68 ~DwarfEntryParserTest() {};
SearchEntryTest(uintptr_t pc,const UnwindTableInfo & uti,UnwindEntryInfo & uei)69 bool SearchEntryTest(uintptr_t pc, const UnwindTableInfo& uti, UnwindEntryInfo& uei)
70 {
71 return SearchEntry(pc, uti, uei);
72 }
ParseFdeTest(uintptr_t addr,FrameDescEntry & fde)73 bool ParseFdeTest(uintptr_t addr, FrameDescEntry &fde)
74 {
75 return ParseFde(addr, addr, fde);
76 };
77
ParseCieTest(uintptr_t cieAddr,CommonInfoEntry & cieInfo)78 bool ParseCieTest(uintptr_t cieAddr, CommonInfoEntry &cieInfo)
79 {
80 return ParseCie(cieAddr, cieAddr, cieInfo);
81 };
82 };
83
84 struct MemoryArea {
MemoryAreaOHOS::HiviewDFX::MemoryArea85 MemoryArea(uintptr_t addr, std::vector<uint8_t> buffer)
86 {
87 this->addr = addr;
88 this->data = buffer;
89 }
90 uintptr_t addr;
91 std::vector<uint8_t> data;
92 };
93
94 class DfxMemoryTest : public DfxMemory {
95 public:
DfxMemoryTest()96 DfxMemoryTest() {};
~DfxMemoryTest()97 virtual ~DfxMemoryTest() {};
98 size_t Read(uintptr_t& addr, void* val, size_t size, bool incre = false) override;
99 void SetBuffer(uintptr_t addr, std::vector<uint8_t> buffer);
100 void Reset();
101 bool increaseAddr = false;
102
103 private:
104 std::vector<MemoryArea> buffers;
105 };
106
Reset()107 void DfxMemoryTest::Reset()
108 {
109 buffers.clear();
110 }
111
Read(uintptr_t & addr,void * val,size_t size,bool incre)112 size_t DfxMemoryTest::Read(uintptr_t& addr, void* val, size_t size, bool incre)
113 {
114 printf("DfxMemoryTest::Request Read:%" PRIxPTR " size:%zu\n", addr, size);
115 for (const auto& buffer : buffers) {
116 if (addr >= buffer.addr &&
117 addr + size <= buffer.addr + buffer.data.size()) {
118 size_t offset = addr - buffer.addr;
119 auto data = const_cast<uint8_t*>(buffer.data.data());
120 (void)memcpy_s(val, size, data + offset, size);
121 if (increaseAddr) {
122 addr = addr + size;
123 }
124 printf("DfxMemoryTest::Read addr:0x%" PRIxPTR "\n", addr);
125 return size;
126 }
127 }
128 return 0;
129 }
130
SetBuffer(uintptr_t addr,std::vector<uint8_t> buffer)131 void DfxMemoryTest::SetBuffer(uintptr_t addr, std::vector<uint8_t> buffer)
132 {
133 printf("DfxMemoryTest::SetBuffer:%" PRIxPTR " size:%zu\n", addr, buffer.size());
134 buffers.push_back({addr, buffer});
135 }
136
137 class DwarfOpTest : public DwarfOp<uintptr_t> {
138 public:
139 using DwarfOp<uintptr_t>::DwarfOp;
140 bool Test01();
141 bool Test02();
142 bool Test03();
143 bool Test04(std::shared_ptr<DfxMemoryTest> memory);
144 bool Test05(std::shared_ptr<DfxMemoryTest> memory);
145 bool Test06();
146 bool Test07();
147 bool Test08();
148 bool Test09(std::shared_ptr<DfxMemoryTest> memory);
149 bool Test10(std::shared_ptr<DfxMemoryTest> memory);
150 friend class DwarfTest;
151 };
152
Test01()153 bool DwarfOpTest::Test01()
154 {
155 std::shared_ptr<DfxRegs> regs = std::make_shared<DfxRegsArm64>();
156 uintptr_t addr = 0;
157 return Eval(*(regs.get()), 0, addr);
158 }
159
Test02()160 bool DwarfOpTest::Test02()
161 {
162 bool ret = false;
163 const uintptr_t value = 10;
164 StackPush(value);
165 ret = (value == stack_.front());
166 StackReset(0);
167 ret &= (0 == stack_.front());
168 return ret;
169 }
170
Test03()171 bool DwarfOpTest::Test03()
172 {
173 StackReset(0);
174 bool ret = false;
175 const uintptr_t value = 10;
176 StackPush(value);
177 ret = (value == StackPop());
178 ret &= (StackAt(0) == 0);
179 ret &= (StackSize() == 1);
180 return ret;
181 }
182
Test04(std::shared_ptr<DfxMemoryTest> memory)183 bool DwarfOpTest::Test04(std::shared_ptr<DfxMemoryTest> memory)
184 {
185 // OpDerefSize
186 bool ret = false;
187 StackReset(0);
188 std::vector<uint8_t> exprData {
189 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09
190 };
191
192 std::vector<uint8_t> valueData {
193 0x08, // U8
194 0x10, 0x11, // U16
195 0x20, 0x21, 0x22, 0x23, // U32
196 0x31, 0x32, 0x33, 0x34, // U32
197 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, // U64
198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, // U64
199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, // U64
200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, // U64
201 };
202
203 uintptr_t exprPtr = reinterpret_cast<uintptr_t>(exprData.data());
204 uintptr_t valuePtr = reinterpret_cast<uintptr_t>(valueData.data());
205 memory->SetBuffer(valuePtr, valueData);
206 memory->SetBuffer(exprPtr, exprData);
207 printf("Test04 exprPtr:%" PRIxPTR " valuePtr:%" PRIxPTR "\n", exprPtr, valuePtr);
208
209 // u8
210 StackPush(valuePtr);
211 OpDerefSize(exprPtr);
212 uintptr_t value = StackPop();
213 uintptr_t expectedValue = 0x08;
214 ret = (value == expectedValue);
215 printf("Test04-u8 value:%" PRIxPTR " expectedValue:%" PRIxPTR "\n", value, expectedValue);
216
217 // u16
218 valuePtr = valuePtr + sizeof(uint8_t);
219 exprPtr = exprPtr + sizeof(uint8_t);
220 StackPush(valuePtr);
221 OpDerefSize(exprPtr);
222 value = StackPop();
223 expectedValue = 0x1110;
224 ret &= (value == expectedValue);
225 printf("Test04-u16 value:%" PRIxPTR " expectedValue:%" PRIxPTR "\n", value, expectedValue);
226
227 // u32
228 valuePtr = valuePtr + sizeof(uint16_t);
229 exprPtr = exprPtr + sizeof(uint8_t);
230 StackPush(valuePtr);
231 OpDerefSize(exprPtr);
232 value = StackPop();
233 expectedValue = 0x23222120;
234 ret &= (value == expectedValue);
235 printf("Test04-u32-0 value:%" PRIxPTR " expectedValue:%" PRIxPTR "\n", value, expectedValue);
236
237 // u32
238 valuePtr = valuePtr + sizeof(uint32_t);
239 exprPtr = exprPtr + sizeof(uint8_t);
240 StackPush(valuePtr);
241 OpDerefSize(exprPtr);
242 value = StackPop();
243 expectedValue = 0x34333231;
244 ret &= (value == expectedValue);
245 printf("Test04-u32-1 value:%" PRIxPTR " expectedValue:%" PRIxPTR "\n", value, expectedValue);
246
247 // u64
248 valuePtr = valuePtr + sizeof(uint32_t);
249 exprPtr = exprPtr + sizeof(uint8_t);
250 StackPush(valuePtr);
251 OpDerefSize(exprPtr);
252 value = StackPop();
253 expectedValue = 0x4847464544434241;
254 ret &= (value == expectedValue);
255 printf("Test04-u64-0 value:%" PRIxPTR " expectedValue:%" PRIxPTR "\n", value, expectedValue);
256 return ret;
257 }
258
Test05(std::shared_ptr<DfxMemoryTest> memory)259 bool DwarfOpTest::Test05(std::shared_ptr<DfxMemoryTest> memory)
260 {
261 bool ret = false;
262 StackReset(0);
263 memory->Reset();
264 std::vector<uint8_t> valueData {
265 0x31, 0x32, 0x33, 0x34, 0x31, 0x32, 0x33, 0x34,
266 };
267 // OpDeref
268 uintptr_t valuePtr = reinterpret_cast<uintptr_t>(valueData.data());
269 memory->SetBuffer(valuePtr, valueData);
270 OpPush(valuePtr);
271 OpDeref();
272 uintptr_t value = StackPop();
273 uintptr_t expectedValue = 0x3433323134333231;
274 printf("Test05-u64 value:%" PRIxPTR " expectedValue:%" PRIxPTR "\n", value, expectedValue);
275 ret = (value == expectedValue);
276 printf("Test05-01 %d\n", ret);
277 OpPush(valuePtr);
278 OpDup();
279 ret &= (StackAt(0) == valuePtr);
280 printf("Test05-02 %d\n", ret);
281 ret &= (StackAt(1) == valuePtr);
282 printf("Test05-03 %d\n", ret);
283 return ret;
284 }
285
Test06()286 bool DwarfOpTest::Test06()
287 {
288 // OpDrop OpOver OpSwap OpRot
289 MAYBE_UNUSED bool ret = false;
290 StackReset(0);
291 ret = (StackSize() == 1);
292 OpPush(1);
293 ret &= (StackSize() == 2); // 2:stack_.size()
294
295 OpDrop();
296 ret &= (StackSize() == 1);
297
298 OpPush(1);
299 OpPush(2); // 2:stack_.index
300 ret &= (StackSize() == 3); // 3:stack_.size()
301
302 OpOver();
303 ret &= (StackSize() == 4); // 4:stack_.size()
304 uintptr_t value = StackPop();
305 ret &= (value == 1);
306 ret &= (StackSize() == 3); // 3:stack_.size()
307
308 ret &= (StackAt(0) == 2); // 2:stack.value
309 ret &= (StackAt(1) == 1);
310 OpSwap();
311 ret &= (StackAt(0) == 1);
312 ret &= (StackAt(1) == 2); // 2:stack.value
313
314 OpRot();
315 ret &= (StackAt(0) == 0);
316 ret &= (StackAt(1) == 1);
317 ret &= (StackAt(2) == 2); // 2:stack.value
318 return true;
319 }
320
Test07()321 bool DwarfOpTest::Test07()
322 {
323 bool ret = false;
324 StackReset(0);
325 intptr_t value = -10;
326 StackPush(value);
327 OpAbs();
328 ret = (static_cast<uintptr_t>(-value) == StackPop());
329
330 StackReset(0);
331 StackPush(0x1122334455667788);
332 StackPush(0xFFFFFFFF00000000);
333 OpAnd();
334 ret &= (0x1122334400000000 == StackPop());
335
336 StackReset(0);
337 StackPush(0x8);
338 StackPush(0x2);
339 OpDiv();
340 ret &= (0x4 == StackPop());
341
342 StackReset(0);
343 StackPush(0x8);
344 StackPush(0x2);
345 OpMinus();
346 ret &= (0x6 == StackPop());
347
348 StackReset(0);
349 StackPush(0x8);
350 StackPush(0x2);
351 OpMod();
352 ret &= (0 == StackPop());
353
354 StackReset(0);
355 StackPush(0x8);
356 StackPush(0x2);
357 OpMul();
358 ret &= (0x10 == StackPop());
359
360 StackReset(0);
361 StackPush(0x8);
362 OpNeg();
363 ret &= (static_cast<uintptr_t>(STACK_VALUE) == StackPop());
364
365 StackReset(0);
366 StackPush(1);
367 OpNot();
368 ret &= (static_cast<uintptr_t>(~1) == StackPop());
369 return ret;
370 }
371
Test08()372 bool DwarfOpTest::Test08()
373 {
374 bool ret = false;
375 StackReset(0);
376 StackPush(0x2);
377 StackPush(0x2);
378 OpEQ();
379 ret = (1 == StackPop());
380
381 StackReset(0);
382 StackPush(0x2);
383 StackPush(0x3);
384 OpGE();
385 ret &= (0 == StackPop());
386
387 StackReset(0);
388 StackPush(0x2);
389 StackPush(0x3);
390 OpGT();
391 ret &= (0 == StackPop());
392
393 StackReset(0);
394 StackPush(0x2);
395 StackPush(0x3);
396 OpLE();
397 ret &= (1 == StackPop());
398
399 StackReset(0);
400 StackPush(0x2);
401 StackPush(0x3);
402 OpLT();
403 ret &= (1 == StackPop());
404
405 StackReset(0);
406 StackPush(0x2);
407 StackPush(0x3);
408 OpNE();
409 ret &= (1 == StackPop());
410 return ret;
411 }
412
Test09(std::shared_ptr<DfxMemoryTest> memory)413 bool DwarfOpTest::Test09(std::shared_ptr<DfxMemoryTest> memory)
414 {
415 bool ret = false;
416 StackReset(0);
417 memory->Reset();
418 std::vector<uint8_t> exprData {
419 0x10, 0x00,
420 };
421 uintptr_t exprPtr = reinterpret_cast<uintptr_t>(exprData.data());
422 memory->SetBuffer(exprPtr, exprData);
423 OpPlusULEBConst(exprPtr);
424 uintptr_t value = StackPop();
425 printf("Test09-01 value:%" PRIxPTR "\n", value);
426 ret = (value == 0x10);
427
428 StackReset(0);
429 uintptr_t exprPtrOld = exprPtr;
430 OpSkip(exprPtr);
431 ret &= (exprPtrOld + exprData[0] == exprPtr);
432 printf("Test09-02 exprPtrOld:%" PRIxPTR " exprPtrNew:%" PRIxPTR "\n",
433 exprPtrOld, exprPtr);
434
435 StackReset(0);
436 StackPush(0x2);
437 exprPtr = exprPtrOld;
438 OpBra(exprPtr);
439 ret &= (exprPtrOld + exprData[0] == exprPtr);
440 printf("Test09-03 exprPtrOld:%" PRIxPTR " exprPtrNew:%" PRIxPTR "\n",
441 exprPtrOld, exprPtr);
442
443 StackReset(0);
444 exprPtr = exprPtrOld;
445 OpBra(exprPtr);
446 ret &= (exprPtrOld == exprPtr);
447 printf("Test09-04 exprPtrOld:%" PRIxPTR " exprPtrNew:%" PRIxPTR "\n",
448 exprPtrOld, exprPtr);
449 return ret;
450 }
451
Test10(std::shared_ptr<DfxMemoryTest> memory)452 bool DwarfOpTest::Test10(std::shared_ptr<DfxMemoryTest> memory)
453 {
454 bool ret = false;
455 memory->Reset();
456 std::vector<uint8_t> exprData {
457 0x1e, 0x00,
458 };
459 uintptr_t exprPtr = reinterpret_cast<uintptr_t>(exprData.data());
460 memory->SetBuffer(exprPtr, exprData);
461
462 StackReset(0);
463 OpLit(DW_OP_lit1);
464 uintptr_t value = StackPop();
465 ret = (value == 0x01);
466 printf("Test10-01 value:%" PRIxPTR " ret:%d\n", value, ret);
467
468 OpLit(DW_OP_lit31);
469 value = StackPop();
470 ret &= (value == 0x1f);
471 printf("Test10-02 value:%" PRIxPTR " ret:%d\n", value, ret);
472
473 StackReset(0);
474 auto reg = std::make_shared<DfxRegsArm64>();
475 (*reg)[0] = 0xa;
476 OpReg(DW_OP_reg0, *(reg.get()));
477 value = StackPop();
478 ret &= (value == 0xa);
479 printf("Test10-03 value:%" PRIxPTR " ret:%d\n", value, ret);
480
481 StackReset(0);
482 (*reg)[0x1e] = 0x14;
483 OpRegx(exprPtr, *(reg.get()));
484 value = StackPop();
485 ret &= (value == 0x14);
486 printf("Test10-04 value:%" PRIxPTR " ret:%d\n", value, ret);
487
488 StackReset(0);
489 OpBReg(DW_OP_breg0, exprPtr, *(reg.get()));
490 value = StackPop();
491 ret &= (value == 0x28); // 0xa + 0x1e
492 printf("Test10-05 value:%" PRIxPTR " ret:%d\n", value, ret);
493
494 StackReset(0);
495 OpBRegx(exprPtr, *(reg.get()));
496 value = StackPop();
497 ret &= (value == 0x32); // 0x14 + 0x1e
498 printf("Test10-06 value:%" PRIxPTR " ret:%d\n", value, ret);
499 return ret;
500 }
501
502 using RequestFdFunc = int32_t (*)(int32_t);
503 namespace {
504 /**
505 * @tc.name: DwarfTest001
506 * @tc.desc: test parse fde in libfaultloggerd_client.so
507 * @tc.type: FUNC
508 */
509 HWTEST_F(DwarfTest, DwarfTest001, TestSize.Level2)
510 {
511 GTEST_LOG_(INFO) << "DwarfTest001: start.";
512 void* handle = dlopen("libjson_stack_formatter.z.so", RTLD_LAZY | RTLD_NODELETE);
513 bool isSuccess = handle != nullptr;
514 if (!isSuccess) {
515 ASSERT_FALSE(isSuccess);
516 printf("Failed to dlopen libfaultloggerd, %s\n", dlerror());
517 } else {
518 RequestFdFunc requestFdFunc = (RequestFdFunc)dlsym(handle,
519 "_ZN4OHOS9HiviewDFX16DfxJsonFormatter15FormatJsonStack" \
520 "ENSt3__h12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEERS8_");
521 isSuccess = requestFdFunc != nullptr;
522 if (!isSuccess) {
523 ASSERT_FALSE(isSuccess);
524 printf("Failed to find RequestFdFunc, %s\n", dlerror());
525 } else {
526 const uintptr_t pcOffset = 48;
527 uintptr_t pc = reinterpret_cast<uintptr_t>(requestFdFunc) + pcOffset;
528 struct UnwindTableInfo uti;
529 ASSERT_EQ(DfxElf::FindUnwindTableLocal(pc, uti), 0);
530
531 auto memory = std::make_shared<DfxMemory>(UNWIND_TYPE_LOCAL);
532 DwarfEntryParserTest dwarfEntryParser(memory);
533 struct UnwindEntryInfo pi;
534 ASSERT_EQ(true, dwarfEntryParser.SearchEntryTest(pc, uti, pi));
535
536 FrameDescEntry fde;
537 ASSERT_EQ(true, dwarfEntryParser.ParseFdeTest(reinterpret_cast<uintptr_t>(pi.unwindInfo), fde));
538 ASSERT_GT(fde.cieAddr, 0);
539
540 CommonInfoEntry cie;
541 ASSERT_EQ(true, dwarfEntryParser.ParseCieTest(fde.cieAddr, cie));
542
543 RegLocState rsState;
544 DwarfCfaInstructions instructions(memory);
545 ASSERT_EQ(true, instructions.Parse(pc, fde, rsState));
546 /*
547 Version: 1
548 Augmentation: "zR"
549 Code alignment factor: 1
550 Data alignment factor: -4
551 Return address column: 30
552 Augmentation data: 1b
553 DW_CFA_def_cfa: r31 (sp) ofs 0
554 DW_CFA_nop
555 DW_CFA_nop
556 DW_CFA_nop
557 DW_CFA_nop
558 */
559 ASSERT_EQ(cie.codeAlignFactor, 1);
560 ASSERT_EQ(cie.dataAlignFactor, -4);
561 ASSERT_EQ(cie.returnAddressRegister, 30);
562 ASSERT_EQ(cie.hasAugmentationData, true);
563 ASSERT_EQ(cie.pointerEncoding, 0x1b);
564
565 /*
566 DW_CFA_advance_loc: 20 to 0000000000002718
567 DW_CFA_def_cfa_offset: 112
568 DW_CFA_advance_loc: 28 to 0000000000002734
569 DW_CFA_def_cfa: r29 (x29) ofs 112
570 DW_CFA_offset: r15 (x15) at cfa-8
571 DW_CFA_offset: r19 (x19) at cfa-16
572 DW_CFA_offset: r20 (x20) at cfa-24
573 DW_CFA_offset: r21 (x21) at cfa-32
574 DW_CFA_offset: r22 (x22) at cfa-40
575 DW_CFA_offset: r23 (x23) at cfa-48
576 DW_CFA_offset: r24 (x24) at cfa-56
577 DW_CFA_offset: r25 (x25) at cfa-64
578 DW_CFA_offset: r26 (x26) at cfa-72
579 DW_CFA_offset: r27 (x27) at cfa-80
580 DW_CFA_offset: r28 (x28) at cfa-96
581 DW_CFA_offset: r30 (x30) at cfa-104
582 DW_CFA_offset: r29 (x29) at cfa-112
583 */
584 ASSERT_EQ(fde.pcStart, reinterpret_cast<uintptr_t>(requestFdFunc));
585 ASSERT_EQ(rsState.cfaReg, REG_AARCH64_X29);
586 ASSERT_EQ(rsState.cfaRegOffset, 112); // 112 : DW_CFA_def_cfa: r29 (x29) ofs 112
587
588 size_t qutIdx = 0;
589 if (DfxRegsQut::IsQutReg(static_cast<uint16_t>(REG_AARCH64_X30), qutIdx)) {
590 ASSERT_EQ(static_cast<uint8_t>(rsState.locs[qutIdx].type),
591 static_cast<uint8_t>(REG_LOC_MEM_OFFSET));
592 ASSERT_EQ(rsState.locs[qutIdx].val, -104); // -104: r30 (x30) at cfa-104
593 }
594 if (DfxRegsQut::IsQutReg(static_cast<uint16_t>(REG_AARCH64_X29), qutIdx)) {
595 ASSERT_EQ(static_cast<uint8_t>(rsState.locs[qutIdx].type),
596 static_cast<uint8_t>(REG_LOC_MEM_OFFSET));
597 ASSERT_EQ(rsState.locs[qutIdx].val, -112); // -112: r29 (x29) at cfa-112
598 }
599
600 RegLocState rsState2;
601 ASSERT_EQ(true, instructions.Parse(reinterpret_cast<uintptr_t>(requestFdFunc), fde, rsState2));
602 ASSERT_EQ(rsState2.cfaReg, REG_AARCH64_X31);
603 ASSERT_EQ(rsState2.cfaRegOffset, 0); // DW_CFA_def_cfa: r31 (sp) ofs 0
604
605 RegLocState rsState3;
606 ASSERT_EQ(true, instructions.Parse(reinterpret_cast<uintptr_t>(requestFdFunc) + 24, fde, rsState3));
607 ASSERT_EQ(rsState3.cfaReg, REG_AARCH64_X31);
608 ASSERT_EQ(rsState3.cfaRegOffset, 112); // 112 : DW_CFA_def_cfa_offset: 112
609 GTEST_LOG_(INFO) << "DwarfTest001: end.";
610 }
611 }
612 }
613
614 struct FdeParseResult {
615 int32_t index;
616 uintptr_t relPcStart;
617 uintptr_t relPcEnd;
618 std::vector<std::string> operateResult;
619 };
620
621 static std::vector<std::string> cieResult = {
622 "DW_CFA_def_cfa: r31 ofs 0",
623 "DW_CFA_nop",
624 "DW_CFA_nop",
625 "DW_CFA_nop",
626 "DW_CFA_nop"
627 };
628
PrintOperations(const std::string & msg,std::vector<std::string> & operations)629 void PrintOperations(const std::string& msg, std::vector<std::string>& operations)
630 {
631 printf("%s\n", msg.c_str());
632 for (const auto& operation : operations) {
633 printf("%s\n", operation.c_str());
634 }
635 }
636
CheckFdeResult(std::shared_ptr<FdeParseResult> result)637 bool CheckFdeResult(std::shared_ptr<FdeParseResult> result)
638 {
639 std::ifstream infile("/data/test/dwarf_test_aarch64_elf_result2");
640 std::string line;
641 std::vector<std::string> operands;
642 std::vector<std::string> expectedResult = cieResult;
643 expectedResult.insert(std::end(expectedResult),
644 std::begin((*result).operateResult),
645 std::end((*result).operateResult));
646 while (std::getline(infile, line)) {
647 if (line.find("DW_CFA") != std::string::npos) {
648 operands.push_back(line);
649 }
650 }
651
652 if (expectedResult.size() != operands.size()) {
653 printf("Failed to check operations size for index:%d\n", result->index);
654 PrintOperations("Expected result:", expectedResult);
655 PrintOperations("Current result:", operands);
656 return false;
657 }
658
659 printf("CheckFdeResult index:%d\n", result->index);
660 for (size_t i = 0; i < operands.size(); i++) {
661 std::string cfaCmd = OHOS::TrimStr(expectedResult[i]);
662 auto pos = cfaCmd.find(":");
663 if (pos != std::string::npos) {
664 cfaCmd = cfaCmd.substr(0, pos);
665 expectedResult[i] = cfaCmd;
666 }
667
668 if (operands[i].find(cfaCmd) == std::string::npos) {
669 printf("Failed to check operations for index:%d\n", result->index);
670 PrintOperations("Expected result:", expectedResult);
671 PrintOperations("Current result:", operands);
672 return false;
673 }
674 }
675 return true;
676 }
677
ParseFdeResultFromFile()678 std::vector<std::shared_ptr<FdeParseResult>> ParseFdeResultFromFile()
679 {
680 std::vector<std::shared_ptr<FdeParseResult>> ret;
681 std::ifstream infile("/data/test/dwarf_test_aarch64_elf_result");
682 std::string line;
683 std::shared_ptr<FdeParseResult> result = nullptr;
684 int32_t index = 0;
685 while (std::getline(infile, line)) {
686 if (line.find("FDE cie=") != std::string::npos) {
687 if (result != nullptr) {
688 ret.push_back(result);
689 }
690 result = std::make_shared<FdeParseResult>();
691 auto pos0 = line.find("pc=");
692 std::string pcRange = line.substr(pos0 + strlen("pc="));
693 auto pos1 = pcRange.find("..");
694 std::string pcStart = pcRange.substr(0, pos1);
695 std::string pcEnd = pcRange.substr(pos1 + strlen(".."));
696 result->relPcStart = std::stoul(pcStart, nullptr, HEX);
697 result->relPcEnd = std::stoul(pcEnd, nullptr, HEX);
698 result->index = index;
699 index++;
700 continue;
701 }
702
703 if (result == nullptr) {
704 continue;
705 }
706
707 if (line.empty()) {
708 continue;
709 }
710
711 if (line.find("ZERO terminator") != std::string::npos) {
712 ret.push_back(result);
713 break;
714 }
715
716 result->operateResult.push_back(line);
717 }
718 return ret;
719 }
720
RedirectStdErrToFile(const std::string & path)721 int32_t RedirectStdErrToFile(const std::string& path)
722 {
723 int output = open(path.c_str(), O_RDWR | O_CREAT, 0777);
724 int32_t oldFd = dup(STDERR_FILENO);
725 dup2(output, STDERR_FILENO);
726 close(output);
727 return oldFd;
728 }
729
730 /**
731 * @tc.name: DwarfTest002
732 * @tc.desc: test dwarf cfa operations
733 * @tc.type: FUNC
734 */
735 HWTEST_F(DwarfTest, DwarfTest002, TestSize.Level2)
736 {
737 GTEST_LOG_(INFO) << "DwarfTest002: start.";
738 RegularElfFactory elfFactory("/data/test/dwarf_test_aarch64_elf");
739 auto elf = elfFactory.Create();
740 ASSERT_NE(elf, nullptr);
741 uint64_t loadbase = reinterpret_cast<uint64_t>(elf->GetMmapPtr());
742 elf->SetLoadBase(loadbase);
743 /*
744 7fb92b7000-7fb9326000 r--p 00000000 b3:07 1817 dwarf_test_aarch64_elf
745 7fb9326000-7fb93d1000 r-xp 0006e000 b3:07 1817 dwarf_test_aarch64_elf
746 7fb93d1000-7fb93d3000 r--p 00118000 b3:07 1817 dwarf_test_aarch64_elf
747 7fb93d3000-7fb93d5000 rw-p 00119000 b3:07 1817 dwarf_test_aarch64_elf
748 LOAD 0x000000000006e640 0x000000000006f640 0x000000000006f640
749 0x00000000000a8ec0 0x00000000000a8ec0 R E 0x1000
750 */
751 uint64_t startPc = loadbase + 0x6F640;
752 uint64_t endPc = startPc + 0xa8ec0;
753 printf("startPc:%p endPc:%p\n", reinterpret_cast<void*>(startPc), reinterpret_cast<void*>(endPc));
754 uint64_t mapStart = loadbase + 0x6F000;
755 uint64_t mapEnd = mapStart + 0xab000;
756 const uint64_t offset = 0x6e000;
757 auto map1 = std::make_shared<DfxMap>(mapStart, mapEnd, offset, "r-xp", "dwarf_test_aarch64_elf");
758 UnwindTableInfo info {};
759 ASSERT_EQ(0, elf->FindUnwindTableInfo(startPc + 0x2, map1, info));
760 ASSERT_EQ(info.startPc, startPc);
761 ASSERT_EQ(info.endPc, endPc);
762 ASSERT_NE(info.format, -1);
763 auto testElfFdeResult = ParseFdeResultFromFile();
764 auto memory = std::make_shared<DfxMemory>(UNWIND_TYPE_LOCAL);
765 DwarfEntryParserTest dwarfEntryParser(memory);
766 ASSERT_EQ(testElfFdeResult.size(), info.tableLen); // cie
767 int index = 0;
768 for (auto& fdeResult : testElfFdeResult) {
769 auto pc = fdeResult->relPcEnd - 2 + loadbase;
770 ASSERT_GT(pc, fdeResult->relPcStart + loadbase);
771 ASSERT_LT(pc, fdeResult->relPcEnd + loadbase);
772
773 struct UnwindEntryInfo pi;
774 ASSERT_EQ(true, dwarfEntryParser.SearchEntryTest(pc, info, pi));
775
776 FrameDescEntry fde;
777 ASSERT_EQ(true, dwarfEntryParser.ParseFdeTest(reinterpret_cast<uintptr_t>(pi.unwindInfo), fde));
778 ASSERT_GT(fde.cieAddr, 0);
779 ASSERT_EQ(fde.pcStart, fdeResult->relPcStart + loadbase);
780 ASSERT_EQ(fde.pcEnd, fdeResult->relPcEnd + loadbase);
781
782 CommonInfoEntry cie;
783 ASSERT_EQ(true, dwarfEntryParser.ParseCieTest(fde.cieAddr, cie));
784 remove("/data/test/dwarf_test_aarch64_elf_result2");
785
786 int oldFd = RedirectStdErrToFile("/data/test/dwarf_test_aarch64_elf_result2");
787 ASSERT_GT(oldFd, 0);
788 fprintf(stderr, "currentFdeIndex:%d relPcStart:%p relPcEnd:%p begin\n",
789 index, (void*)fdeResult->relPcStart, (void*)fdeResult->relPcEnd);
790 RegLocState rsState;
791 DwarfCfaInstructions instructions(memory);
792 ASSERT_EQ(true, instructions.Parse(pc, fde, rsState));
793 fprintf(stderr, "currentFdeIndex:%d relPcStart:%p relPcEnd:%p end\n",
794 index, (void*)fdeResult->relPcStart, (void*)fdeResult->relPcEnd);
795 dup2(oldFd, STDERR_FILENO);
796 if (!CheckFdeResult(fdeResult)) {
797 FAIL() << "Failed to check dw_cfa_operations";
798 break;
799 }
800 index++;
801 }
802 GTEST_LOG_(INFO) << "DwarfTest002: end.\n";
803 }
804
805 /**
806 * @tc.name: DwarfTest003
807 * @tc.desc: test dwarf operations
808 * @tc.type: FUNC
809 */
810 HWTEST_F(DwarfTest, DwarfTest003, TestSize.Level2)
811 {
812 GTEST_LOG_(INFO) << "DwarfTest003: start.\n";
813 auto memory = std::make_shared<DfxMemoryTest>();
814 DwarfOpTest op(memory);
815 ASSERT_EQ(op.Test01(), false);
816 ASSERT_EQ(op.Test02(), true);
817 ASSERT_EQ(op.Test03(), true);
818 ASSERT_EQ(op.Test04(memory), true);
819 ASSERT_EQ(op.Test05(memory), true);
820 ASSERT_EQ(op.Test06(), true);
821 ASSERT_EQ(op.Test07(), true);
822 ASSERT_EQ(op.Test08(), true);
823 ASSERT_EQ(op.Test09(memory), true);
824 ASSERT_EQ(op.Test10(memory), true);
825 GTEST_LOG_(INFO) << "DwarfTest003: end.\n";
826 }
827
828 /**
829 * @tc.name: DwarfTest004
830 * @tc.desc: test dwarf DW_OP_reserved oprations
831 * @tc.type: FUNC
832 */
833 HWTEST_F(DwarfTest, DwarfTest004, TestSize.Level0)
834 {
835 GTEST_LOG_(INFO) << "DwarfTest004: start.\n";
836 auto memory = std::make_shared<DfxMemoryTest>();
837 memory->increaseAddr = true;
838 DwarfOpTest op(memory);
839 std::vector<uint8_t> opcodes = {
840 0x08, // size
841 0x01, 0x02, 0x04, 0x05, 0x07, // DW_OP_reserved
842 0x01, 0x02, 0x04, 0x05, 0x07, // DW_OP_reserved
843 };
844 uintptr_t exprPtr = reinterpret_cast<uintptr_t>(opcodes.data());
845 memory->SetBuffer(exprPtr, opcodes);
846 auto reg = std::make_shared<DfxRegsArm64>();
847 auto ret = op.Eval(*reg.get(), 0, exprPtr);
848 ASSERT_EQ(ret, 0);
849 printf("DwarfTest004:%" PRIxPTR "\n", ret);
850 GTEST_LOG_(INFO) << "DwarfTest004: end.\n";
851 }
852
853 /**
854 * @tc.name: DwarfTest005
855 * @tc.desc: test dwarf DW_OP_addr oprations
856 * @tc.type: FUNC
857 */
858 HWTEST_F(DwarfTest, DwarfTest005, TestSize.Level2)
859 {
860 GTEST_LOG_(INFO) << "DwarfTest005: start.\n";
861 auto memory = std::make_shared<DfxMemoryTest>();
862 memory->increaseAddr = true;
863 DwarfOpTest op(memory);
864 std::vector<uint8_t> opcodes = {
865 0x0a, // size
866 DW_OP_addr, // DW_OP_addr
867 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
868 DW_OP_deref, 0x01, 0x01, 0x01, 0x01, // DW_OP_deref
869 };
870
871 std::vector<uint8_t> data = {
872 0x02, 0x04, 0x05, 0x07,
873 0x02, 0x04, 0x05, 0x07,
874 };
875
876 uintptr_t exprPtr = reinterpret_cast<uintptr_t>(opcodes.data());
877 memory->SetBuffer(exprPtr, opcodes);
878 memory->SetBuffer(0x4, data);
879
880 auto reg = std::make_shared<DfxRegsArm64>();
881 uintptr_t ret = op.Eval(*reg.get(), 0, exprPtr);
882 ASSERT_EQ(ret, 0x0705040207050402);
883 printf("DwarfTest005:%" PRIxPTR "\n", ret);
884 GTEST_LOG_(INFO) << "DwarfTest005: end.\n";
885 }
886
887 /**
888 * @tc.name: DwarfTest006
889 * @tc.desc: test dwarf DW_OP_const oprations
890 * @tc.type: FUNC
891 */
892 HWTEST_F(DwarfTest, DwarfTest006, TestSize.Level2)
893 {
894 GTEST_LOG_(INFO) << "DwarfTest006: start.\n";
895 auto memory = std::make_shared<DfxMemoryTest>();
896 memory->increaseAddr = true;
897 DwarfOpTest op(memory);
898 std::vector<uint8_t> opcodes = {
899 0x2a, // size
900 DW_OP_constu, 0x01,
901 DW_OP_consts, 0x01,
902 DW_OP_const1u, 0x01,
903 DW_OP_const1s, 0x02,
904 DW_OP_const2u, 0x03, 0x04,
905 DW_OP_const2s, 0x04, 0x04,
906 DW_OP_const4u, 0x03, 0x04, 0x03, 0x04,
907 DW_OP_const4s, 0x04, 0x04, 0x03, 0x04,
908 DW_OP_const8u,
909 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
910 DW_OP_const8s,
911 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
912 0x01, 0x01, 0x01, 0x01,
913 };
914
915 uintptr_t exprPtr = reinterpret_cast<uintptr_t>(opcodes.data());
916 memory->SetBuffer(exprPtr, opcodes);
917 auto reg = std::make_shared<DfxRegsArm64>();
918 uintptr_t ret = op.Eval(*reg.get(), 0, exprPtr);
919 ASSERT_EQ(ret, 0x0403040304030403);
920 printf("DwarfTest006:%" PRIxPTR "\n", ret);
921 GTEST_LOG_(INFO) << "DwarfTest006: end.\n";
922 }
923
924 /**
925 * @tc.name: DwarfTest007
926 * @tc.desc: test dwarf DW_OP_litxx oprations
927 * @tc.type: FUNC
928 */
929 HWTEST_F(DwarfTest, DwarfTest007, TestSize.Level2)
930 {
931 GTEST_LOG_(INFO) << "DwarfTest007: start.\n";
932 auto memory = std::make_shared<DfxMemoryTest>();
933 memory->increaseAddr = true;
934 DwarfOpTest op(memory);
935 std::vector<uint8_t> opcodes = {
936 0x20, // size
937 DW_OP_lit0,
938 DW_OP_lit1, DW_OP_lit2, DW_OP_lit3, DW_OP_lit4,
939 DW_OP_lit5, DW_OP_lit6, DW_OP_lit7, DW_OP_lit8,
940 DW_OP_lit9, DW_OP_lit10, DW_OP_lit11, DW_OP_lit12,
941 DW_OP_lit13, DW_OP_lit14, DW_OP_lit15, DW_OP_lit16,
942 DW_OP_lit17, DW_OP_lit18, DW_OP_lit19, DW_OP_lit20,
943 DW_OP_lit21, DW_OP_lit22, DW_OP_lit23, DW_OP_lit24,
944 DW_OP_lit25, DW_OP_lit26, DW_OP_lit27, DW_OP_lit28,
945 DW_OP_lit29, DW_OP_lit30, DW_OP_lit31,
946 0x01, 0x01, 0x01, 0x01,
947 };
948
949 uintptr_t exprPtr = reinterpret_cast<uintptr_t>(opcodes.data());
950 memory->SetBuffer(exprPtr, opcodes);
951 auto reg = std::make_shared<DfxRegsArm64>();
952 uintptr_t ret = op.Eval(*reg.get(), 0, exprPtr);
953 ASSERT_EQ(ret, static_cast<uintptr_t>(DW_OP_lit31 - DW_OP_lit0));
954 printf("DwarfTest007:%" PRIxPTR "\n", ret);
955 GTEST_LOG_(INFO) << "DwarfTest007: end.\n";
956 }
957
958 /**
959 * @tc.name: DwarfTest008
960 * @tc.desc: test dwarf DW_OP_regxx oprations
961 * @tc.type: FUNC
962 */
963 HWTEST_F(DwarfTest, DwarfTest008, TestSize.Level2)
964 {
965 GTEST_LOG_(INFO) << "DwarfTest008: start.\n";
966 auto memory = std::make_shared<DfxMemoryTest>();
967 memory->increaseAddr = true;
968 DwarfOpTest op(memory);
969 std::vector<uint8_t> opcodes = {
970 0x20, // size
971 DW_OP_reg0,
972 DW_OP_reg1, DW_OP_reg2, DW_OP_reg3, DW_OP_reg4,
973 DW_OP_reg5, DW_OP_reg6, DW_OP_reg7, DW_OP_reg8,
974 DW_OP_reg9, DW_OP_reg10, DW_OP_reg11, DW_OP_reg12,
975 DW_OP_reg13, DW_OP_reg14, DW_OP_reg15, DW_OP_reg16,
976 DW_OP_reg17, DW_OP_reg18, DW_OP_reg19, DW_OP_reg20,
977 DW_OP_reg21, DW_OP_reg22, DW_OP_reg23, DW_OP_reg24,
978 DW_OP_reg25, DW_OP_reg26, DW_OP_reg27, DW_OP_reg28,
979 DW_OP_reg29, DW_OP_reg30, DW_OP_reg31,
980 0x01, 0x01, 0x01, 0x01,
981 };
982
983 uintptr_t exprPtr = reinterpret_cast<uintptr_t>(opcodes.data());
984 memory->SetBuffer(exprPtr, opcodes);
985 auto reg = std::make_shared<DfxRegsArm64>();
986 const uintptr_t result = 0x5544332211;
987 (*reg)[DW_OP_reg31 - DW_OP_reg0] = result;
988 uintptr_t ret = op.Eval(*reg.get(), 0, exprPtr);
989 ASSERT_EQ(ret, result);
990 printf("DwarfTest008:%" PRIxPTR "\n", ret);
991 GTEST_LOG_(INFO) << "DwarfTest008: end.\n";
992 }
993
994 /**
995 * @tc.name: DwarfTest009
996 * @tc.desc: test dwarf DW_OP_nop oprations
997 * @tc.type: FUNC
998 */
999 HWTEST_F(DwarfTest, DwarfTest009, TestSize.Level2)
1000 {
1001 GTEST_LOG_(INFO) << "DwarfTest009: start.\n";
1002 auto memory = std::make_shared<DfxMemoryTest>();
1003 memory->increaseAddr = true;
1004 DwarfOpTest op(memory);
1005 std::vector<uint8_t> opcodes = {
1006 0x0a, // size
1007 DW_OP_fbreg,
1008 DW_OP_piece,
1009 DW_OP_xderef,
1010 DW_OP_xderef_size,
1011 DW_OP_nop,
1012 DW_OP_push_object_address,
1013 DW_OP_call2,
1014 DW_OP_call4,
1015 DW_OP_call_ref,
1016 DW_OP_lo_user,
1017 0x01, 0x01, 0x01, 0x01,
1018 };
1019 uintptr_t exprPtr = reinterpret_cast<uintptr_t>(opcodes.data());
1020 memory->SetBuffer(exprPtr, opcodes);
1021 auto reg = std::make_shared<DfxRegsArm64>();
1022 uintptr_t ret = op.Eval(*reg.get(), 0, exprPtr);
1023 ASSERT_EQ(ret, 0);
1024 printf("DwarfTest009:%" PRIxPTR "\n", ret);
1025 GTEST_LOG_(INFO) << "DwarfTest009: end.\n";
1026 }
1027
1028 /**
1029 * @tc.name: DwarfTest010
1030 * @tc.desc: test dwarf numerical oprations
1031 * @tc.type: FUNC
1032 */
1033 HWTEST_F(DwarfTest, DwarfTest010, TestSize.Level2)
1034 {
1035 GTEST_LOG_(INFO) << "DwarfTest010: start.\n";
1036 auto memory = std::make_shared<DfxMemoryTest>();
1037 memory->increaseAddr = true;
1038 DwarfOpTest op(memory);
1039 std::vector<uint8_t> opcodes = {
1040 0x09, // size
1041 DW_OP_lit31,
1042 DW_OP_dup,
1043 DW_OP_dup,
1044 DW_OP_swap,
1045 DW_OP_rot,
1046 DW_OP_abs,
1047 DW_OP_and,
1048 DW_OP_div,
1049 0x01, 0x01, 0x01, 0x01,
1050 };
1051 uintptr_t exprPtr = reinterpret_cast<uintptr_t>(opcodes.data());
1052 memory->SetBuffer(exprPtr, opcodes);
1053 auto reg = std::make_shared<DfxRegsArm64>();
1054 uintptr_t ret = op.Eval(*reg.get(), 0, exprPtr);
1055 ASSERT_EQ(ret, 1);
1056 printf("DwarfTest010:%" PRIxPTR "\n", ret);
1057 GTEST_LOG_(INFO) << "DwarfTest010: end.\n";
1058 }
1059
1060
1061 /**
1062 * @tc.name: DwarfTest011
1063 * @tc.desc: test dwarf numerical oprations 2
1064 * @tc.type: FUNC
1065 */
1066 HWTEST_F(DwarfTest, DwarfTest011, TestSize.Level2)
1067 {
1068 GTEST_LOG_(INFO) << "DwarfTest011: start.\n";
1069 auto memory = std::make_shared<DfxMemoryTest>();
1070 memory->increaseAddr = true;
1071 DwarfOpTest op(memory);
1072 std::vector<uint8_t> opcodes = {
1073 0x05, // size
1074 DW_OP_lit31,
1075 DW_OP_dup,
1076 DW_OP_over,
1077 DW_OP_drop,
1078 DW_OP_minus,
1079 0x01, 0x01, 0x01, 0x01,
1080 };
1081 uintptr_t exprPtr = reinterpret_cast<uintptr_t>(opcodes.data());
1082 memory->SetBuffer(exprPtr, opcodes);
1083 auto reg = std::make_shared<DfxRegsArm64>();
1084 uintptr_t ret = op.Eval(*reg.get(), 0, exprPtr);
1085 ASSERT_EQ(ret, 0);
1086 printf("DwarfTest011:%" PRIxPTR "\n", ret);
1087 GTEST_LOG_(INFO) << "DwarfTest011: end.\n";
1088 }
1089
1090 /**
1091 * @tc.name: DwarfTest012
1092 * @tc.desc: test dwarf numerical oprations 3
1093 * @tc.type: FUNC
1094 */
1095 HWTEST_F(DwarfTest, DwarfTest012, TestSize.Level2)
1096 {
1097 GTEST_LOG_(INFO) << "DwarfTest012: start.\n";
1098 auto memory = std::make_shared<DfxMemoryTest>();
1099 memory->increaseAddr = true;
1100 DwarfOpTest op(memory);
1101 std::vector<uint8_t> opcodes = {
1102 0x09, // size
1103 DW_OP_lit5,
1104 DW_OP_lit2,
1105 DW_OP_mod, // 5 % 2
1106 DW_OP_lit2,
1107 DW_OP_mul, // 1 * 2
1108 DW_OP_lit2,
1109 DW_OP_plus, // 2 + 2
1110 DW_OP_lit4,
1111 DW_OP_eq,
1112 0x01, 0x01, 0x01, 0x01,
1113 };
1114 uintptr_t exprPtr = reinterpret_cast<uintptr_t>(opcodes.data());
1115 memory->SetBuffer(exprPtr, opcodes);
1116 auto reg = std::make_shared<DfxRegsArm64>();
1117 uintptr_t ret = op.Eval(*reg.get(), 0, exprPtr);
1118 ASSERT_EQ(ret, 1);
1119 printf("DwarfTest012:%" PRIxPTR "\n", ret);
1120 GTEST_LOG_(INFO) << "DwarfTest012: end.\n";
1121 }
1122
1123 /**
1124 * @tc.name: DwarfTest013
1125 * @tc.desc: test dwarf logical oprations
1126 * @tc.type: FUNC
1127 */
1128 HWTEST_F(DwarfTest, DwarfTest013, TestSize.Level2)
1129 {
1130 GTEST_LOG_(INFO) << "DwarfTest013: start.\n";
1131 auto memory = std::make_shared<DfxMemoryTest>();
1132 memory->increaseAddr = true;
1133 DwarfOpTest op(memory);
1134 std::vector<uint8_t> opcodes = {
1135 0x0a, // size
1136 DW_OP_lit1, // 1
1137 DW_OP_lit1, // 1
1138 DW_OP_shl, // 1 << 1
1139 DW_OP_lit1, // 1
1140 DW_OP_shr, // 2 >> 1
1141 DW_OP_lit1, // 1
1142 DW_OP_shra, // 1
1143 DW_OP_xor, // 0
1144 DW_OP_lit1, // 1
1145 DW_OP_eq, // 0
1146 0x01, 0x01, 0x01, 0x01,
1147 };
1148 uintptr_t exprPtr = reinterpret_cast<uintptr_t>(opcodes.data());
1149 memory->SetBuffer(exprPtr, opcodes);
1150 auto reg = std::make_shared<DfxRegsArm64>();
1151 uintptr_t ret = op.Eval(*reg.get(), 0, exprPtr);
1152 ASSERT_EQ(ret, 0);
1153 printf("DwarfTest013:%" PRIxPTR "\n", ret);
1154 GTEST_LOG_(INFO) << "DwarfTest013: end.\n";
1155 }
1156
1157 /**
1158 * @tc.name: DwarfTest014
1159 * @tc.desc: test dwarf logical oprations
1160 * @tc.type: FUNC
1161 */
1162 HWTEST_F(DwarfTest, DwarfTest014, TestSize.Level2)
1163 {
1164 GTEST_LOG_(INFO) << "DwarfTest014: start.\n";
1165 auto memory = std::make_shared<DfxMemory>();
1166 auto unwindEntryParser = std::make_shared<DwarfEntryParser>(memory);
1167 UnwindTableInfo uti;
1168 UnwindEntryInfo uei;
1169 bool ret = unwindEntryParser->LinearSearchEntry(0, uti, uei);
1170 ASSERT_FALSE(ret);
1171 FrameDescEntry fdeInfo;
1172 uintptr_t addr = 0;
1173 unwindEntryParser->GetCieOrFde(addr, fdeInfo);
1174 GTEST_LOG_(INFO) << "DwarfTest014: end.\n";
1175 }
1176
1177 /**
1178 * @tc.name: DfxInstructionsTest001
1179 * @tc.desc: test DfxInstructions Flush
1180 * @tc.type: FUNC
1181 */
1182 HWTEST_F(DwarfTest, DfxInstructionsTest001, TestSize.Level2)
1183 {
1184 GTEST_LOG_(INFO) << "DfxInstructionsTest001: start.\n";
1185 auto instructions = std::make_shared<DfxInstructions>();
1186 auto regs = DfxRegs::Create();
1187 RegLoc loc;
1188 auto memory = std::make_shared<DfxMemory>();
1189 uintptr_t val;
1190 loc.type = REG_LOC_VAL_OFFSET;
1191 bool ret = instructions->Flush(*(regs.get()), memory, 0, loc, val);
1192 ASSERT_EQ(ret, true);
1193 loc.type = REG_LOC_VAL_OFFSET;
1194 ret = instructions->Flush(*(regs.get()), nullptr, 0, loc, val);
1195 ASSERT_EQ(ret, false);
1196 loc.type = REG_LOC_MEM_OFFSET;
1197 ret = instructions->Flush(*(regs.get()), memory, 0, loc, val);
1198 ASSERT_EQ(ret, true);
1199 loc.type = REG_LOC_REGISTER;
1200 ret = instructions->Flush(*(regs.get()), memory, 0, loc, val);
1201 ASSERT_EQ(ret, true);
1202 loc.type = REG_LOC_MEM_EXPRESSION;
1203 ret = instructions->Flush(*(regs.get()), memory, 0, loc, val);
1204 ASSERT_EQ(ret, true);
1205 loc.type = REG_LOC_VAL_EXPRESSION;
1206 ret = instructions->Flush(*(regs.get()), memory, 0, loc, val);
1207 ASSERT_EQ(ret, true);
1208 loc.type = REG_LOC_UNUSED;
1209 ret = instructions->Flush(*(regs.get()), memory, 0, loc, val);
1210 ASSERT_EQ(ret, false);
1211 GTEST_LOG_(INFO) << "DfxInstructionsTest001: end.\n";
1212 }
1213
DwarfDecode(uint8_t opCode)1214 static bool DwarfDecode(uint8_t opCode)
1215 {
1216 auto memory = std::make_shared<DfxMemory>(UNWIND_TYPE_LOCAL);
1217 DwarfCfaInstructions instructions(memory);
1218 CommonInfoEntry cie;
1219 cie.pointerEncoding = DW_EH_PE_omit;
1220 uintptr_t pcOffset = 0;
1221 uint8_t values[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8};
1222 uintptr_t instPtr = reinterpret_cast<uintptr_t>(&values[0]);
1223 RegLocState rsState;
1224 bool ret = instructions.DecodeDwCfa(opCode, cie, pcOffset, instPtr, rsState);
1225 return ret;
1226 }
1227
1228 /**
1229 * @tc.name: DwarfCfaInstructionsTest001
1230 * @tc.desc: test DecodeDwCfa functions
1231 * @tc.type: FUNC
1232 */
1233 HWTEST_F(DwarfTest, DwarfCfaInstructionsTest001, TestSize.Level2)
1234 {
1235 GTEST_LOG_(INFO) << "DwarfCfaInstructionsTest001: start.";
1236 uint8_t values[] = {DW_CFA_set_loc, DW_CFA_undefined, DW_CFA_register,
1237 DW_CFA_def_cfa_register, DW_CFA_offset_extended_sf, DW_CFA_def_cfa_sf,
1238 DW_CFA_def_cfa_offset_sf, DW_CFA_val_offset, DW_CFA_val_offset_sf, DW_CFA_def_cfa_expression,
1239 DW_CFA_expression, DW_CFA_val_expression, DW_CFA_GNU_negative_offset_extended};
1240 for (size_t i = 0; i < sizeof(values) / sizeof(uint8_t); i++) {
1241 ASSERT_EQ(DwarfDecode(values[i]), true);
1242 }
1243 GTEST_LOG_(INFO) << "DwarfCfaInstructionsTest001: end.";
1244 }
1245 }
1246 } // namespace HiviewDFX
1247 } // namespace OHOS
1248