• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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) && __riscv_xlen == 64
44     auto dfxregs = std::make_shared<DfxRegsRiscv64>();
45 #elif defined(__x86_64__)
46     auto dfxregs = std::make_shared<DfxRegsX86_64>();
47 #else
48 #error "Unsupported architecture"
49 #endif
50     return dfxregs;
51 }
52 
CreateFromUcontext(const ucontext_t & context)53 std::shared_ptr<DfxRegs> DfxRegs::CreateFromUcontext(const ucontext_t& context)
54 {
55     auto dfxregs = DfxRegs::Create();
56     dfxregs->SetFromUcontext(context);
57     return dfxregs;
58 }
59 
CreateFromRegs(const UnwindMode mode,const uintptr_t * regs)60 std::shared_ptr<DfxRegs> DfxRegs::CreateFromRegs(const UnwindMode mode, const uintptr_t* regs)
61 {
62     auto dfxregs = DfxRegs::Create();
63     if (mode == UnwindMode::DWARF_UNWIND) {
64         dfxregs->SetRegsData(regs, REG_LAST);
65     } else if (mode == UnwindMode::FRAMEPOINTER_UNWIND) {
66         dfxregs->SetFromFpMiniRegs(regs, FP_MINI_REGS_SIZE);
67     } else if (mode == UnwindMode::MINIMAL_UNWIND) {
68         dfxregs->SetFromQutMiniRegs(regs, QUT_MINI_REGS_SIZE);
69     }
70     return dfxregs;
71 }
72 
CreateRemoteRegs(pid_t pid)73 std::shared_ptr<DfxRegs> DfxRegs::CreateRemoteRegs(pid_t pid)
74 {
75     if (pid <= 0) {
76         return nullptr;
77     }
78     auto dfxregs = DfxRegs::Create();
79     gregset_t regs;
80     struct iovec iov;
81     iov.iov_base = &regs;
82     iov.iov_len = sizeof(regs);
83     // must be attach first
84     if (ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov) == -1) {
85         LOGE("Failed to ptrace pid(%d), errno=%d", pid, errno);
86         return nullptr;
87     }
88     if (memcpy_s(dfxregs->regsData_.data(),
89         REG_LAST * sizeof(uintptr_t), &regs,
90         REG_LAST * sizeof(uintptr_t)) != 0) {
91         LOGE("Failed to memcpy regs data, errno=%d", errno);
92         return nullptr;
93     }
94     return dfxregs;
95 }
96 
GetRegsData() const97 std::vector<uintptr_t> DfxRegs::GetRegsData() const
98 {
99     return regsData_;
100 }
101 
SetRegsData(const std::vector<uintptr_t> & regs)102 void DfxRegs::SetRegsData(const std::vector<uintptr_t>& regs)
103 {
104     regsData_ = regs;
105 }
106 
SetRegsData(const uintptr_t * regs,const size_t size)107 void DfxRegs::SetRegsData(const uintptr_t* regs, const size_t size)
108 {
109     size_t cpySize = (size > RegsSize()) ? RegsSize() : size;
110     if (memcpy_s(RawData(), cpySize * sizeof(uintptr_t), regs, cpySize * sizeof(uintptr_t)) != 0) {
111         LOGE("Failed to set regs data, errno=%d", errno);
112     }
113 }
114 
GetReg(size_t idx)115 uintptr_t* DfxRegs::GetReg(size_t idx)
116 {
117     if (idx >= REG_LAST) {
118         return nullptr;
119     }
120     return &(regsData_[idx]);
121 }
122 
SetReg(const int idx,const uintptr_t * val)123 void DfxRegs::SetReg(const int idx, const uintptr_t* val)
124 {
125     if (idx >= REG_LAST) {
126         return;
127     }
128     regsData_[idx] = *val;
129 }
130 
GetSpecialRegs(uintptr_t & fp,uintptr_t & lr,uintptr_t & sp,uintptr_t & pc) const131 void DfxRegs::GetSpecialRegs(uintptr_t& fp, uintptr_t& lr, uintptr_t& sp, uintptr_t& pc) const
132 {
133 #if defined(__arm__) || defined(__aarch64__) || defined(__riscv)
134     fp = regsData_[REG_FP];
135     lr = regsData_[REG_LR];
136 #endif
137     sp = regsData_[REG_SP];
138     pc = regsData_[REG_PC];
139 }
140 
SetSpecialRegs(uintptr_t fp,uintptr_t lr,uintptr_t sp,uintptr_t pc)141 void DfxRegs::SetSpecialRegs(uintptr_t fp, uintptr_t lr, uintptr_t sp, uintptr_t pc)
142 {
143 #if defined(__arm__) || defined(__aarch64__) || defined(__riscv)
144     regsData_[REG_FP] = fp;
145     regsData_[REG_LR] = lr;
146 #endif
147     regsData_[REG_SP] = sp;
148     regsData_[REG_PC] = pc;
149 }
150 
GetSp() const151 uintptr_t DfxRegs::GetSp() const
152 {
153     return regsData_[REG_SP];
154 }
155 
SetSp(uintptr_t sp)156 void DfxRegs::SetSp(uintptr_t sp)
157 {
158     regsData_[REG_SP] = sp;
159 }
160 
GetPc() const161 uintptr_t DfxRegs::GetPc() const
162 {
163     return regsData_[REG_PC];
164 }
165 
SetPc(uintptr_t pc)166 void DfxRegs::SetPc(uintptr_t pc)
167 {
168     regsData_[REG_PC] = pc;
169 }
170 
GetFp() const171 uintptr_t DfxRegs::GetFp() const
172 {
173 #if defined(__arm__) || defined(__aarch64__)
174     return regsData_[REG_FP];
175 #else
176     return 0;
177 #endif
178 }
179 
SetFp(uintptr_t fp)180 void DfxRegs::SetFp(uintptr_t fp)
181 {
182 #if defined(__arm__) || defined(__aarch64__)  || defined(__riscv)
183     regsData_[REG_FP] = fp;
184 #endif
185 }
186 
GetSpecialRegsName(uintptr_t val) const187 std::string DfxRegs::GetSpecialRegsName(uintptr_t val) const
188 {
189     uintptr_t fp = 0, lr = 0, sp = 0, pc = 0;
190     GetSpecialRegs(fp, lr, sp, pc);
191     if (val == pc) {
192         return "pc";
193     } else if (val == lr) {
194         return "lr";
195     } else if (val == sp) {
196         return "sp";
197     } else if (val == fp) {
198         return "fp";
199     }
200     return "";
201 }
202 
PrintSpecialRegs() const203 std::string DfxRegs::PrintSpecialRegs() const
204 {
205     uintptr_t fp = 0, lr = 0, sp = 0, pc = 0;
206     GetSpecialRegs(fp, lr, sp, pc);
207     std::string regsStr;
208 #ifdef __LP64__
209     regsStr = StringPrintf("fp:%016lx sp:%016lx lr:%016lx pc:%016lx\n", fp, sp, lr, pc);
210 #else
211     regsStr = StringPrintf("fp:%08x sp:%08x lr:%08x pc:%08x\n", fp, sp, lr, pc);
212 #endif
213     return regsStr;
214 }
215 } // namespace HiviewDFX
216 } // namespace OHOS
217