• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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