1/*
2 * Copyright (c) 2022 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#include <ctime>
18#include <securec.h>
19#include <string>
20#include <vector>
21
22#include "dfx_elf.h"
23#include "dfx_maps.h"
24#include "dfx_memory.h"
25#include "dfx_regs.h"
26#include "dfx_regs_get.h"
27#include "dfx_symbols.h"
28#include "dfx_ptrace.h"
29#include "dfx_test_util.h"
30#include "dwarf_define.h"
31#include "stack_util.h"
32
33using namespace OHOS::HiviewDFX;
34using namespace testing::ext;
35using namespace std;
36
37namespace OHOS {
38namespace HiviewDFX {
39class DfxMemoryTest : public testing::Test {
40public:
41    static void SetUpTestCase(void) {}
42    static void TearDownTestCase(void) {}
43    void SetUp() {}
44    void TearDown() {}
45};
46
47namespace {
48/**
49 * @tc.name: DfxMemoryTest001
50 * @tc.desc: test DfxMemory class ReadReg
51 * @tc.type: FUNC
52 */
53HWTEST_F(DfxMemoryTest, DfxMemoryTest001, TestSize.Level2)
54{
55    GTEST_LOG_(INFO) << "DfxMemoryTest001: start.";
56    uintptr_t regs[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa};
57    UnwindContext ctx;
58    ctx.regs = DfxRegs::CreateFromRegs(UnwindMode::DWARF_UNWIND, regs, sizeof(regs) / sizeof(regs[0]));
59    auto acc = std::make_shared<DfxAccessorsLocal>();
60    auto memory = std::make_shared<DfxMemory>(acc);
61    memory->SetCtx(&ctx);
62    uintptr_t value;
63    bool ret = memory->ReadReg(0, &value);
64    EXPECT_EQ(true, ret) << "DfxMemoryTest001: ret" << ret;
65    EXPECT_EQ(static_cast<uintptr_t>(0x1), value) << "DfxMemoryTest001: value" << value;
66    GTEST_LOG_(INFO) << "DfxMemoryTest001: end.";
67}
68
69/**
70 * @tc.name: DfxMemoryTest002
71 * @tc.desc: test DfxMemory class Read
72 * @tc.type: FUNC
73 */
74HWTEST_F(DfxMemoryTest, DfxMemoryTest002, TestSize.Level2)
75{
76    GTEST_LOG_(INFO) << "DfxMemoryTest002: start.";
77    uint8_t values[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8};
78
79    uintptr_t addr = reinterpret_cast<uintptr_t>(&values[0]);
80    uintptr_t value;
81    auto acc = std::make_shared<DfxAccessorsLocal>();
82    auto memory = std::make_shared<DfxMemory>(acc);
83    bool ret = memory->ReadUptr(addr, &value, false);
84    EXPECT_EQ(true, ret) << "DfxMemoryTest002: ret:" << ret;
85
86
87    uint64_t tmp;
88    memory->Read(addr, &tmp, sizeof(uint8_t), false);
89    ASSERT_EQ(tmp, 0x01);
90
91    memory->Read(addr, &tmp, sizeof(uint16_t), false);
92    ASSERT_EQ(tmp, 0x0201);
93
94    memory->Read(addr, &tmp, sizeof(uint32_t), false);
95    ASSERT_EQ(tmp, 0x04030201);
96
97    memory->Read(addr, &tmp, sizeof(uint64_t), false);
98    ASSERT_EQ(tmp, 0x0807060504030201);
99
100    GTEST_LOG_(INFO) << "DfxMemoryTest002: end.";
101}
102
103/**
104 * @tc.name: DfxMemoryTest003
105 * @tc.desc: test DfxMemory class Read
106 * @tc.type: FUNC
107 */
108HWTEST_F(DfxMemoryTest, DfxMemoryTest003, TestSize.Level2)
109{
110    GTEST_LOG_(INFO) << "DfxMemoryTest003: start.";
111    uint8_t values[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8};
112    UnwindContext ctx;
113    auto acc = std::make_shared<DfxAccessorsLocal>();
114    ASSERT_TRUE(GetSelfStackRange(ctx.stackBottom, ctx.stackTop));
115    auto memory = std::make_shared<DfxMemory>(acc);
116    memory->SetCtx(&ctx);
117    uintptr_t addr = reinterpret_cast<uintptr_t>(&values[0]);
118    uintptr_t value;
119    ASSERT_TRUE(memory->ReadUptr(addr, &value, false));
120#if defined(__arm__)
121    ASSERT_EQ(value, 0x04030201);
122#elif defined(__aarch64__)
123    ASSERT_EQ(value, 0x0807060504030201);
124#endif
125
126    uint64_t tmp;
127    ASSERT_TRUE(memory->Read(addr, &tmp, sizeof(uint8_t), false));
128    ASSERT_EQ(tmp, 0x01);
129
130    ASSERT_TRUE(memory->Read(addr, &tmp, sizeof(uint16_t), false));
131    ASSERT_EQ(tmp, 0x0201);
132
133    ASSERT_TRUE(memory->Read(addr, &tmp, sizeof(uint32_t), false));
134    ASSERT_EQ(tmp, 0x04030201);
135
136    ASSERT_TRUE(memory->Read(addr, &tmp, sizeof(uint64_t), false));
137    ASSERT_EQ(tmp, 0x0807060504030201);
138
139    GTEST_LOG_(INFO) << "DfxMemoryTest003: end.";
140}
141
142/**
143 * @tc.name: DfxMemoryTest004
144 * @tc.desc: test DfxMemory class Read
145 * @tc.type: FUNC
146 */
147HWTEST_F(DfxMemoryTest, DfxMemoryTest004, TestSize.Level2)
148{
149    GTEST_LOG_(INFO) << "DfxMemoryTest004: start.";
150    uint8_t values[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8};
151    UnwindContext ctx;
152    auto acc = std::make_shared<DfxAccessorsLocal>();
153    ASSERT_TRUE(GetSelfStackRange(ctx.stackBottom, ctx.stackTop));
154    auto memory = std::make_shared<DfxMemory>(acc);
155    memory->SetCtx(&ctx);
156    uintptr_t addr = reinterpret_cast<uintptr_t>(&values[0]);
157    uint8_t tmp8;
158    ASSERT_TRUE(memory->ReadU8(addr, &tmp8, false));
159    ASSERT_EQ(tmp8, 0x01);
160    uint16_t tmp16;
161    ASSERT_TRUE(memory->ReadU16(addr, &tmp16, false));
162    ASSERT_EQ(tmp16, 0x0201);
163    uint32_t tmp32;
164    ASSERT_TRUE(memory->ReadU32(addr, &tmp32, false));
165    ASSERT_EQ(tmp32, 0x04030201);
166    uint64_t tmp64;
167    ASSERT_TRUE(memory->ReadU64(addr, &tmp64, false));
168    ASSERT_EQ(tmp64, 0x0807060504030201);
169    GTEST_LOG_(INFO) << "DfxMemoryTest004: end.";
170}
171
172/**
173 * @tc.name: DfxMemoryTest005
174 * @tc.desc: test DfxMemory class Read
175 * @tc.type: FUNC
176 */
177HWTEST_F(DfxMemoryTest, DfxMemoryTest005, TestSize.Level2)
178{
179    GTEST_LOG_(INFO) << "DfxMemoryTest005: start.";
180    uint8_t values[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8};
181    UnwindContext ctx;
182    auto acc = std::make_shared<DfxAccessorsLocal>();
183    ASSERT_TRUE(GetSelfStackRange(ctx.stackBottom, ctx.stackTop));
184    auto memory = std::make_shared<DfxMemory>(acc);
185    memory->SetCtx(&ctx);
186    uintptr_t addr = reinterpret_cast<uintptr_t>(&values[0]);
187    uintptr_t valuePrel32;
188    ASSERT_TRUE(memory->ReadPrel31(addr, &valuePrel32));
189    ASSERT_EQ(valuePrel32, 0x04030201 + addr);
190    char testStr[] = "Test ReadString Func";
191    std::string resultStr;
192    uintptr_t addrStr = reinterpret_cast<uintptr_t>(&testStr[0]);
193    ASSERT_TRUE(memory->ReadString(addrStr, &resultStr, sizeof(testStr)/sizeof(char), false));
194    ASSERT_EQ(testStr, resultStr);
195    ASSERT_EQ(memory->ReadUleb128(addr), 1U);
196    ASSERT_EQ(memory->ReadSleb128(addr), 2);
197    GTEST_LOG_(INFO) << "DfxMemoryTest005: end.";
198}
199
200/**
201 * @tc.name: DfxMemoryTest006
202 * @tc.desc: test DfxMemory class Read
203 * @tc.type: FUNC
204 */
205HWTEST_F(DfxMemoryTest, DfxMemoryTest006, TestSize.Level2)
206{
207    GTEST_LOG_(INFO) << "DfxMemoryTest006: start.";
208    UnwindContext ctx;
209    auto acc = std::make_shared<DfxAccessorsLocal>();
210    ASSERT_TRUE(GetSelfStackRange(ctx.stackBottom, ctx.stackTop));
211    auto memory = std::make_shared<DfxMemory>(acc);
212    memory->SetCtx(&ctx);
213    ASSERT_EQ(memory->GetEncodedSize(DW_EH_PE_absptr), sizeof(uintptr_t));
214    ASSERT_EQ(memory->GetEncodedSize(DW_EH_PE_sdata1), 1);
215    ASSERT_EQ(memory->GetEncodedSize(DW_EH_PE_sdata2), 2);
216    ASSERT_EQ(memory->GetEncodedSize(DW_EH_PE_sdata4), 4);
217    ASSERT_EQ(memory->GetEncodedSize(DW_EH_PE_sdata8), 8);
218    GTEST_LOG_(INFO) << "DfxMemoryTest006: end.";
219}
220
221/**
222 * @tc.name: DfxMemoryTest007
223 * @tc.desc: test DfxMemory class ReadReg in remote case
224 * @tc.type: FUNC
225 */
226HWTEST_F(DfxMemoryTest, DfxMemoryTest007, TestSize.Level2)
227{
228    GTEST_LOG_(INFO) << "DfxMemoryTest007: start.";
229    uintptr_t regs[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa};
230    UnwindContext ctx;
231    ctx.regs = DfxRegs::CreateFromRegs(UnwindMode::DWARF_UNWIND, regs, sizeof(regs) / sizeof(regs[0]));
232    auto acc = std::make_shared<DfxAccessorsRemote>();
233    auto memory = std::make_shared<DfxMemory>(acc);
234    memory->SetCtx(&ctx);
235    uintptr_t value;
236    bool ret = memory->ReadReg(0, &value);
237    EXPECT_EQ(true, ret) << "DfxMemoryTest007: ret" << ret;
238    EXPECT_EQ(static_cast<uintptr_t>(0x1), value) << "DfxMemoryTest007: value" << value;
239    GTEST_LOG_(INFO) << "DfxMemoryTest007: end.";
240}
241/**
242 * @tc.name: DfxMemoryTest008
243 * @tc.desc: test DfxMemory class Read in remote case
244 * @tc.type: FUNC
245 */
246HWTEST_F(DfxMemoryTest, DfxMemoryTest008, TestSize.Level2)
247{
248    GTEST_LOG_(INFO) << "DfxMemoryTest008: start.";
249    static pid_t pid = getpid();
250    uint8_t values[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8};
251    pid_t child = fork();
252    if (child == 0) {
253        GTEST_LOG_(INFO) << "pid: " << pid << ", ppid:" << getppid();
254        DfxPtrace::Attach(pid);
255        uintptr_t value;
256        UnwindContext ctx;
257        ctx.pid = pid;
258        auto acc = std::make_shared<DfxAccessorsRemote>();
259        auto memory = std::make_shared<DfxMemory>(acc);
260        memory->SetCtx(&ctx);
261        uintptr_t addr = reinterpret_cast<uintptr_t>(&values[0]);
262        bool ret = memory->ReadUptr(addr, &value, false);
263        EXPECT_EQ(true, ret) << "DfxMemoryTest008: ret:" << ret;
264        uint64_t tmp;
265        memory->Read(addr, &tmp, sizeof(uint8_t), false);
266        EXPECT_EQ(tmp, 0x01);
267
268        memory->Read(addr, &tmp, sizeof(uint16_t), false);
269        EXPECT_EQ(tmp, 0x0201);
270
271        memory->Read(addr, &tmp, sizeof(uint32_t), false);
272        EXPECT_EQ(tmp, 0x04030201);
273
274        memory->Read(addr, &tmp, sizeof(uint64_t), false);
275        EXPECT_EQ(tmp, 0x0807060504030201);
276        DfxPtrace::Detach(pid);
277        _exit(0);
278    }
279    int status;
280    int ret = wait(&status);
281    GTEST_LOG_(INFO) << "Status:" << status << " Result:" << ret;
282    GTEST_LOG_(INFO) << "DfxMemoryTest008: end.";
283}
284
285/**
286 * @tc.name: DfxMemoryTest009
287 * @tc.desc: test DfxMemory class Read in remote case
288 * @tc.type: FUNC
289 */
290HWTEST_F(DfxMemoryTest, DfxMemoryTest009, TestSize.Level2)
291{
292    GTEST_LOG_(INFO) << "DfxMemoryTest009: start.";
293    static pid_t pid = getpid();
294    uint8_t values[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8};
295    pid_t child = fork();
296    if (child == 0) {
297        GTEST_LOG_(INFO) << "pid: " << pid << ", ppid:" << getppid();
298        DfxPtrace::Attach(pid);
299        UnwindContext ctx;
300        ctx.pid = pid;
301        auto acc = std::make_shared<DfxAccessorsRemote>();
302        auto memory = std::make_shared<DfxMemory>(acc);
303        memory->SetCtx(&ctx);
304        uintptr_t addr = reinterpret_cast<uintptr_t>(&values[0]);
305        uintptr_t value;
306        ASSERT_TRUE(memory->ReadUptr(addr, &value, false));
307#if defined(__arm__)
308        ASSERT_EQ(value, 0x04030201);
309#elif defined(__aarch64__)
310        ASSERT_EQ(value, 0x0807060504030201);
311#endif
312
313        uint64_t tmp;
314        ASSERT_TRUE(memory->Read(addr, &tmp, sizeof(uint8_t), false));
315        ASSERT_EQ(tmp, 0x01);
316
317        ASSERT_TRUE(memory->Read(addr, &tmp, sizeof(uint16_t), false));
318        ASSERT_EQ(tmp, 0x0201);
319
320        ASSERT_TRUE(memory->Read(addr, &tmp, sizeof(uint32_t), false));
321        ASSERT_EQ(tmp, 0x04030201);
322
323        ASSERT_TRUE(memory->Read(addr, &tmp, sizeof(uint64_t), false));
324        ASSERT_EQ(tmp, 0x0807060504030201);
325        DfxPtrace::Detach(pid);
326        _exit(0);
327    }
328    int status;
329    int ret = wait(&status);
330    GTEST_LOG_(INFO) << "Status:" << status << " Result:" << ret;
331    GTEST_LOG_(INFO) << "DfxMemoryTest009: end.";
332}
333
334/**
335 * @tc.name: DfxMemoryTest010
336 * @tc.desc: test DfxMemory class Read in remote case
337 * @tc.type: FUNC
338 */
339HWTEST_F(DfxMemoryTest, DfxMemoryTest010, TestSize.Level2)
340{
341    GTEST_LOG_(INFO) << "DfxMemoryTest010: start.";
342    static pid_t pid = getpid();
343    uint8_t values[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8};
344    pid_t child = fork();
345    if (child == 0) {
346        GTEST_LOG_(INFO) << "pid: " << pid << ", ppid:" << getppid();
347        DfxPtrace::Attach(pid);
348
349        UnwindContext ctx;
350        ctx.pid = pid;
351        auto acc = std::make_shared<DfxAccessorsRemote>();
352        auto memory = std::make_shared<DfxMemory>(acc);
353        memory->SetCtx(&ctx);
354        uintptr_t addr = reinterpret_cast<uintptr_t>(&values[0]);
355        uint8_t tmp8;
356        ASSERT_TRUE(memory->ReadU8(addr, &tmp8, false));
357        ASSERT_EQ(tmp8, 0x01);
358        uint16_t tmp16;
359        ASSERT_TRUE(memory->ReadU16(addr, &tmp16, false));
360        ASSERT_EQ(tmp16, 0x0201);
361        uint32_t tmp32;
362        ASSERT_TRUE(memory->ReadU32(addr, &tmp32, false));
363        ASSERT_EQ(tmp32, 0x04030201);
364        uint64_t tmp64;
365        ASSERT_TRUE(memory->ReadU64(addr, &tmp64, false));
366        ASSERT_EQ(tmp64, 0x0807060504030201);
367        DfxPtrace::Detach(pid);
368        _exit(0);
369    }
370    int status;
371    int ret = wait(&status);
372    GTEST_LOG_(INFO) << "Status:" << status << " Result:" << ret;
373    GTEST_LOG_(INFO) << "DfxMemoryTest010: end.";
374}
375
376/**
377 * @tc.name: DfxMemoryTest011
378 * @tc.desc: test DfxMemory class Read in remote case
379 * @tc.type: FUNC
380 */
381HWTEST_F(DfxMemoryTest, DfxMemoryTest011, TestSize.Level2)
382{
383    GTEST_LOG_(INFO) << "DfxMemoryTest011: start.";
384    static pid_t pid = getpid();
385    uint8_t values[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8};
386    char testStr[] = "Test ReadString Func";
387    pid_t child = fork();
388    if (child == 0) {
389        GTEST_LOG_(INFO) << "pid: " << pid << ", ppid:" << getppid();
390        DfxPtrace::Attach(getppid());
391        UnwindContext ctx;
392        ctx.pid = getppid();
393        auto acc = std::make_shared<DfxAccessorsRemote>();
394        auto memory = std::make_shared<DfxMemory>(acc);
395        memory->SetCtx(&ctx);
396        uintptr_t addr = reinterpret_cast<uintptr_t>(&values[0]);
397        std::string resultStr;
398        uintptr_t addrStr = reinterpret_cast<uintptr_t>(&testStr[0]);
399        ASSERT_TRUE(memory->ReadString(addrStr, &resultStr, sizeof(testStr)/sizeof(char), false));
400        ASSERT_EQ(testStr, resultStr);
401        ASSERT_TRUE(memory->ReadString(addrStr, &resultStr, sizeof(testStr)/sizeof(char), true));
402        ASSERT_EQ(testStr, resultStr);
403        ASSERT_EQ(memory->ReadUleb128(addr), 1U);
404        ASSERT_EQ(memory->ReadSleb128(addr), 2);
405        DfxPtrace::Detach(pid);
406        _exit(0);
407    }
408    int status;
409    int ret = wait(&status);
410    GTEST_LOG_(INFO) << "Status:" << status << " Result:" << ret;
411    GTEST_LOG_(INFO) << "DfxMemoryTest011: end.";
412}
413
414/**
415 * @tc.name: DfxMemoryTest012
416 * @tc.desc: test DfxMemory class Read in remote case
417 * @tc.type: FUNC
418 */
419HWTEST_F(DfxMemoryTest, DfxMemoryTest012, TestSize.Level2)
420{
421    GTEST_LOG_(INFO) << "DfxMemoryTest012: start.";
422    static pid_t pid = getpid();
423    pid_t child = fork();
424    if (child == 0) {
425        GTEST_LOG_(INFO) << "pid: " << pid << ", ppid:" << getppid();
426        DfxPtrace::Attach(pid);
427        UnwindContext ctx;
428        ctx.pid = pid;
429        auto acc = std::make_shared<DfxAccessorsRemote>();
430        auto memory = std::make_shared<DfxMemory>(acc);
431        memory->SetCtx(&ctx);
432        ASSERT_EQ(memory->GetEncodedSize(DW_EH_PE_absptr), sizeof(uintptr_t));
433        ASSERT_EQ(memory->GetEncodedSize(DW_EH_PE_sdata1), 1);
434        ASSERT_EQ(memory->GetEncodedSize(DW_EH_PE_sdata2), 2);
435        ASSERT_EQ(memory->GetEncodedSize(DW_EH_PE_sdata4), 4);
436        ASSERT_EQ(memory->GetEncodedSize(DW_EH_PE_sdata8), 8);
437        DfxPtrace::Detach(pid);
438        _exit(0);
439    }
440    int status;
441    int ret = wait(&status);
442    GTEST_LOG_(INFO) << "Status:" << status << " Result:" << ret;
443    GTEST_LOG_(INFO) << "DfxMemoryTest012: end.";
444}
445
446/**
447 * @tc.name: DfxMemoryTest013
448 * @tc.desc: test DfxMemory class Read in error case
449 * @tc.type: FUNC
450 */
451HWTEST_F(DfxMemoryTest, DfxMemoryTest013, TestSize.Level2)
452{
453    GTEST_LOG_(INFO) << "DfxMemoryTest013: start.";
454    auto acc = std::make_shared<DfxAccessorsLocal>();
455    auto memory = std::make_shared<DfxMemory>(acc);
456    uintptr_t val;
457    EXPECT_FALSE(memory->ReadReg(0, &val));
458    uintptr_t regs[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa};
459    UnwindContext ctx;
460    ctx.regs = DfxRegs::CreateFromRegs(UnwindMode::DWARF_UNWIND, regs, sizeof(regs) / sizeof(regs[0]));
461    memory->SetCtx(&ctx);
462    EXPECT_FALSE(memory->ReadReg(-1, &val));
463
464    uint8_t values[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8};
465    uintptr_t addr = reinterpret_cast<uintptr_t>(&values[0]);
466    EXPECT_FALSE(memory->ReadMem(addr, nullptr));
467    EXPECT_FALSE(memory->ReadUptr(addr, nullptr, false));
468    EXPECT_FALSE(memory->Read(addr, nullptr, sizeof(uint8_t), false));
469    EXPECT_FALSE(memory->ReadU8(addr, nullptr, false));
470    EXPECT_FALSE(memory->ReadU16(addr, nullptr, false));
471    EXPECT_FALSE(memory->ReadU32(addr, nullptr, false));
472    EXPECT_FALSE(memory->ReadU64(addr, nullptr, false));
473    GTEST_LOG_(INFO) << "DfxMemoryTest013: end.";
474}
475
476/**
477 * @tc.name: DfxMemoryTest014
478 * @tc.desc: test DfxMemory class ReadProcMemByPid
479 * @tc.type: FUNC
480 */
481HWTEST_F(DfxMemoryTest, DfxMemoryTest014, TestSize.Level2)
482{
483    GTEST_LOG_(INFO) << "DfxMemoryTest014: start.";
484    std::string res = ExecuteCommands("uname");
485    bool linuxKernel = res.find("Linux") != std::string::npos;
486    if (linuxKernel) {
487        ASSERT_TRUE(linuxKernel);
488        return;
489    }
490    pid_t pid = GetProcessPid(FOUNDATION_NAME);
491    auto maps = DfxMaps::Create(pid);
492    std::vector<std::shared_ptr<DfxMap>> shmmMaps;
493    ASSERT_TRUE(maps->FindMapsByName("[shmm]", shmmMaps));
494    std::shared_ptr<DfxMap> shmmMap = nullptr;
495    for (auto map : shmmMaps) {
496        if (map->IsMapExec()) {
497            shmmMap = map;
498            break;
499        }
500    }
501    ASSERT_TRUE(shmmMap != nullptr);
502    auto shmmData = std::make_shared<std::vector<uint8_t>>(shmmMap->end - shmmMap->begin);
503    DfxMemory::ReadProcMemByPid(pid, shmmMap->begin, shmmData->data(), shmmMap->end - shmmMap->begin);
504    auto shmmElf = std::make_shared<DfxElf>(shmmData->data(), shmmMap->end - shmmMap->begin);
505    ASSERT_TRUE(shmmElf->IsValid());
506    std::vector<DfxSymbol> shmmSyms;
507    DfxSymbols::ParseSymbols(shmmSyms, shmmElf, "");
508    GTEST_LOG_(INFO) << "shmm symbols size" << shmmSyms.size();
509    ASSERT_GT(shmmSyms.size(), 0);
510    for (auto& sym : shmmSyms) {
511        GTEST_LOG_(INFO) << sym.ToDebugString();
512    }
513    GTEST_LOG_(INFO) << "DfxMemoryTest014 : end.";
514}
515}
516} // namespace HiviewDFX
517} // namespace OHOS
518