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