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