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