• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 #if defined(__aarch64__)
16 #include "dfx_coredump_writer.h"
17 
18 #include <cerrno>
19 #include <csignal>
20 #include <cstdint>
21 #include <cstdio>
22 #include <cstdlib>
23 #include <cstring>
24 #include <fstream>
25 #include <iostream>
26 #include <string>
27 #include <vector>
28 
29 #include <dirent.h>
30 #include <fcntl.h>
31 #include <pthread.h>
32 #include <sys/mman.h>
33 #include <sys/ptrace.h>
34 #include <sys/resource.h>
35 #include <sys/types.h>
36 #include <sys/user.h>
37 #include <sys/wait.h>
38 #include <unistd.h>
39 
40 #include "dfx_define.h"
41 
42 namespace OHOS {
43 namespace HiviewDFX {
44 static const char NOTE_NAME_CORE[8] = "CORE";
45 static const char NOTE_NAME_LINUX[8] = "LINUX";
46 const char *const UID = "Uid:";
47 const char *const GID = "Gid:";
48 const char *const PPID = "PPid:";
49 const char *const SIGPND = "SigPnd:";
50 const char *const SIGBLK = "SigBlk:";
51 
Write()52 char* ProgramSegmentHeaderWriter::Write()
53 {
54     Elf64_Phdr ptNote;
55     PtNoteFill(ptNote);
56 
57     if (!CopyAndAdvance(&ptNote, sizeof(ptNote))) {
58         DFXLOGE("Write ptNote fail, errno:%{public}d", errno);
59         return currentPointer_;
60     }
61 
62     Elf64_Phdr ptLoad;
63     Elf64_Half lineNumber = 1;
64 
65     for (const auto &region : maps_) {
66         std::string pri(region.priority);
67         if (pri.find('r') == std::string::npos || pri.find('p') == std::string::npos) {
68             continue;
69         }
70         PtLoadFill(ptLoad, region);
71         if (!CopyAndAdvance(&ptLoad, sizeof(ptLoad))) {
72             DFXLOGE("Write ptLoad fail, errno:%{public}d", errno);
73             return currentPointer_;
74         }
75         lineNumber++;
76     }
77 
78     char *ptNoteAddr = mappedMemory_ + sizeof(Elf64_Ehdr);
79     char *ptLoadAddr = ptNoteAddr + sizeof(Elf64_Phdr);
80 
81     char *pOffsetAddr = ptLoadAddr + offsetof(Elf64_Phdr, p_offset);
82     Elf64_Off *pOffset = reinterpret_cast<Elf64_Off *>(pOffsetAddr);
83     *pOffset = sizeof(Elf64_Ehdr) + (lineNumber * sizeof(Elf64_Phdr));
84 
85     char *pFileszAddrLast = ptLoadAddr + offsetof(Elf64_Phdr, p_filesz);
86     Elf64_Xword *pFileszLast = reinterpret_cast<Elf64_Xword *>(pFileszAddrLast);
87 
88     Elf64_Off pOffsetValueLast = *pOffset;
89 
90     for (Elf64_Half i = 0; i < (lineNumber - 2); i++) { // 2
91         pOffsetAddr += sizeof(Elf64_Phdr);
92         pOffset = reinterpret_cast<Elf64_Off *>(pOffsetAddr);
93 
94         *pOffset = pOffsetValueLast + *pFileszLast;
95 
96         pOffsetValueLast = *pOffset;
97         pFileszAddrLast += sizeof(Elf64_Phdr);
98         pFileszLast = reinterpret_cast<Elf64_Xword *>(pFileszAddrLast);
99     }
100 
101     pOffsetAddr = ptNoteAddr + offsetof(Elf64_Phdr, p_offset);
102     pOffset = reinterpret_cast<Elf64_Off *>(pOffsetAddr);
103 
104     *pOffset = pOffsetValueLast + *pFileszLast;
105 
106     ePhnum_ = lineNumber;
107     return currentPointer_;
108 }
109 
PtLoadFill(Elf64_Phdr & ph,const DumpMemoryRegions & region)110 void ProgramSegmentHeaderWriter::PtLoadFill(Elf64_Phdr &ph, const DumpMemoryRegions &region)
111 {
112     Elf64_Word pFlags = 0x00;
113     if (region.priority[0] == 'r' || region.priority[0] == '-') {
114         pFlags |= PF_R;
115     }
116     if (region.priority[1] == 'w') {
117         pFlags |= PF_W;
118     }
119     if (region.priority[2] == 'x') { // 2
120         pFlags |= PF_X;
121     }
122     ProgramSegmentHeaderFill(ph, PT_LOAD, pFlags, region);
123 }
124 
PtNoteFill(Elf64_Phdr & ph)125 void ProgramSegmentHeaderWriter::PtNoteFill(Elf64_Phdr &ph)
126 {
127     struct DumpMemoryRegions region;
128     Elf64_Word pFlags = PF_R;
129     region.startHex = 0x00;
130     region.endHex = 0x00;
131     region.memorySizeHex = 0x00;
132     ProgramSegmentHeaderFill(ph, PT_NOTE, pFlags, region);
133 }
134 
ProgramSegmentHeaderFill(Elf64_Phdr & ph,Elf64_Word pType,Elf64_Word pFlags,const DumpMemoryRegions & region)135 void ProgramSegmentHeaderWriter::ProgramSegmentHeaderFill(Elf64_Phdr &ph, Elf64_Word pType,
136     Elf64_Word pFlags, const DumpMemoryRegions &region)
137 {
138     ph.p_type = pType;
139     ph.p_flags = pFlags;
140     ph.p_offset = sizeof(Elf64_Ehdr);
141     ph.p_vaddr = region.startHex;
142     ph.p_paddr = 0x00;
143     ph.p_filesz = region.memorySizeHex;
144     ph.p_memsz = ph.p_filesz;
145     ph.p_align = 0x1;
146 }
147 
Write()148 char* LoadSegmentWriter::Write()
149 {
150     char *ptLoadAddr = mappedMemory_ + sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr);
151     Elf64_Phdr *ptLoad = reinterpret_cast<Elf64_Phdr *>(ptLoadAddr);
152     if (ptLoad == nullptr) {
153         return currentPointer_;
154     }
155     for (Elf64_Half i = 0; i < (ePhnum_ - 1); i++) {
156         ReadProcessVmmem(*ptLoad);
157         ptLoad += 1;
158     }
159     return currentPointer_;
160 }
161 
ReadProcessVmmem(Elf64_Phdr & ptLoad)162 void LoadSegmentWriter::ReadProcessVmmem(Elf64_Phdr &ptLoad)
163 {
164     struct iovec local[1];
165     struct iovec remote[1];
166 
167     local[0].iov_base = currentPointer_;
168     local[0].iov_len = ptLoad.p_memsz;
169 
170     remote[0].iov_base = reinterpret_cast<void *>(ptLoad.p_vaddr);
171     remote[0].iov_len = ptLoad.p_memsz;
172     ssize_t nread = process_vm_readv(pid_, local, 1, remote, 1, 0);
173     if (nread == -1) {
174         (void)memset_s(currentPointer_, ptLoad.p_memsz, -1, ptLoad.p_memsz);
175     }
176     ptLoad.p_offset = reinterpret_cast<uintptr_t>(currentPointer_) - reinterpret_cast<uintptr_t>(mappedMemory_);
177     currentPointer_ += ptLoad.p_memsz;
178 }
179 
Write()180 char* NoteSegmentWriter::Write()
181 {
182     char *noteStart = currentPointer_;
183     PrpsinfoWrite();
184     MultiThreadNoteWrite();
185     AuxvWrite();
186     FileWrite();
187 
188     Elf64_Phdr *ptNote = reinterpret_cast<Elf64_Phdr *>(mappedMemory_ + sizeof(Elf64_Ehdr));
189 
190     ptNote->p_filesz = reinterpret_cast<uintptr_t>(currentPointer_) - reinterpret_cast<uintptr_t>(noteStart);
191 
192     ptNote->p_offset = reinterpret_cast<uintptr_t>(noteStart) - reinterpret_cast<uintptr_t>(mappedMemory_);
193     return currentPointer_;
194 }
195 
SetKeyThreadData(CoreDumpKeyThreadData coreDumpKeyThreadData)196 void NoteSegmentWriter::SetKeyThreadData(CoreDumpKeyThreadData coreDumpKeyThreadData)
197 {
198     coreDumpKeyThreadData_ = coreDumpKeyThreadData;
199 }
200 
PrpsinfoWrite()201 bool NoteSegmentWriter::PrpsinfoWrite()
202 {
203     NoteWrite(NT_PRPSINFO, sizeof(prpsinfo_t), NOTE_NAME_CORE);
204     prpsinfo_t ntPrpsinfo;
205     FillPrpsinfo(ntPrpsinfo);
206     if (!CopyAndAdvance(&ntPrpsinfo, sizeof(ntPrpsinfo))) {
207         DFXLOGE("Write ntPrpsinfo fail, errno:%{public}d", errno);
208         return false;
209     }
210     return true;
211 }
212 
FillPrpsinfo(prpsinfo_t & ntPrpsinfo)213 void NoteSegmentWriter::FillPrpsinfo(prpsinfo_t &ntPrpsinfo)
214 {
215     ReadProcessStat(ntPrpsinfo);
216     ReadProcessStatus(ntPrpsinfo);
217     ReadProcessComm(ntPrpsinfo);
218     ReadProcessCmdline(ntPrpsinfo);
219 }
220 
NoteWrite(uint32_t noteType,size_t descSize,const char * noteName)221 bool NoteSegmentWriter::NoteWrite(uint32_t noteType, size_t descSize, const char* noteName)
222 {
223     Elf64_Nhdr note;
224     note.n_namesz = strlen(noteName) + 1;
225     note.n_descsz = descSize;
226     note.n_type = noteType;
227     if (!CopyAndAdvance(&note, sizeof(note))) {
228         DFXLOGE("Write note fail, errno:%{public}d", errno);
229         return false;
230     }
231     constexpr size_t nameSize = 8; // 8
232     if (memcpy_s(currentPointer_, nameSize, noteName, nameSize) != EOK) {
233         DFXLOGE("memcpy fail, errno:%{public}d", errno);
234         return false;
235     }
236     currentPointer_ += nameSize;
237     return true;
238 }
239 
ReadProcessStat(prpsinfo_t & ntPrpsinfo)240 bool NoteSegmentWriter::ReadProcessStat(prpsinfo_t &ntPrpsinfo)
241 {
242     std::string filePath = "/proc/" + std::to_string(pid_) + "/stat";
243     std::ifstream statFile(filePath);
244     if (!statFile.is_open()) {
245         DFXLOGE("open %{public}s fail, errno:%{public}d", filePath.c_str(), errno);
246         return false;
247     }
248 
249     std::string line;
250     if (!std::getline(statFile, line)) {
251         DFXLOGE("read %{public}s fail, errno:%{public}d", filePath.c_str(), errno);
252         return false;
253     }
254 
255     std::istringstream iss(line);
256 
257     int pid;
258     std::string comm;
259     char state;
260     unsigned long prFlag;
261     int dummyInt;
262 
263     iss >> pid >> comm >> state;
264 
265     for (int i = 0; i < 5; ++i) { // 5
266         iss >> dummyInt;
267     }
268 
269     iss >> prFlag;
270 
271     ntPrpsinfo.pr_state = state;
272     ntPrpsinfo.pr_sname = state;
273     ntPrpsinfo.pr_zomb = (state == 'Z') ? 1 : 0;
274     ntPrpsinfo.pr_flag = prFlag;
275     statFile.close();
276     return true;
277 }
278 
ReadProcessStatus(prpsinfo_t & ntPrpsinfo)279 bool NoteSegmentWriter::ReadProcessStatus(prpsinfo_t &ntPrpsinfo)
280 {
281     ntPrpsinfo.pr_nice = getpriority(PRIO_PROCESS, pid_);
282     unsigned int prUid = 0;
283     unsigned int prGid = 0;
284     int prPpid = 0;
285     char buffer[1024];
286 
287     std::string filePath = "/proc/" + std::to_string(pid_) + "/status";
288     FILE *file = fopen(filePath.c_str(), "r");
289     if (!file) {
290         DFXLOGE("open %{public}s fail, errno:%{public}d", filePath.c_str(), errno);
291         return false;
292     }
293 
294     while (fgets(buffer, sizeof(buffer), file) != nullptr) {
295         if (strncmp(buffer, UID, strlen(UID)) == 0) {
296             if (sscanf_s(buffer + strlen(UID), "%u", &prUid) != 1) {
297                 continue;
298             }
299         } else if (strncmp(buffer, GID, strlen(GID)) == 0) {
300             if (sscanf_s(buffer + strlen(GID), "%u", &prGid) != 1) {
301                 continue;
302             }
303         } else if (strncmp(buffer, PPID, strlen(PPID)) == 0) {
304             if (sscanf_s(buffer + strlen(PPID), "%d", &prPpid) != 1) {
305                 continue;
306             }
307         }
308     }
309     (void)fclose(file);
310     ntPrpsinfo.pr_uid = prUid;
311     ntPrpsinfo.pr_gid = prGid;
312     ntPrpsinfo.pr_pid = pid_;
313     ntPrpsinfo.pr_ppid = prPpid;
314     ntPrpsinfo.pr_pgrp = getpgrp();
315     ntPrpsinfo.pr_sid = getsid(ntPrpsinfo.pr_pid);
316     return true;
317 }
318 
ReadProcessComm(prpsinfo_t & ntPrpsinfo)319 bool NoteSegmentWriter::ReadProcessComm(prpsinfo_t &ntPrpsinfo)
320 {
321     std::string filePath = "/proc/" + std::to_string(pid_) + "/comm";
322     FILE *file = fopen(filePath.c_str(), "r");
323     if (!file) {
324         DFXLOGE("open %{public}s fail, errno:%{public}d", filePath.c_str(), errno);
325         return false;
326     }
327     if (fgets(ntPrpsinfo.pr_fname, sizeof(ntPrpsinfo.pr_fname), file) == nullptr) {
328         DFXLOGE("read comm fail, errno:%{public}d", errno);
329         (void)fclose(file);
330         return false;
331     }
332     (void)fclose(file);
333     return true;
334 }
335 
ReadProcessCmdline(prpsinfo_t & ntPrpsinfo)336 bool NoteSegmentWriter::ReadProcessCmdline(prpsinfo_t &ntPrpsinfo)
337 {
338     std::string filePath = "/proc/" + std::to_string(pid_) + "/cmdline";
339     FILE *file = fopen(filePath.c_str(), "r");
340     if (!file) {
341         DFXLOGE("open %{public}s fail, errno:%{public}d", filePath.c_str(), errno);
342         return false;
343     }
344     char cmdline[256];
345     size_t len = fread(cmdline, 1, sizeof(cmdline) - 1, file);
346     (void)fclose(file);
347 
348     if (len <= 0) {
349         DFXLOGE("read %{public}s fail, errno:%{public}d", filePath.c_str(), errno);
350         return false;
351     }
352     cmdline[len] = '\0';
353 
354     (void)memset_s(&ntPrpsinfo.pr_psargs, sizeof(ntPrpsinfo.pr_psargs), 0, sizeof(ntPrpsinfo.pr_psargs));
355     auto ret = strncpy_s(ntPrpsinfo.pr_psargs, sizeof(ntPrpsinfo.pr_psargs),
356         cmdline, sizeof(ntPrpsinfo.pr_psargs) - 1);
357     if (ret != 0) {
358         DFXLOGE("strncpy_s fail, err:%{public}d", ret);
359         return false;
360     }
361     return true;
362 }
363 
MultiThreadNoteWrite()364 bool NoteSegmentWriter::MultiThreadNoteWrite()
365 {
366     std::string filePath = "/proc/" + std::to_string(pid_) + "/task";
367     DIR *dir = opendir(filePath.c_str());
368     if (!dir) {
369         DFXLOGE("open %{public}s fail, errno:%{public}d", filePath.c_str(), errno);
370         return false;
371     }
372 
373     struct dirent *entry;
374     while ((entry = readdir(dir)) != nullptr) {
375         if (entry->d_name[0] >= '0' && entry->d_name[0] <= '9') {
376             pid_t tid = strtol(entry->d_name, nullptr, 10);
377             ThreadNoteWrite(tid);
378         }
379     }
380     closedir(dir);
381     return true;
382 }
383 
ThreadNoteWrite(pid_t tid)384 void NoteSegmentWriter::ThreadNoteWrite(pid_t tid)
385 {
386     PrstatusWrite(tid);
387     ArmPacMaskWrite(tid);
388     FpregsetWrite(tid);
389     SiginfoWrite(tid);
390     ArmTaggedAddrCtrlWrite();
391 }
392 
ArmPacMaskWrite(pid_t tid)393 bool NoteSegmentWriter::ArmPacMaskWrite(pid_t tid)
394 {
395     if (!NoteWrite(NT_ARM_PAC_MASK, sizeof(UserPacMask), NOTE_NAME_LINUX)) {
396         return false;
397     }
398 
399     UserPacMask ntUserPacMask;
400     if (tid == targetTid_) {
401         ntUserPacMask = coreDumpKeyThreadData_.ntUserPacMask;
402     } else {
403         GetRegset(tid, NT_ARM_PAC_MASK, ntUserPacMask);
404     }
405     if (!CopyAndAdvance(&ntUserPacMask, sizeof(ntUserPacMask))) {
406         DFXLOGE("Write ntUserPacMask fail, errno:%{public}d", errno);
407         return false;
408     }
409     return true;
410 }
411 
PrstatusWrite(pid_t tid)412 bool NoteSegmentWriter::PrstatusWrite(pid_t tid)
413 {
414     NoteWrite(NT_PRSTATUS, sizeof(prstatus_t), NOTE_NAME_CORE);
415     prstatus_t ntPrstatus;
416     GetPrStatus(ntPrstatus, tid);
417     GetPrReg(ntPrstatus, tid);
418     if (!CopyAndAdvance(&ntPrstatus, sizeof(ntPrstatus))) {
419         DFXLOGE("Write ntPrstatus fail, errno:%{public}d", errno);
420         return false;
421     }
422     return true;
423 }
424 
FpregsetWrite(pid_t tid)425 bool NoteSegmentWriter::FpregsetWrite(pid_t tid)
426 {
427     if (!NoteWrite(NT_FPREGSET, sizeof(struct user_fpsimd_struct), NOTE_NAME_CORE)) {
428         return false;
429     }
430 
431     struct user_fpsimd_struct ntFpregset;
432     if (tid == targetTid_) {
433         ntFpregset = coreDumpKeyThreadData_.ntFpregset;
434     } else {
435         GetRegset(tid, NT_FPREGSET, ntFpregset);
436     }
437 
438     if (!CopyAndAdvance(&ntFpregset, sizeof(ntFpregset))) {
439         DFXLOGE("Write ntFpregset fail, errno:%{public}d", errno);
440         return false;
441     }
442     return true;
443 }
444 
SiginfoWrite(pid_t tid)445 bool NoteSegmentWriter::SiginfoWrite(pid_t tid)
446 {
447     if (!NoteWrite(NT_SIGINFO, sizeof(siginfo_t), NOTE_NAME_CORE)) {
448         return false;
449     }
450 
451     siginfo_t ntSiginfo;
452 
453     if (tid == targetTid_) {
454         ntSiginfo = coreDumpKeyThreadData_.ntSiginfo;
455     } else {
456         GetSiginfoCommon(ntSiginfo, tid);
457     }
458 
459     if (!CopyAndAdvance(&ntSiginfo, sizeof(ntSiginfo))) {
460         DFXLOGE("Write ntSiginfo fail, errno:%{public}d", errno);
461         return false;
462     }
463     return true;
464 }
465 
ArmTaggedAddrCtrlWrite()466 bool NoteSegmentWriter::ArmTaggedAddrCtrlWrite()
467 {
468     if (!NoteWrite(0x409, sizeof(long), NOTE_NAME_LINUX)) {
469         return false;
470     }
471 
472     (void)memset_s(currentPointer_, sizeof(long), 0, sizeof(long));
473     currentPointer_ += sizeof(long);
474     return true;
475 }
476 
GetPrStatus(prstatus_t & ntPrstatus,pid_t tid)477 bool NoteSegmentWriter::GetPrStatus(prstatus_t &ntPrstatus, pid_t tid)
478 {
479     if (tid == targetTid_ && coreDumpKeyThreadData_.prStatusValid) {
480         ntPrstatus.pr_cursig = coreDumpKeyThreadData_.ntPrstatus.pr_info.si_signo;
481     } else {
482         if (GetSiginfoCommon(ntPrstatus.pr_info, tid)) {
483             ntPrstatus.pr_cursig = ntPrstatus.pr_info.si_signo;
484         }
485     }
486 
487     char buffer[1024];
488     std::string filePath = "/proc/" + std::to_string(tid) + "/status";
489     FILE *file = fopen(filePath.c_str(), "r");
490     if (!file) {
491         DFXLOGE("open %{public}s fail, errno:%{public}d", filePath.c_str(), errno);
492         return false;
493     }
494     while (fgets(buffer, sizeof(buffer), file) != nullptr) {
495         if (strncmp(buffer, PPID, strlen(PPID)) == 0) {
496             if (sscanf_s(buffer + strlen(PPID), "%d", &ntPrstatus.pr_ppid) != 1) {
497                 continue;
498             }
499         } else if (strncmp(buffer, SIGPND, strlen(SIGPND)) == 0) {
500             if (sscanf_s(buffer + strlen(SIGPND), "%lx", &ntPrstatus.pr_sigpend) != 1) {
501                 continue;
502             }
503         } else if (strncmp(buffer, SIGBLK, strlen(SIGBLK)) == 0) {
504             if (sscanf_s(buffer + strlen(SIGBLK), "%lx", &ntPrstatus.pr_sighold) != 1) {
505                 continue;
506             }
507         }
508     }
509 
510     (void)fclose(file);
511     ntPrstatus.pr_pid = tid;
512     ntPrstatus.pr_pgrp = getpgrp();
513     ntPrstatus.pr_sid = getsid(ntPrstatus.pr_pid);
514     if (!GetRusage(ntPrstatus)) {
515         DFXLOGE("failed to get rusage, tid:%{public}d, errno:%{public}d", tid, errno);
516         return false;
517     }
518     return true;
519 }
520 
GetRusage(prstatus_t & ntPrstatus)521 bool NoteSegmentWriter::GetRusage(prstatus_t &ntPrstatus)
522 {
523     struct rusage usage;
524     getrusage(RUSAGE_SELF, &usage);
525     if (memcpy_s(&ntPrstatus.pr_utime, sizeof(ntPrstatus.pr_utime), &usage.ru_utime, sizeof(usage.ru_utime)) != 0) {
526         return false;
527     }
528     if (memcpy_s(&ntPrstatus.pr_stime, sizeof(ntPrstatus.pr_stime), &usage.ru_stime, sizeof(usage.ru_stime)) != 0) {
529         return false;
530     }
531     getrusage(RUSAGE_CHILDREN, &usage);
532     if (memcpy_s(&ntPrstatus.pr_cutime, sizeof(ntPrstatus.pr_cutime), &usage.ru_utime, sizeof(usage.ru_utime)) != 0) {
533         return false;
534     }
535     if (memcpy_s(&ntPrstatus.pr_cstime, sizeof(ntPrstatus.pr_cstime), &usage.ru_stime, sizeof(usage.ru_stime)) != 0) {
536         return false;
537     }
538     return true;
539 }
540 
GetPrReg(prstatus_t & ntPrstatus,pid_t tid)541 bool NoteSegmentWriter::GetPrReg(prstatus_t &ntPrstatus, pid_t tid)
542 {
543     if (tid == targetTid_) {
544         if (memcpy_s(&(ntPrstatus.pr_reg), sizeof(ntPrstatus.pr_reg), keyRegs_->RawData(),
545             sizeof(ntPrstatus.pr_reg)) != 0) {
546             DFXLOGE("Failed to memcpy regs data, errno = %{public}d", errno);
547             return false;
548         }
549         ntPrstatus.pr_fpvalid = coreDumpKeyThreadData_.fpRegValid;
550     } else {
551         struct iovec iov;
552         (void)memset_s(&iov, sizeof(iov), 0, sizeof(iov));
553         iov.iov_base = &(ntPrstatus.pr_reg);
554         iov.iov_len = sizeof(ntPrstatus.pr_reg);
555         if (ptrace(PTRACE_GETREGSET, tid, NT_PRSTATUS, &iov) == -1) {
556             DFXLOGE("ptrace failed NT_PRSTATUS, tid:%{public}d, errno:%{public}d", tid, errno);
557             return false;
558         }
559         struct user_fpsimd_struct ntFpregset;
560         if (GetRegset(tid, NT_FPREGSET, ntFpregset)) {
561             ntPrstatus.pr_fpvalid = 1;
562         } else {
563             ntPrstatus.pr_fpvalid = 0;
564         }
565     }
566     return true;
567 }
568 
AuxvWrite()569 bool NoteSegmentWriter::AuxvWrite()
570 {
571     Elf64_Nhdr *note = reinterpret_cast<Elf64_Nhdr *>(currentPointer_);
572     note->n_namesz = 0x05;
573     note->n_type = NT_AUXV;
574 
575     currentPointer_ += sizeof(Elf64_Nhdr);
576     char noteName[8] = "CORE";
577     if (!CopyAndAdvance(noteName, sizeof(noteName))) {
578         DFXLOGE("Wrtie noteName fail, errno:%{public}d", errno);
579         return false;
580     }
581 
582     if (!ReadProcessAuxv(note)) {
583         DFXLOGE("Read targetPid Process Auxv fail");
584     }
585     return true;
586 }
587 
ReadProcessAuxv(Elf64_Nhdr * note)588 bool NoteSegmentWriter::ReadProcessAuxv(Elf64_Nhdr *note)
589 {
590     std::string filePath = "/proc/" + std::to_string(pid_) + "/auxv";
591     FILE *file = fopen(filePath.c_str(), "r");
592     if (!file) {
593         note->n_descsz = 0;
594         DFXLOGE("open %{public}s fail, errno:%{public}d", filePath.c_str(), errno);
595         return false;
596     }
597     Elf64_auxv_t ntAuxv;
598     note->n_descsz = 0;
599     while (fread(&ntAuxv, sizeof(Elf64_auxv_t), 1, file) == 1) {
600         note->n_descsz += sizeof(ntAuxv);
601         if (!CopyAndAdvance(&ntAuxv, sizeof(ntAuxv))) {
602             DFXLOGE("Wrtie ntAuxv fail, errno:%{public}d", errno);
603             (void)fclose(file);
604             return false;
605         }
606         if (ntAuxv.a_type == AT_NULL) {
607             break;
608         }
609     }
610     (void)fclose(file);
611     return true;
612 }
613 
FileWrite()614 bool NoteSegmentWriter::FileWrite()
615 {
616     Elf64_Nhdr *note = reinterpret_cast<Elf64_Nhdr *>(currentPointer_);
617     note->n_namesz = 0x05;
618     note->n_type = NT_FILE;
619 
620     currentPointer_ += sizeof(Elf64_Nhdr);
621     char noteName[8] = "CORE";
622     if (!CopyAndAdvance(noteName, sizeof(noteName))) {
623         DFXLOGE("Wrtie notename fail, errno:%{public}d", errno);
624         return false;
625     }
626 
627     char *startPointer = currentPointer_;
628     FileHeader *ntFileHd = reinterpret_cast<FileHeader *>(currentPointer_);
629     ntFileHd->pageSize = 0x01;
630     currentPointer_ += sizeof(FileHeader);
631 
632     Elf64_Half lineNumber = 1;
633     WriteAddrRelated();
634     WriteFilePath(lineNumber);
635 
636     note->n_descsz = reinterpret_cast<uintptr_t>(currentPointer_) - reinterpret_cast<uintptr_t>(startPointer);
637     ntFileHd->count = lineNumber - 1;
638 
639     uint8_t remain = note->n_descsz % 4; // 4
640     for (uint8_t i = 0; i < (4 - remain); i++) { // 4
641         if (remain == 0) {
642             break;
643         }
644         *currentPointer_ = 0;
645         currentPointer_ += 1;
646     }
647     return true;
648 }
649 
WriteAddrRelated()650 bool NoteSegmentWriter::WriteAddrRelated()
651 {
652     for (const auto& region : maps_) {
653         if (region.pathName[0] != '/' || (region.priority[0] != 'r')) {
654             continue;
655         }
656         FileMap ntFile;
657         ntFile.start = region.startHex;
658         ntFile.end = region.endHex;
659         ntFile.offset = region.offsetHex;
660         if (!CopyAndAdvance(&ntFile, sizeof(ntFile))) {
661             DFXLOGE("Wrtie ntFile fail, errno:%{public}d", errno);
662             return false;
663         }
664     }
665     return true;
666 }
667 
WriteFilePath(Elf64_Half & lineNumber)668 bool NoteSegmentWriter::WriteFilePath(Elf64_Half &lineNumber)
669 {
670     for (const auto& region : maps_) {
671         if (region.pathName[0] != '/' || (region.priority[0] != 'r')) {
672             continue;
673         }
674         if (!CopyAndAdvance(region.pathName, strlen(region.pathName))) {
675             DFXLOGE("Wrtie pathName fail, errno:%{public}d", errno);
676             return false;
677         }
678         *currentPointer_ = '\0';
679         currentPointer_ += 1;
680         lineNumber += 1;
681     }
682     return true;
683 }
684 
Write()685 char* SectionHeaderTableWriter::Write()
686 {
687     Elf64_Ehdr *elfHeader = reinterpret_cast<Elf64_Ehdr *>(mappedMemory_);
688     Elf64_Phdr *programHeader = reinterpret_cast<Elf64_Phdr *>(mappedMemory_ + sizeof(Elf64_Ehdr));
689 
690     char *strTableAddr = currentPointer_;
691     char strTable[22] = "..shstrtab.note0.load"; // 22
692     (void)memset_s(currentPointer_, sizeof(strTable), 0, sizeof(strTable)); // 22
693 
694     strTable[0] = 0x00;
695     strTable[10] = 0x00; // 10
696     strTable[16] = 0x00; // 16
697     if (!CopyAndAdvance(strTable, sizeof(strTable))) {
698         DFXLOGE("Wrtie strTable fail, errno:%{public}d", errno);
699         return currentPointer_;
700     }
701 
702     Elf64_Off offset = Elf64_Off(currentPointer_ - mappedMemory_);
703     uint8_t remain = offset % 8; // 8
704     AdjustOffset(remain);
705     elfHeader->e_shoff = static_cast<Elf64_Off>(currentPointer_ - mappedMemory_);
706     (void)memset_s(currentPointer_, sizeof(Elf64_Shdr), 0, sizeof(Elf64_Shdr));
707     currentPointer_ += sizeof(Elf64_Shdr);
708     Elf64_Shdr *sectionHeader = reinterpret_cast<Elf64_Shdr *>(currentPointer_);
709     sectionHeader->sh_name = 0x0B;
710     SectionHeaderFill(sectionHeader, SHT_NOTE, SHF_ALLOC, programHeader);
711     sectionHeader += 1;
712     programHeader += 1;
713     for (int i = 0; i < elfHeader->e_shnum - 3; i++) { // 3
714         sectionHeader->sh_name = 0x11;
715         Elf64_Xword shFlag = 0x00;
716         if (programHeader->p_flags == PF_R) {
717             shFlag = SHF_ALLOC;
718         } else if (programHeader->p_flags == (PF_R | PF_W)) {
719             shFlag = SHF_WRITE | SHF_ALLOC;
720         } else if (programHeader->p_flags == (PF_R | PF_X)) {
721             shFlag = SHF_ALLOC | SHF_EXECINSTR;
722         }
723         SectionHeaderFill(sectionHeader, SHT_PROGBITS, shFlag, programHeader);
724         sectionHeader += 1;
725         programHeader += 1;
726     }
727     sectionHeader->sh_name = 0x01;
728     SectionHeaderFill(sectionHeader, SHT_STRTAB, 0x00, programHeader);
729     sectionHeader->sh_addr = 0x00;
730 
731     sectionHeader->sh_offset = static_cast<Elf64_Off>(strTableAddr - mappedMemory_);
732     sectionHeader->sh_size = 0x16;
733     sectionHeader += 1;
734     currentPointer_ = reinterpret_cast<char*>(sectionHeader);
735     return currentPointer_;
736 }
737 
AdjustOffset(uint8_t remain)738 void SectionHeaderTableWriter::AdjustOffset(uint8_t remain)
739 {
740     if (remain > 8) { // 8
741         return;
742     }
743     for (uint8_t i = 0; i < (8 - remain); i++) { // 8
744         if (remain == 0) {
745             break;
746         }
747         *currentPointer_ = 0;
748         currentPointer_ += 1;
749     }
750 }
751 
SectionHeaderFill(Elf64_Shdr * sectionHeader,Elf64_Word shType,Elf64_Xword shFlag,Elf64_Phdr * programHeader)752 void SectionHeaderTableWriter::SectionHeaderFill(Elf64_Shdr *sectionHeader, Elf64_Word shType,
753     Elf64_Xword shFlag, Elf64_Phdr *programHeader)
754 {
755     sectionHeader->sh_type = shType;
756     sectionHeader->sh_flags = shFlag;
757     sectionHeader->sh_addr = programHeader->p_vaddr;
758     sectionHeader->sh_offset = programHeader->p_offset;
759     sectionHeader->sh_size = programHeader->p_filesz;
760     sectionHeader->sh_link = 0x00;
761     sectionHeader->sh_info = 0x00;
762     sectionHeader->sh_addralign = 0x1;
763     sectionHeader->sh_entsize = 0x00;
764 }
765 
766 } // namespace HiviewDFX
767 } // namespace OHOS
768 #endif