• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     switch (mode) {
72         case UnwindMode::DWARF_UNWIND:
73             dfxregs->SetRegsData(regs, REG_LAST);
74             break;
75         case UnwindMode::FRAMEPOINTER_UNWIND:
76             dfxregs->SetFromFpMiniRegs(regs, FP_MINI_REGS_SIZE);
77             break;
78         case UnwindMode::MINIMAL_UNWIND:
79             dfxregs->SetFromQutMiniRegs(regs, QUT_MINI_REGS_SIZE);
80             break;
81         default:
82             break;
83     }
84     return dfxregs;
85 }
86 
CreateRemoteRegs(pid_t pid)87 std::shared_ptr<DfxRegs> DfxRegs::CreateRemoteRegs(pid_t pid)
88 {
89     if (pid <= 0) {
90         return nullptr;
91     }
92     auto dfxregs = DfxRegs::Create();
93     gregset_t regs;
94     struct iovec iov;
95     iov.iov_base = &regs;
96     iov.iov_len = sizeof(regs);
97     // must be attach first
98     if (ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov) == -1) {
99         DFXLOGE("Failed to ptrace pid(%{public}d), errno=%{public}d", pid, errno);
100         return nullptr;
101     }
102 #if defined(__x86_64__)
103     dfxregs->regsData_[REG_X86_64_RAX] = regs[RAX];
104     dfxregs->regsData_[REG_X86_64_RDX] = regs[RDX];
105     dfxregs->regsData_[REG_X86_64_RCX] = regs[RCX];
106     dfxregs->regsData_[REG_X86_64_RBX] = regs[RBX];
107     dfxregs->regsData_[REG_X86_64_RSI] = regs[RSI];
108     dfxregs->regsData_[REG_X86_64_RDI] = regs[RDI];
109     dfxregs->regsData_[REG_X86_64_RBP] = regs[RBP];
110     dfxregs->regsData_[REG_X86_64_RSP] = regs[RSP];
111     dfxregs->regsData_[REG_X86_64_R8] = regs[R8];
112     dfxregs->regsData_[REG_X86_64_R9] = regs[R9];
113     dfxregs->regsData_[REG_X86_64_R10] = regs[R10];
114     dfxregs->regsData_[REG_X86_64_R11] = regs[R11];
115     dfxregs->regsData_[REG_X86_64_R12] = regs[R12];
116     dfxregs->regsData_[REG_X86_64_R13] = regs[R13];
117     dfxregs->regsData_[REG_X86_64_R14] = regs[R14];
118     dfxregs->regsData_[REG_X86_64_R15] = regs[R15];
119     dfxregs->regsData_[REG_X86_64_RIP] = regs[RIP];
120 #else
121     if (memcpy_s(dfxregs->regsData_.data(), REG_LAST * sizeof(uintptr_t), &regs, REG_LAST * sizeof(uintptr_t)) != 0) {
122         DFXLOGE("Failed to memcpy regs data, errno=%{public}d", errno);
123         return nullptr;
124     }
125 #endif
126     return dfxregs;
127 }
128 
GetRegsData() const129 std::vector<uintptr_t> DfxRegs::GetRegsData() const
130 {
131     return regsData_;
132 }
133 
SetRegsData(const std::vector<uintptr_t> & regs)134 void DfxRegs::SetRegsData(const std::vector<uintptr_t>& regs)
135 {
136     regsData_ = regs;
137 }
138 
SetRegsData(const uintptr_t * regs,const size_t size)139 void DfxRegs::SetRegsData(const uintptr_t* regs, const size_t size)
140 {
141     size_t cpySize = (size > RegsSize()) ? RegsSize() : size;
142     if (memcpy_s(RawData(), RegsSize() * sizeof(uintptr_t), regs, cpySize * sizeof(uintptr_t)) != 0) {
143         DFXLOGE("Failed to set regs data, errno=%{public}d", errno);
144     }
145 }
146 
GetReg(size_t idx)147 uintptr_t* DfxRegs::GetReg(size_t idx)
148 {
149     if (idx >= REG_LAST) {
150         return nullptr;
151     }
152     return &(regsData_[idx]);
153 }
154 
SetReg(const int idx,const uintptr_t * val)155 void DfxRegs::SetReg(const int idx, const uintptr_t* val)
156 {
157     if (idx >= REG_LAST) {
158         return;
159     }
160     regsData_[idx] = *val;
161 }
162 
GetSpecialRegs(uintptr_t & fp,uintptr_t & lr,uintptr_t & sp,uintptr_t & pc) const163 void DfxRegs::GetSpecialRegs(uintptr_t& fp, uintptr_t& lr, uintptr_t& sp, uintptr_t& pc) const
164 {
165 #if defined(__arm__) || defined(__aarch64__) || defined(__riscv) || defined(__loongarch_lp64)
166     fp = regsData_[REG_FP];
167     lr = regsData_[REG_LR];
168 #endif
169     sp = regsData_[REG_SP];
170     pc = regsData_[REG_PC];
171 }
172 
SetSpecialRegs(uintptr_t fp,uintptr_t lr,uintptr_t sp,uintptr_t pc)173 void DfxRegs::SetSpecialRegs(uintptr_t fp, uintptr_t lr, uintptr_t sp, uintptr_t pc)
174 {
175 #if defined(__arm__) || defined(__aarch64__) || defined(__riscv) || defined(__loongarch_lp64)
176     regsData_[REG_FP] = fp;
177     regsData_[REG_LR] = lr;
178 #endif
179     regsData_[REG_SP] = sp;
180     regsData_[REG_PC] = pc;
181 }
182 
GetSp() const183 uintptr_t DfxRegs::GetSp() const
184 {
185     return regsData_[REG_SP];
186 }
187 
SetSp(uintptr_t sp)188 void DfxRegs::SetSp(uintptr_t sp)
189 {
190     regsData_[REG_SP] = sp;
191 }
192 
GetPc() const193 uintptr_t DfxRegs::GetPc() const
194 {
195     return regsData_[REG_PC];
196 }
197 
SetPc(uintptr_t pc)198 void DfxRegs::SetPc(uintptr_t pc)
199 {
200     regsData_[REG_PC] = pc;
201 }
202 
GetFp() const203 uintptr_t DfxRegs::GetFp() const
204 {
205 #if defined(__arm__) || defined(__aarch64__) || defined(__loongarch_lp64)
206     return regsData_[REG_FP];
207 #else
208     return 0;
209 #endif
210 }
211 
SetFp(uintptr_t fp)212 void DfxRegs::SetFp(uintptr_t fp)
213 {
214 #if defined(__arm__) || defined(__aarch64__)  || defined(__riscv) || defined(__loongarch_lp64)
215     regsData_[REG_FP] = fp;
216 #endif
217 }
218 
GetSpecialRegsName(uintptr_t val) const219 std::string DfxRegs::GetSpecialRegsName(uintptr_t val) const
220 {
221     uintptr_t fp = 0, lr = 0, sp = 0, pc = 0;
222     GetSpecialRegs(fp, lr, sp, pc);
223     if (val == pc) {
224         return "pc";
225     } else if (val == lr) {
226         return "lr";
227     } else if (val == sp) {
228         return "sp";
229     } else if (val == fp) {
230         return "fp";
231     }
232     return "";
233 }
234 
GetSpecialRegsNameByIndex(int index) const235 std::string DfxRegs::GetSpecialRegsNameByIndex(int index) const
236 {
237     switch (index) {
238 #if defined(__arm__) || defined(__aarch64__) || defined(__riscv)
239         case REG_FP:
240             return "fp";
241         case REG_LR:
242             return "lr";
243 #endif
244         case REG_SP:
245             return "sp";
246         case REG_PC:
247             return "pc";
248         default:
249             return "";
250     }
251     return "";
252 }
253 
PrintSpecialRegs() const254 std::string DfxRegs::PrintSpecialRegs() const
255 {
256     uintptr_t fp = 0;
257     uintptr_t lr = 0;
258     uintptr_t sp = 0;
259     uintptr_t pc = 0;
260     GetSpecialRegs(fp, lr, sp, pc);
261     std::string regsStr;
262 #ifdef __LP64__
263     regsStr = StringPrintf("fp:%016lx sp:%016lx lr:%016lx pc:%016lx\n", fp, sp, lr, pc);
264 #else
265     regsStr = StringPrintf("fp:%08x sp:%08x lr:%08x pc:%08x\n", fp, sp, lr, pc);
266 #endif
267     return regsStr;
268 }
269 } // namespace HiviewDFX
270 } // namespace OHOS
271