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 ®ion : 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 ®ion)
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 ®ion)
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(¬e, 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