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