diff options
author | Christopher Ferris <cferris@google.com> | 2024-02-26 19:22:17 -0800 |
---|---|---|
committer | Christopher Ferris <cferris@google.com> | 2024-03-05 19:15:59 -0800 |
commit | 838034d87b252c55182913b848dc2edac4fd5bbf (patch) | |
tree | c289046d9143a2d23e80ae59e95467f78d60757f | |
parent | 6ec5d39099e83c3db80117846cf2395815b2ec7f (diff) | |
download | unwinding-838034d87b252c55182913b848dc2edac4fd5bbf.tar.gz |
Update riscv64 handling.
Given that it should be impossible for cores to have different vlenb
values, modify the code to always get the vlenb locally when on a
riscv processor. Add error messages and abort when incorrect code paths
are executed.
Test: All unit tests pass on host.
Test: All unit tests pass on arm64 device.
Test: All unit tests pass on riscv emulator.
Test: Debuggerd unit tests pass on riscv emulator.
Change-Id: I14775fe630a3a2feaf2b9570636f20f843a1f185
-rw-r--r-- | libunwindstack/LogAndroid.cpp | 8 | ||||
-rw-r--r-- | libunwindstack/LogStdout.cpp | 8 | ||||
-rw-r--r-- | libunwindstack/RegsRiscv64.cpp | 23 | ||||
-rw-r--r-- | libunwindstack/include/unwindstack/Log.h | 1 | ||||
-rw-r--r-- | libunwindstack/tests/RegsTest.cpp | 16 |
5 files changed, 49 insertions, 7 deletions
diff --git a/libunwindstack/LogAndroid.cpp b/libunwindstack/LogAndroid.cpp index 6fb613f..2f5b00e 100644 --- a/libunwindstack/LogAndroid.cpp +++ b/libunwindstack/LogAndroid.cpp @@ -66,6 +66,14 @@ void Error(const char* format, ...) { va_end(args); } +void Fatal(const char* format, ...) { + va_list args; + va_start(args, format); + LogWithPriority(ANDROID_LOG_FATAL, 0, format, args); + va_end(args); + abort(); +} + #if defined(__BIONIC__) void AsyncSafe(const char* format, ...) { va_list args; diff --git a/libunwindstack/LogStdout.cpp b/libunwindstack/LogStdout.cpp index bb5c2dd..e54bd11 100644 --- a/libunwindstack/LogStdout.cpp +++ b/libunwindstack/LogStdout.cpp @@ -61,6 +61,14 @@ void Error(const char* format, ...) { va_end(args); } +void Fatal(const char* format, ...) { + va_list args; + va_start(args, format); + PrintToStdout(0, format, args); + va_end(args); + abort(); +} + void AsyncSafe(const char* format, ...) { va_list args; va_start(args, format); diff --git a/libunwindstack/RegsRiscv64.cpp b/libunwindstack/RegsRiscv64.cpp index a69b07f..532b3b1 100644 --- a/libunwindstack/RegsRiscv64.cpp +++ b/libunwindstack/RegsRiscv64.cpp @@ -24,6 +24,7 @@ #include <vector> #include <unwindstack/Elf.h> +#include <unwindstack/Log.h> #include <unwindstack/MachineRiscv64.h> #include <unwindstack/MapInfo.h> #include <unwindstack/Memory.h> @@ -35,30 +36,38 @@ namespace unwindstack { uint64_t RegsRiscv64::GetVlenbFromLocal() { #if defined(__riscv) - // Assumes that all cpus have the same value. uint64_t vlenb; asm volatile("csrr %0, 0xc22\n" : "=r"(vlenb)::); return vlenb; #else - return 0; + Log::Fatal("%s:%d: On non-riscv device, attempt to get vlenb locally.", __FILE__, __LINE__); #endif } +#if defined(__riscv) +uint64_t RegsRiscv64::GetVlenbFromRemote(pid_t) { + // All riscv cores in a cpu are required to have the same vlenb value. + // Note: If a device exists with multiple cpus, but all of the cpus do not + // have the same vlenb, then this method will need to be modified. + return GetVlenbFromLocal(); +} +#else uint64_t RegsRiscv64::GetVlenbFromRemote(pid_t pid) { if (pid == 0) { - return GetVlenbFromLocal(); + Log::Fatal("%s:%d: Attempt to get vlenb remotely from non-riscv device without pid.", __FILE__, + __LINE__); } - // We only care about these values, no need to get the other vector registers. + // We only care about the state values, no need to get anything else. struct riscv64_v_regset_state regs; struct iovec io = {.iov_base = ®s, .iov_len = sizeof(regs)}; if (ptrace(PTRACE_GETREGSET, pid, NT_RISCV_VECTOR, reinterpret_cast<void*>(&io)) == -1) { - // TODO: Workaround due to some devices not properly returning these values. - // This code assumes that all cores on the device have the same vlenb. - return GetVlenbFromLocal(); + Log::Error("Failed to get vlenb from target process %d: %d", pid, errno); + return 0; } return regs.vlenb; } +#endif RegsRiscv64::RegsRiscv64() : RegsImpl<uint64_t>(RISCV64_REG_COUNT, Location(LOCATION_REGISTER, RISCV64_REG_RA)) {} diff --git a/libunwindstack/include/unwindstack/Log.h b/libunwindstack/include/unwindstack/Log.h index 34eb218..be681c0 100644 --- a/libunwindstack/include/unwindstack/Log.h +++ b/libunwindstack/include/unwindstack/Log.h @@ -27,6 +27,7 @@ namespace unwindstack { namespace Log { +[[noreturn]] void Fatal(const char* format, ...) __printflike(1, 2); void Error(const char* format, ...) __printflike(1, 2); void Info(const char* format, ...) __printflike(1, 2); void Info(uint8_t indent, const char* format, ...) __printflike(2, 3); diff --git a/libunwindstack/tests/RegsTest.cpp b/libunwindstack/tests/RegsTest.cpp index 6fb625d..10605ab 100644 --- a/libunwindstack/tests/RegsTest.cpp +++ b/libunwindstack/tests/RegsTest.cpp @@ -18,6 +18,7 @@ #include <memory> +#include <android-base/silent_death_test.h> #include <gtest/gtest.h> #include <unwindstack/Elf.h> @@ -229,6 +230,21 @@ TEST_F(RegsTest, riscv_convert) { EXPECT_EQ(RISCV64_REG_COUNT, regs.Convert(RISCV64_REG_VLENB)); } +#if defined(__riscv) +TEST_F(RegsTest, riscv_get_vlenb) { + RegsRiscv64 regs; + EXPECT_NE(0U, regs.GetVlenbFromLocal()); + EXPECT_NE(0U, regs.GetVlenbFromRemote(0)); +} +#else +using RegsDeathTest = SilentDeathTest; +TEST_F(RegsDeathTest, riscv_get_vlenb) { + RegsRiscv64 regs; + ASSERT_DEATH(regs.GetVlenbFromLocal(), ""); + ASSERT_DEATH(regs.GetVlenbFromRemote(0), ""); +} +#endif + TEST_F(RegsTest, x86_verify_sp_pc) { RegsX86 x86; uint32_t* regs = reinterpret_cast<uint32_t*>(x86.RawData()); |