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
50using namespace OHOS::HiviewDFX;
51using namespace testing::ext;
52using namespace std;
53#define HEX 16
54#define STACK_VALUE (-8)
55
56namespace OHOS {
57namespace HiviewDFX {
58class DwarfTest : public testing::Test {
59public:
60    static void TearDownTestCase(void) {}
61    void SetUp() {}
62    void TearDown() {}
63};
64
65class DwarfSectionTest : public DwarfSection {
66public:
67    explicit DwarfSectionTest(std::shared_ptr<DfxMemory> memory) : DwarfSection(memory) {};
68    ~DwarfSectionTest() {};
69    bool ParseFdeTest(uintptr_t addr, FrameDescEntry &fde)
70    {
71        return ParseFde(addr, addr, fde);
72    };
73
74    bool ParseCieTest(uintptr_t cieAddr, CommonInfoEntry &cieInfo)
75    {
76        return ParseCie(cieAddr, cieAddr, cieInfo);
77    };
78};
79
80struct MemoryArea {
81    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
90class DfxMemoryTest : public DfxMemory {
91public:
92    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
99private:
100    std::vector<MemoryArea> buffers;
101};
102
103void DfxMemoryTest::Reset()
104{
105    buffers.clear();
106}
107
108size_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
127void 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
133class DwarfOpTest : public DwarfOp<uintptr_t> {
134public:
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
149bool 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
156bool 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
167bool 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
179bool 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
255bool 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
282bool 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
317bool 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
368bool 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
409bool 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
448bool 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
498using RequestFdFunc = int32_t (*)(int32_t);
499namespace {
500/**
501 * @tc.name: DwarfTest001
502 * @tc.desc: test parse fde in libfaultloggerd_client.so
503 * @tc.type: FUNC
504 */
505HWTEST_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
612struct FdeParseResult {
613    int32_t index;
614    uintptr_t relPcStart;
615    uintptr_t relPcEnd;
616    std::vector<std::string> operateResult;
617};
618
619static 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
627void 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
635bool 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
676std::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
719int32_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 */
733HWTEST_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 */
808HWTEST_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 */
831HWTEST_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 */
856HWTEST_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 */
890HWTEST_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 */
927HWTEST_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 */
961HWTEST_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 */
997HWTEST_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 */
1031HWTEST_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 */
1064HWTEST_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 */
1093HWTEST_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 */
1126HWTEST_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 */
1160HWTEST_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 */
1197HWTEST_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