1800b99b8Sopenharmony_ci/*
2800b99b8Sopenharmony_ci * Copyright (c) 2021-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 "process_dumper.h"
17800b99b8Sopenharmony_ci
18800b99b8Sopenharmony_ci#include <algorithm>
19800b99b8Sopenharmony_ci#include <cerrno>
20800b99b8Sopenharmony_ci#include <chrono>
21800b99b8Sopenharmony_ci#include <cinttypes>
22800b99b8Sopenharmony_ci#include <csignal>
23800b99b8Sopenharmony_ci#include <cstdio>
24800b99b8Sopenharmony_ci#include <cstdlib>
25800b99b8Sopenharmony_ci#include <cstring>
26800b99b8Sopenharmony_ci#include <dirent.h>
27800b99b8Sopenharmony_ci#include <fcntl.h>
28800b99b8Sopenharmony_ci#include <memory>
29800b99b8Sopenharmony_ci#include <pthread.h>
30800b99b8Sopenharmony_ci#include <securec.h>
31800b99b8Sopenharmony_ci#include <string>
32800b99b8Sopenharmony_ci#include <syscall.h>
33800b99b8Sopenharmony_ci#include <sys/time.h>
34800b99b8Sopenharmony_ci#include <sys/types.h>
35800b99b8Sopenharmony_ci#include <sys/ptrace.h>
36800b99b8Sopenharmony_ci#include <ucontext.h>
37800b99b8Sopenharmony_ci#include <unistd.h>
38800b99b8Sopenharmony_ci
39800b99b8Sopenharmony_ci#include "cppcrash_reporter.h"
40800b99b8Sopenharmony_ci#include "crash_exception.h"
41800b99b8Sopenharmony_ci#include "dfx_config.h"
42800b99b8Sopenharmony_ci#include "dfx_define.h"
43800b99b8Sopenharmony_ci#include "dfx_dump_request.h"
44800b99b8Sopenharmony_ci#include "dfx_dump_res.h"
45800b99b8Sopenharmony_ci#include "dfx_fdsan.h"
46800b99b8Sopenharmony_ci#include "dfx_logger.h"
47800b99b8Sopenharmony_ci#include "dfx_process.h"
48800b99b8Sopenharmony_ci#include "dfx_regs.h"
49800b99b8Sopenharmony_ci#include "dfx_ring_buffer_wrapper.h"
50800b99b8Sopenharmony_ci#include "dfx_stack_info_formatter.h"
51800b99b8Sopenharmony_ci#include "dfx_thread.h"
52800b99b8Sopenharmony_ci#include "dfx_unwind_remote.h"
53800b99b8Sopenharmony_ci#include "dfx_util.h"
54800b99b8Sopenharmony_ci#include "dfx_trace.h"
55800b99b8Sopenharmony_ci#include "elapsed_time.h"
56800b99b8Sopenharmony_ci#include "faultloggerd_client.h"
57800b99b8Sopenharmony_ci#ifndef HISYSEVENT_DISABLE
58800b99b8Sopenharmony_ci#include "hisysevent.h"
59800b99b8Sopenharmony_ci#endif
60800b99b8Sopenharmony_ci#include "printer.h"
61800b99b8Sopenharmony_ci#include "procinfo.h"
62800b99b8Sopenharmony_ci#include "unwinder_config.h"
63800b99b8Sopenharmony_ci#ifndef is_ohos_lite
64800b99b8Sopenharmony_ci#include "parameter.h"
65800b99b8Sopenharmony_ci#include "parameters.h"
66800b99b8Sopenharmony_ci#endif // !is_ohos_lite
67800b99b8Sopenharmony_ci
68800b99b8Sopenharmony_cinamespace OHOS {
69800b99b8Sopenharmony_cinamespace HiviewDFX {
70800b99b8Sopenharmony_cinamespace {
71800b99b8Sopenharmony_ci#undef LOG_DOMAIN
72800b99b8Sopenharmony_ci#undef LOG_TAG
73800b99b8Sopenharmony_ci#define LOG_DOMAIN 0xD002D11
74800b99b8Sopenharmony_ci#define LOG_TAG "DfxProcessDump"
75800b99b8Sopenharmony_ciconst char *const BLOCK_CRASH_PROCESS = "faultloggerd.priv.block_crash_process.enabled";
76800b99b8Sopenharmony_ci
77800b99b8Sopenharmony_cistatic bool IsBlockCrashProcess()
78800b99b8Sopenharmony_ci{
79800b99b8Sopenharmony_ci    bool isBlockCrash = false;
80800b99b8Sopenharmony_ci#ifndef is_ohos_lite
81800b99b8Sopenharmony_ci    isBlockCrash = OHOS::system::GetParameter(BLOCK_CRASH_PROCESS, "false") == "true";
82800b99b8Sopenharmony_ci#endif
83800b99b8Sopenharmony_ci    return isBlockCrash;
84800b99b8Sopenharmony_ci}
85800b99b8Sopenharmony_ci
86800b99b8Sopenharmony_civoid WriteData(int fd, const std::string& data, size_t blockSize)
87800b99b8Sopenharmony_ci{
88800b99b8Sopenharmony_ci    size_t dataSize = data.length();
89800b99b8Sopenharmony_ci    size_t index = 0;
90800b99b8Sopenharmony_ci    while (index < dataSize) {
91800b99b8Sopenharmony_ci        size_t writeLength = (index + blockSize) <= dataSize ? blockSize : (dataSize - index);
92800b99b8Sopenharmony_ci        ssize_t nwrite = OHOS_TEMP_FAILURE_RETRY(write(fd, data.substr(index, writeLength).c_str(), writeLength));
93800b99b8Sopenharmony_ci        if (nwrite != static_cast<ssize_t>(writeLength)) {
94800b99b8Sopenharmony_ci            DFXLOGI("%{public}s :: nwrite: %{public}zd, writeLength: %{public}zu", __func__, nwrite, writeLength);
95800b99b8Sopenharmony_ci        }
96800b99b8Sopenharmony_ci        index += writeLength;
97800b99b8Sopenharmony_ci    }
98800b99b8Sopenharmony_ci    DFXLOGI("%{public}s :: needWriteDataSize: %{public}zu, writeDataSize: %{public}zu", __func__, dataSize, index);
99800b99b8Sopenharmony_ci}
100800b99b8Sopenharmony_ci
101800b99b8Sopenharmony_ci#if !defined(__x86_64__)
102800b99b8Sopenharmony_ciconst int ARG_MAX_NUM = 131072;
103800b99b8Sopenharmony_ci#endif
104800b99b8Sopenharmony_ciusing OpenFilesList = std::map<int, FDInfo>;
105800b99b8Sopenharmony_ci
106800b99b8Sopenharmony_cibool ReadLink(std::string &src, std::string &dst)
107800b99b8Sopenharmony_ci{
108800b99b8Sopenharmony_ci    char buf[PATH_MAX];
109800b99b8Sopenharmony_ci    ssize_t count = readlink(src.c_str(), buf, sizeof(buf) - 1);
110800b99b8Sopenharmony_ci    if (count < 0) {
111800b99b8Sopenharmony_ci        return false;
112800b99b8Sopenharmony_ci    }
113800b99b8Sopenharmony_ci    buf[count] = '\0';
114800b99b8Sopenharmony_ci    dst = buf;
115800b99b8Sopenharmony_ci    return true;
116800b99b8Sopenharmony_ci}
117800b99b8Sopenharmony_ci
118800b99b8Sopenharmony_civoid CollectOpenFiles(OpenFilesList &list, pid_t pid)
119800b99b8Sopenharmony_ci{
120800b99b8Sopenharmony_ci    std::string fdDirName = "/proc/" + std::to_string(pid) + "/fd";
121800b99b8Sopenharmony_ci    std::unique_ptr<DIR, int (*)(DIR *)> dir(opendir(fdDirName.c_str()), closedir);
122800b99b8Sopenharmony_ci    if (dir == nullptr) {
123800b99b8Sopenharmony_ci        DFXLOGE("failed to open directory %{public}s: %{public}s", fdDirName.c_str(), strerror(errno));
124800b99b8Sopenharmony_ci        return;
125800b99b8Sopenharmony_ci    }
126800b99b8Sopenharmony_ci
127800b99b8Sopenharmony_ci    struct dirent *de;
128800b99b8Sopenharmony_ci    while ((de = readdir(dir.get())) != nullptr) {
129800b99b8Sopenharmony_ci        if (*de->d_name == '.') {
130800b99b8Sopenharmony_ci            continue;
131800b99b8Sopenharmony_ci        }
132800b99b8Sopenharmony_ci
133800b99b8Sopenharmony_ci        int fd = atoi(de->d_name);
134800b99b8Sopenharmony_ci        std::string path = fdDirName + "/" + std::string(de->d_name);
135800b99b8Sopenharmony_ci        std::string target;
136800b99b8Sopenharmony_ci        if (ReadLink(path, target)) {
137800b99b8Sopenharmony_ci            list[fd].path = target;
138800b99b8Sopenharmony_ci        } else {
139800b99b8Sopenharmony_ci            list[fd].path = "???";
140800b99b8Sopenharmony_ci            DFXLOGE("failed to readlink %{public}s: %{public}s", path.c_str(), strerror(errno));
141800b99b8Sopenharmony_ci        }
142800b99b8Sopenharmony_ci    }
143800b99b8Sopenharmony_ci}
144800b99b8Sopenharmony_ci
145800b99b8Sopenharmony_ci#if !defined(__x86_64__)
146800b99b8Sopenharmony_civoid FillFdsaninfo(OpenFilesList &list, pid_t nsPid, uint64_t fdTableAddr)
147800b99b8Sopenharmony_ci{
148800b99b8Sopenharmony_ci    constexpr size_t fds = sizeof(FdTable::entries) / sizeof(*FdTable::entries);
149800b99b8Sopenharmony_ci    size_t entryOffset = offsetof(FdTable, entries);
150800b99b8Sopenharmony_ci    uint64_t addr = fdTableAddr + entryOffset;
151800b99b8Sopenharmony_ci    FdEntry entrys[fds];
152800b99b8Sopenharmony_ci    if (DfxMemory::ReadProcMemByPid(nsPid, addr, entrys, sizeof(FdEntry) * fds) != sizeof(FdEntry) * fds) {
153800b99b8Sopenharmony_ci        DFXLOGE("[%{public}d]: read nsPid mem error %{public}s", __LINE__, strerror(errno));
154800b99b8Sopenharmony_ci        return;
155800b99b8Sopenharmony_ci    }
156800b99b8Sopenharmony_ci    for (size_t i = 0; i < fds; i++) {
157800b99b8Sopenharmony_ci        if (entrys[i].close_tag) {
158800b99b8Sopenharmony_ci            list[i].fdsanOwner = entrys[i].close_tag;
159800b99b8Sopenharmony_ci        }
160800b99b8Sopenharmony_ci    }
161800b99b8Sopenharmony_ci
162800b99b8Sopenharmony_ci    size_t overflowOffset = offsetof(FdTable, overflow);
163800b99b8Sopenharmony_ci    uintptr_t overflow = 0;
164800b99b8Sopenharmony_ci    uint64_t tmp = fdTableAddr + overflowOffset;
165800b99b8Sopenharmony_ci    if (DfxMemory::ReadProcMemByPid(nsPid, tmp, &overflow, sizeof(overflow)) != sizeof(overflow)) {
166800b99b8Sopenharmony_ci        return;
167800b99b8Sopenharmony_ci    }
168800b99b8Sopenharmony_ci    if (!overflow) {
169800b99b8Sopenharmony_ci        return;
170800b99b8Sopenharmony_ci    }
171800b99b8Sopenharmony_ci
172800b99b8Sopenharmony_ci    size_t overflowLength;
173800b99b8Sopenharmony_ci    if (DfxMemory::ReadProcMemByPid(nsPid, overflow, &overflowLength, sizeof(overflowLength))
174800b99b8Sopenharmony_ci        != sizeof(overflowLength)) {
175800b99b8Sopenharmony_ci        return;
176800b99b8Sopenharmony_ci    }
177800b99b8Sopenharmony_ci    if (overflowLength > ARG_MAX_NUM) {
178800b99b8Sopenharmony_ci        return;
179800b99b8Sopenharmony_ci    }
180800b99b8Sopenharmony_ci
181800b99b8Sopenharmony_ci    std::vector<FdEntry> overflowFdEntrys(overflowLength);
182800b99b8Sopenharmony_ci    uint64_t address = overflow + offsetof(FdTableOverflow, entries);
183800b99b8Sopenharmony_ci    if (DfxMemory::ReadProcMemByPid(nsPid, address, overflowFdEntrys.data(), sizeof(FdEntry) * overflowLength) !=
184800b99b8Sopenharmony_ci        sizeof(FdEntry) * overflowLength) {
185800b99b8Sopenharmony_ci        DFXLOGE("[%{public}d]: read nsPid mem error %{public}s", __LINE__, strerror(errno));
186800b99b8Sopenharmony_ci        return;
187800b99b8Sopenharmony_ci    }
188800b99b8Sopenharmony_ci    size_t fdIndex = fds;
189800b99b8Sopenharmony_ci    for (size_t i = 0; i < overflowLength; i++) {
190800b99b8Sopenharmony_ci        if (overflowFdEntrys[i].close_tag) {
191800b99b8Sopenharmony_ci            list[fdIndex].fdsanOwner = overflowFdEntrys[i].close_tag;
192800b99b8Sopenharmony_ci        }
193800b99b8Sopenharmony_ci        fdIndex++;
194800b99b8Sopenharmony_ci    }
195800b99b8Sopenharmony_ci}
196800b99b8Sopenharmony_ci#endif
197800b99b8Sopenharmony_ci
198800b99b8Sopenharmony_cistd::string DumpOpenFiles(OpenFilesList &files)
199800b99b8Sopenharmony_ci{
200800b99b8Sopenharmony_ci    std::string openFiles;
201800b99b8Sopenharmony_ci    for (auto &[fd, entry]: files) {
202800b99b8Sopenharmony_ci        const std::string path = entry.path;
203800b99b8Sopenharmony_ci        uint64_t tag = entry.fdsanOwner;
204800b99b8Sopenharmony_ci        const char* type = fdsan_get_tag_type(tag);
205800b99b8Sopenharmony_ci        uint64_t val = fdsan_get_tag_value(tag);
206800b99b8Sopenharmony_ci        if (!path.empty()) {
207800b99b8Sopenharmony_ci            openFiles += std::to_string(fd) + "->" + path + " " + type + " " + std::to_string(val) + "\n";
208800b99b8Sopenharmony_ci        } else {
209800b99b8Sopenharmony_ci            openFiles += "OpenFilesList contain an entry (fd " + std::to_string(fd) + ") with no path or owner\n";
210800b99b8Sopenharmony_ci        }
211800b99b8Sopenharmony_ci    }
212800b99b8Sopenharmony_ci    return openFiles;
213800b99b8Sopenharmony_ci}
214800b99b8Sopenharmony_ci
215800b99b8Sopenharmony_civoid ReadPids(int& realPid, int& vmPid)
216800b99b8Sopenharmony_ci{
217800b99b8Sopenharmony_ci    pid_t pids[PID_MAX] = {0};
218800b99b8Sopenharmony_ci    OHOS_TEMP_FAILURE_RETRY(read(STDIN_FILENO, pids, sizeof(pids)));
219800b99b8Sopenharmony_ci    realPid = pids[REAL_PROCESS_PID];
220800b99b8Sopenharmony_ci    vmPid = pids[VIRTUAL_PROCESS_PID];
221800b99b8Sopenharmony_ci    DFXLOGW("procecdump get real pid is %{public}d vm pid is %{public}d", realPid, vmPid);
222800b99b8Sopenharmony_ci}
223800b99b8Sopenharmony_ci
224800b99b8Sopenharmony_civoid InfoRemoteProcessResult(std::shared_ptr<ProcessDumpRequest> request, int result, int type)
225800b99b8Sopenharmony_ci{
226800b99b8Sopenharmony_ci    if (request == nullptr) {
227800b99b8Sopenharmony_ci        return;
228800b99b8Sopenharmony_ci    }
229800b99b8Sopenharmony_ci    if (request->pmPipeFd[0] != -1) {
230800b99b8Sopenharmony_ci        close(request->pmPipeFd[0]);
231800b99b8Sopenharmony_ci        request->pmPipeFd[0] = -1;
232800b99b8Sopenharmony_ci    }
233800b99b8Sopenharmony_ci    switch (type) {
234800b99b8Sopenharmony_ci        case MAIN_PROCESS:
235800b99b8Sopenharmony_ci            OHOS_TEMP_FAILURE_RETRY(write(request->pmPipeFd[1], &result, sizeof(result)));
236800b99b8Sopenharmony_ci            break;
237800b99b8Sopenharmony_ci        case VIRTUAL_PROCESS:
238800b99b8Sopenharmony_ci            OHOS_TEMP_FAILURE_RETRY(write(request->vmPipeFd[1], &result, sizeof(result)));
239800b99b8Sopenharmony_ci            break;
240800b99b8Sopenharmony_ci        default:
241800b99b8Sopenharmony_ci            break;
242800b99b8Sopenharmony_ci    }
243800b99b8Sopenharmony_ci}
244800b99b8Sopenharmony_ci
245800b99b8Sopenharmony_civoid SetProcessdumpTimeout(siginfo_t &si)
246800b99b8Sopenharmony_ci{
247800b99b8Sopenharmony_ci    if (si.si_signo != SIGDUMP) {
248800b99b8Sopenharmony_ci        return;
249800b99b8Sopenharmony_ci    }
250800b99b8Sopenharmony_ci
251800b99b8Sopenharmony_ci    uint64_t endTime;
252800b99b8Sopenharmony_ci    int tid;
253800b99b8Sopenharmony_ci    ParseSiValue(si, endTime, tid);
254800b99b8Sopenharmony_ci
255800b99b8Sopenharmony_ci    if (tid == 0) {
256800b99b8Sopenharmony_ci        DFXLOGI("reset, prevent incorrect reading sival_int for tid");
257800b99b8Sopenharmony_ci        si.si_value.sival_int = 0;
258800b99b8Sopenharmony_ci    }
259800b99b8Sopenharmony_ci
260800b99b8Sopenharmony_ci    if (endTime == 0) {
261800b99b8Sopenharmony_ci        DFXLOGI("end time is zero, not set new alarm");
262800b99b8Sopenharmony_ci        return;
263800b99b8Sopenharmony_ci    }
264800b99b8Sopenharmony_ci
265800b99b8Sopenharmony_ci    uint64_t curTime = GetAbsTimeMilliSeconds();
266800b99b8Sopenharmony_ci    if (curTime >= endTime) {
267800b99b8Sopenharmony_ci        DFXLOGI("now has timeout, processdump exit");
268800b99b8Sopenharmony_ci#ifndef CLANG_COVERAGE
269800b99b8Sopenharmony_ci        _exit(0);
270800b99b8Sopenharmony_ci#endif
271800b99b8Sopenharmony_ci    }
272800b99b8Sopenharmony_ci    uint64_t diffTime = endTime - curTime;
273800b99b8Sopenharmony_ci
274800b99b8Sopenharmony_ci    DFXLOGI("processdump remain time%{public}" PRIu64 "ms", diffTime);
275800b99b8Sopenharmony_ci    if (diffTime > PROCESSDUMP_TIMEOUT * NUMBER_ONE_THOUSAND) {
276800b99b8Sopenharmony_ci        DFXLOGE("dump remain time is invalid, not set timer");
277800b99b8Sopenharmony_ci        return;
278800b99b8Sopenharmony_ci    }
279800b99b8Sopenharmony_ci
280800b99b8Sopenharmony_ci    struct itimerval timer;
281800b99b8Sopenharmony_ci    timer.it_value.tv_sec = static_cast<int64_t>(diffTime / NUMBER_ONE_THOUSAND);
282800b99b8Sopenharmony_ci    timer.it_value.tv_usec = static_cast<int64_t>(diffTime * NUMBER_ONE_THOUSAND % NUMBER_ONE_MILLION);
283800b99b8Sopenharmony_ci    timer.it_interval.tv_sec = 0;
284800b99b8Sopenharmony_ci    timer.it_interval.tv_usec = 0;
285800b99b8Sopenharmony_ci
286800b99b8Sopenharmony_ci    if (setitimer(ITIMER_REAL, &timer, nullptr) != 0) {
287800b99b8Sopenharmony_ci        DFXLOGE("start processdump timer fail %{public}d", errno);
288800b99b8Sopenharmony_ci    }
289800b99b8Sopenharmony_ci}
290800b99b8Sopenharmony_ci}
291800b99b8Sopenharmony_ci
292800b99b8Sopenharmony_ciProcessDumper &ProcessDumper::GetInstance()
293800b99b8Sopenharmony_ci{
294800b99b8Sopenharmony_ci    static ProcessDumper ins;
295800b99b8Sopenharmony_ci    return ins;
296800b99b8Sopenharmony_ci}
297800b99b8Sopenharmony_ci
298800b99b8Sopenharmony_civoid ProcessDumper::Dump()
299800b99b8Sopenharmony_ci{
300800b99b8Sopenharmony_ci    startTime_ = GetTimeMillisec();
301800b99b8Sopenharmony_ci    std::shared_ptr<ProcessDumpRequest> request = std::make_shared<ProcessDumpRequest>();
302800b99b8Sopenharmony_ci    resDump_ = DumpProcess(request);
303800b99b8Sopenharmony_ci    if (process_ == nullptr) {
304800b99b8Sopenharmony_ci        DFXLOGE("Dump process failed, please check permission and whether pid is valid.");
305800b99b8Sopenharmony_ci    } else {
306800b99b8Sopenharmony_ci        if (isCrash_ && process_->vmThread_ != nullptr) {
307800b99b8Sopenharmony_ci            process_->vmThread_->Detach();
308800b99b8Sopenharmony_ci        }
309800b99b8Sopenharmony_ci        if (process_->keyThread_ != nullptr) {
310800b99b8Sopenharmony_ci            process_->keyThread_->Detach();
311800b99b8Sopenharmony_ci        }
312800b99b8Sopenharmony_ci        if (isCrash_ && (request->dumpMode == FUSION_MODE) && IsBlockCrashProcess()) {
313800b99b8Sopenharmony_ci            DFXLOGI("start block crash process pid %{public}d nspid %{public}d", request->pid, request->nsPid);
314800b99b8Sopenharmony_ci            if (syscall(SYS_tgkill, request->nsPid, request->tid, SIGSTOP) != 0) {
315800b99b8Sopenharmony_ci                DFXLOGE("send signal stop to nsPid %{public}d fail %{public}s", request->nsPid, strerror(errno));
316800b99b8Sopenharmony_ci            }
317800b99b8Sopenharmony_ci        }
318800b99b8Sopenharmony_ci    }
319800b99b8Sopenharmony_ci
320800b99b8Sopenharmony_ci    std::string jsonInfo;
321800b99b8Sopenharmony_ci    if (isJsonDump_ || isCrash_) {
322800b99b8Sopenharmony_ci        DfxStackInfoFormatter formatter(process_, request);
323800b99b8Sopenharmony_ci        formatter.GetStackInfo(isJsonDump_, jsonInfo);
324800b99b8Sopenharmony_ci        DFXLOGI("Finish GetStackInfo len %{public}" PRIuPTR "", jsonInfo.length());
325800b99b8Sopenharmony_ci        if (isJsonDump_) {
326800b99b8Sopenharmony_ci            WriteData(jsonFd_, jsonInfo, MAX_PIPE_SIZE);
327800b99b8Sopenharmony_ci        }
328800b99b8Sopenharmony_ci    }
329800b99b8Sopenharmony_ci
330800b99b8Sopenharmony_ci    finishTime_ = GetTimeMillisec();
331800b99b8Sopenharmony_ci    ReportSigDumpStats(request);
332800b99b8Sopenharmony_ci    // After skipping InitPrintThread due to ptrace failure or other reasons,
333800b99b8Sopenharmony_ci    // request resFd_ to write back the result to dumpcatch
334800b99b8Sopenharmony_ci    if (request->siginfo.si_signo == SIGDUMP && resFd_ == -1) {
335800b99b8Sopenharmony_ci        resFd_ = RequestPipeFd(request->pid, FaultLoggerPipeType::PIPE_FD_JSON_WRITE_RES);
336800b99b8Sopenharmony_ci        if (resFd_ < 0) {
337800b99b8Sopenharmony_ci            resFd_ = RequestPipeFd(request->pid, FaultLoggerPipeType::PIPE_FD_WRITE_RES);
338800b99b8Sopenharmony_ci        }
339800b99b8Sopenharmony_ci    }
340800b99b8Sopenharmony_ci    WriteDumpRes(resDump_);
341800b99b8Sopenharmony_ci    // print keythread base info to hilog when carsh
342800b99b8Sopenharmony_ci    DfxRingBufferWrapper::GetInstance().PrintBaseInfo();
343800b99b8Sopenharmony_ci    DfxRingBufferWrapper::GetInstance().StopThread();
344800b99b8Sopenharmony_ci    DFXLOGW("Finish dump stacktrace for %{public}s(%{public}d:%{public}d).",
345800b99b8Sopenharmony_ci        request->processName, request->pid, request->tid);
346800b99b8Sopenharmony_ci    Report(request, jsonInfo);
347800b99b8Sopenharmony_ci}
348800b99b8Sopenharmony_ci
349800b99b8Sopenharmony_civoid ProcessDumper::Report(std::shared_ptr<ProcessDumpRequest> request, std::string &jsonInfo)
350800b99b8Sopenharmony_ci{
351800b99b8Sopenharmony_ci    if (request == nullptr) {
352800b99b8Sopenharmony_ci        DFXLOGE("request is nullptr.");
353800b99b8Sopenharmony_ci        return;
354800b99b8Sopenharmony_ci    }
355800b99b8Sopenharmony_ci    if (request->msg.type == MESSAGE_FDSAN_DEBUG ||
356800b99b8Sopenharmony_ci        request->msg.type == MESSAGE_JEMALLOC ||
357800b99b8Sopenharmony_ci        request->msg.type == MESSAGE_BADFD) {
358800b99b8Sopenharmony_ci        ReportAddrSanitizer(*request, jsonInfo);
359800b99b8Sopenharmony_ci        return;
360800b99b8Sopenharmony_ci    }
361800b99b8Sopenharmony_ci    if (resDump_ != DumpErrorCode::DUMP_ENOMAP && resDump_ != DumpErrorCode::DUMP_EREADPID) {
362800b99b8Sopenharmony_ci        ReportCrashInfo(jsonInfo);
363800b99b8Sopenharmony_ci    }
364800b99b8Sopenharmony_ci    if ((request->dumpMode == FUSION_MODE) && isCrash_) {
365800b99b8Sopenharmony_ci        InfoRemoteProcessResult(request, OPE_CONTINUE, MAIN_PROCESS);
366800b99b8Sopenharmony_ci    }
367800b99b8Sopenharmony_ci}
368800b99b8Sopenharmony_ci
369800b99b8Sopenharmony_cistatic int32_t ReadRequestAndCheck(std::shared_ptr<ProcessDumpRequest> request)
370800b99b8Sopenharmony_ci{
371800b99b8Sopenharmony_ci    DFX_TRACE_SCOPED("ReadRequestAndCheck");
372800b99b8Sopenharmony_ci    ElapsedTime counter("ReadRequestAndCheck", 20); // 20 : limit cost time 20 ms
373800b99b8Sopenharmony_ci    ssize_t readCount = OHOS_TEMP_FAILURE_RETRY(read(STDIN_FILENO, request.get(), sizeof(ProcessDumpRequest)));
374800b99b8Sopenharmony_ci    request->threadName[NAME_BUF_LEN - 1] = '\0';
375800b99b8Sopenharmony_ci    request->processName[NAME_BUF_LEN - 1] = '\0';
376800b99b8Sopenharmony_ci    request->msg.body[MAX_FATAL_MSG_SIZE - 1] = '\0';
377800b99b8Sopenharmony_ci    request->appRunningId[MAX_APP_RUNNING_UNIQUE_ID_LEN - 1] = '\0';
378800b99b8Sopenharmony_ci    if (readCount != static_cast<long>(sizeof(ProcessDumpRequest))) {
379800b99b8Sopenharmony_ci        DFXLOGE("Failed to read DumpRequest(%{public}d), readCount(%{public}zd).", errno, readCount);
380800b99b8Sopenharmony_ci        ReportCrashException(request->processName, request->pid, request->uid,
381800b99b8Sopenharmony_ci                             CrashExceptionCode::CRASH_DUMP_EREADREQ);
382800b99b8Sopenharmony_ci        return DumpErrorCode::DUMP_EREADREQUEST;
383800b99b8Sopenharmony_ci    }
384800b99b8Sopenharmony_ci
385800b99b8Sopenharmony_ci    return DumpErrorCode::DUMP_ESUCCESS;
386800b99b8Sopenharmony_ci}
387800b99b8Sopenharmony_ci
388800b99b8Sopenharmony_cistd::string GetOpenFiles(int32_t pid, int nsPid, uint64_t fdTableAddr)
389800b99b8Sopenharmony_ci{
390800b99b8Sopenharmony_ci    DFX_TRACE_SCOPED("GetOpenFiles");
391800b99b8Sopenharmony_ci    OpenFilesList openFies;
392800b99b8Sopenharmony_ci    CollectOpenFiles(openFies, pid);
393800b99b8Sopenharmony_ci#if !defined(__x86_64__)
394800b99b8Sopenharmony_ci    FillFdsaninfo(openFies, nsPid, fdTableAddr);
395800b99b8Sopenharmony_ci#endif
396800b99b8Sopenharmony_ci    std::string fds = DumpOpenFiles(openFies);
397800b99b8Sopenharmony_ci    DFXLOGI("get open files info finish");
398800b99b8Sopenharmony_ci    return fds;
399800b99b8Sopenharmony_ci}
400800b99b8Sopenharmony_ci
401800b99b8Sopenharmony_civoid ProcessDumper::InitRegs(std::shared_ptr<ProcessDumpRequest> request, int &dumpRes)
402800b99b8Sopenharmony_ci{
403800b99b8Sopenharmony_ci    DFX_TRACE_SCOPED("InitRegs");
404800b99b8Sopenharmony_ci    uint32_t opeResult = OPE_SUCCESS;
405800b99b8Sopenharmony_ci    if (request->dumpMode == FUSION_MODE) {
406800b99b8Sopenharmony_ci        if (!DfxUnwindRemote::GetInstance().InitProcessAllThreadRegs(request, process_)) {
407800b99b8Sopenharmony_ci            DFXLOGE("Failed to init process regs.");
408800b99b8Sopenharmony_ci            dumpRes = DumpErrorCode::DUMP_ESTOPUNWIND;
409800b99b8Sopenharmony_ci            opeResult = OPE_FAIL;
410800b99b8Sopenharmony_ci        }
411800b99b8Sopenharmony_ci
412800b99b8Sopenharmony_ci        InfoRemoteProcessResult(request, opeResult, MAIN_PROCESS);
413800b99b8Sopenharmony_ci        DFXLOGI("get all tid regs finish");
414800b99b8Sopenharmony_ci    }
415800b99b8Sopenharmony_ci}
416800b99b8Sopenharmony_ci
417800b99b8Sopenharmony_cibool ProcessDumper::IsTargetProcessAlive(std::shared_ptr<ProcessDumpRequest> request)
418800b99b8Sopenharmony_ci{
419800b99b8Sopenharmony_ci    if ((request->dumpMode == SPLIT_MODE) && ((!isCrash_ && (syscall(SYS_getppid) != request->nsPid)) ||
420800b99b8Sopenharmony_ci        (isCrash_ && (syscall(SYS_getppid) != request->vmNsPid)))) {
421800b99b8Sopenharmony_ci        DfxRingBufferWrapper::GetInstance().AppendMsg(
422800b99b8Sopenharmony_ci            "Target process has been killed, the crash log may not be fully generated.");
423800b99b8Sopenharmony_ci        ReportCrashException(request->processName, request->pid, request->uid,
424800b99b8Sopenharmony_ci                             CrashExceptionCode::CRASH_DUMP_EKILLED);
425800b99b8Sopenharmony_ci        return false;
426800b99b8Sopenharmony_ci    }
427800b99b8Sopenharmony_ci    return true;
428800b99b8Sopenharmony_ci}
429800b99b8Sopenharmony_ci
430800b99b8Sopenharmony_civoid ProcessDumper::UnwindWriteJit(const ProcessDumpRequest &request)
431800b99b8Sopenharmony_ci{
432800b99b8Sopenharmony_ci    if (!isCrash_) {
433800b99b8Sopenharmony_ci        return;
434800b99b8Sopenharmony_ci    }
435800b99b8Sopenharmony_ci
436800b99b8Sopenharmony_ci    const auto& jitCache = unwinder_->GetJitCache();
437800b99b8Sopenharmony_ci    if (jitCache.empty()) {
438800b99b8Sopenharmony_ci        return;
439800b99b8Sopenharmony_ci    }
440800b99b8Sopenharmony_ci    struct FaultLoggerdRequest jitRequest;
441800b99b8Sopenharmony_ci    (void)memset_s(&jitRequest, sizeof(jitRequest), 0, sizeof(jitRequest));
442800b99b8Sopenharmony_ci    jitRequest.type = FaultLoggerType::JIT_CODE_LOG;
443800b99b8Sopenharmony_ci    jitRequest.pid = request.pid;
444800b99b8Sopenharmony_ci    jitRequest.tid = request.tid;
445800b99b8Sopenharmony_ci    jitRequest.uid = request.uid;
446800b99b8Sopenharmony_ci    jitRequest.time = OHOS::HiviewDFX::GetTimeMilliSeconds();
447800b99b8Sopenharmony_ci    int32_t fd = RequestFileDescriptorEx(&jitRequest);
448800b99b8Sopenharmony_ci    if (fd == -1) {
449800b99b8Sopenharmony_ci        DFXLOGE("request jitlog fd failed.");
450800b99b8Sopenharmony_ci        return;
451800b99b8Sopenharmony_ci    }
452800b99b8Sopenharmony_ci    if (unwinder_->ArkWriteJitCodeToFile(fd) < 0) {
453800b99b8Sopenharmony_ci        DFXLOGE("jit code write file failed.");
454800b99b8Sopenharmony_ci    }
455800b99b8Sopenharmony_ci    (void)close(fd);
456800b99b8Sopenharmony_ci}
457800b99b8Sopenharmony_ci
458800b99b8Sopenharmony_cistd::string ProcessDumper::ReadStringByPtrace(pid_t tid, uintptr_t addr)
459800b99b8Sopenharmony_ci{
460800b99b8Sopenharmony_ci    constexpr int bufLen = 256;
461800b99b8Sopenharmony_ci    long buffer[bufLen] = {0};
462800b99b8Sopenharmony_ci    for (int i = 0; i < bufLen - 1; i++) {
463800b99b8Sopenharmony_ci        long ret = ptrace(PTRACE_PEEKTEXT, tid, reinterpret_cast<void*>(addr + sizeof(long) * i), nullptr);
464800b99b8Sopenharmony_ci        if (ret == -1) {
465800b99b8Sopenharmony_ci            DFXLOGE("read target mem by ptrace failed, errno(%{public}s).", strerror(errno));
466800b99b8Sopenharmony_ci            break;
467800b99b8Sopenharmony_ci        }
468800b99b8Sopenharmony_ci        buffer[i] = ret;
469800b99b8Sopenharmony_ci        if (ret == 0) {
470800b99b8Sopenharmony_ci            break;
471800b99b8Sopenharmony_ci        }
472800b99b8Sopenharmony_ci    }
473800b99b8Sopenharmony_ci    char* val = reinterpret_cast<char*>(buffer);
474800b99b8Sopenharmony_ci    return std::string(val);
475800b99b8Sopenharmony_ci}
476800b99b8Sopenharmony_ci
477800b99b8Sopenharmony_civoid ProcessDumper::GetCrashObj(std::shared_ptr<ProcessDumpRequest> request)
478800b99b8Sopenharmony_ci{
479800b99b8Sopenharmony_ci#ifdef __LP64__
480800b99b8Sopenharmony_ci    if (!isCrash_ || request->crashObj == 0) {
481800b99b8Sopenharmony_ci        return;
482800b99b8Sopenharmony_ci    }
483800b99b8Sopenharmony_ci    uintptr_t type = request->crashObj >> 56; // 56 :: Move 56 bit to the right
484800b99b8Sopenharmony_ci    uintptr_t addr = request->crashObj & 0xffffffffffffff;
485800b99b8Sopenharmony_ci    switch (type) {
486800b99b8Sopenharmony_ci        case 0: {
487800b99b8Sopenharmony_ci            if (process_ != nullptr) {
488800b99b8Sopenharmony_ci                process_->SetFatalMessage(process_->GetFatalMessage() + ReadStringByPtrace(request->nsPid, addr));
489800b99b8Sopenharmony_ci            }
490800b99b8Sopenharmony_ci            break;
491800b99b8Sopenharmony_ci        }
492800b99b8Sopenharmony_ci        default:
493800b99b8Sopenharmony_ci            break;
494800b99b8Sopenharmony_ci    }
495800b99b8Sopenharmony_ci#endif
496800b99b8Sopenharmony_ci}
497800b99b8Sopenharmony_ci
498800b99b8Sopenharmony_cibool ProcessDumper::Unwind(std::shared_ptr<ProcessDumpRequest> request, int &dumpRes, pid_t vmPid)
499800b99b8Sopenharmony_ci{
500800b99b8Sopenharmony_ci    // dump unwind should still keep main thread or aim thread is frist unwind
501800b99b8Sopenharmony_ci    if (!isCrash_) {
502800b99b8Sopenharmony_ci        int tid = request->siginfo.si_value.sival_int;
503800b99b8Sopenharmony_ci        tid = tid != 0 ? tid : request->nsPid;
504800b99b8Sopenharmony_ci        for (auto &thread : process_->GetOtherThreads()) {
505800b99b8Sopenharmony_ci            if (thread->threadInfo_.nsTid == tid) {
506800b99b8Sopenharmony_ci                swap(process_->keyThread_, thread);
507800b99b8Sopenharmony_ci                break;
508800b99b8Sopenharmony_ci            }
509800b99b8Sopenharmony_ci        }
510800b99b8Sopenharmony_ci    }
511800b99b8Sopenharmony_ci    GetCrashObj(request);
512800b99b8Sopenharmony_ci    if (!DfxUnwindRemote::GetInstance().UnwindProcess(request, process_, unwinder_, vmPid)) {
513800b99b8Sopenharmony_ci        DFXLOGE("Failed to unwind process.");
514800b99b8Sopenharmony_ci        dumpRes = DumpErrorCode::DUMP_ESTOPUNWIND;
515800b99b8Sopenharmony_ci        return false;
516800b99b8Sopenharmony_ci    }
517800b99b8Sopenharmony_ci
518800b99b8Sopenharmony_ci    UnwindWriteJit(*request);
519800b99b8Sopenharmony_ci    return true;
520800b99b8Sopenharmony_ci}
521800b99b8Sopenharmony_ci
522800b99b8Sopenharmony_ciint ProcessDumper::DumpProcess(std::shared_ptr<ProcessDumpRequest> request)
523800b99b8Sopenharmony_ci{
524800b99b8Sopenharmony_ci    DFX_TRACE_SCOPED("DumpProcess");
525800b99b8Sopenharmony_ci    int dumpRes = DumpErrorCode::DUMP_ESUCCESS;
526800b99b8Sopenharmony_ci    uint32_t opeResult = OPE_SUCCESS;
527800b99b8Sopenharmony_ci    do {
528800b99b8Sopenharmony_ci        if ((dumpRes = ReadRequestAndCheck(request)) != DumpErrorCode::DUMP_ESUCCESS) {
529800b99b8Sopenharmony_ci            break;
530800b99b8Sopenharmony_ci        }
531800b99b8Sopenharmony_ci        SetProcessdumpTimeout(request->siginfo);
532800b99b8Sopenharmony_ci        isCrash_ = request->siginfo.si_signo != SIGDUMP;
533800b99b8Sopenharmony_ci        bool isLeakDump = request->siginfo.si_signo == SIGLEAK_STACK;
534800b99b8Sopenharmony_ci        // We need check pid is same with getppid().
535800b99b8Sopenharmony_ci        // As in signal handler, current process is a child process, and target pid is our parent process.
536800b99b8Sopenharmony_ci        // If pid namespace is enabled, both ppid and pid are equal one.
537800b99b8Sopenharmony_ci        // In this case, we have to parse /proc/self/status
538800b99b8Sopenharmony_ci        if ((request->dumpMode == SPLIT_MODE) && (((!isCrash_) && (syscall(SYS_getppid) != request->nsPid)) ||
539800b99b8Sopenharmony_ci            ((isCrash_ || isLeakDump) && (syscall(SYS_getppid) != request->vmNsPid)))) {
540800b99b8Sopenharmony_ci            DFXLOGE("Target process(%{public}s:%{public}d) is not parent pid(%{public}ld), " \
541800b99b8Sopenharmony_ci                "exit processdump for signal(%{public}d).",
542800b99b8Sopenharmony_ci                request->processName, request->nsPid, syscall(SYS_getppid), request->siginfo.si_signo);
543800b99b8Sopenharmony_ci            dumpRes = DumpErrorCode::DUMP_EGETPPID;
544800b99b8Sopenharmony_ci            break;
545800b99b8Sopenharmony_ci        }
546800b99b8Sopenharmony_ci        DFXLOGW("Processdump SigVal(%{public}d), TargetPid(%{public}d:%{public}d), TargetTid(%{public}d), " \
547800b99b8Sopenharmony_ci            "threadname(%{public}s).",
548800b99b8Sopenharmony_ci            request->siginfo.si_value.sival_int, request->pid, request->nsPid, request->tid, request->threadName);
549800b99b8Sopenharmony_ci
550800b99b8Sopenharmony_ci        if (InitProcessInfo(request) < 0) {
551800b99b8Sopenharmony_ci            DFXLOGE("Failed to init crash process info.");
552800b99b8Sopenharmony_ci            dumpRes = DumpErrorCode::DUMP_EATTACH;
553800b99b8Sopenharmony_ci            break;
554800b99b8Sopenharmony_ci        }
555800b99b8Sopenharmony_ci        InitRegs(request, dumpRes);
556800b99b8Sopenharmony_ci        pid_t vmPid = 0;
557800b99b8Sopenharmony_ci        if (!InitUnwinder(request, vmPid, dumpRes) && (isCrash_ && !isLeakDump)) {
558800b99b8Sopenharmony_ci            opeResult = OPE_FAIL;
559800b99b8Sopenharmony_ci            break;
560800b99b8Sopenharmony_ci        }
561800b99b8Sopenharmony_ci        if (InitPrintThread(request) < 0) {
562800b99b8Sopenharmony_ci            DFXLOGE("Failed to init print thread.");
563800b99b8Sopenharmony_ci            dumpRes = DumpErrorCode::DUMP_EGETFD;
564800b99b8Sopenharmony_ci        }
565800b99b8Sopenharmony_ci        ReadFdTable(*request);
566800b99b8Sopenharmony_ci        if (!Unwind(request, dumpRes, vmPid)) {
567800b99b8Sopenharmony_ci            opeResult = OPE_FAIL;
568800b99b8Sopenharmony_ci        }
569800b99b8Sopenharmony_ci    } while (false);
570800b99b8Sopenharmony_ci    if (request->dumpMode == FUSION_MODE) {
571800b99b8Sopenharmony_ci        InfoRemoteProcessResult(request, opeResult, VIRTUAL_PROCESS);
572800b99b8Sopenharmony_ci    }
573800b99b8Sopenharmony_ci    if (dumpRes == DumpErrorCode::DUMP_ESUCCESS && !IsTargetProcessAlive(request)) {
574800b99b8Sopenharmony_ci        dumpRes = DumpErrorCode::DUMP_EGETPPID;
575800b99b8Sopenharmony_ci    }
576800b99b8Sopenharmony_ci    return dumpRes;
577800b99b8Sopenharmony_ci}
578800b99b8Sopenharmony_ci
579800b99b8Sopenharmony_cibool ProcessDumper::InitVmThread(std::shared_ptr<ProcessDumpRequest> request)
580800b99b8Sopenharmony_ci{
581800b99b8Sopenharmony_ci    if (request == nullptr || process_ == nullptr) {
582800b99b8Sopenharmony_ci        return false;
583800b99b8Sopenharmony_ci    }
584800b99b8Sopenharmony_ci    if (isCrash_ && request->vmPid != 0) {
585800b99b8Sopenharmony_ci        if (getppid() != request->vmNsPid) {
586800b99b8Sopenharmony_ci            DFXLOGE("VM process(%{public}d) should be parent pid.", request->vmNsPid);
587800b99b8Sopenharmony_ci            ReportCrashException(request->processName, request->pid, request->uid,
588800b99b8Sopenharmony_ci                                 CrashExceptionCode::CRASH_DUMP_EPARENTPID);
589800b99b8Sopenharmony_ci            return false;
590800b99b8Sopenharmony_ci        }
591800b99b8Sopenharmony_ci        process_->vmThread_ = DfxThread::Create(request->vmPid, request->vmPid, request->vmNsPid);
592800b99b8Sopenharmony_ci        if ((process_->vmThread_ == nullptr) || (!process_->vmThread_->Attach(PTRACE_ATTATCH_KEY_THREAD_TIMEOUT))) {
593800b99b8Sopenharmony_ci            DFXLOGE("Failed to attach vm thread(%{public}d).", request->vmNsPid);
594800b99b8Sopenharmony_ci            return false;
595800b99b8Sopenharmony_ci        }
596800b99b8Sopenharmony_ci
597800b99b8Sopenharmony_ci        process_->vmThread_->SetThreadRegs(DfxRegs::CreateFromUcontext(request->context));
598800b99b8Sopenharmony_ci        process_->vmThread_->threadInfo_.threadName = std::string(request->threadName);
599800b99b8Sopenharmony_ci    }
600800b99b8Sopenharmony_ci    return true;
601800b99b8Sopenharmony_ci}
602800b99b8Sopenharmony_ci
603800b99b8Sopenharmony_cibool ProcessDumper::InitKeyThread(std::shared_ptr<ProcessDumpRequest> request)
604800b99b8Sopenharmony_ci{
605800b99b8Sopenharmony_ci    if (request == nullptr || process_ == nullptr) {
606800b99b8Sopenharmony_ci        return false;
607800b99b8Sopenharmony_ci    }
608800b99b8Sopenharmony_ci    pid_t nsTid = request->tid;
609800b99b8Sopenharmony_ci    pid_t tid = process_->ChangeTid(nsTid, true);
610800b99b8Sopenharmony_ci    process_->keyThread_ = DfxThread::Create(process_->processInfo_.pid, tid, nsTid);
611800b99b8Sopenharmony_ci    if ((process_->keyThread_ == nullptr) || (!process_->keyThread_->Attach(PTRACE_ATTATCH_KEY_THREAD_TIMEOUT))) {
612800b99b8Sopenharmony_ci        DFXLOGE("Failed to attach key thread(%{public}d).", nsTid);
613800b99b8Sopenharmony_ci        ReportCrashException(request->processName, request->pid, request->uid,
614800b99b8Sopenharmony_ci                             CrashExceptionCode::CRASH_DUMP_EATTACH);
615800b99b8Sopenharmony_ci        if (!isCrash_) {
616800b99b8Sopenharmony_ci            return false;
617800b99b8Sopenharmony_ci        }
618800b99b8Sopenharmony_ci    }
619800b99b8Sopenharmony_ci    if ((process_->keyThread_ != nullptr) && request->dumpMode == FUSION_MODE) {
620800b99b8Sopenharmony_ci        ptrace(PTRACE_CONT, process_->keyThread_->threadInfo_.nsTid, 0, 0);
621800b99b8Sopenharmony_ci    }
622800b99b8Sopenharmony_ci
623800b99b8Sopenharmony_ci    if ((process_->keyThread_ != nullptr) && (request->dumpMode == SPLIT_MODE) && !isCrash_) {
624800b99b8Sopenharmony_ci        process_->keyThread_->SetThreadRegs(DfxRegs::CreateFromUcontext(request->context));
625800b99b8Sopenharmony_ci    }
626800b99b8Sopenharmony_ci
627800b99b8Sopenharmony_ci    if ((process_->keyThread_ != nullptr) && process_->keyThread_->threadInfo_.threadName.empty()) {
628800b99b8Sopenharmony_ci        process_->keyThread_->threadInfo_.threadName = std::string(request->threadName);
629800b99b8Sopenharmony_ci    }
630800b99b8Sopenharmony_ci    return true;
631800b99b8Sopenharmony_ci}
632800b99b8Sopenharmony_ci
633800b99b8Sopenharmony_cibool ProcessDumper::InitUnwinder(std::shared_ptr<ProcessDumpRequest> request, pid_t &vmPid, int &dumpRes)
634800b99b8Sopenharmony_ci{
635800b99b8Sopenharmony_ci    DFX_TRACE_SCOPED("InitUnwinder");
636800b99b8Sopenharmony_ci    pid_t realPid = 0;
637800b99b8Sopenharmony_ci    if (request->dumpMode == FUSION_MODE) {
638800b99b8Sopenharmony_ci        ReadPids(realPid, vmPid);
639800b99b8Sopenharmony_ci        if (realPid == 0 || vmPid == 0) {
640800b99b8Sopenharmony_ci            ReportCrashException(request->processName, request->pid, request->uid,
641800b99b8Sopenharmony_ci                CrashExceptionCode::CRASH_DUMP_EREADPID);
642800b99b8Sopenharmony_ci            DFXLOGE("Failed to read real pid!");
643800b99b8Sopenharmony_ci            dumpRes = DumpErrorCode::DUMP_EREADPID;
644800b99b8Sopenharmony_ci            return false;
645800b99b8Sopenharmony_ci        }
646800b99b8Sopenharmony_ci    }
647800b99b8Sopenharmony_ci
648800b99b8Sopenharmony_ci    // frezze detach after vm process create
649800b99b8Sopenharmony_ci    if (!isCrash_) {
650800b99b8Sopenharmony_ci        if (process_->keyThread_ != nullptr) {
651800b99b8Sopenharmony_ci            process_->keyThread_->Detach();
652800b99b8Sopenharmony_ci        }
653800b99b8Sopenharmony_ci        process_->Detach();
654800b99b8Sopenharmony_ci        DFXLOGI("ptrace detach all tids");
655800b99b8Sopenharmony_ci    }
656800b99b8Sopenharmony_ci
657800b99b8Sopenharmony_ci    if (request->dumpMode == FUSION_MODE) {
658800b99b8Sopenharmony_ci        unwinder_ = std::make_shared<Unwinder>(realPid, vmPid, isCrash_);
659800b99b8Sopenharmony_ci    } else {
660800b99b8Sopenharmony_ci        if (isCrash_) {
661800b99b8Sopenharmony_ci            unwinder_ = std::make_shared<Unwinder>(process_->vmThread_->threadInfo_.pid);
662800b99b8Sopenharmony_ci        } else {
663800b99b8Sopenharmony_ci            unwinder_ = std::make_shared<Unwinder>(process_->processInfo_.pid, false);
664800b99b8Sopenharmony_ci        }
665800b99b8Sopenharmony_ci    }
666800b99b8Sopenharmony_ci    if (unwinder_ == nullptr) {
667800b99b8Sopenharmony_ci        DFXLOGE("unwinder_ is nullptr!");
668800b99b8Sopenharmony_ci        return false;
669800b99b8Sopenharmony_ci    }
670800b99b8Sopenharmony_ci    if (unwinder_->GetMaps() == nullptr) {
671800b99b8Sopenharmony_ci        ReportCrashException(request->processName, request->pid, request->uid,
672800b99b8Sopenharmony_ci            CrashExceptionCode::CRASH_LOG_EMAPLOS);
673800b99b8Sopenharmony_ci        DFXLOGE("Mapinfo of crashed process is not exist!");
674800b99b8Sopenharmony_ci        dumpRes = DumpErrorCode::DUMP_ENOMAP;
675800b99b8Sopenharmony_ci        return false;
676800b99b8Sopenharmony_ci    }
677800b99b8Sopenharmony_ci    return true;
678800b99b8Sopenharmony_ci}
679800b99b8Sopenharmony_ci
680800b99b8Sopenharmony_ciint ProcessDumper::InitProcessInfo(std::shared_ptr<ProcessDumpRequest> request)
681800b99b8Sopenharmony_ci{
682800b99b8Sopenharmony_ci    DFX_TRACE_SCOPED("InitProcessInfo");
683800b99b8Sopenharmony_ci    if (request->pid <= 0) {
684800b99b8Sopenharmony_ci        return -1;
685800b99b8Sopenharmony_ci    }
686800b99b8Sopenharmony_ci    process_ = DfxProcess::Create(request->pid, request->nsPid);
687800b99b8Sopenharmony_ci    if (process_ == nullptr) {
688800b99b8Sopenharmony_ci        return -1;
689800b99b8Sopenharmony_ci    }
690800b99b8Sopenharmony_ci    if (process_->processInfo_.processName.empty()) {
691800b99b8Sopenharmony_ci        process_->processInfo_.processName = std::string(request->processName);
692800b99b8Sopenharmony_ci    }
693800b99b8Sopenharmony_ci    process_->processInfo_.uid = request->uid;
694800b99b8Sopenharmony_ci    process_->recycleTid_ = request->recycleTid;
695800b99b8Sopenharmony_ci    process_->SetFatalMessage(request->msg.body);
696800b99b8Sopenharmony_ci
697800b99b8Sopenharmony_ci    if (!InitVmThread(request)) {
698800b99b8Sopenharmony_ci        return -1;
699800b99b8Sopenharmony_ci    }
700800b99b8Sopenharmony_ci
701800b99b8Sopenharmony_ci    if (!InitKeyThread(request)) {
702800b99b8Sopenharmony_ci        return -1;
703800b99b8Sopenharmony_ci    }
704800b99b8Sopenharmony_ci
705800b99b8Sopenharmony_ci    DFXLOGI("ptrace attach all tids");
706800b99b8Sopenharmony_ci    bool isLeakDump = request->siginfo.si_signo == SIGLEAK_STACK;
707800b99b8Sopenharmony_ci    if (isCrash_ && !isLeakDump) {
708800b99b8Sopenharmony_ci        process_->InitOtherThreads();
709800b99b8Sopenharmony_ci        process_->Attach();
710800b99b8Sopenharmony_ci    } else {
711800b99b8Sopenharmony_ci        if (!isLeakDump) {
712800b99b8Sopenharmony_ci            process_->InitOtherThreads();
713800b99b8Sopenharmony_ci            if (request->dumpMode == FUSION_MODE) {
714800b99b8Sopenharmony_ci                process_->Attach();
715800b99b8Sopenharmony_ci            }
716800b99b8Sopenharmony_ci        }
717800b99b8Sopenharmony_ci    }
718800b99b8Sopenharmony_ci#if defined(PROCESSDUMP_MINIDEBUGINFO)
719800b99b8Sopenharmony_ci    UnwinderConfig::SetEnableMiniDebugInfo(true);
720800b99b8Sopenharmony_ci    UnwinderConfig::SetEnableLoadSymbolLazily(true);
721800b99b8Sopenharmony_ci#endif
722800b99b8Sopenharmony_ci    return 0;
723800b99b8Sopenharmony_ci}
724800b99b8Sopenharmony_ci
725800b99b8Sopenharmony_ciint ProcessDumper::GetLogTypeByRequest(const ProcessDumpRequest &request)
726800b99b8Sopenharmony_ci{
727800b99b8Sopenharmony_ci    switch (request.siginfo.si_signo) {
728800b99b8Sopenharmony_ci        case SIGLEAK_STACK:
729800b99b8Sopenharmony_ci            switch (request.msg.type) {
730800b99b8Sopenharmony_ci                case MESSAGE_FDSAN_DEBUG:
731800b99b8Sopenharmony_ci                    FALLTHROUGH_INTENDED;
732800b99b8Sopenharmony_ci                case MESSAGE_JEMALLOC:
733800b99b8Sopenharmony_ci                    FALLTHROUGH_INTENDED;
734800b99b8Sopenharmony_ci                case MESSAGE_BADFD:
735800b99b8Sopenharmony_ci                    return FaultLoggerType::CPP_STACKTRACE;
736800b99b8Sopenharmony_ci                default:
737800b99b8Sopenharmony_ci                    return FaultLoggerType::LEAK_STACKTRACE;
738800b99b8Sopenharmony_ci            }
739800b99b8Sopenharmony_ci        case SIGDUMP:
740800b99b8Sopenharmony_ci            return FaultLoggerType::CPP_STACKTRACE;
741800b99b8Sopenharmony_ci        default:
742800b99b8Sopenharmony_ci            return FaultLoggerType::CPP_CRASH;
743800b99b8Sopenharmony_ci    }
744800b99b8Sopenharmony_ci}
745800b99b8Sopenharmony_ci
746800b99b8Sopenharmony_ciint32_t ProcessDumper::CreateFileForCrash(int32_t pid, uint64_t time) const
747800b99b8Sopenharmony_ci{
748800b99b8Sopenharmony_ci    const std::string logFilePath = "/log/crash";
749800b99b8Sopenharmony_ci    const std::string logFileType = "cppcrash";
750800b99b8Sopenharmony_ci    const int32_t logcrashFileProp = 0640; // 0640:-rw-r-----
751800b99b8Sopenharmony_ci    if (access(logFilePath.c_str(), F_OK) != 0) {
752800b99b8Sopenharmony_ci        DFXLOGE("%{public}s is not exist.", logFilePath.c_str());
753800b99b8Sopenharmony_ci        return INVALID_FD;
754800b99b8Sopenharmony_ci    }
755800b99b8Sopenharmony_ci    std::string logPath = logFilePath + "/" + logFileType + "-" + std::to_string(pid) + "-" + std::to_string(time);
756800b99b8Sopenharmony_ci    int32_t fd = OHOS_TEMP_FAILURE_RETRY(open(logPath.c_str(), O_RDWR | O_CREAT, logcrashFileProp));
757800b99b8Sopenharmony_ci    if (fd == INVALID_FD) {
758800b99b8Sopenharmony_ci        DFXLOGE("create %{public}s failed, errno=%{public}d", logPath.c_str(), errno);
759800b99b8Sopenharmony_ci    } else {
760800b99b8Sopenharmony_ci        DFXLOGI("create crash path %{public}s succ.", logPath.c_str());
761800b99b8Sopenharmony_ci    }
762800b99b8Sopenharmony_ci    return fd;
763800b99b8Sopenharmony_ci}
764800b99b8Sopenharmony_ci
765800b99b8Sopenharmony_ciint ProcessDumper::InitPrintThread(std::shared_ptr<ProcessDumpRequest> request)
766800b99b8Sopenharmony_ci{
767800b99b8Sopenharmony_ci    DFX_TRACE_SCOPED("InitPrintThread");
768800b99b8Sopenharmony_ci    int fd = -1;
769800b99b8Sopenharmony_ci    struct FaultLoggerdRequest faultloggerdRequest;
770800b99b8Sopenharmony_ci    (void)memset_s(&faultloggerdRequest, sizeof(faultloggerdRequest), 0, sizeof(struct FaultLoggerdRequest));
771800b99b8Sopenharmony_ci    faultloggerdRequest.type = ProcessDumper::GetLogTypeByRequest(*request);
772800b99b8Sopenharmony_ci    faultloggerdRequest.pid = request->pid;
773800b99b8Sopenharmony_ci    faultloggerdRequest.tid = request->tid;
774800b99b8Sopenharmony_ci    faultloggerdRequest.uid = request->uid;
775800b99b8Sopenharmony_ci    faultloggerdRequest.time = request->timeStamp;
776800b99b8Sopenharmony_ci    isJsonDump_ = false;
777800b99b8Sopenharmony_ci    jsonFd_ = -1;
778800b99b8Sopenharmony_ci    if (isCrash_ || faultloggerdRequest.type == FaultLoggerType::LEAK_STACKTRACE) {
779800b99b8Sopenharmony_ci        fd = RequestFileDescriptorEx(&faultloggerdRequest);
780800b99b8Sopenharmony_ci        if (fd == -1) {
781800b99b8Sopenharmony_ci            fd = CreateFileForCrash(request->pid, request->timeStamp);
782800b99b8Sopenharmony_ci        }
783800b99b8Sopenharmony_ci        DfxRingBufferWrapper::GetInstance().SetWriteFunc(ProcessDumper::WriteDumpBuf);
784800b99b8Sopenharmony_ci    } else {
785800b99b8Sopenharmony_ci        jsonFd_ = RequestPipeFd(request->pid, FaultLoggerPipeType::PIPE_FD_JSON_WRITE_BUF);
786800b99b8Sopenharmony_ci        if (jsonFd_ < 0) {
787800b99b8Sopenharmony_ci            // If fd returns -1, we try to obtain the fd that needs to return JSON style
788800b99b8Sopenharmony_ci            fd = RequestPipeFd(request->pid, FaultLoggerPipeType::PIPE_FD_WRITE_BUF);
789800b99b8Sopenharmony_ci            resFd_ = RequestPipeFd(request->pid, FaultLoggerPipeType::PIPE_FD_WRITE_RES);
790800b99b8Sopenharmony_ci            DFXLOGD("write buf fd: %{public}d, write res fd: %{public}d", fd, resFd_);
791800b99b8Sopenharmony_ci        } else {
792800b99b8Sopenharmony_ci            resFd_ = RequestPipeFd(request->pid, FaultLoggerPipeType::PIPE_FD_JSON_WRITE_RES);
793800b99b8Sopenharmony_ci            DFXLOGD("write json fd: %{public}d, res fd: %{public}d", jsonFd_, resFd_);
794800b99b8Sopenharmony_ci        }
795800b99b8Sopenharmony_ci    }
796800b99b8Sopenharmony_ci    if (jsonFd_ > 0) {
797800b99b8Sopenharmony_ci        isJsonDump_ = true;
798800b99b8Sopenharmony_ci    }
799800b99b8Sopenharmony_ci    if ((fd < 0) && (jsonFd_ < 0)) {
800800b99b8Sopenharmony_ci        DFXLOGW("Failed to request fd from faultloggerd.");
801800b99b8Sopenharmony_ci        ReportCrashException(request->processName, request->pid, request->uid,
802800b99b8Sopenharmony_ci                             CrashExceptionCode::CRASH_DUMP_EWRITEFD);
803800b99b8Sopenharmony_ci    }
804800b99b8Sopenharmony_ci    if (!isJsonDump_) {
805800b99b8Sopenharmony_ci        DfxRingBufferWrapper::GetInstance().SetWriteBufFd(fd);
806800b99b8Sopenharmony_ci    }
807800b99b8Sopenharmony_ci    DfxRingBufferWrapper::GetInstance().StartThread();
808800b99b8Sopenharmony_ci    return isJsonDump_ ? jsonFd_ : fd;
809800b99b8Sopenharmony_ci}
810800b99b8Sopenharmony_ci
811800b99b8Sopenharmony_ciint ProcessDumper::WriteDumpBuf(int fd, const char* buf, const int len)
812800b99b8Sopenharmony_ci{
813800b99b8Sopenharmony_ci    if (buf == nullptr) {
814800b99b8Sopenharmony_ci        return -1;
815800b99b8Sopenharmony_ci    }
816800b99b8Sopenharmony_ci    return WriteLog(fd, "%s", buf);
817800b99b8Sopenharmony_ci}
818800b99b8Sopenharmony_ci
819800b99b8Sopenharmony_civoid ProcessDumper::WriteDumpRes(int32_t res)
820800b99b8Sopenharmony_ci{
821800b99b8Sopenharmony_ci    DFXLOGI("%{public}s :: res: %{public}d", __func__, res);
822800b99b8Sopenharmony_ci    if (resFd_ > 0) {
823800b99b8Sopenharmony_ci        ssize_t nwrite = OHOS_TEMP_FAILURE_RETRY(write(resFd_, &res, sizeof(res)));
824800b99b8Sopenharmony_ci        if (nwrite < 0) {
825800b99b8Sopenharmony_ci            DFXLOGE("%{public}s write fail, err:%{public}d", __func__, errno);
826800b99b8Sopenharmony_ci        }
827800b99b8Sopenharmony_ci        close(resFd_);
828800b99b8Sopenharmony_ci        resFd_ = -1;
829800b99b8Sopenharmony_ci    } else {
830800b99b8Sopenharmony_ci        if (res != DUMP_ESUCCESS) {
831800b99b8Sopenharmony_ci            DfxRingBufferWrapper::GetInstance().AppendMsg("Result:\n");
832800b99b8Sopenharmony_ci            DfxRingBufferWrapper::GetInstance().AppendMsg(DfxDumpRes::ToString(res) + "\n");
833800b99b8Sopenharmony_ci        }
834800b99b8Sopenharmony_ci    }
835800b99b8Sopenharmony_ci}
836800b99b8Sopenharmony_ci
837800b99b8Sopenharmony_cibool ProcessDumper::IsCrash() const
838800b99b8Sopenharmony_ci{
839800b99b8Sopenharmony_ci    return isCrash_;
840800b99b8Sopenharmony_ci}
841800b99b8Sopenharmony_ci
842800b99b8Sopenharmony_civoid ProcessDumper::ReportSigDumpStats(const std::shared_ptr<ProcessDumpRequest> &request) const
843800b99b8Sopenharmony_ci{
844800b99b8Sopenharmony_ci    if (isCrash_) {
845800b99b8Sopenharmony_ci        return;
846800b99b8Sopenharmony_ci    }
847800b99b8Sopenharmony_ci
848800b99b8Sopenharmony_ci    std::vector<uint8_t> buf(sizeof(struct FaultLoggerdStatsRequest), 0);
849800b99b8Sopenharmony_ci    auto stat = reinterpret_cast<struct FaultLoggerdStatsRequest*>(buf.data());
850800b99b8Sopenharmony_ci    stat->type = PROCESS_DUMP;
851800b99b8Sopenharmony_ci    stat->pid = request->pid;
852800b99b8Sopenharmony_ci    stat->signalTime = request->timeStamp;
853800b99b8Sopenharmony_ci    stat->processdumpStartTime = startTime_;
854800b99b8Sopenharmony_ci    stat->processdumpFinishTime = finishTime_;
855800b99b8Sopenharmony_ci    if (memcpy_s(stat->targetProcess, sizeof(stat->targetProcess),
856800b99b8Sopenharmony_ci        request->processName, sizeof(request->processName)) != 0) {
857800b99b8Sopenharmony_ci        DFXLOGE("Failed to copy target processName (%{public}d)", errno);
858800b99b8Sopenharmony_ci        return;
859800b99b8Sopenharmony_ci    }
860800b99b8Sopenharmony_ci
861800b99b8Sopenharmony_ci    ReportDumpStats(stat);
862800b99b8Sopenharmony_ci}
863800b99b8Sopenharmony_ci
864800b99b8Sopenharmony_civoid ProcessDumper::ReportCrashInfo(const std::string& jsonInfo)
865800b99b8Sopenharmony_ci{
866800b99b8Sopenharmony_ci    if (reporter_ != nullptr) {
867800b99b8Sopenharmony_ci        reporter_->SetCppCrashInfo(jsonInfo);
868800b99b8Sopenharmony_ci        reporter_->ReportToHiview();
869800b99b8Sopenharmony_ci        reporter_->ReportToAbilityManagerService();
870800b99b8Sopenharmony_ci    }
871800b99b8Sopenharmony_ci}
872800b99b8Sopenharmony_ci
873800b99b8Sopenharmony_civoid ProcessDumper::ReportAddrSanitizer(ProcessDumpRequest &request, std::string &jsonInfo)
874800b99b8Sopenharmony_ci{
875800b99b8Sopenharmony_ci#ifndef HISYSEVENT_DISABLE
876800b99b8Sopenharmony_ci    std::string fingerPrint = request.processName;
877800b99b8Sopenharmony_ci    std::string reason = "DEBUG SIGNAL";
878800b99b8Sopenharmony_ci    if (process_ != nullptr && process_->keyThread_ != nullptr) {
879800b99b8Sopenharmony_ci        constexpr size_t MAX_FRAME_CNT = 3;
880800b99b8Sopenharmony_ci        auto& frames = process_->keyThread_->GetFrames();
881800b99b8Sopenharmony_ci        for (size_t index = 0, cnt = 0; cnt < MAX_FRAME_CNT && index < frames.size(); index++) {
882800b99b8Sopenharmony_ci            if (frames[index].mapName.find("ld-musl-", 0) != std::string::npos) {
883800b99b8Sopenharmony_ci                continue;
884800b99b8Sopenharmony_ci            }
885800b99b8Sopenharmony_ci            fingerPrint = fingerPrint + frames[index].funcName;
886800b99b8Sopenharmony_ci            cnt++;
887800b99b8Sopenharmony_ci        }
888800b99b8Sopenharmony_ci        reason = process_->reason;
889800b99b8Sopenharmony_ci    }
890800b99b8Sopenharmony_ci    size_t hashVal = std::hash<std::string>()(fingerPrint);
891800b99b8Sopenharmony_ci    HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::RELIABILITY, "ADDR_SANITIZER",
892800b99b8Sopenharmony_ci                    OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
893800b99b8Sopenharmony_ci                    "MODULE", request.processName,
894800b99b8Sopenharmony_ci                    "PID", request.pid,
895800b99b8Sopenharmony_ci                    "HAPPEN_TIME", request.timeStamp,
896800b99b8Sopenharmony_ci                    "REASON", reason,
897800b99b8Sopenharmony_ci                    "FINGERPRINT", std::to_string(hashVal));
898800b99b8Sopenharmony_ci    DFXLOGI("%{public}s", "Report fdsan event done.");
899800b99b8Sopenharmony_ci#else
900800b99b8Sopenharmony_ci    DFXLOGI("%{public}s", "Not supported for fdsan reporting.");
901800b99b8Sopenharmony_ci#endif
902800b99b8Sopenharmony_ci}
903800b99b8Sopenharmony_ci
904800b99b8Sopenharmony_civoid ProcessDumper::ReadFdTable(const ProcessDumpRequest &request)
905800b99b8Sopenharmony_ci{
906800b99b8Sopenharmony_ci    // Non crash, leak, jemalloc do not read fdtable
907800b99b8Sopenharmony_ci    if (!isCrash_ ||
908800b99b8Sopenharmony_ci        (request.siginfo.si_signo == SIGLEAK_STACK &&
909800b99b8Sopenharmony_ci         (request.msg.type == NONE ||
910800b99b8Sopenharmony_ci          request.msg.type == MESSAGE_FATAL ||
911800b99b8Sopenharmony_ci          request.msg.type == MESSAGE_JEMALLOC))) {
912800b99b8Sopenharmony_ci        return;
913800b99b8Sopenharmony_ci    }
914800b99b8Sopenharmony_ci    process_->openFiles = GetOpenFiles(request.pid, request.nsPid, request.fdTableAddr);
915800b99b8Sopenharmony_ci    reporter_ = std::make_shared<CppCrashReporter>(request.timeStamp, process_, request.dumpMode);
916800b99b8Sopenharmony_ci}
917800b99b8Sopenharmony_ci} // namespace HiviewDFX
918800b99b8Sopenharmony_ci} // namespace OHOS
919