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 = ®s, .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