blob: 9fd0fa792c0684365cadcb08c25df3094bb90687 [file] [log] [blame]
Andrew Geisslerfc113ea2023-03-31 09:59:46 -05001From: Guo Ren <guoren@linux.alibaba.com>
2Date: Wed, 29 Jun 2022 16:46:46 +0800
3Subject: Add riscv64 support
4
5This patch contains the dwarf unwind support for 64bit risc-v.
6
7 * DwarfCfa.cpp (cfa_def_cfa_register): setup register if CFA_REG is
8 not setup for riscv64
9 * Elf.cpp (GetRelPc): convert offset to virtual address for riscv64.
10 * ElfInterface.cpp (GetVirtAddrFromOffset): New for riscv64.
11 * RegsRiscv64.cpp (StepIfSignalHandler): Fix signal frame check.
12 libunwindstack/include/unwindstack/
13 * ElfInterface.h (GetVirtAddrFromOffset): New for riscv64.
14 libunwindstack/tests/
15 * DwarfCfaTest.cpp (cfa_def_cfa_register): ok for riscv64.
16 * RegsStepIfSignalHandlerTest.cpp (riscv64_step_if_signal_handler): Fix
17 testcase for riscv64
18
19Test: Builds.
20Test: All unit tests pass.
21
22Signed-off-by: Guo Ren <guoren@linux.alibaba.com>
23Signed-off-by: Lifang Xia <lifang_xia@linux.alibaba.com>
24Signed-off-by: Mao Han <han_mao@linux.alibaba.com>
25Change-Id: Ib21ddf23cc83f332af202df7bffcaceec16063e0
26---
Andrew Geissler220dafd2023-10-04 10:18:08 -050027Upstream-Status: Pending
28
Andrew Geisslerfc113ea2023-03-31 09:59:46 -050029 system/core/libunwindstack/Android.bp | 1 +
30 system/core/libunwindstack/Elf.cpp | 2 +
31 system/core/libunwindstack/Regs.cpp | 10 ++
32 system/core/libunwindstack/RegsRiscv64.cpp | 156 +++++++++++++++++++++
33 .../core/libunwindstack/include/unwindstack/Elf.h | 5 +
34 .../include/unwindstack/MachineRiscv64.h | 59 ++++++++
35 .../include/unwindstack/RegsGetLocal.h | 43 ++++++
36 .../include/unwindstack/RegsRiscv64.h | 59 ++++++++
37 .../include/unwindstack/UcontextRiscv64.h | 80 +++++++++++
38 .../include/unwindstack/UserRiscv64.h | 37 +++++
39 system/core/libunwindstack/tools/unwind.cpp | 3 +
40 .../core/libunwindstack/tools/unwind_symbols.cpp | 3 +
41 12 files changed, 458 insertions(+)
42 create mode 100644 system/core/libunwindstack/RegsRiscv64.cpp
43 create mode 100644 system/core/libunwindstack/include/unwindstack/MachineRiscv64.h
44 create mode 100644 system/core/libunwindstack/include/unwindstack/RegsRiscv64.h
45 create mode 100644 system/core/libunwindstack/include/unwindstack/UcontextRiscv64.h
46 create mode 100644 system/core/libunwindstack/include/unwindstack/UserRiscv64.h
47
48diff --git a/system/core/libunwindstack/Android.bp b/system/core/libunwindstack/Android.bp
49index 3695f72..f1f9c68 100644
50--- a/system/core/libunwindstack/Android.bp
51+++ b/system/core/libunwindstack/Android.bp
52@@ -70,6 +70,7 @@ cc_library {
53 "RegsArm64.cpp",
54 "RegsX86.cpp",
55 "RegsX86_64.cpp",
56+ "RegsRiscv64.cpp",
57 "RegsMips.cpp",
58 "RegsMips64.cpp",
59 "Unwinder.cpp",
60diff --git a/system/core/libunwindstack/Elf.cpp b/system/core/libunwindstack/Elf.cpp
61index f01b092..3c2088b 100644
62--- a/system/core/libunwindstack/Elf.cpp
63+++ b/system/core/libunwindstack/Elf.cpp
64@@ -290,6 +290,8 @@ ElfInterface* Elf::CreateInterfaceFromMemory(Memory* memory) {
65 arch_ = ARCH_X86_64;
66 } else if (e_machine == EM_MIPS) {
67 arch_ = ARCH_MIPS64;
68+ } else if (e_machine == EM_RISCV) {
69+ arch_ = ARCH_RISCV64;
70 } else {
71 // Unsupported.
72 ALOGI("64 bit elf that is neither aarch64 nor x86_64 nor mips64: e_machine = %d\n",
73diff --git a/system/core/libunwindstack/Regs.cpp b/system/core/libunwindstack/Regs.cpp
74index c7dec52..447a554 100644
75--- a/system/core/libunwindstack/Regs.cpp
76+++ b/system/core/libunwindstack/Regs.cpp
77@@ -27,12 +27,14 @@
78 #include <unwindstack/RegsArm64.h>
79 #include <unwindstack/RegsMips.h>
80 #include <unwindstack/RegsMips64.h>
81+#include <unwindstack/RegsRiscv64.h>
82 #include <unwindstack/RegsX86.h>
83 #include <unwindstack/RegsX86_64.h>
84 #include <unwindstack/UserArm.h>
85 #include <unwindstack/UserArm64.h>
86 #include <unwindstack/UserMips.h>
87 #include <unwindstack/UserMips64.h>
88+#include <unwindstack/UserRiscv64.h>
89 #include <unwindstack/UserX86.h>
90 #include <unwindstack/UserX86_64.h>
91
92@@ -67,6 +69,8 @@ Regs* Regs::RemoteGet(pid_t pid) {
93 return RegsMips::Read(buffer.data());
94 case sizeof(mips64_user_regs):
95 return RegsMips64::Read(buffer.data());
96+ case sizeof(riscv64_user_regs):
97+ return RegsRiscv64::Read(buffer.data());
98 }
99 return nullptr;
100 }
101@@ -85,6 +89,8 @@ Regs* Regs::CreateFromUcontext(ArchEnum arch, void* ucontext) {
102 return RegsMips::CreateFromUcontext(ucontext);
103 case ARCH_MIPS64:
104 return RegsMips64::CreateFromUcontext(ucontext);
105+ case ARCH_RISCV64:
106+ return RegsRiscv64::CreateFromUcontext(ucontext);
107 case ARCH_UNKNOWN:
108 default:
109 return nullptr;
110@@ -104,6 +110,8 @@ ArchEnum Regs::CurrentArch() {
111 return ARCH_MIPS;
112 #elif defined(__mips__) && defined(__LP64__)
113 return ARCH_MIPS64;
114+#elif defined(__riscv)
115+ return ARCH_RISCV64;
116 #else
117 abort();
118 #endif
119@@ -123,6 +131,8 @@ Regs* Regs::CreateFromLocal() {
120 regs = new RegsMips();
121 #elif defined(__mips__) && defined(__LP64__)
122 regs = new RegsMips64();
123+#elif defined(__riscv)
124+ regs = new RegsRiscv64();
125 #else
126 abort();
127 #endif
128diff --git a/system/core/libunwindstack/RegsRiscv64.cpp b/system/core/libunwindstack/RegsRiscv64.cpp
129new file mode 100644
130index 0000000..887762a
131--- /dev/null
132+++ b/system/core/libunwindstack/RegsRiscv64.cpp
133@@ -0,0 +1,156 @@
134+/*
135+ * Copyright (C) 2022 The Android Open Source Project
136+ *
137+ * Licensed under the Apache License, Version 2.0 (the "License");
138+ * you may not use this file except in compliance with the License.
139+ * You may obtain a copy of the License at
140+ *
141+ * http://www.apache.org/licenses/LICENSE-2.0
142+ *
143+ * Unless required by applicable law or agreed to in writing, software
144+ * distributed under the License is distributed on an "AS IS" BASIS,
145+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
146+ * See the License for the specific language governing permissions and
147+ * limitations under the License.
148+ */
149+
150+#include <stdint.h>
151+#include <string.h>
152+
153+#include <functional>
154+
155+#include <unwindstack/Elf.h>
156+#include <unwindstack/MachineRiscv64.h>
157+#include <unwindstack/MapInfo.h>
158+#include <unwindstack/Memory.h>
159+#include <unwindstack/RegsRiscv64.h>
160+#include <unwindstack/UcontextRiscv64.h>
161+#include <unwindstack/UserRiscv64.h>
162+
163+namespace unwindstack {
164+
165+RegsRiscv64::RegsRiscv64()
166+ : RegsImpl<uint64_t>(RISCV64_REG_MAX, Location(LOCATION_REGISTER, RISCV64_REG_RA)) {}
167+
168+ArchEnum RegsRiscv64::Arch() {
169+ return ARCH_RISCV64;
170+}
171+
172+uint64_t RegsRiscv64::pc() {
173+ return regs_[RISCV64_REG_PC];
174+}
175+
176+uint64_t RegsRiscv64::sp() {
177+ return regs_[RISCV64_REG_SP];
178+}
179+
180+void RegsRiscv64::set_pc(uint64_t pc) {
181+ regs_[RISCV64_REG_PC] = pc;
182+}
183+
184+void RegsRiscv64::set_sp(uint64_t sp) {
185+ regs_[RISCV64_REG_SP] = sp;
186+}
187+
188+uint64_t RegsRiscv64::GetPcAdjustment(uint64_t rel_pc, Elf*) {
189+ if (rel_pc < 8) {
190+ return 0;
191+ }
192+ // For now, just assume no compact branches
193+ return 8;
194+}
195+
196+bool RegsRiscv64::SetPcFromReturnAddress(Memory*) {
197+ uint64_t ra = regs_[RISCV64_REG_RA];
198+ if (regs_[RISCV64_REG_PC] == ra) {
199+ return false;
200+ }
201+
202+ regs_[RISCV64_REG_PC] = ra;
203+ return true;
204+}
205+
206+void RegsRiscv64::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
207+ fn("pc", regs_[RISCV64_REG_PC]);
208+ fn("ra", regs_[RISCV64_REG_RA]);
209+ fn("sp", regs_[RISCV64_REG_SP]);
210+ fn("gp", regs_[RISCV64_REG_GP]);
211+ fn("tp", regs_[RISCV64_REG_TP]);
212+ fn("t0", regs_[RISCV64_REG_T0]);
213+ fn("t1", regs_[RISCV64_REG_T1]);
214+ fn("t2", regs_[RISCV64_REG_T2]);
215+ fn("t3", regs_[RISCV64_REG_T3]);
216+ fn("t4", regs_[RISCV64_REG_T4]);
217+ fn("t5", regs_[RISCV64_REG_T5]);
218+ fn("t6", regs_[RISCV64_REG_T6]);
219+ fn("s0", regs_[RISCV64_REG_S0]);
220+ fn("s1", regs_[RISCV64_REG_S1]);
221+ fn("s2", regs_[RISCV64_REG_S2]);
222+ fn("s3", regs_[RISCV64_REG_S3]);
223+ fn("s4", regs_[RISCV64_REG_S4]);
224+ fn("s5", regs_[RISCV64_REG_S5]);
225+ fn("s6", regs_[RISCV64_REG_S6]);
226+ fn("s7", regs_[RISCV64_REG_S7]);
227+ fn("s8", regs_[RISCV64_REG_S8]);
228+ fn("s9", regs_[RISCV64_REG_S9]);
229+ fn("s10", regs_[RISCV64_REG_S10]);
230+ fn("s11", regs_[RISCV64_REG_S11]);
231+ fn("a0", regs_[RISCV64_REG_A0]);
232+ fn("a1", regs_[RISCV64_REG_A1]);
233+ fn("a2", regs_[RISCV64_REG_A2]);
234+ fn("a3", regs_[RISCV64_REG_A3]);
235+ fn("a4", regs_[RISCV64_REG_A4]);
236+ fn("a5", regs_[RISCV64_REG_A5]);
237+ fn("a6", regs_[RISCV64_REG_A6]);
238+ fn("a7", regs_[RISCV64_REG_A7]);
239+}
240+
241+Regs* RegsRiscv64::Read(void* remote_data) {
242+ riscv64_user_regs* user = reinterpret_cast<riscv64_user_regs*>(remote_data);
243+
244+ RegsRiscv64* regs = new RegsRiscv64();
245+ memcpy(regs->RawData(), &user->regs[0], RISCV64_REG_MAX * sizeof(uint64_t));
246+ // uint64_t* reg_data = reinterpret_cast<uint64_t*>(regs->RawData());
247+ return regs;
248+}
249+
250+Regs* RegsRiscv64::CreateFromUcontext(void* ucontext) {
251+ riscv64_ucontext_t* riscv64_ucontext = reinterpret_cast<riscv64_ucontext_t*>(ucontext);
252+
253+ RegsRiscv64* regs = new RegsRiscv64();
254+ memcpy(regs->RawData(), &riscv64_ucontext->uc_mcontext.__gregs[0],
255+ RISCV64_REG_MAX * sizeof(uint64_t));
256+ return regs;
257+}
258+
259+bool RegsRiscv64::StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) {
260+ uint64_t data;
261+ Memory* elf_memory = elf->memory();
262+ // Read from elf memory since it is usually more expensive to read from
263+ // process memory.
264+ if (!elf_memory->ReadFully(elf_offset, &data, sizeof(data))) {
265+ return false;
266+ }
267+ // Look for the kernel sigreturn function.
268+ // __kernel_rt_sigreturn:
269+ // li a7, __NR_rt_sigreturn
270+ // scall
271+
272+ const uint8_t li_scall[] = {0x93, 0x08, 0xb0, 0x08, 0x73, 0x00, 0x00, 0x00};
273+ if (memcmp(&data, &li_scall, 8) != 0) {
274+ return false;
275+ }
276+
277+ // SP + sizeof(siginfo_t) + uc_mcontext offset + PC offset.
278+ if (!process_memory->ReadFully(regs_[RISCV64_REG_SP] + 0x80 + 0xb0 + 0x00, regs_.data(),
279+ sizeof(uint64_t) * (RISCV64_REG_MAX))) {
280+ return false;
281+ }
282+ return true;
283+}
284+
285+Regs* RegsRiscv64::Clone() {
286+ return new RegsRiscv64(*this);
287+}
288+
289+} // namespace unwindstack
290diff --git a/system/core/libunwindstack/include/unwindstack/Elf.h b/system/core/libunwindstack/include/unwindstack/Elf.h
291index 472ed92..88fa0ff 100644
292--- a/system/core/libunwindstack/include/unwindstack/Elf.h
293+++ b/system/core/libunwindstack/include/unwindstack/Elf.h
294@@ -32,6 +32,10 @@
295 #define EM_AARCH64 183
296 #endif
297
298+#if !defined(EM_RISCV)
299+#define EM_RISCV 243
300+#endif
301+
302 namespace unwindstack {
303
304 // Forward declaration.
305@@ -46,6 +50,7 @@ enum ArchEnum : uint8_t {
306 ARCH_X86_64,
307 ARCH_MIPS,
308 ARCH_MIPS64,
309+ ARCH_RISCV64,
310 };
311
312 class Elf {
313diff --git a/system/core/libunwindstack/include/unwindstack/MachineRiscv64.h b/system/core/libunwindstack/include/unwindstack/MachineRiscv64.h
314new file mode 100644
315index 0000000..397e680
316--- /dev/null
317+++ b/system/core/libunwindstack/include/unwindstack/MachineRiscv64.h
318@@ -0,0 +1,59 @@
319+/*
320+ * Copyright (C) 2022 The Android Open Source Project
321+ *
322+ * Licensed under the Apache License, Version 2.0 (the "License");
323+ * you may not use this file except in compliance with the License.
324+ * You may obtain a copy of the License at
325+ *
326+ * http://www.apache.org/licenses/LICENSE-2.0
327+ *
328+ * Unless required by applicable law or agreed to in writing, software
329+ * distributed under the License is distributed on an "AS IS" BASIS,
330+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
331+ * See the License for the specific language governing permissions and
332+ * limitations under the License.
333+ */
334+
335+#pragma once
336+
337+#include <stdint.h>
338+
339+namespace unwindstack {
340+
341+enum Riscv64Reg : uint16_t {
342+ RISCV64_REG_PC,
343+ RISCV64_REG_RA,
344+ RISCV64_REG_SP,
345+ RISCV64_REG_GP,
346+ RISCV64_REG_TP,
347+ RISCV64_REG_T0,
348+ RISCV64_REG_T1,
349+ RISCV64_REG_T2,
350+ RISCV64_REG_S0,
351+ RISCV64_REG_S1,
352+ RISCV64_REG_A0,
353+ RISCV64_REG_A1,
354+ RISCV64_REG_A2,
355+ RISCV64_REG_A3,
356+ RISCV64_REG_A4,
357+ RISCV64_REG_A5,
358+ RISCV64_REG_A6,
359+ RISCV64_REG_A7,
360+ RISCV64_REG_S2,
361+ RISCV64_REG_S3,
362+ RISCV64_REG_S4,
363+ RISCV64_REG_S5,
364+ RISCV64_REG_S6,
365+ RISCV64_REG_S7,
366+ RISCV64_REG_S8,
367+ RISCV64_REG_S9,
368+ RISCV64_REG_S10,
369+ RISCV64_REG_S11,
370+ RISCV64_REG_T3,
371+ RISCV64_REG_T4,
372+ RISCV64_REG_T5,
373+ RISCV64_REG_T6,
374+ RISCV64_REG_MAX,
375+};
376+
377+} // namespace unwindstack
378diff --git a/system/core/libunwindstack/include/unwindstack/RegsGetLocal.h b/system/core/libunwindstack/include/unwindstack/RegsGetLocal.h
379index f0b5e3a..698eba2 100644
380--- a/system/core/libunwindstack/include/unwindstack/RegsGetLocal.h
381+++ b/system/core/libunwindstack/include/unwindstack/RegsGetLocal.h
382@@ -81,6 +81,49 @@ inline __attribute__((__always_inline__)) void AsmGetRegs(void* reg_data) {
383 : "x12", "x13", "memory");
384 }
385
386+#elif defined(__riscv)
387+
388+inline __attribute__((__always_inline__)) void AsmGetRegs(void* reg_data) {
389+ asm volatile(
390+ "1:\n"
391+ "sd ra, 8(%[base])\n"
392+ "sd sp, 16(%[base])\n"
393+ "sd gp, 24(%[base])\n"
394+ "sd tp, 32(%[base])\n"
395+ "sd t0, 40(%[base])\n"
396+ "sd t1, 48(%[base])\n"
397+ "sd t2, 56(%[base])\n"
398+ "sd s0, 64(%[base])\n"
399+ "sd s1, 72(%[base])\n"
400+ "sd a0, 80(%[base])\n"
401+ "sd a1, 88(%[base])\n"
402+ "sd a2, 96(%[base])\n"
403+ "sd a3, 104(%[base])\n"
404+ "sd a4, 112(%[base])\n"
405+ "sd a5, 120(%[base])\n"
406+ "sd a6, 128(%[base])\n"
407+ "sd a7, 136(%[base])\n"
408+ "sd s2, 144(%[base])\n"
409+ "sd s3, 152(%[base])\n"
410+ "sd s4, 160(%[base])\n"
411+ "sd s5, 168(%[base])\n"
412+ "sd s6, 176(%[base])\n"
413+ "sd s7, 184(%[base])\n"
414+ "sd s8, 192(%[base])\n"
415+ "sd s9, 200(%[base])\n"
416+ "sd s10, 208(%[base])\n"
417+ "sd s11, 216(%[base])\n"
418+ "sd t3, 224(%[base])\n"
419+ "sd t4, 232(%[base])\n"
420+ "sd t5, 240(%[base])\n"
421+ "sd t6, 248(%[base])\n"
422+ "la t1, 1b\n"
423+ "sd t1, 0(%[base])\n"
424+ : [base] "+r"(reg_data)
425+ :
426+ : "t1", "memory");
427+}
428+
429 #elif defined(__i386__) || defined(__x86_64__) || defined(__mips__)
430
431 extern "C" void AsmGetRegs(void* regs);
432diff --git a/system/core/libunwindstack/include/unwindstack/RegsRiscv64.h b/system/core/libunwindstack/include/unwindstack/RegsRiscv64.h
433new file mode 100644
434index 0000000..eb09397
435--- /dev/null
436+++ b/system/core/libunwindstack/include/unwindstack/RegsRiscv64.h
437@@ -0,0 +1,59 @@
438+/*
439+ * Copyright (C) 2022 The Android Open Source Project
440+ *
441+ * Licensed under the Apache License, Version 2.0 (the "License");
442+ * you may not use this file except in compliance with the License.
443+ * You may obtain a copy of the License at
444+ *
445+ * http://www.apache.org/licenses/LICENSE-2.0
446+ *
447+ * Unless required by applicable law or agreed to in writing, software
448+ * distributed under the License is distributed on an "AS IS" BASIS,
449+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
450+ * See the License for the specific language governing permissions and
451+ * limitations under the License.
452+ */
453+
454+#pragma once
455+
456+#include <stdint.h>
457+
458+#include <functional>
459+
460+#include <unwindstack/Elf.h>
461+#include <unwindstack/Regs.h>
462+
463+namespace unwindstack {
464+
465+// Forward declarations.
466+class Memory;
467+
468+class RegsRiscv64 : public RegsImpl<uint64_t> {
469+ public:
470+ RegsRiscv64();
471+ virtual ~RegsRiscv64() = default;
472+
473+ ArchEnum Arch() override final;
474+
475+ uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
476+
477+ bool SetPcFromReturnAddress(Memory* process_memory) override;
478+
479+ bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override;
480+
481+ void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
482+
483+ uint64_t pc() override;
484+ uint64_t sp() override;
485+
486+ void set_pc(uint64_t pc) override;
487+ void set_sp(uint64_t sp) override;
488+
489+ Regs* Clone() override final;
490+
491+ static Regs* Read(void* data);
492+
493+ static Regs* CreateFromUcontext(void* ucontext);
494+};
495+
496+} // namespace unwindstack
497diff --git a/system/core/libunwindstack/include/unwindstack/UcontextRiscv64.h b/system/core/libunwindstack/include/unwindstack/UcontextRiscv64.h
498new file mode 100644
499index 0000000..c6c82b1
500--- /dev/null
501+++ b/system/core/libunwindstack/include/unwindstack/UcontextRiscv64.h
502@@ -0,0 +1,80 @@
503+/*
504+ * Copyright (C) 2014 The Android Open Source Project
505+ * All rights reserved.
506+ *
507+ * Redistribution and use in source and binary forms, with or without
508+ * modification, are permitted provided that the following conditions
509+ * are met:
510+ * * Redistributions of source code must retain the above copyright
511+ * notice, this list of conditions and the following disclaimer.
512+ * * Redistributions in binary form must reproduce the above copyright
513+ * notice, this list of conditions and the following disclaimer in
514+ * the documentation and/or other materials provided with the
515+ * distribution.
516+ *
517+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
518+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
519+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
520+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
521+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
522+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
523+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
524+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
525+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
526+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
527+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
528+ * SUCH DAMAGE.
529+ */
530+
531+#pragma once
532+
533+#include <sys/cdefs.h>
534+
535+typedef uint64_t __riscv_mc_gp_state[32]; // unsigned long
536+
537+struct __riscv_mc_f_ext_state {
538+ uint32_t __f[32];
539+ uint32_t __fcsr;
540+};
541+
542+struct __riscv_mc_d_ext_state {
543+ uint64_t __f[32];
544+ uint32_t __fcsr;
545+};
546+
547+struct __riscv_mc_q_ext_state {
548+ uint64_t __f[64] __attribute__((__aligned__(16)));
549+ uint32_t __fcsr;
550+ uint32_t __reserved[3];
551+};
552+
553+union __riscv_mc_fp_state {
554+ struct __riscv_mc_f_ext_state __f;
555+ struct __riscv_mc_d_ext_state __d;
556+ struct __riscv_mc_q_ext_state __q;
557+};
558+
559+struct __riscv_stack_t {
560+ uint64_t ss_sp;
561+ int32_t ss_flags;
562+ uint64_t ss_size;
563+};
564+
565+struct riscv64_sigset_t {
566+ uint64_t sig; // unsigned long
567+};
568+
569+struct riscv64_mcontext_t {
570+ __riscv_mc_gp_state __gregs;
571+ union __riscv_mc_fp_state __fpregs;
572+};
573+
574+struct riscv64_ucontext_t {
575+ uint64_t uc_flags; // unsigned long
576+ struct riscv64_ucontext_t* uc_link;
577+ __riscv_stack_t uc_stack;
578+ riscv64_sigset_t uc_sigmask;
579+ /* The kernel adds extra padding here to allow sigset_t to grow. */
580+ int8_t __padding[128 - sizeof(riscv64_sigset_t)]; // char
581+ riscv64_mcontext_t uc_mcontext;
582+};
583diff --git a/system/core/libunwindstack/include/unwindstack/UserRiscv64.h b/system/core/libunwindstack/include/unwindstack/UserRiscv64.h
584new file mode 100644
585index 0000000..1e91228
586--- /dev/null
587+++ b/system/core/libunwindstack/include/unwindstack/UserRiscv64.h
588@@ -0,0 +1,37 @@
589+/*
590+ * Copyright (C) 2016 The Android Open Source Project
591+ * All rights reserved.
592+ *
593+ * Redistribution and use in source and binary forms, with or without
594+ * modification, are permitted provided that the following conditions
595+ * are met:
596+ * * Redistributions of source code must retain the above copyright
597+ * notice, this list of conditions and the following disclaimer.
598+ * * Redistributions in binary form must reproduce the above copyright
599+ * notice, this list of conditions and the following disclaimer in
600+ * the documentation and/or other materials provided with the
601+ * distribution.
602+ *
603+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
604+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
605+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
606+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
607+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
608+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
609+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
610+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
611+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
612+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
613+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
614+ * SUCH DAMAGE.
615+ */
616+
617+#pragma once
618+
619+namespace unwindstack {
620+
621+struct riscv64_user_regs {
622+ uint64_t regs[32];
623+};
624+
625+} // namespace unwindstack
626diff --git a/system/core/libunwindstack/tools/unwind.cpp b/system/core/libunwindstack/tools/unwind.cpp
627index 1812e50..ae20891 100644
628--- a/system/core/libunwindstack/tools/unwind.cpp
629+++ b/system/core/libunwindstack/tools/unwind.cpp
630@@ -83,6 +83,9 @@ void DoUnwind(pid_t pid) {
631 case unwindstack::ARCH_MIPS64:
632 printf("mips64");
633 break;
634+ case unwindstack::ARCH_RISCV64:
635+ printf("riscv64");
636+ break;
637 default:
638 printf("unknown\n");
639 return;
640diff --git a/system/core/libunwindstack/tools/unwind_symbols.cpp b/system/core/libunwindstack/tools/unwind_symbols.cpp
641index 8df2284..976db56 100644
642--- a/system/core/libunwindstack/tools/unwind_symbols.cpp
643+++ b/system/core/libunwindstack/tools/unwind_symbols.cpp
644@@ -77,6 +77,9 @@ int main(int argc, char** argv) {
645 case EM_AARCH64:
646 printf("ABI: arm64\n");
647 break;
648+ case EM_RISCV:
649+ printf("ABI: riscv64\n");
650+ break;
651 case EM_386:
652 printf("ABI: x86\n");
653 break;