From d26df3e669877e18763df1ccfe0b27f61203658e Mon Sep 17 00:00:00 2001 From: Guo Ren Date: Wed, 29 Jun 2022 16:46:46 +0800 Subject: [PATCH] Add riscv64 support This patch contains the dwarf unwind support for 64bit risc-v. * DwarfCfa.cpp (cfa_def_cfa_register): setup register if CFA_REG is not setup for riscv64 * Elf.cpp (GetRelPc): convert offset to virtual address for riscv64. * ElfInterface.cpp (GetVirtAddrFromOffset): New for riscv64. * RegsRiscv64.cpp (StepIfSignalHandler): Fix signal frame check. libunwindstack/include/unwindstack/ * ElfInterface.h (GetVirtAddrFromOffset): New for riscv64. libunwindstack/tests/ * DwarfCfaTest.cpp (cfa_def_cfa_register): ok for riscv64. * RegsStepIfSignalHandlerTest.cpp (riscv64_step_if_signal_handler): Fix testcase for riscv64 Test: Builds. Test: All unit tests pass. Signed-off-by: Guo Ren Signed-off-by: Lifang Xia Signed-off-by: Mao Han Change-Id: Ib21ddf23cc83f332af202df7bffcaceec16063e0 Gbp-Pq: Topic system/core Gbp-Pq: Name Add-riscv64-support.patch --- system/core/libunwindstack/Android.bp | 1 + system/core/libunwindstack/Elf.cpp | 2 + system/core/libunwindstack/Regs.cpp | 10 ++ system/core/libunwindstack/RegsRiscv64.cpp | 156 ++++++++++++++++++ .../libunwindstack/include/unwindstack/Elf.h | 5 + .../include/unwindstack/MachineRiscv64.h | 59 +++++++ .../include/unwindstack/RegsGetLocal.h | 43 +++++ .../include/unwindstack/RegsRiscv64.h | 59 +++++++ .../include/unwindstack/UcontextRiscv64.h | 80 +++++++++ .../include/unwindstack/UserRiscv64.h | 37 +++++ system/core/libunwindstack/tools/unwind.cpp | 3 + .../libunwindstack/tools/unwind_symbols.cpp | 3 + 12 files changed, 458 insertions(+) create mode 100644 system/core/libunwindstack/RegsRiscv64.cpp create mode 100644 system/core/libunwindstack/include/unwindstack/MachineRiscv64.h create mode 100644 system/core/libunwindstack/include/unwindstack/RegsRiscv64.h create mode 100644 system/core/libunwindstack/include/unwindstack/UcontextRiscv64.h create mode 100644 system/core/libunwindstack/include/unwindstack/UserRiscv64.h diff --git a/system/core/libunwindstack/Android.bp b/system/core/libunwindstack/Android.bp index 3695f72f..f1f9c682 100644 --- a/system/core/libunwindstack/Android.bp +++ b/system/core/libunwindstack/Android.bp @@ -70,6 +70,7 @@ cc_library { "RegsArm64.cpp", "RegsX86.cpp", "RegsX86_64.cpp", + "RegsRiscv64.cpp", "RegsMips.cpp", "RegsMips64.cpp", "Unwinder.cpp", diff --git a/system/core/libunwindstack/Elf.cpp b/system/core/libunwindstack/Elf.cpp index f01b0926..3c2088b9 100644 --- a/system/core/libunwindstack/Elf.cpp +++ b/system/core/libunwindstack/Elf.cpp @@ -290,6 +290,8 @@ ElfInterface* Elf::CreateInterfaceFromMemory(Memory* memory) { arch_ = ARCH_X86_64; } else if (e_machine == EM_MIPS) { arch_ = ARCH_MIPS64; + } else if (e_machine == EM_RISCV) { + arch_ = ARCH_RISCV64; } else { // Unsupported. ALOGI("64 bit elf that is neither aarch64 nor x86_64 nor mips64: e_machine = %d\n", diff --git a/system/core/libunwindstack/Regs.cpp b/system/core/libunwindstack/Regs.cpp index c7dec525..447a5544 100644 --- a/system/core/libunwindstack/Regs.cpp +++ b/system/core/libunwindstack/Regs.cpp @@ -27,12 +27,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include @@ -67,6 +69,8 @@ Regs* Regs::RemoteGet(pid_t pid) { return RegsMips::Read(buffer.data()); case sizeof(mips64_user_regs): return RegsMips64::Read(buffer.data()); + case sizeof(riscv64_user_regs): + return RegsRiscv64::Read(buffer.data()); } return nullptr; } @@ -85,6 +89,8 @@ Regs* Regs::CreateFromUcontext(ArchEnum arch, void* ucontext) { return RegsMips::CreateFromUcontext(ucontext); case ARCH_MIPS64: return RegsMips64::CreateFromUcontext(ucontext); + case ARCH_RISCV64: + return RegsRiscv64::CreateFromUcontext(ucontext); case ARCH_UNKNOWN: default: return nullptr; @@ -104,6 +110,8 @@ ArchEnum Regs::CurrentArch() { return ARCH_MIPS; #elif defined(__mips__) && defined(__LP64__) return ARCH_MIPS64; +#elif defined(__riscv) + return ARCH_RISCV64; #else abort(); #endif @@ -123,6 +131,8 @@ Regs* Regs::CreateFromLocal() { regs = new RegsMips(); #elif defined(__mips__) && defined(__LP64__) regs = new RegsMips64(); +#elif defined(__riscv) + regs = new RegsRiscv64(); #else abort(); #endif diff --git a/system/core/libunwindstack/RegsRiscv64.cpp b/system/core/libunwindstack/RegsRiscv64.cpp new file mode 100644 index 00000000..887762a8 --- /dev/null +++ b/system/core/libunwindstack/RegsRiscv64.cpp @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace unwindstack { + +RegsRiscv64::RegsRiscv64() + : RegsImpl(RISCV64_REG_MAX, Location(LOCATION_REGISTER, RISCV64_REG_RA)) {} + +ArchEnum RegsRiscv64::Arch() { + return ARCH_RISCV64; +} + +uint64_t RegsRiscv64::pc() { + return regs_[RISCV64_REG_PC]; +} + +uint64_t RegsRiscv64::sp() { + return regs_[RISCV64_REG_SP]; +} + +void RegsRiscv64::set_pc(uint64_t pc) { + regs_[RISCV64_REG_PC] = pc; +} + +void RegsRiscv64::set_sp(uint64_t sp) { + regs_[RISCV64_REG_SP] = sp; +} + +uint64_t RegsRiscv64::GetPcAdjustment(uint64_t rel_pc, Elf*) { + if (rel_pc < 8) { + return 0; + } + // For now, just assume no compact branches + return 8; +} + +bool RegsRiscv64::SetPcFromReturnAddress(Memory*) { + uint64_t ra = regs_[RISCV64_REG_RA]; + if (regs_[RISCV64_REG_PC] == ra) { + return false; + } + + regs_[RISCV64_REG_PC] = ra; + return true; +} + +void RegsRiscv64::IterateRegisters(std::function fn) { + fn("pc", regs_[RISCV64_REG_PC]); + fn("ra", regs_[RISCV64_REG_RA]); + fn("sp", regs_[RISCV64_REG_SP]); + fn("gp", regs_[RISCV64_REG_GP]); + fn("tp", regs_[RISCV64_REG_TP]); + fn("t0", regs_[RISCV64_REG_T0]); + fn("t1", regs_[RISCV64_REG_T1]); + fn("t2", regs_[RISCV64_REG_T2]); + fn("t3", regs_[RISCV64_REG_T3]); + fn("t4", regs_[RISCV64_REG_T4]); + fn("t5", regs_[RISCV64_REG_T5]); + fn("t6", regs_[RISCV64_REG_T6]); + fn("s0", regs_[RISCV64_REG_S0]); + fn("s1", regs_[RISCV64_REG_S1]); + fn("s2", regs_[RISCV64_REG_S2]); + fn("s3", regs_[RISCV64_REG_S3]); + fn("s4", regs_[RISCV64_REG_S4]); + fn("s5", regs_[RISCV64_REG_S5]); + fn("s6", regs_[RISCV64_REG_S6]); + fn("s7", regs_[RISCV64_REG_S7]); + fn("s8", regs_[RISCV64_REG_S8]); + fn("s9", regs_[RISCV64_REG_S9]); + fn("s10", regs_[RISCV64_REG_S10]); + fn("s11", regs_[RISCV64_REG_S11]); + fn("a0", regs_[RISCV64_REG_A0]); + fn("a1", regs_[RISCV64_REG_A1]); + fn("a2", regs_[RISCV64_REG_A2]); + fn("a3", regs_[RISCV64_REG_A3]); + fn("a4", regs_[RISCV64_REG_A4]); + fn("a5", regs_[RISCV64_REG_A5]); + fn("a6", regs_[RISCV64_REG_A6]); + fn("a7", regs_[RISCV64_REG_A7]); +} + +Regs* RegsRiscv64::Read(void* remote_data) { + riscv64_user_regs* user = reinterpret_cast(remote_data); + + RegsRiscv64* regs = new RegsRiscv64(); + memcpy(regs->RawData(), &user->regs[0], RISCV64_REG_MAX * sizeof(uint64_t)); + // uint64_t* reg_data = reinterpret_cast(regs->RawData()); + return regs; +} + +Regs* RegsRiscv64::CreateFromUcontext(void* ucontext) { + riscv64_ucontext_t* riscv64_ucontext = reinterpret_cast(ucontext); + + RegsRiscv64* regs = new RegsRiscv64(); + memcpy(regs->RawData(), &riscv64_ucontext->uc_mcontext.__gregs[0], + RISCV64_REG_MAX * sizeof(uint64_t)); + return regs; +} + +bool RegsRiscv64::StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) { + uint64_t data; + Memory* elf_memory = elf->memory(); + // Read from elf memory since it is usually more expensive to read from + // process memory. + if (!elf_memory->ReadFully(elf_offset, &data, sizeof(data))) { + return false; + } + // Look for the kernel sigreturn function. + // __kernel_rt_sigreturn: + // li a7, __NR_rt_sigreturn + // scall + + const uint8_t li_scall[] = {0x93, 0x08, 0xb0, 0x08, 0x73, 0x00, 0x00, 0x00}; + if (memcmp(&data, &li_scall, 8) != 0) { + return false; + } + + // SP + sizeof(siginfo_t) + uc_mcontext offset + PC offset. + if (!process_memory->ReadFully(regs_[RISCV64_REG_SP] + 0x80 + 0xb0 + 0x00, regs_.data(), + sizeof(uint64_t) * (RISCV64_REG_MAX))) { + return false; + } + return true; +} + +Regs* RegsRiscv64::Clone() { + return new RegsRiscv64(*this); +} + +} // namespace unwindstack diff --git a/system/core/libunwindstack/include/unwindstack/Elf.h b/system/core/libunwindstack/include/unwindstack/Elf.h index 472ed925..88fa0ff5 100644 --- a/system/core/libunwindstack/include/unwindstack/Elf.h +++ b/system/core/libunwindstack/include/unwindstack/Elf.h @@ -32,6 +32,10 @@ #define EM_AARCH64 183 #endif +#if !defined(EM_RISCV) +#define EM_RISCV 243 +#endif + namespace unwindstack { // Forward declaration. @@ -46,6 +50,7 @@ enum ArchEnum : uint8_t { ARCH_X86_64, ARCH_MIPS, ARCH_MIPS64, + ARCH_RISCV64, }; class Elf { diff --git a/system/core/libunwindstack/include/unwindstack/MachineRiscv64.h b/system/core/libunwindstack/include/unwindstack/MachineRiscv64.h new file mode 100644 index 00000000..397e6801 --- /dev/null +++ b/system/core/libunwindstack/include/unwindstack/MachineRiscv64.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace unwindstack { + +enum Riscv64Reg : uint16_t { + RISCV64_REG_PC, + RISCV64_REG_RA, + RISCV64_REG_SP, + RISCV64_REG_GP, + RISCV64_REG_TP, + RISCV64_REG_T0, + RISCV64_REG_T1, + RISCV64_REG_T2, + RISCV64_REG_S0, + RISCV64_REG_S1, + RISCV64_REG_A0, + RISCV64_REG_A1, + RISCV64_REG_A2, + RISCV64_REG_A3, + RISCV64_REG_A4, + RISCV64_REG_A5, + RISCV64_REG_A6, + RISCV64_REG_A7, + RISCV64_REG_S2, + RISCV64_REG_S3, + RISCV64_REG_S4, + RISCV64_REG_S5, + RISCV64_REG_S6, + RISCV64_REG_S7, + RISCV64_REG_S8, + RISCV64_REG_S9, + RISCV64_REG_S10, + RISCV64_REG_S11, + RISCV64_REG_T3, + RISCV64_REG_T4, + RISCV64_REG_T5, + RISCV64_REG_T6, + RISCV64_REG_MAX, +}; + +} // namespace unwindstack diff --git a/system/core/libunwindstack/include/unwindstack/RegsGetLocal.h b/system/core/libunwindstack/include/unwindstack/RegsGetLocal.h index f0b5e3a1..698eba22 100644 --- a/system/core/libunwindstack/include/unwindstack/RegsGetLocal.h +++ b/system/core/libunwindstack/include/unwindstack/RegsGetLocal.h @@ -81,6 +81,49 @@ inline __attribute__((__always_inline__)) void AsmGetRegs(void* reg_data) { : "x12", "x13", "memory"); } +#elif defined(__riscv) + +inline __attribute__((__always_inline__)) void AsmGetRegs(void* reg_data) { + asm volatile( + "1:\n" + "sd ra, 8(%[base])\n" + "sd sp, 16(%[base])\n" + "sd gp, 24(%[base])\n" + "sd tp, 32(%[base])\n" + "sd t0, 40(%[base])\n" + "sd t1, 48(%[base])\n" + "sd t2, 56(%[base])\n" + "sd s0, 64(%[base])\n" + "sd s1, 72(%[base])\n" + "sd a0, 80(%[base])\n" + "sd a1, 88(%[base])\n" + "sd a2, 96(%[base])\n" + "sd a3, 104(%[base])\n" + "sd a4, 112(%[base])\n" + "sd a5, 120(%[base])\n" + "sd a6, 128(%[base])\n" + "sd a7, 136(%[base])\n" + "sd s2, 144(%[base])\n" + "sd s3, 152(%[base])\n" + "sd s4, 160(%[base])\n" + "sd s5, 168(%[base])\n" + "sd s6, 176(%[base])\n" + "sd s7, 184(%[base])\n" + "sd s8, 192(%[base])\n" + "sd s9, 200(%[base])\n" + "sd s10, 208(%[base])\n" + "sd s11, 216(%[base])\n" + "sd t3, 224(%[base])\n" + "sd t4, 232(%[base])\n" + "sd t5, 240(%[base])\n" + "sd t6, 248(%[base])\n" + "la t1, 1b\n" + "sd t1, 0(%[base])\n" + : [base] "+r"(reg_data) + : + : "t1", "memory"); +} + #elif defined(__i386__) || defined(__x86_64__) || defined(__mips__) extern "C" void AsmGetRegs(void* regs); diff --git a/system/core/libunwindstack/include/unwindstack/RegsRiscv64.h b/system/core/libunwindstack/include/unwindstack/RegsRiscv64.h new file mode 100644 index 00000000..eb093978 --- /dev/null +++ b/system/core/libunwindstack/include/unwindstack/RegsRiscv64.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include + +#include +#include + +namespace unwindstack { + +// Forward declarations. +class Memory; + +class RegsRiscv64 : public RegsImpl { + public: + RegsRiscv64(); + virtual ~RegsRiscv64() = default; + + ArchEnum Arch() override final; + + uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override; + + bool SetPcFromReturnAddress(Memory* process_memory) override; + + bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override; + + void IterateRegisters(std::function) override final; + + uint64_t pc() override; + uint64_t sp() override; + + void set_pc(uint64_t pc) override; + void set_sp(uint64_t sp) override; + + Regs* Clone() override final; + + static Regs* Read(void* data); + + static Regs* CreateFromUcontext(void* ucontext); +}; + +} // namespace unwindstack diff --git a/system/core/libunwindstack/include/unwindstack/UcontextRiscv64.h b/system/core/libunwindstack/include/unwindstack/UcontextRiscv64.h new file mode 100644 index 00000000..c6c82b1a --- /dev/null +++ b/system/core/libunwindstack/include/unwindstack/UcontextRiscv64.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#pragma once + +#include + +typedef uint64_t __riscv_mc_gp_state[32]; // unsigned long + +struct __riscv_mc_f_ext_state { + uint32_t __f[32]; + uint32_t __fcsr; +}; + +struct __riscv_mc_d_ext_state { + uint64_t __f[32]; + uint32_t __fcsr; +}; + +struct __riscv_mc_q_ext_state { + uint64_t __f[64] __attribute__((__aligned__(16))); + uint32_t __fcsr; + uint32_t __reserved[3]; +}; + +union __riscv_mc_fp_state { + struct __riscv_mc_f_ext_state __f; + struct __riscv_mc_d_ext_state __d; + struct __riscv_mc_q_ext_state __q; +}; + +struct __riscv_stack_t { + uint64_t ss_sp; + int32_t ss_flags; + uint64_t ss_size; +}; + +struct riscv64_sigset_t { + uint64_t sig; // unsigned long +}; + +struct riscv64_mcontext_t { + __riscv_mc_gp_state __gregs; + union __riscv_mc_fp_state __fpregs; +}; + +struct riscv64_ucontext_t { + uint64_t uc_flags; // unsigned long + struct riscv64_ucontext_t* uc_link; + __riscv_stack_t uc_stack; + riscv64_sigset_t uc_sigmask; + /* The kernel adds extra padding here to allow sigset_t to grow. */ + int8_t __padding[128 - sizeof(riscv64_sigset_t)]; // char + riscv64_mcontext_t uc_mcontext; +}; diff --git a/system/core/libunwindstack/include/unwindstack/UserRiscv64.h b/system/core/libunwindstack/include/unwindstack/UserRiscv64.h new file mode 100644 index 00000000..1e912283 --- /dev/null +++ b/system/core/libunwindstack/include/unwindstack/UserRiscv64.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#pragma once + +namespace unwindstack { + +struct riscv64_user_regs { + uint64_t regs[32]; +}; + +} // namespace unwindstack diff --git a/system/core/libunwindstack/tools/unwind.cpp b/system/core/libunwindstack/tools/unwind.cpp index 1812e503..ae208913 100644 --- a/system/core/libunwindstack/tools/unwind.cpp +++ b/system/core/libunwindstack/tools/unwind.cpp @@ -83,6 +83,9 @@ void DoUnwind(pid_t pid) { case unwindstack::ARCH_MIPS64: printf("mips64"); break; + case unwindstack::ARCH_RISCV64: + printf("riscv64"); + break; default: printf("unknown\n"); return; diff --git a/system/core/libunwindstack/tools/unwind_symbols.cpp b/system/core/libunwindstack/tools/unwind_symbols.cpp index 8df22841..976db560 100644 --- a/system/core/libunwindstack/tools/unwind_symbols.cpp +++ b/system/core/libunwindstack/tools/unwind_symbols.cpp @@ -77,6 +77,9 @@ int main(int argc, char** argv) { case EM_AARCH64: printf("ABI: arm64\n"); break; + case EM_RISCV: + printf("ABI: riscv64\n"); + break; case EM_386: printf("ABI: x86\n"); break; -- 2.30.2