1800b99b8Sopenharmony_ci/*
2800b99b8Sopenharmony_ci * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License.
5800b99b8Sopenharmony_ci * You may obtain a copy of the License at
6800b99b8Sopenharmony_ci *
7800b99b8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8800b99b8Sopenharmony_ci *
9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and
13800b99b8Sopenharmony_ci * limitations under the License.
14800b99b8Sopenharmony_ci */
15800b99b8Sopenharmony_ci
16800b99b8Sopenharmony_ci#include "dfx_mmap.h"
17800b99b8Sopenharmony_ci
18800b99b8Sopenharmony_ci#include <fcntl.h>
19800b99b8Sopenharmony_ci#include <securec.h>
20800b99b8Sopenharmony_ci
21800b99b8Sopenharmony_ci#include "dfx_define.h"
22800b99b8Sopenharmony_ci#include "dfx_log.h"
23800b99b8Sopenharmony_ci#include "dfx_util.h"
24800b99b8Sopenharmony_ci
25800b99b8Sopenharmony_cinamespace OHOS {
26800b99b8Sopenharmony_cinamespace HiviewDFX {
27800b99b8Sopenharmony_cinamespace {
28800b99b8Sopenharmony_ci#undef LOG_DOMAIN
29800b99b8Sopenharmony_ci#undef LOG_TAG
30800b99b8Sopenharmony_ci#define LOG_DOMAIN 0xD002D11
31800b99b8Sopenharmony_ci#define LOG_TAG "DfxMmap"
32800b99b8Sopenharmony_ci}
33800b99b8Sopenharmony_ci
34800b99b8Sopenharmony_cibool DfxMmap::Init(const int fd, const size_t size, const off_t offset)
35800b99b8Sopenharmony_ci{
36800b99b8Sopenharmony_ci    Clear();
37800b99b8Sopenharmony_ci
38800b99b8Sopenharmony_ci    if (fd < 0) {
39800b99b8Sopenharmony_ci        return false;
40800b99b8Sopenharmony_ci    }
41800b99b8Sopenharmony_ci    mmap_ = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, offset);
42800b99b8Sopenharmony_ci    if (mmap_ == MAP_FAILED) {
43800b99b8Sopenharmony_ci        DFXLOGE("Failed to mmap, errno(%{public}d)", errno);
44800b99b8Sopenharmony_ci        size_ = 0;
45800b99b8Sopenharmony_ci        return false;
46800b99b8Sopenharmony_ci    }
47800b99b8Sopenharmony_ci    size_ = size;
48800b99b8Sopenharmony_ci    DFXLOGD("mmap size %{public}zu", size_);
49800b99b8Sopenharmony_ci    return true;
50800b99b8Sopenharmony_ci}
51800b99b8Sopenharmony_ci
52800b99b8Sopenharmony_cibool DfxMmap::Init(uint8_t *decompressedData, size_t size)
53800b99b8Sopenharmony_ci{
54800b99b8Sopenharmony_ci    if (!decompressedData || size == 0) {
55800b99b8Sopenharmony_ci        return false;
56800b99b8Sopenharmony_ci    }
57800b99b8Sopenharmony_ci
58800b99b8Sopenharmony_ci    // this pointer was managed by shared_ptr will not occur double free issue.
59800b99b8Sopenharmony_ci    mmap_ = decompressedData;
60800b99b8Sopenharmony_ci    size_ = size;
61800b99b8Sopenharmony_ci    return true;
62800b99b8Sopenharmony_ci}
63800b99b8Sopenharmony_ci
64800b99b8Sopenharmony_civoid DfxMmap::Clear()
65800b99b8Sopenharmony_ci{
66800b99b8Sopenharmony_ci    if ((mmap_ != MAP_FAILED) && (needUnmap_)) {
67800b99b8Sopenharmony_ci        munmap(mmap_, size_);
68800b99b8Sopenharmony_ci        mmap_ = MAP_FAILED;
69800b99b8Sopenharmony_ci    }
70800b99b8Sopenharmony_ci}
71800b99b8Sopenharmony_ci
72800b99b8Sopenharmony_cisize_t DfxMmap::Read(uintptr_t& addr, void* val, size_t size, bool incre)
73800b99b8Sopenharmony_ci{
74800b99b8Sopenharmony_ci    if ((mmap_ == MAP_FAILED) || (val == nullptr)) {
75800b99b8Sopenharmony_ci        return 0;
76800b99b8Sopenharmony_ci    }
77800b99b8Sopenharmony_ci
78800b99b8Sopenharmony_ci    size_t ptr = static_cast<size_t>(addr);
79800b99b8Sopenharmony_ci    if (ptr >= size_) {
80800b99b8Sopenharmony_ci        DFXLOGU("pos: %{public}zu, size: %{public}zu", ptr, size_);
81800b99b8Sopenharmony_ci        return 0;
82800b99b8Sopenharmony_ci    }
83800b99b8Sopenharmony_ci
84800b99b8Sopenharmony_ci    size_t left = size_ - ptr;
85800b99b8Sopenharmony_ci    const uint8_t* actualBase = static_cast<const uint8_t*>(mmap_) + ptr;
86800b99b8Sopenharmony_ci    size_t actualLen = std::min(left, size);
87800b99b8Sopenharmony_ci    if (memcpy_s(val, actualLen, actualBase, actualLen) != 0) {
88800b99b8Sopenharmony_ci        DFXLOGE("Failed to memcpy_s");
89800b99b8Sopenharmony_ci        return 0;
90800b99b8Sopenharmony_ci    }
91800b99b8Sopenharmony_ci    if (incre) {
92800b99b8Sopenharmony_ci        addr += actualLen;
93800b99b8Sopenharmony_ci    }
94800b99b8Sopenharmony_ci    return actualLen;
95800b99b8Sopenharmony_ci}
96800b99b8Sopenharmony_ci} // namespace HiviewDFX
97800b99b8Sopenharmony_ci} // namespace OHOS
98