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
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 @@
   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 @@
   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 @@
 
 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 = &regs, .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 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 @@
   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());