1 /*
2 * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "dfx_regs.h"
17 #include "dfx_regs_qut.h"
18
19 #include <elf.h>
20 #include <securec.h>
21 #include <sys/ptrace.h>
22 #include <sys/uio.h>
23 #include "dfx_define.h"
24 #include "dfx_log.h"
25 #include "string_printf.h"
26
27 namespace OHOS {
28 namespace HiviewDFX {
29 namespace {
30 #undef LOG_DOMAIN
31 #undef LOG_TAG
32 #define LOG_DOMAIN 0xD002D11
33 #define LOG_TAG "DfxRegs"
34 }
35 std::vector<uint16_t> DfxRegsQut::qutRegs_ = {};
36
Create()37 std::shared_ptr<DfxRegs> DfxRegs::Create()
38 {
39 #if defined(__arm__)
40 auto dfxregs = std::make_shared<DfxRegsArm>();
41 #elif defined(__aarch64__)
42 auto dfxregs = std::make_shared<DfxRegsArm64>();
43 #elif defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 64
44 auto dfxregs = std::make_shared<DfxRegsRiscv64>();
45 #elif defined(__x86_64__)
46 auto dfxregs = std::make_shared<DfxRegsX86_64>();
47 #elif defined(__loongarch_lp64)
48 auto dfxregs = std::make_shared<DfxRegsLoongArch64>();
49 #else
50 #error "Unsupported architecture"
51 #endif
52 return dfxregs;
53 }
54
CreateFromUcontext(const ucontext_t & context)55 std::shared_ptr<DfxRegs> DfxRegs::CreateFromUcontext(const ucontext_t& context)
56 {
57 auto dfxregs = DfxRegs::Create();
58 dfxregs->SetFromUcontext(context);
59 return dfxregs;
60 }
61
CreateFromRegs(const UnwindMode mode,const uintptr_t * regs,size_t size)62 std::shared_ptr<DfxRegs> DfxRegs::CreateFromRegs(const UnwindMode mode, const uintptr_t* regs,
63 size_t size)
64 {
65 auto dfxregs = DfxRegs::Create();
66 if ((mode == UnwindMode::FRAMEPOINTER_UNWIND && size < FP_MINI_REGS_SIZE) ||
67 (mode == UnwindMode::MINIMAL_UNWIND && size < QUT_MINI_REGS_SIZE)) {
68 DFXLOGE("The number of long groups is too short");
69 return dfxregs;
70 }
71 if (mode == UnwindMode::DWARF_UNWIND) {
72 dfxregs->SetRegsData(regs, REG_LAST);
73 } else if (mode == UnwindMode::FRAMEPOINTER_UNWIND) {
74 dfxregs->SetFromFpMiniRegs(regs, FP_MINI_REGS_SIZE);
75 } else if (mode == UnwindMode::MINIMAL_UNWIND) {
76 dfxregs->SetFromQutMiniRegs(regs, QUT_MINI_REGS_SIZE);
77 }
78 return dfxregs;
79 }
80
CreateRemoteRegs(pid_t pid)81 std::shared_ptr<DfxRegs> DfxRegs::CreateRemoteRegs(pid_t pid)
82 {
83 if (pid <= 0) {
84 return nullptr;
85 }
86 auto dfxregs = DfxRegs::Create();
87 gregset_t regs;
88 struct iovec iov;
89 iov.iov_base = ®s;
90 iov.iov_len = sizeof(regs);
91 // must be attach first
92 if (ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov) == -1) {
93 DFXLOGE("Failed to ptrace pid(%{public}d), errno=%{public}d", pid, errno);
94 return nullptr;
95 }
96 #if defined(__x86_64__)
97 dfxregs->regsData_[REG_X86_64_RAX] = regs[RAX];
98 dfxregs->regsData_[REG_X86_64_RDX] = regs[RDX];
99 dfxregs->regsData_[REG_X86_64_RCX] = regs[RCX];
100 dfxregs->regsData_[REG_X86_64_RBX] = regs[RBX];
101 dfxregs->regsData_[REG_X86_64_RSI] = regs[RSI];
102 dfxregs->regsData_[REG_X86_64_RDI] = regs[RDI];
103 dfxregs->regsData_[REG_X86_64_RBP] = regs[RBP];
104 dfxregs->regsData_[REG_X86_64_RSP] = regs[RSP];
105 dfxregs->regsData_[REG_X86_64_R8] = regs[R8];
106 dfxregs->regsData_[REG_X86_64_R9] = regs[R9];
107 dfxregs->regsData_[REG_X86_64_R10] = regs[R10];
108 dfxregs->regsData_[REG_X86_64_R11] = regs[R11];
109 dfxregs->regsData_[REG_X86_64_R12] = regs[R12];
110 dfxregs->regsData_[REG_X86_64_R13] = regs[R13];
111 dfxregs->regsData_[REG_X86_64_R14] = regs[R14];
112 dfxregs->regsData_[REG_X86_64_R15] = regs[R15];
113 dfxregs->regsData_[REG_X86_64_RIP] = regs[RIP];
114 #else
115 if (memcpy_s(dfxregs->regsData_.data(), REG_LAST * sizeof(uintptr_t), ®s, REG_LAST * sizeof(uintptr_t)) != 0) {
116 DFXLOGE("Failed to memcpy regs data, errno=%{public}d", errno);
117 return nullptr;
118 }
119 #endif
120 return dfxregs;
121 }
122
GetRegsData() const123 std::vector<uintptr_t> DfxRegs::GetRegsData() const
124 {
125 return regsData_;
126 }
127
SetRegsData(const std::vector<uintptr_t> & regs)128 void DfxRegs::SetRegsData(const std::vector<uintptr_t>& regs)
129 {
130 regsData_ = regs;
131 }
132
SetRegsData(const uintptr_t * regs,const size_t size)133 void DfxRegs::SetRegsData(const uintptr_t* regs, const size_t size)
134 {
135 size_t cpySize = (size > RegsSize()) ? RegsSize() : size;
136 if (memcpy_s(RawData(), cpySize * sizeof(uintptr_t), regs, cpySize * sizeof(uintptr_t)) != 0) {
137 DFXLOGE("Failed to set regs data, errno=%{public}d", errno);
138 }
139 }
140
GetReg(size_t idx)141 uintptr_t* DfxRegs::GetReg(size_t idx)
142 {
143 if (idx >= REG_LAST) {
144 return nullptr;
145 }
146 return &(regsData_[idx]);
147 }
148
SetReg(const int idx,const uintptr_t * val)149 void DfxRegs::SetReg(const int idx, const uintptr_t* val)
150 {
151 if (idx >= REG_LAST) {
152 return;
153 }
154 regsData_[idx] = *val;
155 }
156
GetSpecialRegs(uintptr_t & fp,uintptr_t & lr,uintptr_t & sp,uintptr_t & pc) const157 void DfxRegs::GetSpecialRegs(uintptr_t& fp, uintptr_t& lr, uintptr_t& sp, uintptr_t& pc) const
158 {
159 #if defined(__arm__) || defined(__aarch64__) || defined(__riscv) || defined(__loongarch_lp64)
160 fp = regsData_[REG_FP];
161 lr = regsData_[REG_LR];
162 #endif
163 sp = regsData_[REG_SP];
164 pc = regsData_[REG_PC];
165 }
166
SetSpecialRegs(uintptr_t fp,uintptr_t lr,uintptr_t sp,uintptr_t pc)167 void DfxRegs::SetSpecialRegs(uintptr_t fp, uintptr_t lr, uintptr_t sp, uintptr_t pc)
168 {
169 #if defined(__arm__) || defined(__aarch64__) || defined(__riscv) || defined(__loongarch_lp64)
170 regsData_[REG_FP] = fp;
171 regsData_[REG_LR] = lr;
172 #endif
173 regsData_[REG_SP] = sp;
174 regsData_[REG_PC] = pc;
175 }
176
GetSp() const177 uintptr_t DfxRegs::GetSp() const
178 {
179 return regsData_[REG_SP];
180 }
181
SetSp(uintptr_t sp)182 void DfxRegs::SetSp(uintptr_t sp)
183 {
184 regsData_[REG_SP] = sp;
185 }
186
GetPc() const187 uintptr_t DfxRegs::GetPc() const
188 {
189 return regsData_[REG_PC];
190 }
191
SetPc(uintptr_t pc)192 void DfxRegs::SetPc(uintptr_t pc)
193 {
194 regsData_[REG_PC] = pc;
195 }
196
GetFp() const197 uintptr_t DfxRegs::GetFp() const
198 {
199 #if defined(__arm__) || defined(__aarch64__) || defined(__loongarch_lp64)
200 return regsData_[REG_FP];
201 #else
202 return 0;
203 #endif
204 }
205
SetFp(uintptr_t fp)206 void DfxRegs::SetFp(uintptr_t fp)
207 {
208 #if defined(__arm__) || defined(__aarch64__) || defined(__riscv) || defined(__loongarch_lp64)
209 regsData_[REG_FP] = fp;
210 #endif
211 }
212
GetSpecialRegsName(uintptr_t val) const213 std::string DfxRegs::GetSpecialRegsName(uintptr_t val) const
214 {
215 uintptr_t fp = 0, lr = 0, sp = 0, pc = 0;
216 GetSpecialRegs(fp, lr, sp, pc);
217 if (val == pc) {
218 return "pc";
219 } else if (val == lr) {
220 return "lr";
221 } else if (val == sp) {
222 return "sp";
223 } else if (val == fp) {
224 return "fp";
225 }
226 return "";
227 }
228
GetSpecialRegsNameByIndex(int index) const229 std::string DfxRegs::GetSpecialRegsNameByIndex(int index) const
230 {
231 switch (index) {
232 #if defined(__arm__) || defined(__aarch64__) || defined(__riscv)
233 case REG_FP:
234 return "fp";
235 case REG_LR:
236 return "lr";
237 #endif
238 case REG_SP:
239 return "sp";
240 case REG_PC:
241 return "pc";
242 default:
243 return "";
244 }
245 return "";
246 }
247
PrintSpecialRegs() const248 std::string DfxRegs::PrintSpecialRegs() const
249 {
250 uintptr_t fp = 0, lr = 0, sp = 0, pc = 0;
251 GetSpecialRegs(fp, lr, sp, pc);
252 std::string regsStr;
253 #ifdef __LP64__
254 regsStr = StringPrintf("fp:%016lx sp:%016lx lr:%016lx pc:%016lx\n", fp, sp, lr, pc);
255 #else
256 regsStr = StringPrintf("fp:%08x sp:%08x lr:%08x pc:%08x\n", fp, sp, lr, pc);
257 #endif
258 return regsStr;
259 }
260 } // namespace HiviewDFX
261 } // namespace OHOS
262