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