Browse Source

third_party: crashpad: port for RISC-V

Patch cherry-picked from:
https://github.com/felixonmars/archriscv-packages/tree/master/chromium

Signed-off-by: Rebecca Chang Swee Fun <rebecca.chang@starfivetech.com>
Rebecca Chang Swee Fun 1 year ago
parent
commit
786ce95eda

+ 35 - 0
third_party/crashpad/crashpad/minidump/minidump_context.h

@@ -637,6 +637,41 @@ struct MinidumpContextMIPS64 {
   uint64_t fir;
 };
 
+//! \brief 64bit RISC-V-specifc flags for MinidumpContextRISCV64::context_flags.
+//! Based on minidump_cpu_riscv64.h from breakpad
+enum MinidumpContextRISCV64Flags : uint32_t {
+  //! \brief Identifies the context structure as RISCV64.
+  kMinidumpContextRISCV64 = 0x00080000,
+
+  //! \brief Indicates the validity of integer registers.
+  //!
+  //! Registers `x1`-`x31` and pc are valid.
+  kMinidumpContextRISCV64Integer = kMinidumpContextRISCV64 | 0x00000002,
+
+  //! \brief Indicates the validity of floating point registers.
+  //!
+  //! Floating point registers `f0`-`f31`, and `fcsr` are valid
+  kMinidumpContextRISCV64FloatingPoint = kMinidumpContextRISCV64 | 0x00000004,
+
+  //! \brief Indicates the validity of all registers.
+  kMinidumpContextRISCV64All = kMinidumpContextRISCV64Integer |
+                              kMinidumpContextRISCV64FloatingPoint,
+};
+
+//! \brief A 64bit RISCV CPU context (register state) carried in a minidump file.
+struct MinidumpContextRISCV64 {
+  uint64_t context_flags;
+
+  //! \brief General purpose registers.
+  uint64_t regs[32];
+
+  //! \brief FPU registers.
+  uint64_t fpregs[32];
+
+  //! \brief FPU status register.
+  uint64_t fcsr;
+};
+
 }  // namespace crashpad
 
 #endif  // CRASHPAD_MINIDUMP_MINIDUMP_CONTEXT_H_

+ 44 - 0
third_party/crashpad/crashpad/minidump/minidump_context_writer.cc

@@ -102,6 +102,13 @@ MinidumpContextWriter::CreateFromSnapshot(const CPUContext* context_snapshot) {
       break;
     }
 
+    case kCPUArchitectureRISCV64: {
+      context = std::make_unique<MinidumpContextRISCV64Writer>();
+      reinterpret_cast<MinidumpContextRISCV64Writer*>(context.get())
+          ->InitializeFromSnapshot(context_snapshot->riscv64);
+      break;
+    }
+
     default: {
       LOG(ERROR) << "unknown context architecture "
                  << context_snapshot->architecture;
@@ -556,4 +563,41 @@ size_t MinidumpContextMIPS64Writer::ContextSize() const {
   return sizeof(context_);
 }
 
+MinidumpContextRISCV64Writer::MinidumpContextRISCV64Writer()
+    : MinidumpContextWriter(), context_() {
+  context_.context_flags = kMinidumpContextRISCV64;
+}
+
+MinidumpContextRISCV64Writer::~MinidumpContextRISCV64Writer() = default;
+
+void MinidumpContextRISCV64Writer::InitializeFromSnapshot(
+    const CPUContextRISCV64* context_snapshot) {
+  DCHECK_EQ(state(), kStateMutable);
+  DCHECK_EQ(context_.context_flags, kMinidumpContextRISCV64);
+
+  context_.context_flags = kMinidumpContextRISCV64All;
+
+  static_assert(sizeof(context_.regs) == sizeof(context_snapshot->regs),
+                "GPRs size mismatch");
+  memcpy(context_.regs, context_snapshot->regs, sizeof(context_.regs));
+
+  static_assert(sizeof(context_.fpregs) == sizeof(context_snapshot->fpregs),
+                "FPRs size mismatch");
+  memcpy(context_.fpregs,
+         context_snapshot->fpregs,
+         sizeof(context_.fpregs));
+  context_.fcsr = context_snapshot->fcsr;
+}
+
+bool MinidumpContextRISCV64Writer::WriteObject(
+    FileWriterInterface* file_writer) {
+  DCHECK_EQ(state(), kStateWritable);
+  return file_writer->Write(&context_, sizeof(context_));
+}
+
+size_t MinidumpContextRISCV64Writer::ContextSize() const {
+  DCHECK_GE(state(), kStateFrozen);
+  return sizeof(context_);
+}
+
 }  // namespace crashpad

+ 41 - 0
third_party/crashpad/crashpad/minidump/minidump_context_writer.h

@@ -369,6 +369,47 @@ class MinidumpContextMIPS64Writer final : public MinidumpContextWriter {
   MinidumpContextMIPS64 context_;
 };
 
+//! \brief The writer for a MinidumpContextRISCV64 structure in a minidump file.
+class MinidumpContextRISCV64Writer final : public MinidumpContextWriter {
+ public:
+  MinidumpContextRISCV64Writer();
+  ~MinidumpContextRISCV64Writer() override;
+
+  MinidumpContextRISCV64Writer(const MinidumpContextRISCV64Writer&) = delete;
+  void operator=(const MinidumpContextRISCV64Writer&) = delete;
+
+  //! \brief Initializes the MinidumpContextRISCV based on \a context_snapshot.
+  //!
+  //! \param[in] context_snapshot The context snapshot to use as source data.
+  //!
+  //! \note Valid in #kStateMutable. No mutation of context() may be done before
+  //!     calling this method, and it is not normally necessary to alter
+  //!     context() after calling this method.
+  void InitializeFromSnapshot(const CPUContextRISCV64* context_snapshot);
+
+  //! \brief Returns a pointer to the context structure that this object will
+  //!     write.
+  //!
+  //! \attention This returns a non-`const` pointer to this object’s private
+  //!     data so that a caller can populate the context structure directly.
+  //!     This is done because providing setter interfaces to each field in the
+  //!     context structure would be unwieldy and cumbersome. Care must be taken
+  //!     to populate the context structure correctly. The context structure
+  //!     must only be modified while this object is in the #kStateMutable
+  //!     state.
+  MinidumpContextRISCV64* context() { return &context_; }
+
+ protected:
+  // MinidumpWritable:
+  bool WriteObject(FileWriterInterface* file_writer) override;
+
+  // MinidumpContextWriter:
+  size_t ContextSize() const override;
+
+ private:
+  MinidumpContextRISCV64 context_;
+};
+
 }  // namespace crashpad
 
 #endif  // CRASHPAD_MINIDUMP_MINIDUMP_CONTEXT_WRITER_H_

+ 4 - 0
third_party/crashpad/crashpad/minidump/minidump_misc_info_writer.cc

@@ -175,6 +175,10 @@ std::string MinidumpMiscInfoDebugBuildString() {
   static constexpr char kCPU[] = "mips";
 #elif defined(ARCH_CPU_MIPS64EL)
   static constexpr char kCPU[] = "mips64";
+#elif defined(ARCH_CPU_RISCV)
+  static constexpr char kCPU[] = "riscv";
+#elif defined(ARCH_CPU_RISCV64)
+  static constexpr char kCPU[] = "riscv64";
 #else
 #error define kCPU for this CPU
 #endif

+ 10 - 0
third_party/crashpad/crashpad/snapshot/capture_memory.cc

@@ -117,6 +117,16 @@ void CaptureMemory::PointedToByContext(const CPUContext& context,
   for (size_t i = 0; i < std::size(context.mipsel->regs); ++i) {
     MaybeCaptureMemoryAround(delegate, context.mipsel->regs[i]);
   }
+#elif defined(ARCH_CPU_RISCV_FAMILY)
+  if (context.architecture == kCPUArchitectureRISCV) {
+    for (size_t i = 0; i < std::size(context.riscv->regs); ++i) {
+      MaybeCaptureMemoryAround(delegate, context.riscv->regs[i]);
+    }
+  } else {
+    for (size_t i = 0; i < std::size(context.riscv64->regs); ++i) {
+      MaybeCaptureMemoryAround(delegate, context.riscv64->regs[i]);
+    }
+  }
 #else
 #error Port.
 #endif

+ 7 - 1
third_party/crashpad/crashpad/snapshot/cpu_architecture.h

@@ -43,7 +43,13 @@ enum CPUArchitecture {
   kCPUArchitectureMIPSEL,
 
   //! \brief 64-bit MIPSEL.
-  kCPUArchitectureMIPS64EL
+  kCPUArchitectureMIPS64EL,
+
+  //! \brief 32-bit RISCV.
+  kCPUArchitectureRISCV,
+
+  //! \brief 64-bit RISCV.
+  kCPUArchitectureRISCV64
 };
 
 }  // namespace crashpad

+ 2 - 0
third_party/crashpad/crashpad/snapshot/cpu_context.cc

@@ -226,10 +226,12 @@ bool CPUContext::Is64Bit() const {
     case kCPUArchitectureX86_64:
     case kCPUArchitectureARM64:
     case kCPUArchitectureMIPS64EL:
+    case kCPUArchitectureRISCV64:
       return true;
     case kCPUArchitectureX86:
     case kCPUArchitectureARM:
     case kCPUArchitectureMIPSEL:
+    case kCPUArchitectureRISCV:
       return false;
     default:
       NOTREACHED();

+ 16 - 0
third_party/crashpad/crashpad/snapshot/cpu_context.h

@@ -362,6 +362,20 @@ struct CPUContextMIPS64 {
   uint64_t fir;
 };
 
+//! \brief A context structure carrying RISC CPU state.
+struct CPUContextRISCV {
+  uint32_t regs[32];
+  uint64_t fpregs[32];
+  uint32_t fcsr;
+};
+
+//! \brief A context structure carrying RISC64 CPU state.
+struct CPUContextRISCV64 {
+  uint64_t regs[32];
+  uint64_t fpregs[32];
+  uint32_t fcsr;
+};
+
 //! \brief A context structure capable of carrying the context of any supported
 //!     CPU architecture.
 struct CPUContext {
@@ -402,6 +416,8 @@ struct CPUContext {
     CPUContextARM64* arm64;
     CPUContextMIPS* mipsel;
     CPUContextMIPS64* mips64;
+    CPUContextRISCV* riscv;
+    CPUContextRISCV64* riscv64;
   };
 };
 

+ 24 - 0
third_party/crashpad/crashpad/snapshot/linux/cpu_context_linux.cc

@@ -266,6 +266,30 @@ void InitializeCPUContextARM64_OnlyFPSIMD(
   context->fpcr = float_context.fpcr;
 }
 
+#elif defined(ARCH_CPU_RISCV_FAMILY)
+
+template <typename Traits>
+void InitializeCPUContextRISCV(
+    const typename Traits::SignalThreadContext& thread_context,
+    const typename Traits::SignalFloatContext& float_context,
+    typename Traits::CPUContext* context) {
+  static_assert(sizeof(context->regs) == sizeof(thread_context),
+                "registers size mismatch");
+  static_assert(sizeof(context->fpregs) == sizeof(float_context.f),
+                "fp registers size mismatch");
+  memcpy(&context->regs, &thread_context, sizeof(context->regs));
+  memcpy(&context->fpregs, &float_context, sizeof(context->fpregs));
+  context->fcsr = float_context.fcsr;
+}
+template void InitializeCPUContextRISCV<ContextTraits32>(
+    const ContextTraits32::SignalThreadContext& thread_context,
+    const ContextTraits32::SignalFloatContext& float_context,
+    ContextTraits32::CPUContext* context);
+template void InitializeCPUContextRISCV<ContextTraits64>(
+    const ContextTraits64::SignalThreadContext& thread_context,
+    const ContextTraits64::SignalFloatContext& float_context,
+    ContextTraits64::CPUContext* context);
+
 #endif  // ARCH_CPU_X86_FAMILY
 
 }  // namespace internal

+ 16 - 0
third_party/crashpad/crashpad/snapshot/linux/cpu_context_linux.h

@@ -174,6 +174,22 @@ void InitializeCPUContextMIPS(
 
 #endif  // ARCH_CPU_MIPS_FAMILY || DOXYGEN
 
+#if defined(ARCH_CPU_RISCV_FAMILY) || DOXYGEN
+
+//! \brief Initializes a CPUContextRISCV structure from native context
+//!     structures on Linux.
+//!
+//! \param[in] thread_context The native thread context.
+//! \param[in] float_context The native float context.
+//! \param[out] context The CPUContextRISCV structure to initialize.
+template <typename Traits>
+void InitializeCPUContextRISCV(
+    const typename Traits::SignalThreadContext& thread_context,
+    const typename Traits::SignalFloatContext& float_context,
+    typename Traits::CPUContext* context);
+
+#endif  // ARCH_CPU_RISCV_FAMILY || DOXYGEN
+
 }  // namespace internal
 }  // namespace crashpad
 

+ 54 - 0
third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.cc

@@ -324,6 +324,60 @@ bool ExceptionSnapshotLinux::ReadContext<ContextTraits64>(
   return internal::ReadContext<ContextTraits64>(
       reader, context_address, context_.mips64);
 }
+#elif defined(ARCH_CPU_RISCV_FAMILY)
+
+template <typename Traits>
+static bool ReadContext(ProcessReaderLinux* reader,
+                        LinuxVMAddress context_address,
+                        typename Traits::CPUContext* dest_context) {
+  const ProcessMemory* memory = reader->Memory();
+
+  LinuxVMAddress gregs_address = context_address +
+                                 offsetof(UContext<Traits>, mcontext) +
+                                 offsetof(typename Traits::MContext, gregs);
+
+  typename Traits::SignalThreadContext thread_context;
+  if (!memory->Read(gregs_address, sizeof(thread_context), &thread_context)) {
+    LOG(ERROR) << "Couldn't read gregs";
+    return false;
+  }
+
+  LinuxVMAddress fpregs_address = context_address +
+                                  offsetof(UContext<Traits>, mcontext) +
+                                  offsetof(typename Traits::MContext, fpregs);
+
+  typename Traits::SignalFloatContext fp_context;
+  if (!memory->Read(fpregs_address, sizeof(fp_context), &fp_context)) {
+    LOG(ERROR) << "Couldn't read fpregs";
+    return false;
+  }
+
+  InitializeCPUContextRISCV<Traits>(thread_context, fp_context, dest_context);
+
+  return true;
+}
+
+template <>
+bool ExceptionSnapshotLinux::ReadContext<ContextTraits32>(
+    ProcessReaderLinux* reader,
+    LinuxVMAddress context_address) {
+  context_.architecture = kCPUArchitectureRISCV;
+  context_.riscv = &context_union_.riscv;
+
+  return internal::ReadContext<ContextTraits32>(
+      reader, context_address, context_.riscv);
+}
+
+template <>
+bool ExceptionSnapshotLinux::ReadContext<ContextTraits64>(
+    ProcessReaderLinux* reader,
+    LinuxVMAddress context_address) {
+  context_.architecture = kCPUArchitectureRISCV64;
+  context_.riscv64 = &context_union_.riscv64;
+
+  return internal::ReadContext<ContextTraits64>(
+      reader, context_address, context_.riscv64);
+}
 
 #endif  // ARCH_CPU_X86_FAMILY
 

+ 3 - 0
third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.h

@@ -89,6 +89,9 @@ class ExceptionSnapshotLinux final : public ExceptionSnapshot {
 #elif defined(ARCH_CPU_MIPS_FAMILY)
     CPUContextMIPS mipsel;
     CPUContextMIPS64 mips64;
+#elif defined(ARCH_CPU_RISCV_FAMILY)
+    CPUContextRISCV riscv;
+    CPUContextRISCV64 riscv64;
 #endif
   } context_union_;
   CPUContext context_;

+ 3 - 0
third_party/crashpad/crashpad/snapshot/linux/process_reader_linux.cc

@@ -127,6 +127,9 @@ void ProcessReaderLinux::Thread::InitializeStack(ProcessReaderLinux* reader) {
 #elif defined(ARCH_CPU_MIPS_FAMILY)
   stack_pointer = reader->Is64Bit() ? thread_info.thread_context.t64.regs[29]
                                     : thread_info.thread_context.t32.regs[29];
+#elif defined(ARCH_CPU_RISCV_FAMILY)
+  stack_pointer = reader->Is64Bit() ? thread_info.thread_context.t64.sp
+	                            : thread_info.thread_context.t32.sp;
 #else
 #error Port.
 #endif

+ 60 - 0
third_party/crashpad/crashpad/snapshot/linux/signal_context.h

@@ -421,6 +421,66 @@ static_assert(offsetof(UContext<ContextTraits64>, mcontext.fpregs) ==
                   offsetof(ucontext_t, uc_mcontext.fpregs),
               "context offset mismatch");
 #endif
+#elif defined(ARCH_CPU_RISCV_FAMILY)
+
+struct MContext32 {
+  uint32_t gregs[32];
+  uint64_t fpregs[32];
+  unsigned int fcsr;
+};
+
+struct MContext64 {
+  uint64_t gregs[32];
+  uint64_t fpregs[32];
+  unsigned int fcsr;
+};
+
+struct ContextTraits32 : public Traits32 {
+  using MContext = MContext32;
+  using SignalThreadContext = ThreadContext::t32_t;
+  using SignalFloatContext = FloatContext::f32_t;
+  using CPUContext = CPUContextRISCV;
+};
+
+struct ContextTraits64 : public Traits64 {
+  using MContext = MContext64;
+  using SignalThreadContext = ThreadContext::t64_t;
+  using SignalFloatContext = FloatContext::f64_t;
+  using CPUContext = CPUContextRISCV64;
+};
+
+template <typename Traits>
+struct UContext {
+  typename Traits::ULong flags;
+  typename Traits::Address link;
+  SignalStack<Traits> stack;
+  Sigset<Traits> sigmask;
+  char padding[128 - sizeof(sigmask)];
+  typename Traits::Char_64Only padding2[8];
+  typename Traits::MContext mcontext;
+};
+
+#if defined(ARCH_CPU_RISCV)
+static_assert(offsetof(UContext<ContextTraits32>, mcontext) ==
+                  offsetof(ucontext_t, uc_mcontext),
+              "context offset mismatch");
+static_assert(offsetof(UContext<ContextTraits32>, mcontext.gregs) ==
+                  offsetof(ucontext_t, uc_mcontext.__gregs),
+              "context offset mismatch");
+static_assert(offsetof(UContext<ContextTraits32>, mcontext.fpregs) ==
+                  offsetof(ucontext_t, uc_mcontext.__fpregs),
+              "context offset mismatch");
+#elif defined(ARCH_CPU_RISCV64)
+static_assert(offsetof(UContext<ContextTraits64>, mcontext) ==
+                  offsetof(ucontext_t, uc_mcontext),
+              "context offset mismatch");
+static_assert(offsetof(UContext<ContextTraits64>, mcontext.gregs) ==
+                  offsetof(ucontext_t, uc_mcontext.__gregs),
+              "context offset mismatch");
+static_assert(offsetof(UContext<ContextTraits64>, mcontext.fpregs) ==
+                  offsetof(ucontext_t, uc_mcontext.__fpregs),
+              "context offset mismatch");
+#endif
 
 #else
 #error Port.

+ 12 - 0
third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.cc

@@ -205,6 +205,9 @@ CPUArchitecture SystemSnapshotLinux::GetCPUArchitecture() const {
 #elif defined(ARCH_CPU_MIPS_FAMILY)
   return process_reader_->Is64Bit() ? kCPUArchitectureMIPS64EL
                                     : kCPUArchitectureMIPSEL;
+#elif defined(ARCH_CPU_RISCV_FAMILY)
+  return process_reader_->Is64Bit() ? kCPUArchitectureRISCV64
+	                            : kCPUArchitectureRISCV;
 #else
 #error port to your architecture
 #endif
@@ -220,6 +223,9 @@ uint32_t SystemSnapshotLinux::CPURevision() const {
 #elif defined(ARCH_CPU_MIPS_FAMILY)
   // Not implementable on MIPS
   return 0;
+#elif defined(ARCH_CPU_RISCV_FAMILY)
+  // Not implementable on RISCV
+  return 0;
 #else
 #error port to your architecture
 #endif
@@ -240,6 +246,9 @@ std::string SystemSnapshotLinux::CPUVendor() const {
 #elif defined(ARCH_CPU_MIPS_FAMILY)
   // Not implementable on MIPS
   return std::string();
+#elif defined(ARCH_CPU_RISCV_FAMILY)
+  // Not implementable on RISCV
+  return std::string();
 #else
 #error port to your architecture
 #endif
@@ -373,6 +382,9 @@ bool SystemSnapshotLinux::NXEnabled() const {
 #elif defined(ARCH_CPU_MIPS_FAMILY)
   // Not implementable on MIPS
   return false;
+#elif defined(ARCH_CPU_RISCV_FAMILY)
+  // Not implementable on RISCV
+  return false;
 #else
 #error Port.
 #endif  // ARCH_CPU_X86_FAMILY

+ 16 - 0
third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.cc

@@ -190,6 +190,22 @@ bool ThreadSnapshotLinux::Initialize(
         thread.thread_info.float_context.f32,
         context_.mipsel);
   }
+#elif defined(ARCH_CPU_RISCV_FAMILY)
+  if (process_reader->Is64Bit()) {
+    context_.architecture = kCPUArchitectureRISCV64;
+    context_.riscv64 = &context_union_.riscv64;
+    InitializeCPUContextRISCV<ContextTraits64>(
+	thread.thread_info.thread_context.t64,
+	thread.thread_info.float_context.f64,
+	context_.riscv64);
+  } else {
+    context_.architecture = kCPUArchitectureRISCV;
+    context_.riscv = &context_union_.riscv;
+    InitializeCPUContextRISCV<ContextTraits32>(
+	thread.thread_info.thread_context.t32,
+	thread.thread_info.float_context.f32,
+	context_.riscv);
+  }
 #else
 #error Port.
 #endif

+ 3 - 0
third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.h

@@ -74,6 +74,9 @@ class ThreadSnapshotLinux final : public ThreadSnapshot {
 #elif defined(ARCH_CPU_MIPS_FAMILY)
     CPUContextMIPS mipsel;
     CPUContextMIPS64 mips64;
+#elif defined(ARCH_CPU_RISCV_FAMILY)
+    CPUContextRISCV riscv;
+    CPUContextRISCV64 riscv64;
 #else
 #error Port.
 #endif  // ARCH_CPU_X86_FAMILY

+ 44 - 0
third_party/crashpad/crashpad/util/linux/ptracer.cc

@@ -397,6 +397,50 @@ bool GetThreadArea64(pid_t tid,
   *address = FromPointerCast<LinuxVMAddress>(result);
   return true;
 }
+#elif defined(ARCH_CPU_RISCV_FAMILY)
+
+template <typename Destination>
+bool GetRegisterSet(pid_t tid, int set, Destination* dest, bool can_log) {
+  iovec iov;
+  iov.iov_base = dest;
+  iov.iov_len = sizeof(*dest);
+  if (ptrace(PTRACE_GETREGSET, tid, reinterpret_cast<void*>(set), &iov) != 0) {
+    PLOG_IF(ERROR, can_log) << "ptrace";
+    return false;
+  }
+  if (iov.iov_len != sizeof(*dest)) {
+    LOG_IF(ERROR, can_log) << "Unexpected registers size";
+    return false;
+  }
+  return true;
+}
+
+bool GetFloatingPointRegisters32(pid_t tid,
+                                 FloatContext* context,
+                                 bool can_log) {
+  return false;
+}
+
+bool GetFloatingPointRegisters64(pid_t tid,
+                                 FloatContext* context,
+                                 bool can_log) {
+  return GetRegisterSet(tid, NT_PRFPREG, &context->f64.f, can_log);
+}
+
+bool GetThreadArea32(pid_t tid,
+                     const ThreadContext& context,
+                     LinuxVMAddress* address,
+                     bool can_log) {
+  return false;
+}
+
+bool GetThreadArea64(pid_t tid,
+                     const ThreadContext& context,
+                     LinuxVMAddress* address,
+                     bool can_log) {
+  *address = context.t64.tp;
+  return true;
+}
 
 #else
 #error Port.

+ 77 - 1
third_party/crashpad/crashpad/util/linux/thread_info.h

@@ -79,6 +79,40 @@ union ThreadContext {
     uint32_t cp0_status;
     uint32_t cp0_cause;
     uint32_t padding1_;
+#elif defined(ARCH_CPU_RISCV_FAMILY)
+    // Reflects user_regs_struct in asm/ptrace.h.
+    uint32_t pc;
+    uint32_t ra;
+    uint32_t sp;
+    uint32_t gp;
+    uint32_t tp;
+    uint32_t t0;
+    uint32_t t1;
+    uint32_t t2;
+    uint32_t s0;
+    uint32_t s1;
+    uint32_t a0;
+    uint32_t a1;
+    uint32_t a2;
+    uint32_t a3;
+    uint32_t a4;
+    uint32_t a5;
+    uint32_t a6;
+    uint32_t a7;
+    uint32_t s2;
+    uint32_t s3;
+    uint32_t s4;
+    uint32_t s5;
+    uint32_t s6;
+    uint32_t s7;
+    uint32_t s8;
+    uint32_t s9;
+    uint32_t s10;
+    uint32_t s11;
+    uint32_t t3;
+    uint32_t t4;
+    uint32_t t5;
+    uint32_t t6;
 #else
 #error Port.
 #endif  // ARCH_CPU_X86_FAMILY
@@ -132,6 +166,40 @@ union ThreadContext {
     uint64_t cp0_badvaddr;
     uint64_t cp0_status;
     uint64_t cp0_cause;
+#elif defined(ARCH_CPU_RISCV_FAMILY)
+    // Reflects user_regs_struct in asm/ptrace.h.
+    uint64_t pc;
+    uint64_t ra;
+    uint64_t sp;
+    uint64_t gp;
+    uint64_t tp;
+    uint64_t t0;
+    uint64_t t1;
+    uint64_t t2;
+    uint64_t s0;
+    uint64_t s1;
+    uint64_t a0;
+    uint64_t a1;
+    uint64_t a2;
+    uint64_t a3;
+    uint64_t a4;
+    uint64_t a5;
+    uint64_t a6;
+    uint64_t a7;
+    uint64_t s2;
+    uint64_t s3;
+    uint64_t s4;
+    uint64_t s5;
+    uint64_t s6;
+    uint64_t s7;
+    uint64_t s8;
+    uint64_t s9;
+    uint64_t s10;
+    uint64_t s11;
+    uint64_t t3;
+    uint64_t t4;
+    uint64_t t5;
+    uint64_t t6;
 #else
 #error Port.
 #endif  // ARCH_CPU_X86_FAMILY
@@ -143,11 +211,12 @@ union ThreadContext {
   using NativeThreadContext = user_regs;
 #elif defined(ARCH_CPU_MIPS_FAMILY)
 // No appropriate NativeThreadsContext type available for MIPS
+#elif defined(ARCH_CPU_RISCV_FAMILY)
 #else
 #error Port.
 #endif  // ARCH_CPU_X86_FAMILY || ARCH_CPU_ARM64
 
-#if !defined(ARCH_CPU_MIPS_FAMILY)
+#if !defined(ARCH_CPU_MIPS_FAMILY) && !defined(ARCH_CPU_RISCV_FAMILY)
 #if defined(ARCH_CPU_32_BITS)
   static_assert(sizeof(t32_t) == sizeof(NativeThreadContext), "Size mismatch");
 #else  // ARCH_CPU_64_BITS
@@ -218,6 +287,9 @@ union FloatContext {
     } fpregs[32];
     uint32_t fpcsr;
     uint32_t fpu_id;
+#elif defined(ARCH_CPU_RISCV_FAMILY)
+    uint64_t f[32];
+    uint32_t fcsr;
 #else
 #error Port.
 #endif  // ARCH_CPU_X86_FAMILY
@@ -252,6 +324,9 @@ union FloatContext {
     double fpregs[32];
     uint32_t fpcsr;
     uint32_t fpu_id;
+#elif defined(ARCH_CPU_RISCV_FAMILY)
+    uint64_t f[32];
+    uint32_t fcsr;
 #else
 #error Port.
 #endif  // ARCH_CPU_X86_FAMILY
@@ -281,6 +356,7 @@ union FloatContext {
   static_assert(sizeof(f64) == sizeof(user_fpsimd_struct), "Size mismatch");
 #elif defined(ARCH_CPU_MIPS_FAMILY)
 // No appropriate floating point context native type for available MIPS.
+#elif defined(ARCH_CPU_RISCV_FAMILY)
 #else
 #error Port.
 #endif  // ARCH_CPU_X86

+ 2 - 0
third_party/crashpad/crashpad/util/net/http_transport_libcurl.cc

@@ -237,6 +237,8 @@ std::string UserAgent() {
 #elif defined(ARCH_CPU_BIG_ENDIAN)
     static constexpr char arch[] = "aarch64_be";
 #endif
+#elif defined(ARCH_CPU_RISCV64)
+    static constexpr char arch[] = "riscv64";
 #else
 #error Port
 #endif