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