xref: /aosp_15_r20/system/unwinding/libunwindstack/RegsRiscv64.cpp (revision eb293b8f56ee8303637c5595cfcdeef8039e85c6)
1*eb293b8fSAndroid Build Coastguard Worker /*
2*eb293b8fSAndroid Build Coastguard Worker  * Copyright (C) 2022 The Android Open Source Project
3*eb293b8fSAndroid Build Coastguard Worker  *
4*eb293b8fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*eb293b8fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*eb293b8fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*eb293b8fSAndroid Build Coastguard Worker  *
8*eb293b8fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*eb293b8fSAndroid Build Coastguard Worker  *
10*eb293b8fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*eb293b8fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*eb293b8fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*eb293b8fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*eb293b8fSAndroid Build Coastguard Worker  * limitations under the License.
15*eb293b8fSAndroid Build Coastguard Worker  */
16*eb293b8fSAndroid Build Coastguard Worker 
17*eb293b8fSAndroid Build Coastguard Worker #include <elf.h>
18*eb293b8fSAndroid Build Coastguard Worker #include <stdint.h>
19*eb293b8fSAndroid Build Coastguard Worker #include <string.h>
20*eb293b8fSAndroid Build Coastguard Worker #include <sys/ptrace.h>
21*eb293b8fSAndroid Build Coastguard Worker #include <sys/uio.h>
22*eb293b8fSAndroid Build Coastguard Worker 
23*eb293b8fSAndroid Build Coastguard Worker #include <functional>
24*eb293b8fSAndroid Build Coastguard Worker #include <vector>
25*eb293b8fSAndroid Build Coastguard Worker 
26*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Elf.h>
27*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Log.h>
28*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/MachineRiscv64.h>
29*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/MapInfo.h>
30*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Memory.h>
31*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/RegsRiscv64.h>
32*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/UcontextRiscv64.h>
33*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/UserRiscv64.h>
34*eb293b8fSAndroid Build Coastguard Worker 
35*eb293b8fSAndroid Build Coastguard Worker namespace unwindstack {
36*eb293b8fSAndroid Build Coastguard Worker 
GetVlenbFromLocal()37*eb293b8fSAndroid Build Coastguard Worker uint64_t RegsRiscv64::GetVlenbFromLocal() {
38*eb293b8fSAndroid Build Coastguard Worker #if defined(__riscv)
39*eb293b8fSAndroid Build Coastguard Worker   uint64_t vlenb;
40*eb293b8fSAndroid Build Coastguard Worker   asm volatile("csrr %0, 0xc22\n" : "=r"(vlenb)::);
41*eb293b8fSAndroid Build Coastguard Worker   return vlenb;
42*eb293b8fSAndroid Build Coastguard Worker #else
43*eb293b8fSAndroid Build Coastguard Worker   Log::Fatal("%s:%d: On non-riscv device, attempt to get vlenb locally.", __FILE__, __LINE__);
44*eb293b8fSAndroid Build Coastguard Worker #endif
45*eb293b8fSAndroid Build Coastguard Worker }
46*eb293b8fSAndroid Build Coastguard Worker 
47*eb293b8fSAndroid Build Coastguard Worker #if defined(__riscv)
GetVlenbFromRemote(pid_t)48*eb293b8fSAndroid Build Coastguard Worker uint64_t RegsRiscv64::GetVlenbFromRemote(pid_t) {
49*eb293b8fSAndroid Build Coastguard Worker   // All riscv cores in a cpu are required to have the same vlenb value.
50*eb293b8fSAndroid Build Coastguard Worker   // Note: If a device exists with multiple cpus, but all of the cpus do not
51*eb293b8fSAndroid Build Coastguard Worker   // have the same vlenb, then this method will need to be modified.
52*eb293b8fSAndroid Build Coastguard Worker   return GetVlenbFromLocal();
53*eb293b8fSAndroid Build Coastguard Worker }
54*eb293b8fSAndroid Build Coastguard Worker #else
GetVlenbFromRemote(pid_t pid)55*eb293b8fSAndroid Build Coastguard Worker uint64_t RegsRiscv64::GetVlenbFromRemote(pid_t pid) {
56*eb293b8fSAndroid Build Coastguard Worker   if (pid == 0) {
57*eb293b8fSAndroid Build Coastguard Worker     Log::Fatal("%s:%d: Attempt to get vlenb remotely from non-riscv device without pid.", __FILE__,
58*eb293b8fSAndroid Build Coastguard Worker                __LINE__);
59*eb293b8fSAndroid Build Coastguard Worker   }
60*eb293b8fSAndroid Build Coastguard Worker 
61*eb293b8fSAndroid Build Coastguard Worker   // We only care about the state values, no need to get anything else.
62*eb293b8fSAndroid Build Coastguard Worker   struct riscv64_v_regset_state regs;
63*eb293b8fSAndroid Build Coastguard Worker   struct iovec io = {.iov_base = &regs, .iov_len = sizeof(regs)};
64*eb293b8fSAndroid Build Coastguard Worker   if (ptrace(PTRACE_GETREGSET, pid, NT_RISCV_VECTOR, reinterpret_cast<void*>(&io)) == -1) {
65*eb293b8fSAndroid Build Coastguard Worker     Log::Error("Failed to get vlenb from target process %d: %d", pid, errno);
66*eb293b8fSAndroid Build Coastguard Worker     return 0;
67*eb293b8fSAndroid Build Coastguard Worker   }
68*eb293b8fSAndroid Build Coastguard Worker   return regs.vlenb;
69*eb293b8fSAndroid Build Coastguard Worker }
70*eb293b8fSAndroid Build Coastguard Worker #endif
71*eb293b8fSAndroid Build Coastguard Worker 
RegsRiscv64()72*eb293b8fSAndroid Build Coastguard Worker RegsRiscv64::RegsRiscv64()
73*eb293b8fSAndroid Build Coastguard Worker     : RegsImpl<uint64_t>(RISCV64_REG_COUNT, Location(LOCATION_REGISTER, RISCV64_REG_RA)) {}
74*eb293b8fSAndroid Build Coastguard Worker 
Arch()75*eb293b8fSAndroid Build Coastguard Worker ArchEnum RegsRiscv64::Arch() {
76*eb293b8fSAndroid Build Coastguard Worker   return ARCH_RISCV64;
77*eb293b8fSAndroid Build Coastguard Worker }
78*eb293b8fSAndroid Build Coastguard Worker 
pc()79*eb293b8fSAndroid Build Coastguard Worker uint64_t RegsRiscv64::pc() {
80*eb293b8fSAndroid Build Coastguard Worker   return regs_[RISCV64_REG_PC];
81*eb293b8fSAndroid Build Coastguard Worker }
82*eb293b8fSAndroid Build Coastguard Worker 
sp()83*eb293b8fSAndroid Build Coastguard Worker uint64_t RegsRiscv64::sp() {
84*eb293b8fSAndroid Build Coastguard Worker   return regs_[RISCV64_REG_SP];
85*eb293b8fSAndroid Build Coastguard Worker }
86*eb293b8fSAndroid Build Coastguard Worker 
set_pc(uint64_t pc)87*eb293b8fSAndroid Build Coastguard Worker void RegsRiscv64::set_pc(uint64_t pc) {
88*eb293b8fSAndroid Build Coastguard Worker   regs_[RISCV64_REG_PC] = pc;
89*eb293b8fSAndroid Build Coastguard Worker }
90*eb293b8fSAndroid Build Coastguard Worker 
set_sp(uint64_t sp)91*eb293b8fSAndroid Build Coastguard Worker void RegsRiscv64::set_sp(uint64_t sp) {
92*eb293b8fSAndroid Build Coastguard Worker   regs_[RISCV64_REG_SP] = sp;
93*eb293b8fSAndroid Build Coastguard Worker }
94*eb293b8fSAndroid Build Coastguard Worker 
SetPcFromReturnAddress(Memory *)95*eb293b8fSAndroid Build Coastguard Worker bool RegsRiscv64::SetPcFromReturnAddress(Memory*) {
96*eb293b8fSAndroid Build Coastguard Worker   uint64_t ra = regs_[RISCV64_REG_RA];
97*eb293b8fSAndroid Build Coastguard Worker   if (regs_[RISCV64_REG_PC] == ra) {
98*eb293b8fSAndroid Build Coastguard Worker     return false;
99*eb293b8fSAndroid Build Coastguard Worker   }
100*eb293b8fSAndroid Build Coastguard Worker 
101*eb293b8fSAndroid Build Coastguard Worker   regs_[RISCV64_REG_PC] = ra;
102*eb293b8fSAndroid Build Coastguard Worker   return true;
103*eb293b8fSAndroid Build Coastguard Worker }
104*eb293b8fSAndroid Build Coastguard Worker 
IterateRegisters(std::function<void (const char *,uint64_t)> fn)105*eb293b8fSAndroid Build Coastguard Worker void RegsRiscv64::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
106*eb293b8fSAndroid Build Coastguard Worker   fn("pc", regs_[RISCV64_REG_PC]);
107*eb293b8fSAndroid Build Coastguard Worker   fn("ra", regs_[RISCV64_REG_RA]);
108*eb293b8fSAndroid Build Coastguard Worker   fn("sp", regs_[RISCV64_REG_SP]);
109*eb293b8fSAndroid Build Coastguard Worker   fn("gp", regs_[RISCV64_REG_GP]);
110*eb293b8fSAndroid Build Coastguard Worker   fn("tp", regs_[RISCV64_REG_TP]);
111*eb293b8fSAndroid Build Coastguard Worker   fn("t0", regs_[RISCV64_REG_T0]);
112*eb293b8fSAndroid Build Coastguard Worker   fn("t1", regs_[RISCV64_REG_T1]);
113*eb293b8fSAndroid Build Coastguard Worker   fn("t2", regs_[RISCV64_REG_T2]);
114*eb293b8fSAndroid Build Coastguard Worker   fn("t3", regs_[RISCV64_REG_T3]);
115*eb293b8fSAndroid Build Coastguard Worker   fn("t4", regs_[RISCV64_REG_T4]);
116*eb293b8fSAndroid Build Coastguard Worker   fn("t5", regs_[RISCV64_REG_T5]);
117*eb293b8fSAndroid Build Coastguard Worker   fn("t6", regs_[RISCV64_REG_T6]);
118*eb293b8fSAndroid Build Coastguard Worker   fn("s0", regs_[RISCV64_REG_S0]);
119*eb293b8fSAndroid Build Coastguard Worker   fn("s1", regs_[RISCV64_REG_S1]);
120*eb293b8fSAndroid Build Coastguard Worker   fn("s2", regs_[RISCV64_REG_S2]);
121*eb293b8fSAndroid Build Coastguard Worker   fn("s3", regs_[RISCV64_REG_S3]);
122*eb293b8fSAndroid Build Coastguard Worker   fn("s4", regs_[RISCV64_REG_S4]);
123*eb293b8fSAndroid Build Coastguard Worker   fn("s5", regs_[RISCV64_REG_S5]);
124*eb293b8fSAndroid Build Coastguard Worker   fn("s6", regs_[RISCV64_REG_S6]);
125*eb293b8fSAndroid Build Coastguard Worker   fn("s7", regs_[RISCV64_REG_S7]);
126*eb293b8fSAndroid Build Coastguard Worker   fn("s8", regs_[RISCV64_REG_S8]);
127*eb293b8fSAndroid Build Coastguard Worker   fn("s9", regs_[RISCV64_REG_S9]);
128*eb293b8fSAndroid Build Coastguard Worker   fn("s10", regs_[RISCV64_REG_S10]);
129*eb293b8fSAndroid Build Coastguard Worker   fn("s11", regs_[RISCV64_REG_S11]);
130*eb293b8fSAndroid Build Coastguard Worker   fn("a0", regs_[RISCV64_REG_A0]);
131*eb293b8fSAndroid Build Coastguard Worker   fn("a1", regs_[RISCV64_REG_A1]);
132*eb293b8fSAndroid Build Coastguard Worker   fn("a2", regs_[RISCV64_REG_A2]);
133*eb293b8fSAndroid Build Coastguard Worker   fn("a3", regs_[RISCV64_REG_A3]);
134*eb293b8fSAndroid Build Coastguard Worker   fn("a4", regs_[RISCV64_REG_A4]);
135*eb293b8fSAndroid Build Coastguard Worker   fn("a5", regs_[RISCV64_REG_A5]);
136*eb293b8fSAndroid Build Coastguard Worker   fn("a6", regs_[RISCV64_REG_A6]);
137*eb293b8fSAndroid Build Coastguard Worker   fn("a7", regs_[RISCV64_REG_A7]);
138*eb293b8fSAndroid Build Coastguard Worker   fn("vlenb", regs_[RISCV64_REG_VLENB]);
139*eb293b8fSAndroid Build Coastguard Worker }
140*eb293b8fSAndroid Build Coastguard Worker 
Read(const void * remote_data,pid_t pid)141*eb293b8fSAndroid Build Coastguard Worker Regs* RegsRiscv64::Read(const void* remote_data, pid_t pid) {
142*eb293b8fSAndroid Build Coastguard Worker   const riscv64_user_regs* user = reinterpret_cast<const riscv64_user_regs*>(remote_data);
143*eb293b8fSAndroid Build Coastguard Worker 
144*eb293b8fSAndroid Build Coastguard Worker   RegsRiscv64* regs = new RegsRiscv64();
145*eb293b8fSAndroid Build Coastguard Worker   memcpy(regs->RawData(), &user->regs[0], RISCV64_REG_REAL_COUNT * sizeof(uint64_t));
146*eb293b8fSAndroid Build Coastguard Worker   regs->regs_[RISCV64_REG_VLENB] = GetVlenbFromRemote(pid);
147*eb293b8fSAndroid Build Coastguard Worker   return regs;
148*eb293b8fSAndroid Build Coastguard Worker }
149*eb293b8fSAndroid Build Coastguard Worker 
CreateFromUcontext(void * ucontext)150*eb293b8fSAndroid Build Coastguard Worker Regs* RegsRiscv64::CreateFromUcontext(void* ucontext) {
151*eb293b8fSAndroid Build Coastguard Worker   riscv64_ucontext_t* riscv64_ucontext = reinterpret_cast<riscv64_ucontext_t*>(ucontext);
152*eb293b8fSAndroid Build Coastguard Worker 
153*eb293b8fSAndroid Build Coastguard Worker   RegsRiscv64* regs = new RegsRiscv64();
154*eb293b8fSAndroid Build Coastguard Worker   memcpy(regs->RawData(), &riscv64_ucontext->uc_mcontext.__gregs[0],
155*eb293b8fSAndroid Build Coastguard Worker          RISCV64_REG_REAL_COUNT * sizeof(uint64_t));
156*eb293b8fSAndroid Build Coastguard Worker 
157*eb293b8fSAndroid Build Coastguard Worker   // TODO: Until b/323045700 is fixed, this code temporarily assumes
158*eb293b8fSAndroid Build Coastguard Worker   // this function will only be called on the same core an unwind occurs.
159*eb293b8fSAndroid Build Coastguard Worker   // If not, the vlenb value might be wrong.
160*eb293b8fSAndroid Build Coastguard Worker   uint64_t* raw_data = reinterpret_cast<uint64_t*>(regs->RawData());
161*eb293b8fSAndroid Build Coastguard Worker   raw_data[RISCV64_REG_VLENB] = GetVlenbFromLocal();
162*eb293b8fSAndroid Build Coastguard Worker   return regs;
163*eb293b8fSAndroid Build Coastguard Worker }
164*eb293b8fSAndroid Build Coastguard Worker 
StepIfSignalHandler(uint64_t elf_offset,Elf * elf,Memory * process_memory)165*eb293b8fSAndroid Build Coastguard Worker bool RegsRiscv64::StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) {
166*eb293b8fSAndroid Build Coastguard Worker   // Read from elf memory since it is usually more expensive to read from
167*eb293b8fSAndroid Build Coastguard Worker   // process memory.
168*eb293b8fSAndroid Build Coastguard Worker   uint64_t data;
169*eb293b8fSAndroid Build Coastguard Worker   if (!elf->memory()->ReadFully(elf_offset, &data, sizeof(data))) {
170*eb293b8fSAndroid Build Coastguard Worker     return false;
171*eb293b8fSAndroid Build Coastguard Worker   }
172*eb293b8fSAndroid Build Coastguard Worker   // Look for the kernel sigreturn function.
173*eb293b8fSAndroid Build Coastguard Worker   // __kernel_rt_sigreturn:
174*eb293b8fSAndroid Build Coastguard Worker   // li a7, __NR_rt_sigreturn
175*eb293b8fSAndroid Build Coastguard Worker   // scall
176*eb293b8fSAndroid Build Coastguard Worker 
177*eb293b8fSAndroid Build Coastguard Worker   const uint8_t li_scall[] = {0x93, 0x08, 0xb0, 0x08, 0x73, 0x00, 0x00, 0x00};
178*eb293b8fSAndroid Build Coastguard Worker   if (memcmp(&data, &li_scall, 8) != 0) {
179*eb293b8fSAndroid Build Coastguard Worker     return false;
180*eb293b8fSAndroid Build Coastguard Worker   }
181*eb293b8fSAndroid Build Coastguard Worker 
182*eb293b8fSAndroid Build Coastguard Worker   // SP + sizeof(siginfo_t) + uc_mcontext offset + PC offset.
183*eb293b8fSAndroid Build Coastguard Worker   if (!process_memory->ReadFully(regs_[RISCV64_REG_SP] + 0x80 + 0xb0 + 0x00, regs_.data(),
184*eb293b8fSAndroid Build Coastguard Worker                                  sizeof(uint64_t) * (RISCV64_REG_REAL_COUNT))) {
185*eb293b8fSAndroid Build Coastguard Worker     return false;
186*eb293b8fSAndroid Build Coastguard Worker   }
187*eb293b8fSAndroid Build Coastguard Worker   return true;
188*eb293b8fSAndroid Build Coastguard Worker }
189*eb293b8fSAndroid Build Coastguard Worker 
Clone()190*eb293b8fSAndroid Build Coastguard Worker Regs* RegsRiscv64::Clone() {
191*eb293b8fSAndroid Build Coastguard Worker   return new RegsRiscv64(*this);
192*eb293b8fSAndroid Build Coastguard Worker }
193*eb293b8fSAndroid Build Coastguard Worker 
Convert(uint16_t reg)194*eb293b8fSAndroid Build Coastguard Worker uint16_t RegsRiscv64::Convert(uint16_t reg) {
195*eb293b8fSAndroid Build Coastguard Worker   if (reg == 0x1c22) {
196*eb293b8fSAndroid Build Coastguard Worker     return RISCV64_REG_VLENB;
197*eb293b8fSAndroid Build Coastguard Worker   }
198*eb293b8fSAndroid Build Coastguard Worker   if (reg == RISCV64_REG_VLENB) {
199*eb293b8fSAndroid Build Coastguard Worker     // It should never be valid for the register to be vlenb naturally.
200*eb293b8fSAndroid Build Coastguard Worker     return total_regs();
201*eb293b8fSAndroid Build Coastguard Worker   }
202*eb293b8fSAndroid Build Coastguard Worker   return reg;
203*eb293b8fSAndroid Build Coastguard Worker }
204*eb293b8fSAndroid Build Coastguard Worker 
205*eb293b8fSAndroid Build Coastguard Worker }  // namespace unwindstack
206