[Lldb-commits] [lldb] 49b3c33 - [lldb][x86_64] Support fs_base/gs_base register in Linux

Jeffrey Tan via lldb-commits lldb-commits at lists.llvm.org
Thu Jul 20 16:32:56 PDT 2023


Author: Jeffrey Tan
Date: 2023-07-20T16:32:47-07:00
New Revision: 49b3c3355f9c36a023e04bba509ac89d15da6ff9

URL: https://github.com/llvm/llvm-project/commit/49b3c3355f9c36a023e04bba509ac89d15da6ff9
DIFF: https://github.com/llvm/llvm-project/commit/49b3c3355f9c36a023e04bba509ac89d15da6ff9.diff

LOG: [lldb][x86_64] Support fs_base/gs_base register in Linux

Summary:
[lldb][x86_64] This patch adds fs_base/gs_base support for Linux x86_64.

Originally, I plan to split the diff into two parts, one to refactoring lldb_xxx_x86_64 => x86_64::lldb_xxx across code base and the other one for adding fs_base/gs_base, but it turns out to be a non-trivial effort to split and very error prone so I decided to keep a single diff to get feedback.

GDB supports fs_base/gs_base registers while LLDB does not. Since both linux coredump note section and ptrace
supports them it is a missing feature.

For context, this is a required feature to support getting pthread pointer on linux from both live and dump debugging.
See thread below for details:
https://discourse.llvm.org/t/how-to-get-pthread-pointer-from-lldb/70542/2?u=jeffreytan81

Implementation wise, we have initially tried `#ifdef` approach to reuse the code but it is introducing very tricky bugs and proves
hard to maintain. Instead the diff completely separates the registers between x86_64 and x86_64_with_base so that non-linux related
implementations can use x86_64 registers while linux uses x86_64_with_base.
Here are the list of changes done in the patch:
* Registers in lldb-x86-register-enums.h are separated into two: x86_64 and x86_64_with_base
* fs_base/gs_base are added into x86_64_with_base
* All linux files are change to use x86_64::lldb_xxx => x86_64_with_base::lldb_xxx
* Support linux elf-core:
	* A new RegisterContextLinuxCore_x86_64 class is added for ThreadElfCore
	* RegisterContextLinuxCore_x86_64 overrides and uses its own register set supports fs_base/gs_base
	* RegisterInfos_x86_64_with_base/RegisterInfos_x86_64_with_base_shared ared added to provide g_contained_XXX/g_invalidate_XXX and RegInfo related code sharing.
* `RegisterContextPOSIX_x86 ::m_gpr_x86_64` seems to be unused so I removed it.
* `NativeRegisterContextDBReg_x86::GetDR()` is overridden in `NativeRegisterContextLinux_x86_64` to make watchpoint work.

Reviewers:clayborg,labath,jingham,jdoerfert,JDevlieghere,kusmour,GeorgeHuyubo

Subscribers:

Tasks:

Tags:

Differential Revision: https://reviews.llvm.org/D155256

Added: 
    lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64_with_base.h
    lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64_with_base_shared.cpp
    lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64_with_base_shared.h
    lldb/source/Plugins/Process/elf-core/RegisterContextLinuxCore_x86_64.cpp
    lldb/source/Plugins/Process/elf-core/RegisterContextLinuxCore_x86_64.h

Modified: 
    lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
    lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
    lldb/source/Plugins/Process/Utility/CMakeLists.txt
    lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.h
    lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp
    lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
    lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h
    lldb/source/Plugins/Process/Utility/RegisterContext_x86.h
    lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h
    lldb/source/Plugins/Process/elf-core/CMakeLists.txt
    lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
    lldb/test/API/commands/register/register/register_command/TestRegisters.py
    lldb/test/API/functionalities/postmortem/elf-core/thread_crash/TestLinuxCoreThreads.py

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
index e81ef3301f1f13..f0e295b5900867 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
@@ -100,96 +100,97 @@ static_assert((sizeof(g_mpx_regnums_i386) / sizeof(g_mpx_regnums_i386[0])) -
 
 // x86 64-bit general purpose registers.
 static const uint32_t g_gpr_regnums_x86_64[] = {
-    lldb_rax_x86_64,    lldb_rbx_x86_64,    lldb_rcx_x86_64, lldb_rdx_x86_64,
-    lldb_rdi_x86_64,    lldb_rsi_x86_64,    lldb_rbp_x86_64, lldb_rsp_x86_64,
-    lldb_r8_x86_64,     lldb_r9_x86_64,     lldb_r10_x86_64, lldb_r11_x86_64,
-    lldb_r12_x86_64,    lldb_r13_x86_64,    lldb_r14_x86_64, lldb_r15_x86_64,
-    lldb_rip_x86_64,    lldb_rflags_x86_64, lldb_cs_x86_64,  lldb_fs_x86_64,
-    lldb_gs_x86_64,     lldb_ss_x86_64,     lldb_ds_x86_64,  lldb_es_x86_64,
-    lldb_eax_x86_64,    lldb_ebx_x86_64,    lldb_ecx_x86_64, lldb_edx_x86_64,
-    lldb_edi_x86_64,    lldb_esi_x86_64,    lldb_ebp_x86_64, lldb_esp_x86_64,
-    lldb_r8d_x86_64,  // Low 32 bits or r8
-    lldb_r9d_x86_64,  // Low 32 bits or r9
-    lldb_r10d_x86_64, // Low 32 bits or r10
-    lldb_r11d_x86_64, // Low 32 bits or r11
-    lldb_r12d_x86_64, // Low 32 bits or r12
-    lldb_r13d_x86_64, // Low 32 bits or r13
-    lldb_r14d_x86_64, // Low 32 bits or r14
-    lldb_r15d_x86_64, // Low 32 bits or r15
-    lldb_ax_x86_64,     lldb_bx_x86_64,     lldb_cx_x86_64,  lldb_dx_x86_64,
-    lldb_di_x86_64,     lldb_si_x86_64,     lldb_bp_x86_64,  lldb_sp_x86_64,
-    lldb_r8w_x86_64,  // Low 16 bits or r8
-    lldb_r9w_x86_64,  // Low 16 bits or r9
-    lldb_r10w_x86_64, // Low 16 bits or r10
-    lldb_r11w_x86_64, // Low 16 bits or r11
-    lldb_r12w_x86_64, // Low 16 bits or r12
-    lldb_r13w_x86_64, // Low 16 bits or r13
-    lldb_r14w_x86_64, // Low 16 bits or r14
-    lldb_r15w_x86_64, // Low 16 bits or r15
-    lldb_ah_x86_64,     lldb_bh_x86_64,     lldb_ch_x86_64,  lldb_dh_x86_64,
-    lldb_al_x86_64,     lldb_bl_x86_64,     lldb_cl_x86_64,  lldb_dl_x86_64,
-    lldb_dil_x86_64,    lldb_sil_x86_64,    lldb_bpl_x86_64, lldb_spl_x86_64,
-    lldb_r8l_x86_64,    // Low 8 bits or r8
-    lldb_r9l_x86_64,    // Low 8 bits or r9
-    lldb_r10l_x86_64,   // Low 8 bits or r10
-    lldb_r11l_x86_64,   // Low 8 bits or r11
-    lldb_r12l_x86_64,   // Low 8 bits or r12
-    lldb_r13l_x86_64,   // Low 8 bits or r13
-    lldb_r14l_x86_64,   // Low 8 bits or r14
-    lldb_r15l_x86_64,   // Low 8 bits or r15
+    x86_64_with_base::lldb_rax,    x86_64_with_base::lldb_rbx,    x86_64_with_base::lldb_rcx, x86_64_with_base::lldb_rdx,
+    x86_64_with_base::lldb_rdi,    x86_64_with_base::lldb_rsi,    x86_64_with_base::lldb_rbp, x86_64_with_base::lldb_rsp,
+    x86_64_with_base::lldb_r8,     x86_64_with_base::lldb_r9,     x86_64_with_base::lldb_r10, x86_64_with_base::lldb_r11,
+    x86_64_with_base::lldb_r12,    x86_64_with_base::lldb_r13,    x86_64_with_base::lldb_r14, x86_64_with_base::lldb_r15,
+    x86_64_with_base::lldb_rip,    x86_64_with_base::lldb_rflags, x86_64_with_base::lldb_cs,  x86_64_with_base::lldb_fs,
+    x86_64_with_base::lldb_gs,     x86_64_with_base::lldb_ss,     x86_64_with_base::lldb_fs_base, x86_64_with_base::lldb_gs_base,
+    x86_64_with_base::lldb_ds,  x86_64_with_base::lldb_es,
+    x86_64_with_base::lldb_eax,    x86_64_with_base::lldb_ebx,    x86_64_with_base::lldb_ecx, x86_64_with_base::lldb_edx,
+    x86_64_with_base::lldb_edi,    x86_64_with_base::lldb_esi,    x86_64_with_base::lldb_ebp, x86_64_with_base::lldb_esp,
+    x86_64_with_base::lldb_r8d,  // Low 32 bits or r8
+    x86_64_with_base::lldb_r9d,  // Low 32 bits or r9
+    x86_64_with_base::lldb_r10d, // Low 32 bits or r10
+    x86_64_with_base::lldb_r11d, // Low 32 bits or r11
+    x86_64_with_base::lldb_r12d, // Low 32 bits or r12
+    x86_64_with_base::lldb_r13d, // Low 32 bits or r13
+    x86_64_with_base::lldb_r14d, // Low 32 bits or r14
+    x86_64_with_base::lldb_r15d, // Low 32 bits or r15
+    x86_64_with_base::lldb_ax,     x86_64_with_base::lldb_bx,     x86_64_with_base::lldb_cx,  x86_64_with_base::lldb_dx,
+    x86_64_with_base::lldb_di,     x86_64_with_base::lldb_si,     x86_64_with_base::lldb_bp,  x86_64_with_base::lldb_sp,
+    x86_64_with_base::lldb_r8w,  // Low 16 bits or r8
+    x86_64_with_base::lldb_r9w,  // Low 16 bits or r9
+    x86_64_with_base::lldb_r10w, // Low 16 bits or r10
+    x86_64_with_base::lldb_r11w, // Low 16 bits or r11
+    x86_64_with_base::lldb_r12w, // Low 16 bits or r12
+    x86_64_with_base::lldb_r13w, // Low 16 bits or r13
+    x86_64_with_base::lldb_r14w, // Low 16 bits or r14
+    x86_64_with_base::lldb_r15w, // Low 16 bits or r15
+    x86_64_with_base::lldb_ah,     x86_64_with_base::lldb_bh,     x86_64_with_base::lldb_ch,  x86_64_with_base::lldb_dh,
+    x86_64_with_base::lldb_al,     x86_64_with_base::lldb_bl,     x86_64_with_base::lldb_cl,  x86_64_with_base::lldb_dl,
+    x86_64_with_base::lldb_dil,    x86_64_with_base::lldb_sil,    x86_64_with_base::lldb_bpl, x86_64_with_base::lldb_spl,
+    x86_64_with_base::lldb_r8l,    // Low 8 bits or r8
+    x86_64_with_base::lldb_r9l,    // Low 8 bits or r9
+    x86_64_with_base::lldb_r10l,   // Low 8 bits or r10
+    x86_64_with_base::lldb_r11l,   // Low 8 bits or r11
+    x86_64_with_base::lldb_r12l,   // Low 8 bits or r12
+    x86_64_with_base::lldb_r13l,   // Low 8 bits or r13
+    x86_64_with_base::lldb_r14l,   // Low 8 bits or r14
+    x86_64_with_base::lldb_r15l,   // Low 8 bits or r15
     LLDB_INVALID_REGNUM // register sets need to end with this flag
 };
 static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) -
                       1 ==
-                  k_num_gpr_registers_x86_64,
+                  x86_64_with_base::k_num_gpr_registers,
               "g_gpr_regnums_x86_64 has wrong number of register infos");
 
 // x86 64-bit floating point registers.
 static const uint32_t g_fpu_regnums_x86_64[] = {
-    lldb_fctrl_x86_64,  lldb_fstat_x86_64, lldb_ftag_x86_64,
-    lldb_fop_x86_64,    lldb_fiseg_x86_64, lldb_fioff_x86_64,
-    lldb_fip_x86_64,    lldb_foseg_x86_64, lldb_fooff_x86_64,
-    lldb_fdp_x86_64,    lldb_mxcsr_x86_64, lldb_mxcsrmask_x86_64,
-    lldb_st0_x86_64,    lldb_st1_x86_64,   lldb_st2_x86_64,
-    lldb_st3_x86_64,    lldb_st4_x86_64,   lldb_st5_x86_64,
-    lldb_st6_x86_64,    lldb_st7_x86_64,   lldb_mm0_x86_64,
-    lldb_mm1_x86_64,    lldb_mm2_x86_64,   lldb_mm3_x86_64,
-    lldb_mm4_x86_64,    lldb_mm5_x86_64,   lldb_mm6_x86_64,
-    lldb_mm7_x86_64,    lldb_xmm0_x86_64,  lldb_xmm1_x86_64,
-    lldb_xmm2_x86_64,   lldb_xmm3_x86_64,  lldb_xmm4_x86_64,
-    lldb_xmm5_x86_64,   lldb_xmm6_x86_64,  lldb_xmm7_x86_64,
-    lldb_xmm8_x86_64,   lldb_xmm9_x86_64,  lldb_xmm10_x86_64,
-    lldb_xmm11_x86_64,  lldb_xmm12_x86_64, lldb_xmm13_x86_64,
-    lldb_xmm14_x86_64,  lldb_xmm15_x86_64,
+    x86_64_with_base::lldb_fctrl,  x86_64_with_base::lldb_fstat, x86_64_with_base::lldb_ftag,
+    x86_64_with_base::lldb_fop,    x86_64_with_base::lldb_fiseg, x86_64_with_base::lldb_fioff,
+    x86_64_with_base::lldb_fip,    x86_64_with_base::lldb_foseg, x86_64_with_base::lldb_fooff,
+    x86_64_with_base::lldb_fdp,    x86_64_with_base::lldb_mxcsr, x86_64_with_base::lldb_mxcsrmask,
+    x86_64_with_base::lldb_st0,    x86_64_with_base::lldb_st1,   x86_64_with_base::lldb_st2,
+    x86_64_with_base::lldb_st3,    x86_64_with_base::lldb_st4,   x86_64_with_base::lldb_st5,
+    x86_64_with_base::lldb_st6,    x86_64_with_base::lldb_st7,   x86_64_with_base::lldb_mm0,
+    x86_64_with_base::lldb_mm1,    x86_64_with_base::lldb_mm2,   x86_64_with_base::lldb_mm3,
+    x86_64_with_base::lldb_mm4,    x86_64_with_base::lldb_mm5,   x86_64_with_base::lldb_mm6,
+    x86_64_with_base::lldb_mm7,    x86_64_with_base::lldb_xmm0,  x86_64_with_base::lldb_xmm1,
+    x86_64_with_base::lldb_xmm2,   x86_64_with_base::lldb_xmm3,  x86_64_with_base::lldb_xmm4,
+    x86_64_with_base::lldb_xmm5,   x86_64_with_base::lldb_xmm6,  x86_64_with_base::lldb_xmm7,
+    x86_64_with_base::lldb_xmm8,   x86_64_with_base::lldb_xmm9,  x86_64_with_base::lldb_xmm10,
+    x86_64_with_base::lldb_xmm11,  x86_64_with_base::lldb_xmm12, x86_64_with_base::lldb_xmm13,
+    x86_64_with_base::lldb_xmm14,  x86_64_with_base::lldb_xmm15,
     LLDB_INVALID_REGNUM // register sets need to end with this flag
 };
 static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) -
                       1 ==
-                  k_num_fpr_registers_x86_64,
+                  x86_64_with_base::k_num_fpr_registers,
               "g_fpu_regnums_x86_64 has wrong number of register infos");
 
 // x86 64-bit AVX registers.
 static const uint32_t g_avx_regnums_x86_64[] = {
-    lldb_ymm0_x86_64,   lldb_ymm1_x86_64,  lldb_ymm2_x86_64,  lldb_ymm3_x86_64,
-    lldb_ymm4_x86_64,   lldb_ymm5_x86_64,  lldb_ymm6_x86_64,  lldb_ymm7_x86_64,
-    lldb_ymm8_x86_64,   lldb_ymm9_x86_64,  lldb_ymm10_x86_64, lldb_ymm11_x86_64,
-    lldb_ymm12_x86_64,  lldb_ymm13_x86_64, lldb_ymm14_x86_64, lldb_ymm15_x86_64,
+    x86_64_with_base::lldb_ymm0,   x86_64_with_base::lldb_ymm1,  x86_64_with_base::lldb_ymm2,  x86_64_with_base::lldb_ymm3,
+    x86_64_with_base::lldb_ymm4,   x86_64_with_base::lldb_ymm5,  x86_64_with_base::lldb_ymm6,  x86_64_with_base::lldb_ymm7,
+    x86_64_with_base::lldb_ymm8,   x86_64_with_base::lldb_ymm9,  x86_64_with_base::lldb_ymm10, x86_64_with_base::lldb_ymm11,
+    x86_64_with_base::lldb_ymm12,  x86_64_with_base::lldb_ymm13, x86_64_with_base::lldb_ymm14, x86_64_with_base::lldb_ymm15,
     LLDB_INVALID_REGNUM // register sets need to end with this flag
 };
 static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) -
                       1 ==
-                  k_num_avx_registers_x86_64,
+                  x86_64_with_base::k_num_avx_registers,
               "g_avx_regnums_x86_64 has wrong number of register infos");
 
 // x86 64-bit MPX registers.
 static const uint32_t g_mpx_regnums_x86_64[] = {
-    lldb_bnd0_x86_64,    lldb_bnd1_x86_64,    lldb_bnd2_x86_64,
-    lldb_bnd3_x86_64,    lldb_bndcfgu_x86_64, lldb_bndstatus_x86_64,
+    x86_64_with_base::lldb_bnd0,    x86_64_with_base::lldb_bnd1,    x86_64_with_base::lldb_bnd2,
+    x86_64_with_base::lldb_bnd3,    x86_64_with_base::lldb_bndcfgu, x86_64_with_base::lldb_bndstatus,
     LLDB_INVALID_REGNUM // register sets need to end with this flag
 };
 static_assert((sizeof(g_mpx_regnums_x86_64) / sizeof(g_mpx_regnums_x86_64[0])) -
                       1 ==
-                  k_num_mpx_registers_x86_64,
+                  x86_64_with_base::k_num_mpx_registers,
               "g_mpx_regnums_x86_64 has wrong number of register infos");
 
 // Number of register sets provided by this context.
@@ -208,13 +209,13 @@ static const RegisterSet g_reg_sets_i386[k_num_register_sets] = {
 
 // Register sets for x86 64-bit.
 static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = {
-    {"General Purpose Registers", "gpr", k_num_gpr_registers_x86_64,
+    {"General Purpose Registers", "gpr", x86_64_with_base::k_num_gpr_registers,
      g_gpr_regnums_x86_64},
-    {"Floating Point Registers", "fpu", k_num_fpr_registers_x86_64,
+    {"Floating Point Registers", "fpu", x86_64_with_base::k_num_fpr_registers,
      g_fpu_regnums_x86_64},
-    {"Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64,
+    {"Advanced Vector Extensions", "avx", x86_64_with_base::k_num_avx_registers,
      g_avx_regnums_x86_64},
-    { "Memory Protection Extensions", "mpx", k_num_mpx_registers_x86_64,
+    { "Memory Protection Extensions", "mpx", x86_64_with_base::k_num_mpx_registers,
      g_mpx_regnums_x86_64}};
 
 #define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize() + sizeof(FPR))
@@ -330,29 +331,29 @@ NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64(
     m_reg_info.gpr_flags = lldb_eflags_i386;
     break;
   case llvm::Triple::x86_64:
-    m_reg_info.num_registers = k_num_registers_x86_64;
-    m_reg_info.num_gpr_registers = k_num_gpr_registers_x86_64;
-    m_reg_info.num_fpr_registers = k_num_fpr_registers_x86_64;
-    m_reg_info.num_avx_registers = k_num_avx_registers_x86_64;
-    m_reg_info.num_mpx_registers = k_num_mpx_registers_x86_64;
-    m_reg_info.last_gpr = k_last_gpr_x86_64;
-    m_reg_info.first_fpr = k_first_fpr_x86_64;
-    m_reg_info.last_fpr = k_last_fpr_x86_64;
-    m_reg_info.first_st = lldb_st0_x86_64;
-    m_reg_info.last_st = lldb_st7_x86_64;
-    m_reg_info.first_mm = lldb_mm0_x86_64;
-    m_reg_info.last_mm = lldb_mm7_x86_64;
-    m_reg_info.first_xmm = lldb_xmm0_x86_64;
-    m_reg_info.last_xmm = lldb_xmm15_x86_64;
-    m_reg_info.first_ymm = lldb_ymm0_x86_64;
-    m_reg_info.last_ymm = lldb_ymm15_x86_64;
-    m_reg_info.first_mpxr = lldb_bnd0_x86_64;
-    m_reg_info.last_mpxr = lldb_bnd3_x86_64;
-    m_reg_info.first_mpxc = lldb_bndcfgu_x86_64;
-    m_reg_info.last_mpxc = lldb_bndstatus_x86_64;
-    m_reg_info.first_dr = lldb_dr0_x86_64;
-    m_reg_info.last_dr = lldb_dr7_x86_64;
-    m_reg_info.gpr_flags = lldb_rflags_x86_64;
+    m_reg_info.num_registers = x86_64_with_base::k_num_registers;
+    m_reg_info.num_gpr_registers = x86_64_with_base::k_num_gpr_registers;
+    m_reg_info.num_fpr_registers = x86_64_with_base::k_num_fpr_registers;
+    m_reg_info.num_avx_registers = x86_64_with_base::k_num_avx_registers;
+    m_reg_info.num_mpx_registers = x86_64_with_base::k_num_mpx_registers;
+    m_reg_info.last_gpr = x86_64_with_base::k_last_gpr;
+    m_reg_info.first_fpr = x86_64_with_base::k_first_fpr;
+    m_reg_info.last_fpr = x86_64_with_base::k_last_fpr;
+    m_reg_info.first_st = x86_64_with_base::lldb_st0;
+    m_reg_info.last_st = x86_64_with_base::lldb_st7;
+    m_reg_info.first_mm = x86_64_with_base::lldb_mm0;
+    m_reg_info.last_mm = x86_64_with_base::lldb_mm7;
+    m_reg_info.first_xmm = x86_64_with_base::lldb_xmm0;
+    m_reg_info.last_xmm = x86_64_with_base::lldb_xmm15;
+    m_reg_info.first_ymm = x86_64_with_base::lldb_ymm0;
+    m_reg_info.last_ymm = x86_64_with_base::lldb_ymm15;
+    m_reg_info.first_mpxr = x86_64_with_base::lldb_bnd0;
+    m_reg_info.last_mpxr = x86_64_with_base::lldb_bnd3;
+    m_reg_info.first_mpxc = x86_64_with_base::lldb_bndcfgu;
+    m_reg_info.last_mpxc = x86_64_with_base::lldb_bndstatus;
+    m_reg_info.first_dr = x86_64_with_base::lldb_dr0;
+    m_reg_info.last_dr = x86_64_with_base::lldb_dr7;
+    m_reg_info.gpr_flags = x86_64_with_base::lldb_rflags;
     break;
   default:
     assert(false && "Unhandled target architecture.");
@@ -1048,9 +1049,9 @@ NativeRegisterContextLinux_x86_64::GetSyscallData() {
   case llvm::Triple::x86_64: {
     static const uint8_t Syscall[] = {0x0f, 0x05};
     static const uint32_t Args[] = {
-        lldb_rax_x86_64, lldb_rdi_x86_64, lldb_rsi_x86_64, lldb_rdx_x86_64,
-        lldb_r10_x86_64, lldb_r8_x86_64,  lldb_r9_x86_64};
-    return SyscallData{Syscall, Args, lldb_rax_x86_64};
+        x86_64_with_base::lldb_rax, x86_64_with_base::lldb_rdi, x86_64_with_base::lldb_rsi, x86_64_with_base::lldb_rdx,
+        x86_64_with_base::lldb_r10, x86_64_with_base::lldb_r8,  x86_64_with_base::lldb_r9};
+    return SyscallData{Syscall, Args, x86_64_with_base::lldb_rax};
   }
   default:
     llvm_unreachable("Unhandled architecture!");
@@ -1069,4 +1070,16 @@ NativeRegisterContextLinux_x86_64::GetMmapData() {
   }
 }
 
+const RegisterInfo *NativeRegisterContextLinux_x86_64::GetDR(int num) const {
+  assert(num >= 0 && num <= 7);
+  switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
+  case llvm::Triple::x86:
+    return GetRegisterInfoAtIndex(lldb_dr0_i386 + num);
+  case llvm::Triple::x86_64:
+    return GetRegisterInfoAtIndex(x86_64_with_base::lldb_dr0 + num);
+  default:
+    llvm_unreachable("Unhandled target architecture.");
+  }
+}
+
 #endif // defined(__i386__) || defined(__x86_64__)

diff  --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
index 40d086e0811bb3..0078f107d46a49 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
@@ -51,6 +51,8 @@ class NativeRegisterContextLinux_x86_64
 
   std::optional<MmapData> GetMmapData() override;
 
+  const RegisterInfo *GetDR(int num) const override;
+
 protected:
   void *GetGPRBuffer() override { return &m_gpr_x86_64; }
 
@@ -104,7 +106,7 @@ class NativeRegisterContextLinux_x86_64
   YMM m_ymm_set;
   MPX m_mpx_set;
   RegInfo m_reg_info;
-  uint64_t m_gpr_x86_64[k_num_gpr_registers_x86_64];
+  uint64_t m_gpr_x86_64[x86_64_with_base::k_num_gpr_registers];
   uint32_t m_fctrl_offset_in_userarea;
 
   // Private member methods.

diff  --git a/lldb/source/Plugins/Process/Utility/CMakeLists.txt b/lldb/source/Plugins/Process/Utility/CMakeLists.txt
index edf4e851b653cc..1ebd0484f0210a 100644
--- a/lldb/source/Plugins/Process/Utility/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/Utility/CMakeLists.txt
@@ -47,6 +47,7 @@ add_lldb_library(lldbPluginProcessUtility
   RegisterContextThreadMemory.cpp
   RegisterContextWindows_i386.cpp
   RegisterContextWindows_x86_64.cpp
+  RegisterInfos_x86_64_with_base_shared.cpp
   RegisterInfoPOSIX_arm.cpp
   RegisterInfoPOSIX_arm64.cpp
   RegisterInfoPOSIX_loongarch64.cpp

diff  --git a/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.h b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.h
index a4ed8bfb97eafb..4ca288d9dff76c 100644
--- a/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.h
+++ b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.h
@@ -46,7 +46,7 @@ class NativeRegisterContextDBReg_x86
 
   uint32_t NumSupportedHardwareWatchpoints() override;
 
-  const RegisterInfo *GetDR(int num) const;
+  virtual const RegisterInfo *GetDR(int num) const;
 };
 
 } // namespace lldb_private

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp
index 7be58f4fd39e17..63c034a858d7df 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp
@@ -75,10 +75,10 @@ struct UserArea {
   (LLVM_EXTENSION offsetof(UserArea, dbg) +                                    \
    LLVM_EXTENSION offsetof(DBG, dr[reg_index]))
 
-// Include RegisterInfos_x86_64 to declare our g_register_infos_x86_64
+// Include RegisterInfos_x86_64 to declare our g_register_infos_x86_64_with_base
 // structure.
 #define DECLARE_REGISTER_INFOS_X86_64_STRUCT
-#include "RegisterInfos_x86_64.h"
+#include "RegisterInfos_x86_64_with_base.h"
 #undef DECLARE_REGISTER_INFOS_X86_64_STRUCT
 
 static std::vector<lldb_private::RegisterInfo> &GetPrivateRegisterInfoVector() {
@@ -103,7 +103,7 @@ GetRegisterInfo_i386(const lldb_private::ArchSpec &arch) {
 // Include RegisterInfos_x86_64 to update the g_register_infos structure
 //  with x86_64 offsets.
 #define UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
-#include "RegisterInfos_x86_64.h"
+#include "RegisterInfos_x86_64_with_base.h"
 #undef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
   }
 
@@ -115,7 +115,7 @@ static const RegisterInfo *GetRegisterInfoPtr(const ArchSpec &target_arch) {
   case llvm::Triple::x86:
     return GetRegisterInfo_i386(target_arch);
   case llvm::Triple::x86_64:
-    return g_register_infos_x86_64;
+    return g_register_infos_x86_64_with_base;
   default:
     assert(false && "Unhandled target architecture.");
     return nullptr;
@@ -130,8 +130,8 @@ static uint32_t GetRegisterInfoCount(const ArchSpec &target_arch) {
     return static_cast<uint32_t>(GetPrivateRegisterInfoVector().size());
   }
   case llvm::Triple::x86_64:
-    return static_cast<uint32_t>(sizeof(g_register_infos_x86_64) /
-                                 sizeof(g_register_infos_x86_64[0]));
+    return static_cast<uint32_t>(sizeof(g_register_infos_x86_64_with_base) /
+                                 sizeof(g_register_infos_x86_64_with_base[0]));
   default:
     assert(false && "Unhandled target architecture.");
     return 0;
@@ -143,7 +143,7 @@ static uint32_t GetUserRegisterInfoCount(const ArchSpec &target_arch) {
   case llvm::Triple::x86:
     return static_cast<uint32_t>(k_num_user_registers_i386);
   case llvm::Triple::x86_64:
-    return static_cast<uint32_t>(k_num_user_registers_x86_64);
+    return static_cast<uint32_t>(x86_64_with_base::k_num_user_registers);
   default:
     assert(false && "Unhandled target architecture.");
     return 0;

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
index 0e0db843c8b45e..c14eb135c7b105 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
@@ -374,15 +374,15 @@ static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = {
      g_avx_regnums_x86_64}};
 
 bool RegisterContextPOSIX_x86::IsGPR(unsigned reg) {
-  return reg <= m_reg_info.last_gpr; // GPR's come first.
+  return reg <= GetRegInfo().last_gpr; // GPR's come first.
 }
 
 bool RegisterContextPOSIX_x86::IsFPR(unsigned reg) {
-  return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr);
+  return (GetRegInfo().first_fpr <= reg && reg <= GetRegInfo().last_fpr);
 }
 
 bool RegisterContextPOSIX_x86::IsAVX(unsigned reg) {
-  return (m_reg_info.first_ymm <= reg && reg <= m_reg_info.last_ymm);
+  return (GetRegInfo().first_ymm <= reg && reg <= GetRegInfo().last_ymm);
 }
 
 bool RegisterContextPOSIX_x86::IsFPR(unsigned reg, FPRType fpr_type) {
@@ -399,50 +399,6 @@ RegisterContextPOSIX_x86::RegisterContextPOSIX_x86(
     : RegisterContext(thread, concrete_frame_idx) {
   m_register_info_up.reset(register_info);
 
-  switch (register_info->GetTargetArchitecture().GetMachine()) {
-  case llvm::Triple::x86:
-    m_reg_info.num_registers = k_num_registers_i386;
-    m_reg_info.num_gpr_registers = k_num_gpr_registers_i386;
-    m_reg_info.num_fpr_registers = k_num_fpr_registers_i386;
-    m_reg_info.num_avx_registers = k_num_avx_registers_i386;
-    m_reg_info.last_gpr = k_last_gpr_i386;
-    m_reg_info.first_fpr = k_first_fpr_i386;
-    m_reg_info.last_fpr = k_last_fpr_i386;
-    m_reg_info.first_st = lldb_st0_i386;
-    m_reg_info.last_st = lldb_st7_i386;
-    m_reg_info.first_mm = lldb_mm0_i386;
-    m_reg_info.last_mm = lldb_mm7_i386;
-    m_reg_info.first_xmm = lldb_xmm0_i386;
-    m_reg_info.last_xmm = lldb_xmm7_i386;
-    m_reg_info.first_ymm = lldb_ymm0_i386;
-    m_reg_info.last_ymm = lldb_ymm7_i386;
-    m_reg_info.first_dr = lldb_dr0_i386;
-    m_reg_info.gpr_flags = lldb_eflags_i386;
-    break;
-  case llvm::Triple::x86_64:
-    m_reg_info.num_registers = k_num_registers_x86_64;
-    m_reg_info.num_gpr_registers = k_num_gpr_registers_x86_64;
-    m_reg_info.num_fpr_registers = k_num_fpr_registers_x86_64;
-    m_reg_info.num_avx_registers = k_num_avx_registers_x86_64;
-    m_reg_info.last_gpr = k_last_gpr_x86_64;
-    m_reg_info.first_fpr = k_first_fpr_x86_64;
-    m_reg_info.last_fpr = k_last_fpr_x86_64;
-    m_reg_info.first_st = lldb_st0_x86_64;
-    m_reg_info.last_st = lldb_st7_x86_64;
-    m_reg_info.first_mm = lldb_mm0_x86_64;
-    m_reg_info.last_mm = lldb_mm7_x86_64;
-    m_reg_info.first_xmm = lldb_xmm0_x86_64;
-    m_reg_info.last_xmm = lldb_xmm15_x86_64;
-    m_reg_info.first_ymm = lldb_ymm0_x86_64;
-    m_reg_info.last_ymm = lldb_ymm15_x86_64;
-    m_reg_info.first_dr = lldb_dr0_x86_64;
-    m_reg_info.gpr_flags = lldb_rflags_x86_64;
-    break;
-  default:
-    assert(false && "Unhandled target architecture.");
-    break;
-  }
-
   ::memset(&m_fpr, 0, sizeof(FPR));
   ::memset(&m_ymm_set, 0, sizeof(YMM));
 
@@ -466,20 +422,26 @@ void RegisterContextPOSIX_x86::Invalidate() {}
 void RegisterContextPOSIX_x86::InvalidateAllRegisters() {}
 
 unsigned RegisterContextPOSIX_x86::GetRegisterOffset(unsigned reg) {
-  assert(reg < m_reg_info.num_registers && "Invalid register number.");
+  assert(reg < GetRegInfo().num_registers && "Invalid register number.");
   return GetRegisterInfo()[reg].byte_offset;
 }
 
+RegInfo &RegisterContextPOSIX_x86::GetRegInfo() {
+  return GetRegInfoShared(
+      m_register_info_up->GetTargetArchitecture().GetMachine(),
+      /*with_base=*/false);
+}
+
 unsigned RegisterContextPOSIX_x86::GetRegisterSize(unsigned reg) {
-  assert(reg < m_reg_info.num_registers && "Invalid register number.");
+  assert(reg < GetRegInfo().num_registers && "Invalid register number.");
   return GetRegisterInfo()[reg].byte_size;
 }
 
 size_t RegisterContextPOSIX_x86::GetRegisterCount() {
   size_t num_registers =
-      m_reg_info.num_gpr_registers + m_reg_info.num_fpr_registers;
+      GetRegInfo().num_gpr_registers + GetRegInfo().num_fpr_registers;
   if (GetFPRType() == eXSAVE)
-    return num_registers + m_reg_info.num_avx_registers;
+    return num_registers + GetRegInfo().num_avx_registers;
   return num_registers;
 }
 
@@ -488,7 +450,7 @@ size_t RegisterContextPOSIX_x86::GetGPRSize() {
 }
 
 size_t RegisterContextPOSIX_x86::GetFXSAVEOffset() {
-  return GetRegisterInfo()[m_reg_info.first_fpr].byte_offset;
+  return GetRegisterInfo()[GetRegInfo().first_fpr].byte_offset;
 }
 
 const RegisterInfo *RegisterContextPOSIX_x86::GetRegisterInfo() {
@@ -500,7 +462,7 @@ const RegisterInfo *RegisterContextPOSIX_x86::GetRegisterInfo() {
 
 const RegisterInfo *
 RegisterContextPOSIX_x86::GetRegisterInfoAtIndex(size_t reg) {
-  if (reg < m_reg_info.num_registers)
+  if (reg < GetRegInfo().num_registers)
     return &GetRegisterInfo()[reg];
   else
     return nullptr;
@@ -532,7 +494,7 @@ const RegisterSet *RegisterContextPOSIX_x86::GetRegisterSet(size_t set) {
 }
 
 const char *RegisterContextPOSIX_x86::GetRegisterName(unsigned reg) {
-  assert(reg < m_reg_info.num_registers && "Invalid register offset.");
+  assert(reg < GetRegInfo().num_registers && "Invalid register offset.");
   return GetRegisterInfo()[reg].name;
 }
 
@@ -543,10 +505,9 @@ bool RegisterContextPOSIX_x86::CopyYMMtoXSTATE(uint32_t reg,
     return false;
 
   if (byte_order == eByteOrderLittle) {
-    uint32_t reg_no = reg - m_reg_info.first_ymm;
-    YMMToXState(m_ymm_set.ymm[reg_no],
-        m_fpr.fxsave.xmm[reg_no].bytes,
-        m_fpr.xsave.ymmh[reg_no].bytes);
+    uint32_t reg_no = reg - GetRegInfo().first_ymm;
+    YMMToXState(m_ymm_set.ymm[reg_no], m_fpr.fxsave.xmm[reg_no].bytes,
+                m_fpr.xsave.ymmh[reg_no].bytes);
     return true;
   }
 
@@ -560,10 +521,9 @@ bool RegisterContextPOSIX_x86::CopyXSTATEtoYMM(uint32_t reg,
     return false;
 
   if (byte_order == eByteOrderLittle) {
-    uint32_t reg_no = reg - m_reg_info.first_ymm;
-    m_ymm_set.ymm[reg_no] = XStateToYMM(
-        m_fpr.fxsave.xmm[reg_no].bytes,
-        m_fpr.xsave.ymmh[reg_no].bytes);
+    uint32_t reg_no = reg - GetRegInfo().first_ymm;
+    m_ymm_set.ymm[reg_no] = XStateToYMM(m_fpr.fxsave.xmm[reg_no].bytes,
+                                        m_fpr.xsave.ymmh[reg_no].bytes);
     return true;
   }
 

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h
index d6672835b4a814..9284f5cc07d91b 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h
@@ -11,6 +11,7 @@
 
 #include "RegisterContext_x86.h"
 #include "RegisterInfoInterface.h"
+#include "RegisterInfos_x86_64_with_base_shared.h"
 #include "lldb-x86-register-enums.h"
 #include "lldb/Target/RegisterContext.h"
 #include "lldb/Utility/Log.h"
@@ -149,34 +150,6 @@ class RegisterContextPOSIX_x86 : public lldb_private::RegisterContext {
   static uint32_t g_invalidate_st7_64[];
 
 protected:
-  struct RegInfo {
-    uint32_t num_registers;
-    uint32_t num_gpr_registers;
-    uint32_t num_fpr_registers;
-    uint32_t num_avx_registers;
-
-    uint32_t last_gpr;
-    uint32_t first_fpr;
-    uint32_t last_fpr;
-
-    uint32_t first_st;
-    uint32_t last_st;
-    uint32_t first_mm;
-    uint32_t last_mm;
-    uint32_t first_xmm;
-    uint32_t last_xmm;
-    uint32_t first_ymm;
-    uint32_t last_ymm;
-
-    uint32_t first_dr;
-    uint32_t gpr_flags;
-  };
-
-  uint64_t m_gpr_x86_64[lldb_private::k_num_gpr_registers_x86_64]; // 64-bit
-                                                                   // general
-                                                                   // purpose
-                                                                   // registers.
-  RegInfo m_reg_info;
   FPRType
       m_fpr_type; // determines the type of data stored by union FPR, if any.
   lldb_private::FPR m_fpr;     // floating-point registers including extended
@@ -206,6 +179,7 @@ class RegisterContextPOSIX_x86 : public lldb_private::RegisterContext {
   virtual bool ReadFPR() = 0;
   virtual bool WriteGPR() = 0;
   virtual bool WriteFPR() = 0;
+  virtual lldb_private::RegInfo &GetRegInfo();
 };
 
 #endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_X86_H

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterContext_x86.h b/lldb/source/Plugins/Process/Utility/RegisterContext_x86.h
index 76e004ce0ceb11..e24da37b726100 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContext_x86.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterContext_x86.h
@@ -201,6 +201,9 @@ enum {
   dwarf_ds_x86_64,
   dwarf_fs_x86_64,
   dwarf_gs_x86_64,
+  // Base registers
+  dwarf_fs_base_x86_64 = 58,
+  dwarf_gs_base_x86_64 = 59,
   // Floating point control registers
   dwarf_mxcsr_x86_64 = 64, // Media Control and Status
   dwarf_fctrl_x86_64,      // x87 control word

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64_with_base.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64_with_base.h
new file mode 100644
index 00000000000000..39428bdd0a0864
--- /dev/null
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64_with_base.h
@@ -0,0 +1,480 @@
+//===-- RegisterInfos_x86_64_with_base.h ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RegisterInfos_x86_64_with_base_shared.h"
+
+// This file is meant to be textually included. Do not #include modular
+// headers here.
+
+// Computes the offset of the given GPR in the user data area.
+#define GPR_OFFSET(regname) (LLVM_EXTENSION offsetof(GPR, regname))
+
+// Computes the offset of the given FPR in the extended data area.
+#define FPR_OFFSET(regname)                                                    \
+  (LLVM_EXTENSION offsetof(UserArea, fpr) +                                    \
+   LLVM_EXTENSION offsetof(FPR, fxsave) +                                      \
+   LLVM_EXTENSION offsetof(FXSAVE, regname))
+
+// Computes the offset of the YMM register assembled from register halves.
+// Based on DNBArchImplX86_64.cpp from debugserver
+#define YMM_OFFSET(reg_index)                                                  \
+  (LLVM_EXTENSION offsetof(UserArea, fpr) +                                    \
+   LLVM_EXTENSION offsetof(FPR, xsave) +                                       \
+   LLVM_EXTENSION offsetof(XSAVE, ymmh[0]) + (32 * reg_index))
+
+// Guarantees BNDR/BNDC offsets do not overlap with YMM offsets.
+#define GDB_REMOTE_OFFSET 128
+
+#define BNDR_OFFSET(reg_index)                                                 \
+  (LLVM_EXTENSION offsetof(UserArea, fpr) +                                    \
+   LLVM_EXTENSION offsetof(FPR, xsave) +                                       \
+   LLVM_EXTENSION offsetof(XSAVE, mpxr[reg_index]) + GDB_REMOTE_OFFSET)
+
+#define BNDC_OFFSET(reg_index)                                                 \
+  (LLVM_EXTENSION offsetof(UserArea, fpr) +                                    \
+   LLVM_EXTENSION offsetof(FPR, xsave) +                                       \
+   LLVM_EXTENSION offsetof(XSAVE, mpxc[reg_index]) + GDB_REMOTE_OFFSET)
+
+#ifdef DECLARE_REGISTER_INFOS_X86_64_STRUCT
+
+// Number of bytes needed to represent a FPR.
+#define FPR_SIZE(reg) sizeof(((FXSAVE *)nullptr)->reg)
+
+// Number of bytes needed to represent the i'th FP register.
+#define FP_SIZE sizeof(((MMSReg *)nullptr)->bytes)
+
+// Number of bytes needed to represent an XMM register.
+#define XMM_SIZE sizeof(XMMReg)
+
+// Number of bytes needed to represent a YMM register.
+#define YMM_SIZE sizeof(YMMReg)
+
+// Number of bytes needed to represent MPX registers.
+#define BNDR_SIZE sizeof(MPXReg)
+#define BNDC_SIZE sizeof(MPXCsr)
+
+#define DR_SIZE sizeof(((DBG *)nullptr)->dr[0])
+
+// RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB
+
+// Note that the size and offset will be updated by platform-specific classes.
+#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4)                       \
+  {                                                                            \
+    #reg, alt, sizeof(((GPR *)nullptr)->reg), GPR_OFFSET(reg), eEncodingUint,  \
+        eFormatHex,                                                            \
+        {kind1, kind2, kind3, kind4, x86_64_with_base::lldb_##reg}, nullptr,   \
+        nullptr, nullptr,                                                      \
+  }
+
+// Note that the size and offset will be updated by platform-specific classes.
+#define DEFINE_GPR_WITH_BASE(reg, alt, kind1, kind2, kind3, kind4)             \
+  {                                                                            \
+    #reg, alt, sizeof(((GPR *)nullptr)->reg), GPR_OFFSET(reg), eEncodingUint,  \
+        eFormatHex,                                                            \
+        {kind1, kind2, kind3, kind4, x86_64_with_base::lldb_##reg}, nullptr,   \
+        nullptr, nullptr,                                                      \
+  }
+
+#define DEFINE_FPR(name, reg, kind1, kind2, kind3, kind4)                      \
+  {                                                                            \
+    #name, nullptr, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, eFormatHex, \
+        {kind1, kind2, kind3, kind4, x86_64_with_base::lldb_##name}, nullptr,  \
+        nullptr, nullptr,                                                      \
+  }
+
+#define DEFINE_FP_ST(reg, i)                                                   \
+  {                                                                            \
+    #reg #i, nullptr, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(stmm[i]),             \
+        eEncodingVector, eFormatVectorOfUInt8,                                 \
+        {dwarf_st##i##_x86_64, dwarf_st##i##_x86_64, LLDB_INVALID_REGNUM,      \
+         LLDB_INVALID_REGNUM, x86_64_with_base::lldb_st##i},                   \
+        nullptr, nullptr, nullptr,                                             \
+  }
+
+#define DEFINE_FP_MM(reg, i, streg)                                            \
+  {                                                                            \
+    #reg #i, nullptr, sizeof(uint64_t), LLVM_EXTENSION FPR_OFFSET(stmm[i]),    \
+        eEncodingUint, eFormatHex,                                             \
+        {dwarf_mm##i##_x86_64, dwarf_mm##i##_x86_64, LLDB_INVALID_REGNUM,      \
+         LLDB_INVALID_REGNUM, x86_64_with_base::lldb_mm##i},                   \
+        RegisterInfos_x86_64_with_base_shared::g_contained_##streg##_64,       \
+        RegisterInfos_x86_64_with_base_shared::g_invalidate_##streg##_64,      \
+        nullptr,                                                               \
+  }
+
+#define DEFINE_XMM(reg, i)                                                     \
+  {                                                                            \
+    #reg #i, nullptr, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]),             \
+        eEncodingVector, eFormatVectorOfUInt8,                                 \
+        {dwarf_##reg##i##_x86_64, dwarf_##reg##i##_x86_64,                     \
+         LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,                             \
+         x86_64_with_base::lldb_##reg##i},                                     \
+        nullptr, nullptr, nullptr,                                             \
+  }
+
+#define DEFINE_YMM(reg, i)                                                     \
+  {                                                                            \
+    #reg #i, nullptr, YMM_SIZE, LLVM_EXTENSION YMM_OFFSET(i), eEncodingVector, \
+        eFormatVectorOfUInt8,                                                  \
+        {dwarf_##reg##i##h_x86_64, dwarf_##reg##i##h_x86_64,                   \
+         LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,                             \
+         x86_64_with_base::lldb_##reg##i},                                     \
+        nullptr, nullptr, nullptr,                                             \
+  }
+
+#define DEFINE_BNDR(reg, i)                                                    \
+  {                                                                            \
+    #reg #i, nullptr, BNDR_SIZE, LLVM_EXTENSION BNDR_OFFSET(i),                \
+        eEncodingVector, eFormatVectorOfUInt64,                                \
+        {dwarf_##reg##i##_x86_64, dwarf_##reg##i##_x86_64,                     \
+         LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,                             \
+         x86_64_with_base::lldb_##reg##i},                                     \
+        nullptr, nullptr, nullptr,                                             \
+  }
+
+#define DEFINE_BNDC(name, i)                                                   \
+  {                                                                            \
+    #name, nullptr, BNDC_SIZE, LLVM_EXTENSION BNDC_OFFSET(i), eEncodingVector, \
+        eFormatVectorOfUInt8,                                                  \
+        {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        \
+         LLDB_INVALID_REGNUM, x86_64_with_base::lldb_##name},                  \
+        nullptr, nullptr, nullptr,                                             \
+  }
+
+#define DEFINE_DR(reg, i)                                                      \
+  {                                                                            \
+    #reg #i, nullptr, DR_SIZE, DR_OFFSET(i), eEncodingUint, eFormatHex,        \
+        {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        \
+         LLDB_INVALID_REGNUM, x86_64_with_base::lldb_##reg##i},                \
+        nullptr, nullptr, nullptr,                                             \
+  }
+
+#define DEFINE_GPR_PSEUDO_32(reg32, reg64)                                     \
+  {                                                                            \
+    #reg32, nullptr, 4, GPR_OFFSET(reg64), eEncodingUint, eFormatHex,          \
+        {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        \
+         LLDB_INVALID_REGNUM, x86_64_with_base::lldb_##reg32},                 \
+        RegisterInfos_x86_64_with_base_shared::g_contained_##reg64,            \
+        RegisterInfos_x86_64_with_base_shared::g_invalidate_##reg64, nullptr,  \
+  }
+
+#define DEFINE_GPR_PSEUDO_16(reg16, reg64)                                     \
+  {                                                                            \
+    #reg16, nullptr, 2, GPR_OFFSET(reg64), eEncodingUint, eFormatHex,          \
+        {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        \
+         LLDB_INVALID_REGNUM, x86_64_with_base::lldb_##reg16},                 \
+        RegisterInfos_x86_64_with_base_shared::g_contained_##reg64,            \
+        RegisterInfos_x86_64_with_base_shared::g_invalidate_##reg64, nullptr,  \
+  }
+
+#define DEFINE_GPR_PSEUDO_8H(reg8, reg64)                                      \
+  {                                                                            \
+    #reg8, nullptr, 1, GPR_OFFSET(reg64) + 1, eEncodingUint, eFormatHex,       \
+        {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        \
+         LLDB_INVALID_REGNUM, x86_64_with_base::lldb_##reg8},                  \
+        RegisterInfos_x86_64_with_base_shared::g_contained_##reg64,            \
+        RegisterInfos_x86_64_with_base_shared::g_invalidate_##reg64, nullptr,  \
+  }
+
+#define DEFINE_GPR_PSEUDO_8L(reg8, reg64)                                      \
+  {                                                                            \
+    #reg8, nullptr, 1, GPR_OFFSET(reg64), eEncodingUint, eFormatHex,           \
+        {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        \
+         LLDB_INVALID_REGNUM, x86_64_with_base::lldb_##reg8},                  \
+        RegisterInfos_x86_64_with_base_shared::g_contained_##reg64,            \
+        RegisterInfos_x86_64_with_base_shared::g_invalidate_##reg64, nullptr   \
+  }
+
+#define DEFINE_FPR_32(name, reg, kind1, kind2, kind3, kind4, reg64)            \
+  {                                                                            \
+    #name, nullptr, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, eFormatHex, \
+        {kind1, kind2, kind3, kind4, x86_64_with_base::lldb_##name},           \
+        RegisterInfos_x86_64_with_base_shared::g_contained_##reg64,            \
+        RegisterInfos_x86_64_with_base_shared::g_invalidate_##reg64, nullptr,  \
+  }
+
+// clang-format off
+static RegisterInfo g_register_infos_x86_64_with_base[] = {
+// General purpose registers     EH_Frame              DWARF                 Generic                     Process Plugin
+//  ===========================  ==================    ================      =========================   ====================
+    DEFINE_GPR(rax,    nullptr,  dwarf_rax_x86_64,     dwarf_rax_x86_64,     LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(rbx,    nullptr,  dwarf_rbx_x86_64,     dwarf_rbx_x86_64,     LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(rcx,    nullptr,  dwarf_rcx_x86_64,     dwarf_rcx_x86_64,     LLDB_REGNUM_GENERIC_ARG4,   LLDB_INVALID_REGNUM),
+    DEFINE_GPR(rdx,    nullptr,  dwarf_rdx_x86_64,     dwarf_rdx_x86_64,     LLDB_REGNUM_GENERIC_ARG3,   LLDB_INVALID_REGNUM),
+    DEFINE_GPR(rdi,    nullptr,  dwarf_rdi_x86_64,     dwarf_rdi_x86_64,     LLDB_REGNUM_GENERIC_ARG1,   LLDB_INVALID_REGNUM),
+    DEFINE_GPR(rsi,    nullptr,  dwarf_rsi_x86_64,     dwarf_rsi_x86_64,     LLDB_REGNUM_GENERIC_ARG2,   LLDB_INVALID_REGNUM),
+    DEFINE_GPR(rbp,    nullptr,  dwarf_rbp_x86_64,     dwarf_rbp_x86_64,     LLDB_REGNUM_GENERIC_FP,     LLDB_INVALID_REGNUM),
+    DEFINE_GPR(rsp,    nullptr,  dwarf_rsp_x86_64,     dwarf_rsp_x86_64,     LLDB_REGNUM_GENERIC_SP,     LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r8,     nullptr,  dwarf_r8_x86_64,      dwarf_r8_x86_64,      LLDB_REGNUM_GENERIC_ARG5,   LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r9,     nullptr,  dwarf_r9_x86_64,      dwarf_r9_x86_64,      LLDB_REGNUM_GENERIC_ARG6,   LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r10,    nullptr,  dwarf_r10_x86_64,     dwarf_r10_x86_64,     LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r11,    nullptr,  dwarf_r11_x86_64,     dwarf_r11_x86_64,     LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r12,    nullptr,  dwarf_r12_x86_64,     dwarf_r12_x86_64,     LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r13,    nullptr,  dwarf_r13_x86_64,     dwarf_r13_x86_64,     LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r14,    nullptr,  dwarf_r14_x86_64,     dwarf_r14_x86_64,     LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r15,    nullptr,  dwarf_r15_x86_64,     dwarf_r15_x86_64,     LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(rip,    nullptr,  dwarf_rip_x86_64,     dwarf_rip_x86_64,     LLDB_REGNUM_GENERIC_PC,     LLDB_INVALID_REGNUM),
+    DEFINE_GPR(rflags, nullptr,  dwarf_rflags_x86_64,  dwarf_rflags_x86_64,  LLDB_REGNUM_GENERIC_FLAGS,  LLDB_INVALID_REGNUM),
+    DEFINE_GPR(cs,     nullptr,  dwarf_cs_x86_64,      dwarf_cs_x86_64,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(fs,     nullptr,  dwarf_fs_x86_64,      dwarf_fs_x86_64,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(gs,     nullptr,  dwarf_gs_x86_64,      dwarf_gs_x86_64,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(ss,     nullptr,  dwarf_ss_x86_64,      dwarf_ss_x86_64,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(fs_base,     nullptr,  dwarf_fs_base_x86_64,      dwarf_fs_base_x86_64,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(gs_base,     nullptr,  dwarf_gs_base_x86_64,      dwarf_gs_base_x86_64,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(ds,     nullptr,  dwarf_ds_x86_64,      dwarf_ds_x86_64,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(es,     nullptr,  dwarf_es_x86_64,      dwarf_es_x86_64,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+
+    DEFINE_GPR_PSEUDO_32(eax, rax), DEFINE_GPR_PSEUDO_32(ebx, rbx),
+    DEFINE_GPR_PSEUDO_32(ecx, rcx), DEFINE_GPR_PSEUDO_32(edx, rdx),
+    DEFINE_GPR_PSEUDO_32(edi, rdi), DEFINE_GPR_PSEUDO_32(esi, rsi),
+    DEFINE_GPR_PSEUDO_32(ebp, rbp), DEFINE_GPR_PSEUDO_32(esp, rsp),
+    DEFINE_GPR_PSEUDO_32(r8d, r8), DEFINE_GPR_PSEUDO_32(r9d, r9),
+    DEFINE_GPR_PSEUDO_32(r10d, r10), DEFINE_GPR_PSEUDO_32(r11d, r11),
+    DEFINE_GPR_PSEUDO_32(r12d, r12), DEFINE_GPR_PSEUDO_32(r13d, r13),
+    DEFINE_GPR_PSEUDO_32(r14d, r14), DEFINE_GPR_PSEUDO_32(r15d, r15),
+    DEFINE_GPR_PSEUDO_16(ax, rax), DEFINE_GPR_PSEUDO_16(bx, rbx),
+    DEFINE_GPR_PSEUDO_16(cx, rcx), DEFINE_GPR_PSEUDO_16(dx, rdx),
+    DEFINE_GPR_PSEUDO_16(di, rdi), DEFINE_GPR_PSEUDO_16(si, rsi),
+    DEFINE_GPR_PSEUDO_16(bp, rbp), DEFINE_GPR_PSEUDO_16(sp, rsp),
+    DEFINE_GPR_PSEUDO_16(r8w, r8), DEFINE_GPR_PSEUDO_16(r9w, r9),
+    DEFINE_GPR_PSEUDO_16(r10w, r10), DEFINE_GPR_PSEUDO_16(r11w, r11),
+    DEFINE_GPR_PSEUDO_16(r12w, r12), DEFINE_GPR_PSEUDO_16(r13w, r13),
+    DEFINE_GPR_PSEUDO_16(r14w, r14), DEFINE_GPR_PSEUDO_16(r15w, r15),
+    DEFINE_GPR_PSEUDO_8H(ah, rax), DEFINE_GPR_PSEUDO_8H(bh, rbx),
+    DEFINE_GPR_PSEUDO_8H(ch, rcx), DEFINE_GPR_PSEUDO_8H(dh, rdx),
+    DEFINE_GPR_PSEUDO_8L(al, rax), DEFINE_GPR_PSEUDO_8L(bl, rbx),
+    DEFINE_GPR_PSEUDO_8L(cl, rcx), DEFINE_GPR_PSEUDO_8L(dl, rdx),
+    DEFINE_GPR_PSEUDO_8L(dil, rdi), DEFINE_GPR_PSEUDO_8L(sil, rsi),
+    DEFINE_GPR_PSEUDO_8L(bpl, rbp), DEFINE_GPR_PSEUDO_8L(spl, rsp),
+    DEFINE_GPR_PSEUDO_8L(r8l, r8), DEFINE_GPR_PSEUDO_8L(r9l, r9),
+    DEFINE_GPR_PSEUDO_8L(r10l, r10), DEFINE_GPR_PSEUDO_8L(r11l, r11),
+    DEFINE_GPR_PSEUDO_8L(r12l, r12), DEFINE_GPR_PSEUDO_8L(r13l, r13),
+    DEFINE_GPR_PSEUDO_8L(r14l, r14), DEFINE_GPR_PSEUDO_8L(r15l, r15),
+
+//  i387 Floating point registers.         EH_frame             DWARF                Generic              Process Plugin       reg64
+//  ====================================== ===============      ==================   ===================  ==================== =====
+    DEFINE_FPR(fctrl,     fctrl,           dwarf_fctrl_x86_64,  dwarf_fctrl_x86_64,  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+    DEFINE_FPR(fstat,     fstat,           dwarf_fstat_x86_64,  dwarf_fstat_x86_64,  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+    DEFINE_FPR(ftag,      ftag,            LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+    DEFINE_FPR(fop,       fop,             LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+    DEFINE_FPR_32(fiseg,  ptr.i386_.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fip),
+    DEFINE_FPR_32(fioff,  ptr.i386_.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fip),
+    DEFINE_FPR(fip,       ptr.x86_64.fip,  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+    DEFINE_FPR_32(foseg,  ptr.i386_.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fdp),
+    DEFINE_FPR_32(fooff,  ptr.i386_.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fdp),
+    DEFINE_FPR(fdp,       ptr.x86_64.fdp,  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+    DEFINE_FPR(mxcsr,     mxcsr,           dwarf_mxcsr_x86_64,  dwarf_mxcsr_x86_64,  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+    DEFINE_FPR(mxcsrmask, mxcsrmask,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+
+    // FP registers.
+    DEFINE_FP_ST(st, 0), DEFINE_FP_ST(st, 1), DEFINE_FP_ST(st, 2),
+    DEFINE_FP_ST(st, 3), DEFINE_FP_ST(st, 4), DEFINE_FP_ST(st, 5),
+    DEFINE_FP_ST(st, 6), DEFINE_FP_ST(st, 7),
+
+    DEFINE_FP_MM(mm, 0, st0), DEFINE_FP_MM(mm, 1, st1),
+    DEFINE_FP_MM(mm, 2, st2), DEFINE_FP_MM(mm, 3, st3),
+    DEFINE_FP_MM(mm, 4, st4), DEFINE_FP_MM(mm, 5, st5),
+    DEFINE_FP_MM(mm, 6, st6), DEFINE_FP_MM(mm, 7, st7),
+
+    // XMM registers
+    DEFINE_XMM(xmm, 0), DEFINE_XMM(xmm, 1), DEFINE_XMM(xmm, 2),
+    DEFINE_XMM(xmm, 3), DEFINE_XMM(xmm, 4), DEFINE_XMM(xmm, 5),
+    DEFINE_XMM(xmm, 6), DEFINE_XMM(xmm, 7), DEFINE_XMM(xmm, 8),
+    DEFINE_XMM(xmm, 9), DEFINE_XMM(xmm, 10), DEFINE_XMM(xmm, 11),
+    DEFINE_XMM(xmm, 12), DEFINE_XMM(xmm, 13), DEFINE_XMM(xmm, 14),
+    DEFINE_XMM(xmm, 15),
+
+    // Copy of YMM registers assembled from xmm and ymmh
+    DEFINE_YMM(ymm, 0), DEFINE_YMM(ymm, 1), DEFINE_YMM(ymm, 2),
+    DEFINE_YMM(ymm, 3), DEFINE_YMM(ymm, 4), DEFINE_YMM(ymm, 5),
+    DEFINE_YMM(ymm, 6), DEFINE_YMM(ymm, 7), DEFINE_YMM(ymm, 8),
+    DEFINE_YMM(ymm, 9), DEFINE_YMM(ymm, 10), DEFINE_YMM(ymm, 11),
+    DEFINE_YMM(ymm, 12), DEFINE_YMM(ymm, 13), DEFINE_YMM(ymm, 14),
+    DEFINE_YMM(ymm, 15),
+
+    // MPX registers
+    DEFINE_BNDR(bnd, 0),
+    DEFINE_BNDR(bnd, 1),
+    DEFINE_BNDR(bnd, 2),
+    DEFINE_BNDR(bnd, 3),
+
+    DEFINE_BNDC(bndcfgu, 0),
+    DEFINE_BNDC(bndstatus, 1),
+
+    // Debug registers for lldb internal use
+    DEFINE_DR(dr, 0), DEFINE_DR(dr, 1), DEFINE_DR(dr, 2), DEFINE_DR(dr, 3),
+    DEFINE_DR(dr, 4), DEFINE_DR(dr, 5), DEFINE_DR(dr, 6), DEFINE_DR(dr, 7)};
+
+// clang-format on
+
+static_assert(
+    (sizeof(g_register_infos_x86_64_with_base) /
+     sizeof(g_register_infos_x86_64_with_base[0])) ==
+        x86_64_with_base::k_num_registers,
+    "g_register_infos_x86_64_with_base has wrong number of register infos");
+
+#undef FPR_SIZE
+#undef FP_SIZE
+#undef XMM_SIZE
+#undef YMM_SIZE
+#undef DEFINE_GPR
+#undef DEFINE_FPR
+#undef DEFINE_FP
+#undef DEFINE_XMM
+#undef DEFINE_YMM
+#undef DEFINE_BNDR
+#undef DEFINE_BNDC
+#undef DEFINE_DR
+#undef DEFINE_GPR_PSEUDO_32
+#undef DEFINE_GPR_PSEUDO_16
+#undef DEFINE_GPR_PSEUDO_8H
+#undef DEFINE_GPR_PSEUDO_8L
+
+#endif // DECLARE_REGISTER_INFOS_X86_64_STRUCT
+
+#ifdef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
+
+#define UPDATE_GPR_INFO(reg, reg64)                                            \
+  do {                                                                         \
+    g_register_infos[lldb_##reg##_i386].byte_offset = GPR_OFFSET(reg64);       \
+  } while (false);
+
+#define UPDATE_GPR_INFO_8H(reg, reg64)                                         \
+  do {                                                                         \
+    g_register_infos[lldb_##reg##_i386].byte_offset = GPR_OFFSET(reg64) + 1;   \
+  } while (false);
+
+#define UPDATE_FPR_INFO(reg, reg64)                                            \
+  do {                                                                         \
+    g_register_infos[lldb_##reg##_i386].byte_offset = FPR_OFFSET(reg64);       \
+  } while (false);
+
+#define UPDATE_FP_INFO(reg, i)                                                 \
+  do {                                                                         \
+    g_register_infos[lldb_##reg##i##_i386].byte_offset = FPR_OFFSET(stmm[i]);  \
+  } while (false);
+
+#define UPDATE_XMM_INFO(reg, i)                                                \
+  do {                                                                         \
+    g_register_infos[lldb_##reg##i##_i386].byte_offset = FPR_OFFSET(reg[i]);   \
+  } while (false);
+
+#define UPDATE_YMM_INFO(reg, i)                                                \
+  do {                                                                         \
+    g_register_infos[lldb_##reg##i##_i386].byte_offset = YMM_OFFSET(i);        \
+  } while (false);
+
+#define UPDATE_DR_INFO(reg_index)                                              \
+  do {                                                                         \
+    g_register_infos[lldb_dr##reg_index##_i386].byte_offset =                  \
+        DR_OFFSET(reg_index);                                                  \
+  } while (false);
+
+// Update the register offsets
+UPDATE_GPR_INFO(eax, rax);
+UPDATE_GPR_INFO(ebx, rbx);
+UPDATE_GPR_INFO(ecx, rcx);
+UPDATE_GPR_INFO(edx, rdx);
+UPDATE_GPR_INFO(edi, rdi);
+UPDATE_GPR_INFO(esi, rsi);
+UPDATE_GPR_INFO(ebp, rbp);
+UPDATE_GPR_INFO(esp, rsp);
+UPDATE_GPR_INFO(eip, rip);
+UPDATE_GPR_INFO(eflags, rflags);
+UPDATE_GPR_INFO(cs, cs);
+UPDATE_GPR_INFO(fs, fs);
+UPDATE_GPR_INFO(gs, gs);
+UPDATE_GPR_INFO(ss, ss);
+UPDATE_GPR_INFO(ds, ds);
+UPDATE_GPR_INFO(es, es);
+
+UPDATE_GPR_INFO(ax, rax);
+UPDATE_GPR_INFO(bx, rbx);
+UPDATE_GPR_INFO(cx, rcx);
+UPDATE_GPR_INFO(dx, rdx);
+UPDATE_GPR_INFO(di, rdi);
+UPDATE_GPR_INFO(si, rsi);
+UPDATE_GPR_INFO(bp, rbp);
+UPDATE_GPR_INFO(sp, rsp);
+UPDATE_GPR_INFO_8H(ah, rax);
+UPDATE_GPR_INFO_8H(bh, rbx);
+UPDATE_GPR_INFO_8H(ch, rcx);
+UPDATE_GPR_INFO_8H(dh, rdx);
+UPDATE_GPR_INFO(al, rax);
+UPDATE_GPR_INFO(bl, rbx);
+UPDATE_GPR_INFO(cl, rcx);
+UPDATE_GPR_INFO(dl, rdx);
+
+UPDATE_FPR_INFO(fctrl, fctrl);
+UPDATE_FPR_INFO(fstat, fstat);
+UPDATE_FPR_INFO(ftag, ftag);
+UPDATE_FPR_INFO(fop, fop);
+UPDATE_FPR_INFO(fiseg, ptr.i386_.fiseg);
+UPDATE_FPR_INFO(fioff, ptr.i386_.fioff);
+UPDATE_FPR_INFO(fooff, ptr.i386_.fooff);
+UPDATE_FPR_INFO(foseg, ptr.i386_.foseg);
+UPDATE_FPR_INFO(mxcsr, mxcsr);
+UPDATE_FPR_INFO(mxcsrmask, mxcsrmask);
+
+UPDATE_FP_INFO(st, 0);
+UPDATE_FP_INFO(st, 1);
+UPDATE_FP_INFO(st, 2);
+UPDATE_FP_INFO(st, 3);
+UPDATE_FP_INFO(st, 4);
+UPDATE_FP_INFO(st, 5);
+UPDATE_FP_INFO(st, 6);
+UPDATE_FP_INFO(st, 7);
+UPDATE_FP_INFO(mm, 0);
+UPDATE_FP_INFO(mm, 1);
+UPDATE_FP_INFO(mm, 2);
+UPDATE_FP_INFO(mm, 3);
+UPDATE_FP_INFO(mm, 4);
+UPDATE_FP_INFO(mm, 5);
+UPDATE_FP_INFO(mm, 6);
+UPDATE_FP_INFO(mm, 7);
+
+UPDATE_XMM_INFO(xmm, 0);
+UPDATE_XMM_INFO(xmm, 1);
+UPDATE_XMM_INFO(xmm, 2);
+UPDATE_XMM_INFO(xmm, 3);
+UPDATE_XMM_INFO(xmm, 4);
+UPDATE_XMM_INFO(xmm, 5);
+UPDATE_XMM_INFO(xmm, 6);
+UPDATE_XMM_INFO(xmm, 7);
+
+UPDATE_YMM_INFO(ymm, 0);
+UPDATE_YMM_INFO(ymm, 1);
+UPDATE_YMM_INFO(ymm, 2);
+UPDATE_YMM_INFO(ymm, 3);
+UPDATE_YMM_INFO(ymm, 4);
+UPDATE_YMM_INFO(ymm, 5);
+UPDATE_YMM_INFO(ymm, 6);
+UPDATE_YMM_INFO(ymm, 7);
+
+UPDATE_DR_INFO(0);
+UPDATE_DR_INFO(1);
+UPDATE_DR_INFO(2);
+UPDATE_DR_INFO(3);
+UPDATE_DR_INFO(4);
+UPDATE_DR_INFO(5);
+UPDATE_DR_INFO(6);
+UPDATE_DR_INFO(7);
+
+#undef UPDATE_GPR_INFO
+#undef UPDATE_GPR_INFO_8H
+#undef UPDATE_FPR_INFO
+#undef UPDATE_FP_INFO
+#undef UPDATE_XMM_INFO
+#undef UPDATE_YMM_INFO
+#undef UPDATE_DR_INFO
+
+#endif // UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
+
+#undef GPR_OFFSET
+#undef FPR_OFFSET
+#undef YMM_OFFSET

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64_with_base_shared.cpp b/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64_with_base_shared.cpp
new file mode 100644
index 00000000000000..a894dfe6143c41
--- /dev/null
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64_with_base_shared.cpp
@@ -0,0 +1,321 @@
+//===-- RegisterInfos_x86_64_with_base_shared.cpp--------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RegisterInfos_x86_64_with_base_shared.h"
+
+#include "lldb/lldb-defines.h"
+#include <mutex>
+
+using namespace lldb;
+
+namespace lldb_private {
+
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_eax[] = {
+    lldb_eax_i386, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_ebx[] = {
+    lldb_ebx_i386, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_ecx[] = {
+    lldb_ecx_i386, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_edx[] = {
+    lldb_edx_i386, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_edi[] = {
+    lldb_edi_i386, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_esi[] = {
+    lldb_esi_i386, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_ebp[] = {
+    lldb_ebp_i386, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_esp[] = {
+    lldb_esp_i386, LLDB_INVALID_REGNUM};
+
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_eax[] = {
+    lldb_eax_i386, lldb_ax_i386, lldb_ah_i386, lldb_al_i386,
+    LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_ebx[] = {
+    lldb_ebx_i386, lldb_bx_i386, lldb_bh_i386, lldb_bl_i386,
+    LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_ecx[] = {
+    lldb_ecx_i386, lldb_cx_i386, lldb_ch_i386, lldb_cl_i386,
+    LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_edx[] = {
+    lldb_edx_i386, lldb_dx_i386, lldb_dh_i386, lldb_dl_i386,
+    LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_edi[] = {
+    lldb_edi_i386, lldb_di_i386, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_esi[] = {
+    lldb_esi_i386, lldb_si_i386, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_ebp[] = {
+    lldb_ebp_i386, lldb_bp_i386, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_esp[] = {
+    lldb_esp_i386, lldb_sp_i386, LLDB_INVALID_REGNUM};
+
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_rax[] = {
+    x86_64_with_base::lldb_rax, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_rbx[] = {
+    x86_64_with_base::lldb_rbx, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_rcx[] = {
+    x86_64_with_base::lldb_rcx, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_rdx[] = {
+    x86_64_with_base::lldb_rdx, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_rdi[] = {
+    x86_64_with_base::lldb_rdi, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_rsi[] = {
+    x86_64_with_base::lldb_rsi, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_rbp[] = {
+    x86_64_with_base::lldb_rbp, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_rsp[] = {
+    x86_64_with_base::lldb_rsp, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_r8[] = {
+    x86_64_with_base::lldb_r8, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_r9[] = {
+    x86_64_with_base::lldb_r9, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_r10[] = {
+    x86_64_with_base::lldb_r10, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_r11[] = {
+    x86_64_with_base::lldb_r11, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_r12[] = {
+    x86_64_with_base::lldb_r12, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_r13[] = {
+    x86_64_with_base::lldb_r13, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_r14[] = {
+    x86_64_with_base::lldb_r14, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_r15[] = {
+    x86_64_with_base::lldb_r15, LLDB_INVALID_REGNUM};
+
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_rax[] = {
+    x86_64_with_base::lldb_rax, x86_64_with_base::lldb_eax,
+    x86_64_with_base::lldb_ax,  x86_64_with_base::lldb_ah,
+    x86_64_with_base::lldb_al,  LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_rbx[] = {
+    x86_64_with_base::lldb_rbx, x86_64_with_base::lldb_ebx,
+    x86_64_with_base::lldb_bx,  x86_64_with_base::lldb_bh,
+    x86_64_with_base::lldb_bl,  LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_rcx[] = {
+    x86_64_with_base::lldb_rcx, x86_64_with_base::lldb_ecx,
+    x86_64_with_base::lldb_cx,  x86_64_with_base::lldb_ch,
+    x86_64_with_base::lldb_cl,  LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_rdx[] = {
+    x86_64_with_base::lldb_rdx, x86_64_with_base::lldb_edx,
+    x86_64_with_base::lldb_dx,  x86_64_with_base::lldb_dh,
+    x86_64_with_base::lldb_dl,  LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_rdi[] = {
+    x86_64_with_base::lldb_rdi, x86_64_with_base::lldb_edi,
+    x86_64_with_base::lldb_di, x86_64_with_base::lldb_dil, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_rsi[] = {
+    x86_64_with_base::lldb_rsi, x86_64_with_base::lldb_esi,
+    x86_64_with_base::lldb_si, x86_64_with_base::lldb_sil, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_rbp[] = {
+    x86_64_with_base::lldb_rbp, x86_64_with_base::lldb_ebp,
+    x86_64_with_base::lldb_bp, x86_64_with_base::lldb_bpl, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_rsp[] = {
+    x86_64_with_base::lldb_rsp, x86_64_with_base::lldb_esp,
+    x86_64_with_base::lldb_sp, x86_64_with_base::lldb_spl, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_r8[] = {
+    x86_64_with_base::lldb_r8, x86_64_with_base::lldb_r8d,
+    x86_64_with_base::lldb_r8w, x86_64_with_base::lldb_r8l,
+    LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_r9[] = {
+    x86_64_with_base::lldb_r9, x86_64_with_base::lldb_r9d,
+    x86_64_with_base::lldb_r9w, x86_64_with_base::lldb_r9l,
+    LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_r10[] = {
+    x86_64_with_base::lldb_r10, x86_64_with_base::lldb_r10d,
+    x86_64_with_base::lldb_r10w, x86_64_with_base::lldb_r10l,
+    LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_r11[] = {
+    x86_64_with_base::lldb_r11, x86_64_with_base::lldb_r11d,
+    x86_64_with_base::lldb_r11w, x86_64_with_base::lldb_r11l,
+    LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_r12[] = {
+    x86_64_with_base::lldb_r12, x86_64_with_base::lldb_r12d,
+    x86_64_with_base::lldb_r12w, x86_64_with_base::lldb_r12l,
+    LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_r13[] = {
+    x86_64_with_base::lldb_r13, x86_64_with_base::lldb_r13d,
+    x86_64_with_base::lldb_r13w, x86_64_with_base::lldb_r13l,
+    LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_r14[] = {
+    x86_64_with_base::lldb_r14, x86_64_with_base::lldb_r14d,
+    x86_64_with_base::lldb_r14w, x86_64_with_base::lldb_r14l,
+    LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_r15[] = {
+    x86_64_with_base::lldb_r15, x86_64_with_base::lldb_r15d,
+    x86_64_with_base::lldb_r15w, x86_64_with_base::lldb_r15l,
+    LLDB_INVALID_REGNUM};
+
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_fip[] = {
+    x86_64_with_base::lldb_fip, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_fdp[] = {
+    x86_64_with_base::lldb_fdp, LLDB_INVALID_REGNUM};
+
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_fip[] = {
+    x86_64_with_base::lldb_fip, x86_64_with_base::lldb_fioff,
+    x86_64_with_base::lldb_fiseg, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_fdp[] = {
+    x86_64_with_base::lldb_fdp, x86_64_with_base::lldb_fooff,
+    x86_64_with_base::lldb_foseg, LLDB_INVALID_REGNUM};
+
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_st0_32[] = {
+    lldb_st0_i386, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_st1_32[] = {
+    lldb_st1_i386, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_st2_32[] = {
+    lldb_st2_i386, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_st3_32[] = {
+    lldb_st3_i386, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_st4_32[] = {
+    lldb_st4_i386, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_st5_32[] = {
+    lldb_st5_i386, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_st6_32[] = {
+    lldb_st6_i386, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_st7_32[] = {
+    lldb_st7_i386, LLDB_INVALID_REGNUM};
+
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_st0_32[] = {
+    lldb_st0_i386, lldb_mm0_i386, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_st1_32[] = {
+    lldb_st1_i386, lldb_mm1_i386, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_st2_32[] = {
+    lldb_st2_i386, lldb_mm2_i386, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_st3_32[] = {
+    lldb_st3_i386, lldb_mm3_i386, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_st4_32[] = {
+    lldb_st4_i386, lldb_mm4_i386, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_st5_32[] = {
+    lldb_st5_i386, lldb_mm5_i386, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_st6_32[] = {
+    lldb_st6_i386, lldb_mm6_i386, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_st7_32[] = {
+    lldb_st7_i386, lldb_mm7_i386, LLDB_INVALID_REGNUM};
+
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_st0_64[] = {
+    x86_64_with_base::lldb_st0, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_st1_64[] = {
+    x86_64_with_base::lldb_st1, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_st2_64[] = {
+    x86_64_with_base::lldb_st2, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_st3_64[] = {
+    x86_64_with_base::lldb_st3, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_st4_64[] = {
+    x86_64_with_base::lldb_st4, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_st5_64[] = {
+    x86_64_with_base::lldb_st5, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_st6_64[] = {
+    x86_64_with_base::lldb_st6, LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_contained_st7_64[] = {
+    x86_64_with_base::lldb_st7, LLDB_INVALID_REGNUM};
+
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_st0_64[] = {
+    x86_64_with_base::lldb_st0, x86_64_with_base::lldb_mm0,
+    LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_st1_64[] = {
+    x86_64_with_base::lldb_st1, x86_64_with_base::lldb_mm1,
+    LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_st2_64[] = {
+    x86_64_with_base::lldb_st2, x86_64_with_base::lldb_mm2,
+    LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_st3_64[] = {
+    x86_64_with_base::lldb_st3, x86_64_with_base::lldb_mm3,
+    LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_st4_64[] = {
+    x86_64_with_base::lldb_st4, x86_64_with_base::lldb_mm4,
+    LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_st5_64[] = {
+    x86_64_with_base::lldb_st5, x86_64_with_base::lldb_mm5,
+    LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_st6_64[] = {
+    x86_64_with_base::lldb_st6, x86_64_with_base::lldb_mm6,
+    LLDB_INVALID_REGNUM};
+uint32_t RegisterInfos_x86_64_with_base_shared::g_invalidate_st7_64[] = {
+    x86_64_with_base::lldb_st7, x86_64_with_base::lldb_mm7,
+    LLDB_INVALID_REGNUM};
+
+RegInfo &GetRegInfoShared(llvm::Triple::ArchType arch_type, bool with_base) {
+  static std::once_flag once_flag_x86, once_flag_x86_64,
+      once_flag_x86_64_with_base;
+  static RegInfo reg_info_x86, reg_info_x86_64, reg_info_x86_64_with_base;
+
+  switch (arch_type) {
+  case llvm::Triple::x86:
+    std::call_once(once_flag_x86, []() {
+      reg_info_x86.num_registers = k_num_registers_i386;
+      reg_info_x86.num_gpr_registers = k_num_gpr_registers_i386;
+      reg_info_x86.num_fpr_registers = k_num_fpr_registers_i386;
+      reg_info_x86.num_avx_registers = k_num_avx_registers_i386;
+      reg_info_x86.last_gpr = k_last_gpr_i386;
+      reg_info_x86.first_fpr = k_first_fpr_i386;
+      reg_info_x86.last_fpr = k_last_fpr_i386;
+      reg_info_x86.first_st = lldb_st0_i386;
+      reg_info_x86.last_st = lldb_st7_i386;
+      reg_info_x86.first_mm = lldb_mm0_i386;
+      reg_info_x86.last_mm = lldb_mm7_i386;
+      reg_info_x86.first_xmm = lldb_xmm0_i386;
+      reg_info_x86.last_xmm = lldb_xmm7_i386;
+      reg_info_x86.first_ymm = lldb_ymm0_i386;
+      reg_info_x86.last_ymm = lldb_ymm7_i386;
+      reg_info_x86.first_dr = lldb_dr0_i386;
+      reg_info_x86.gpr_flags = lldb_eflags_i386;
+    });
+
+    return reg_info_x86;
+  case llvm::Triple::x86_64:
+    if (with_base) {
+      std::call_once(once_flag_x86_64_with_base, []() {
+        reg_info_x86_64_with_base.num_registers =
+            x86_64_with_base::k_num_registers;
+        reg_info_x86_64_with_base.num_gpr_registers =
+            x86_64_with_base::k_num_gpr_registers;
+        reg_info_x86_64_with_base.num_fpr_registers =
+            x86_64_with_base::k_num_fpr_registers;
+        reg_info_x86_64_with_base.num_avx_registers =
+            x86_64_with_base::k_num_avx_registers;
+        reg_info_x86_64_with_base.last_gpr = x86_64_with_base::k_last_gpr;
+        reg_info_x86_64_with_base.first_fpr = x86_64_with_base::k_first_fpr;
+        reg_info_x86_64_with_base.last_fpr = x86_64_with_base::k_last_fpr;
+        reg_info_x86_64_with_base.first_st = x86_64_with_base::lldb_st0;
+        reg_info_x86_64_with_base.last_st = x86_64_with_base::lldb_st7;
+        reg_info_x86_64_with_base.first_mm = x86_64_with_base::lldb_mm0;
+        reg_info_x86_64_with_base.last_mm = x86_64_with_base::lldb_mm7;
+        reg_info_x86_64_with_base.first_xmm = x86_64_with_base::lldb_xmm0;
+        reg_info_x86_64_with_base.last_xmm = x86_64_with_base::lldb_xmm15;
+        reg_info_x86_64_with_base.first_ymm = x86_64_with_base::lldb_ymm0;
+        reg_info_x86_64_with_base.last_ymm = x86_64_with_base::lldb_ymm15;
+        reg_info_x86_64_with_base.first_dr = x86_64_with_base::lldb_dr0;
+        reg_info_x86_64_with_base.gpr_flags = x86_64_with_base::lldb_rflags;
+      });
+
+      return reg_info_x86_64_with_base;
+    } else {
+      std::call_once(once_flag_x86_64, []() {
+        reg_info_x86_64.num_registers = k_num_registers_x86_64;
+        reg_info_x86_64.num_gpr_registers = k_num_gpr_registers_x86_64;
+        reg_info_x86_64.num_fpr_registers = k_num_fpr_registers_x86_64;
+        reg_info_x86_64.num_avx_registers = k_num_avx_registers_x86_64;
+        reg_info_x86_64.last_gpr = k_last_gpr_x86_64;
+        reg_info_x86_64.first_fpr = k_first_fpr_x86_64;
+        reg_info_x86_64.last_fpr = k_last_fpr_x86_64;
+        reg_info_x86_64.first_st = lldb_st0_x86_64;
+        reg_info_x86_64.last_st = lldb_st7_x86_64;
+        reg_info_x86_64.first_mm = lldb_mm0_x86_64;
+        reg_info_x86_64.last_mm = lldb_mm7_x86_64;
+        reg_info_x86_64.first_xmm = lldb_xmm0_x86_64;
+        reg_info_x86_64.last_xmm = lldb_xmm15_x86_64;
+        reg_info_x86_64.first_ymm = lldb_ymm0_x86_64;
+        reg_info_x86_64.last_ymm = lldb_ymm15_x86_64;
+        reg_info_x86_64.first_dr = lldb_dr0_x86_64;
+        reg_info_x86_64.gpr_flags = lldb_rflags_x86_64;
+      });
+      return reg_info_x86_64;
+    }
+  default:
+    assert(false && "Unhandled target architecture.");
+    break;
+  }
+}
+
+} // namespace lldb_private

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64_with_base_shared.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64_with_base_shared.h
new file mode 100644
index 00000000000000..5e4406c1fa275a
--- /dev/null
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64_with_base_shared.h
@@ -0,0 +1,142 @@
+//===-- RegisterInfos_x86_64_with_base_shared.h -----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
+#include <stdint.h>
+
+#ifndef lldb_RegisterInfos_x86_64_with_base_shared_h
+#define lldb_RegisterInfos_x86_64_with_base_shared_h
+
+#include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h"
+
+namespace lldb_private {
+
+struct RegisterInfos_x86_64_with_base_shared {
+  static uint32_t g_contained_eax[];
+  static uint32_t g_contained_ebx[];
+  static uint32_t g_contained_ecx[];
+  static uint32_t g_contained_edx[];
+  static uint32_t g_contained_edi[];
+  static uint32_t g_contained_esi[];
+  static uint32_t g_contained_ebp[];
+  static uint32_t g_contained_esp[];
+
+  static uint32_t g_invalidate_eax[];
+  static uint32_t g_invalidate_ebx[];
+  static uint32_t g_invalidate_ecx[];
+  static uint32_t g_invalidate_edx[];
+  static uint32_t g_invalidate_edi[];
+  static uint32_t g_invalidate_esi[];
+  static uint32_t g_invalidate_ebp[];
+  static uint32_t g_invalidate_esp[];
+
+  static uint32_t g_contained_rax[];
+  static uint32_t g_contained_rbx[];
+  static uint32_t g_contained_rcx[];
+  static uint32_t g_contained_rdx[];
+  static uint32_t g_contained_rdi[];
+  static uint32_t g_contained_rsi[];
+  static uint32_t g_contained_rbp[];
+  static uint32_t g_contained_rsp[];
+  static uint32_t g_contained_r8[];
+  static uint32_t g_contained_r9[];
+  static uint32_t g_contained_r10[];
+  static uint32_t g_contained_r11[];
+  static uint32_t g_contained_r12[];
+  static uint32_t g_contained_r13[];
+  static uint32_t g_contained_r14[];
+  static uint32_t g_contained_r15[];
+
+  static uint32_t g_invalidate_rax[];
+  static uint32_t g_invalidate_rbx[];
+  static uint32_t g_invalidate_rcx[];
+  static uint32_t g_invalidate_rdx[];
+  static uint32_t g_invalidate_rdi[];
+  static uint32_t g_invalidate_rsi[];
+  static uint32_t g_invalidate_rbp[];
+  static uint32_t g_invalidate_rsp[];
+  static uint32_t g_invalidate_r8[];
+  static uint32_t g_invalidate_r9[];
+  static uint32_t g_invalidate_r10[];
+  static uint32_t g_invalidate_r11[];
+  static uint32_t g_invalidate_r12[];
+  static uint32_t g_invalidate_r13[];
+  static uint32_t g_invalidate_r14[];
+  static uint32_t g_invalidate_r15[];
+
+  static uint32_t g_contained_fip[];
+  static uint32_t g_contained_fdp[];
+
+  static uint32_t g_invalidate_fip[];
+  static uint32_t g_invalidate_fdp[];
+
+  static uint32_t g_contained_st0_32[];
+  static uint32_t g_contained_st1_32[];
+  static uint32_t g_contained_st2_32[];
+  static uint32_t g_contained_st3_32[];
+  static uint32_t g_contained_st4_32[];
+  static uint32_t g_contained_st5_32[];
+  static uint32_t g_contained_st6_32[];
+  static uint32_t g_contained_st7_32[];
+
+  static uint32_t g_invalidate_st0_32[];
+  static uint32_t g_invalidate_st1_32[];
+  static uint32_t g_invalidate_st2_32[];
+  static uint32_t g_invalidate_st3_32[];
+  static uint32_t g_invalidate_st4_32[];
+  static uint32_t g_invalidate_st5_32[];
+  static uint32_t g_invalidate_st6_32[];
+  static uint32_t g_invalidate_st7_32[];
+
+  static uint32_t g_contained_st0_64[];
+  static uint32_t g_contained_st1_64[];
+  static uint32_t g_contained_st2_64[];
+  static uint32_t g_contained_st3_64[];
+  static uint32_t g_contained_st4_64[];
+  static uint32_t g_contained_st5_64[];
+  static uint32_t g_contained_st6_64[];
+  static uint32_t g_contained_st7_64[];
+
+  static uint32_t g_invalidate_st0_64[];
+  static uint32_t g_invalidate_st1_64[];
+  static uint32_t g_invalidate_st2_64[];
+  static uint32_t g_invalidate_st3_64[];
+  static uint32_t g_invalidate_st4_64[];
+  static uint32_t g_invalidate_st5_64[];
+  static uint32_t g_invalidate_st6_64[];
+  static uint32_t g_invalidate_st7_64[];
+};
+
+struct RegInfo {
+  uint32_t num_registers;
+  uint32_t num_gpr_registers;
+  uint32_t num_fpr_registers;
+  uint32_t num_avx_registers;
+
+  uint32_t last_gpr;
+  uint32_t first_fpr;
+  uint32_t last_fpr;
+
+  uint32_t first_st;
+  uint32_t last_st;
+  uint32_t first_mm;
+  uint32_t last_mm;
+  uint32_t first_xmm;
+  uint32_t last_xmm;
+  uint32_t first_ymm;
+  uint32_t last_ymm;
+
+  uint32_t first_dr;
+  uint32_t gpr_flags;
+};
+
+RegInfo &GetRegInfoShared(llvm::Triple::ArchType arch_type, bool with_base);
+
+} // namespace lldb_private
+
+#endif // ifndef lldb_RegisterInfos_x86_64_with_base_shared_h

diff  --git a/lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h b/lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h
index 4d10600f47713e..85aa254d662123 100644
--- a/lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h
+++ b/lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h
@@ -321,6 +321,197 @@ enum {
                                 k_num_mpx_registers_x86_64,
   k_num_dbr_registers_x86_64 = k_last_dbr_x86_64 - k_first_dbr_x86_64 + 1,
 };
+
+// For platform that supports fs_base/gs_base registers.
+namespace x86_64_with_base {
+enum {
+  k_first_gpr,
+  lldb_rax = k_first_gpr,
+  lldb_rbx,
+  lldb_rcx,
+  lldb_rdx,
+  lldb_rdi,
+  lldb_rsi,
+  lldb_rbp,
+  lldb_rsp,
+  lldb_r8,
+  lldb_r9,
+  lldb_r10,
+  lldb_r11,
+  lldb_r12,
+  lldb_r13,
+  lldb_r14,
+  lldb_r15,
+  lldb_rip,
+  lldb_rflags,
+  lldb_cs,
+  lldb_fs,
+  lldb_gs,
+  lldb_ss,
+  lldb_fs_base,
+  lldb_gs_base,
+  lldb_ds,
+  lldb_es,
+
+  k_first_alias,
+  lldb_eax = k_first_alias,
+  lldb_ebx,
+  lldb_ecx,
+  lldb_edx,
+  lldb_edi,
+  lldb_esi,
+  lldb_ebp,
+  lldb_esp,
+  lldb_r8d,  // Low 32 bits of r8
+  lldb_r9d,  // Low 32 bits of r9
+  lldb_r10d, // Low 32 bits of r10
+  lldb_r11d, // Low 32 bits of r11
+  lldb_r12d, // Low 32 bits of r12
+  lldb_r13d, // Low 32 bits of r13
+  lldb_r14d, // Low 32 bits of r14
+  lldb_r15d, // Low 32 bits of r15
+  lldb_ax,
+  lldb_bx,
+  lldb_cx,
+  lldb_dx,
+  lldb_di,
+  lldb_si,
+  lldb_bp,
+  lldb_sp,
+  lldb_r8w,  // Low 16 bits of r8
+  lldb_r9w,  // Low 16 bits of r9
+  lldb_r10w, // Low 16 bits of r10
+  lldb_r11w, // Low 16 bits of r11
+  lldb_r12w, // Low 16 bits of r12
+  lldb_r13w, // Low 16 bits of r13
+  lldb_r14w, // Low 16 bits of r14
+  lldb_r15w, // Low 16 bits of r15
+  lldb_ah,
+  lldb_bh,
+  lldb_ch,
+  lldb_dh,
+  lldb_al,
+  lldb_bl,
+  lldb_cl,
+  lldb_dl,
+  lldb_dil,
+  lldb_sil,
+  lldb_bpl,
+  lldb_spl,
+  lldb_r8l,  // Low 8 bits of r8
+  lldb_r9l,  // Low 8 bits of r9
+  lldb_r10l, // Low 8 bits of r10
+  lldb_r11l, // Low 8 bits of r11
+  lldb_r12l, // Low 8 bits of r12
+  lldb_r13l, // Low 8 bits of r13
+  lldb_r14l, // Low 8 bits of r14
+  lldb_r15l, // Low 8 bits of r15
+  k_last_alias = lldb_r15l,
+
+  k_last_gpr = k_last_alias,
+
+  k_first_fpr,
+  lldb_fctrl = k_first_fpr,
+  lldb_fstat,
+  lldb_ftag,
+  lldb_fop,
+  lldb_fiseg,
+  lldb_fioff,
+  lldb_fip,
+  lldb_foseg,
+  lldb_fooff,
+  lldb_fdp,
+  lldb_mxcsr,
+  lldb_mxcsrmask,
+  lldb_st0,
+  lldb_st1,
+  lldb_st2,
+  lldb_st3,
+  lldb_st4,
+  lldb_st5,
+  lldb_st6,
+  lldb_st7,
+  lldb_mm0,
+  lldb_mm1,
+  lldb_mm2,
+  lldb_mm3,
+  lldb_mm4,
+  lldb_mm5,
+  lldb_mm6,
+  lldb_mm7,
+  lldb_xmm0,
+  lldb_xmm1,
+  lldb_xmm2,
+  lldb_xmm3,
+  lldb_xmm4,
+  lldb_xmm5,
+  lldb_xmm6,
+  lldb_xmm7,
+  lldb_xmm8,
+  lldb_xmm9,
+  lldb_xmm10,
+  lldb_xmm11,
+  lldb_xmm12,
+  lldb_xmm13,
+  lldb_xmm14,
+  lldb_xmm15,
+  k_last_fpr = lldb_xmm15,
+
+  k_first_avx,
+  lldb_ymm0 = k_first_avx,
+  lldb_ymm1,
+  lldb_ymm2,
+  lldb_ymm3,
+  lldb_ymm4,
+  lldb_ymm5,
+  lldb_ymm6,
+  lldb_ymm7,
+  lldb_ymm8,
+  lldb_ymm9,
+  lldb_ymm10,
+  lldb_ymm11,
+  lldb_ymm12,
+  lldb_ymm13,
+  lldb_ymm14,
+  lldb_ymm15,
+  k_last_avx = lldb_ymm15,
+
+  k_first_mpxr,
+  lldb_bnd0 = k_first_mpxr,
+  lldb_bnd1,
+  lldb_bnd2,
+  lldb_bnd3,
+  k_last_mpxr = lldb_bnd3,
+
+  k_first_mpxc,
+  lldb_bndcfgu = k_first_mpxc,
+  lldb_bndstatus,
+  k_last_mpxc = lldb_bndstatus,
+
+  k_first_dbr,
+  lldb_dr0 = k_first_dbr,
+  lldb_dr1,
+  lldb_dr2,
+  lldb_dr3,
+  lldb_dr4,
+  lldb_dr5,
+  lldb_dr6,
+  lldb_dr7,
+  k_last_dbr = lldb_dr7,
+
+  k_num_registers,
+  k_num_gpr_registers = k_last_gpr - k_first_gpr + 1,
+  k_num_fpr_registers = k_last_fpr - k_first_fpr + 1,
+  k_num_avx_registers = k_last_avx - k_first_avx + 1,
+  k_num_mpx_registers = k_last_mpxc - k_first_mpxr + 1,
+  k_num_user_registers = k_num_gpr_registers +
+                                k_num_fpr_registers +
+                                k_num_avx_registers +
+                                k_num_mpx_registers,
+  k_num_dbr_registers = k_last_dbr - k_first_dbr + 1,
+};
+} // namespace x86_64_with_base
+
 }
 
 #endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_X86_REGISTER_ENUMS_H

diff  --git a/lldb/source/Plugins/Process/elf-core/CMakeLists.txt b/lldb/source/Plugins/Process/elf-core/CMakeLists.txt
index 9b6739824c066f..8ddc671e3ae66d 100644
--- a/lldb/source/Plugins/Process/elf-core/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/elf-core/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_lldb_library(lldbPluginProcessElfCore PLUGIN
   ProcessElfCore.cpp
   ThreadElfCore.cpp
+  RegisterContextLinuxCore_x86_64.cpp
   RegisterContextPOSIXCore_arm.cpp
   RegisterContextPOSIXCore_arm64.cpp
   RegisterContextPOSIXCore_mips64.cpp

diff  --git a/lldb/source/Plugins/Process/elf-core/RegisterContextLinuxCore_x86_64.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextLinuxCore_x86_64.cpp
new file mode 100644
index 00000000000000..b806292c7a1a2f
--- /dev/null
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextLinuxCore_x86_64.cpp
@@ -0,0 +1,237 @@
+//===-- RegisterContextLinuxCore_x86_64.cpp -------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RegisterContextLinuxCore_x86_64.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/RegisterValue.h"
+
+using namespace lldb_private;
+
+const uint32_t g_gpr_regnums_i386[] = {
+    lldb_eax_i386,       lldb_ebx_i386,    lldb_ecx_i386, lldb_edx_i386,
+    lldb_edi_i386,       lldb_esi_i386,    lldb_ebp_i386, lldb_esp_i386,
+    lldb_eip_i386,       lldb_eflags_i386, lldb_cs_i386,  lldb_fs_i386,
+    lldb_gs_i386,        lldb_ss_i386,     lldb_ds_i386,  lldb_es_i386,
+    lldb_ax_i386,        lldb_bx_i386,     lldb_cx_i386,  lldb_dx_i386,
+    lldb_di_i386,        lldb_si_i386,     lldb_bp_i386,  lldb_sp_i386,
+    lldb_ah_i386,        lldb_bh_i386,     lldb_ch_i386,  lldb_dh_i386,
+    lldb_al_i386,        lldb_bl_i386,     lldb_cl_i386,  lldb_dl_i386,
+    LLDB_INVALID_REGNUM, // Register sets must be terminated with
+                         // LLDB_INVALID_REGNUM.
+};
+static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) -
+                      1 ==
+                  k_num_gpr_registers_i386,
+              "g_gpr_regnums_i386 has wrong number of register infos");
+
+const uint32_t g_lldb_regnums_i386[] = {
+    lldb_fctrl_i386,    lldb_fstat_i386,     lldb_ftag_i386,  lldb_fop_i386,
+    lldb_fiseg_i386,    lldb_fioff_i386,     lldb_foseg_i386, lldb_fooff_i386,
+    lldb_mxcsr_i386,    lldb_mxcsrmask_i386, lldb_st0_i386,   lldb_st1_i386,
+    lldb_st2_i386,      lldb_st3_i386,       lldb_st4_i386,   lldb_st5_i386,
+    lldb_st6_i386,      lldb_st7_i386,       lldb_mm0_i386,   lldb_mm1_i386,
+    lldb_mm2_i386,      lldb_mm3_i386,       lldb_mm4_i386,   lldb_mm5_i386,
+    lldb_mm6_i386,      lldb_mm7_i386,       lldb_xmm0_i386,  lldb_xmm1_i386,
+    lldb_xmm2_i386,     lldb_xmm3_i386,      lldb_xmm4_i386,  lldb_xmm5_i386,
+    lldb_xmm6_i386,     lldb_xmm7_i386,
+    LLDB_INVALID_REGNUM // Register sets must be terminated with
+                        // LLDB_INVALID_REGNUM.
+};
+static_assert((sizeof(g_lldb_regnums_i386) / sizeof(g_lldb_regnums_i386[0])) -
+                      1 ==
+                  k_num_fpr_registers_i386,
+              "g_lldb_regnums_i386 has wrong number of register infos");
+
+const uint32_t g_avx_regnums_i386[] = {
+    lldb_ymm0_i386,     lldb_ymm1_i386, lldb_ymm2_i386, lldb_ymm3_i386,
+    lldb_ymm4_i386,     lldb_ymm5_i386, lldb_ymm6_i386, lldb_ymm7_i386,
+    LLDB_INVALID_REGNUM // Register sets must be terminated with
+                        // LLDB_INVALID_REGNUM.
+};
+static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) -
+                      1 ==
+                  k_num_avx_registers_i386,
+              " g_avx_regnums_i386 has wrong number of register infos");
+
+static const uint32_t g_gpr_regnums_x86_64[] = {
+    x86_64_with_base::lldb_rax,
+    x86_64_with_base::lldb_rbx,
+    x86_64_with_base::lldb_rcx,
+    x86_64_with_base::lldb_rdx,
+    x86_64_with_base::lldb_rdi,
+    x86_64_with_base::lldb_rsi,
+    x86_64_with_base::lldb_rbp,
+    x86_64_with_base::lldb_rsp,
+    x86_64_with_base::lldb_r8,
+    x86_64_with_base::lldb_r9,
+    x86_64_with_base::lldb_r10,
+    x86_64_with_base::lldb_r11,
+    x86_64_with_base::lldb_r12,
+    x86_64_with_base::lldb_r13,
+    x86_64_with_base::lldb_r14,
+    x86_64_with_base::lldb_r15,
+    x86_64_with_base::lldb_rip,
+    x86_64_with_base::lldb_rflags,
+    x86_64_with_base::lldb_cs,
+    x86_64_with_base::lldb_fs,
+    x86_64_with_base::lldb_gs,
+    x86_64_with_base::lldb_ss,
+    x86_64_with_base::lldb_fs_base,
+    x86_64_with_base::lldb_gs_base,
+    x86_64_with_base::lldb_ds,
+    x86_64_with_base::lldb_es,
+    x86_64_with_base::lldb_eax,
+    x86_64_with_base::lldb_ebx,
+    x86_64_with_base::lldb_ecx,
+    x86_64_with_base::lldb_edx,
+    x86_64_with_base::lldb_edi,
+    x86_64_with_base::lldb_esi,
+    x86_64_with_base::lldb_ebp,
+    x86_64_with_base::lldb_esp,
+    x86_64_with_base::lldb_r8d,  // Low 32 bits or r8
+    x86_64_with_base::lldb_r9d,  // Low 32 bits or r9
+    x86_64_with_base::lldb_r10d, // Low 32 bits or r10
+    x86_64_with_base::lldb_r11d, // Low 32 bits or r11
+    x86_64_with_base::lldb_r12d, // Low 32 bits or r12
+    x86_64_with_base::lldb_r13d, // Low 32 bits or r13
+    x86_64_with_base::lldb_r14d, // Low 32 bits or r14
+    x86_64_with_base::lldb_r15d, // Low 32 bits or r15
+    x86_64_with_base::lldb_ax,
+    x86_64_with_base::lldb_bx,
+    x86_64_with_base::lldb_cx,
+    x86_64_with_base::lldb_dx,
+    x86_64_with_base::lldb_di,
+    x86_64_with_base::lldb_si,
+    x86_64_with_base::lldb_bp,
+    x86_64_with_base::lldb_sp,
+    x86_64_with_base::lldb_r8w,  // Low 16 bits or r8
+    x86_64_with_base::lldb_r9w,  // Low 16 bits or r9
+    x86_64_with_base::lldb_r10w, // Low 16 bits or r10
+    x86_64_with_base::lldb_r11w, // Low 16 bits or r11
+    x86_64_with_base::lldb_r12w, // Low 16 bits or r12
+    x86_64_with_base::lldb_r13w, // Low 16 bits or r13
+    x86_64_with_base::lldb_r14w, // Low 16 bits or r14
+    x86_64_with_base::lldb_r15w, // Low 16 bits or r15
+    x86_64_with_base::lldb_ah,
+    x86_64_with_base::lldb_bh,
+    x86_64_with_base::lldb_ch,
+    x86_64_with_base::lldb_dh,
+    x86_64_with_base::lldb_al,
+    x86_64_with_base::lldb_bl,
+    x86_64_with_base::lldb_cl,
+    x86_64_with_base::lldb_dl,
+    x86_64_with_base::lldb_dil,
+    x86_64_with_base::lldb_sil,
+    x86_64_with_base::lldb_bpl,
+    x86_64_with_base::lldb_spl,
+    x86_64_with_base::lldb_r8l,  // Low 8 bits or r8
+    x86_64_with_base::lldb_r9l,  // Low 8 bits or r9
+    x86_64_with_base::lldb_r10l, // Low 8 bits or r10
+    x86_64_with_base::lldb_r11l, // Low 8 bits or r11
+    x86_64_with_base::lldb_r12l, // Low 8 bits or r12
+    x86_64_with_base::lldb_r13l, // Low 8 bits or r13
+    x86_64_with_base::lldb_r14l, // Low 8 bits or r14
+    x86_64_with_base::lldb_r15l, // Low 8 bits or r15
+    LLDB_INVALID_REGNUM          // Register sets must be terminated with
+                                 // LLDB_INVALID_REGNUM.
+};
+static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) -
+                      1 ==
+                  x86_64_with_base::k_num_gpr_registers,
+              "g_gpr_regnums_x86_64 has wrong number of register infos");
+
+static const uint32_t g_lldb_regnums_x86_64[] = {
+    x86_64_with_base::lldb_fctrl, x86_64_with_base::lldb_fstat,
+    x86_64_with_base::lldb_ftag,  x86_64_with_base::lldb_fop,
+    x86_64_with_base::lldb_fiseg, x86_64_with_base::lldb_fioff,
+    x86_64_with_base::lldb_fip,   x86_64_with_base::lldb_foseg,
+    x86_64_with_base::lldb_fooff, x86_64_with_base::lldb_fdp,
+    x86_64_with_base::lldb_mxcsr, x86_64_with_base::lldb_mxcsrmask,
+    x86_64_with_base::lldb_st0,   x86_64_with_base::lldb_st1,
+    x86_64_with_base::lldb_st2,   x86_64_with_base::lldb_st3,
+    x86_64_with_base::lldb_st4,   x86_64_with_base::lldb_st5,
+    x86_64_with_base::lldb_st6,   x86_64_with_base::lldb_st7,
+    x86_64_with_base::lldb_mm0,   x86_64_with_base::lldb_mm1,
+    x86_64_with_base::lldb_mm2,   x86_64_with_base::lldb_mm3,
+    x86_64_with_base::lldb_mm4,   x86_64_with_base::lldb_mm5,
+    x86_64_with_base::lldb_mm6,   x86_64_with_base::lldb_mm7,
+    x86_64_with_base::lldb_xmm0,  x86_64_with_base::lldb_xmm1,
+    x86_64_with_base::lldb_xmm2,  x86_64_with_base::lldb_xmm3,
+    x86_64_with_base::lldb_xmm4,  x86_64_with_base::lldb_xmm5,
+    x86_64_with_base::lldb_xmm6,  x86_64_with_base::lldb_xmm7,
+    x86_64_with_base::lldb_xmm8,  x86_64_with_base::lldb_xmm9,
+    x86_64_with_base::lldb_xmm10, x86_64_with_base::lldb_xmm11,
+    x86_64_with_base::lldb_xmm12, x86_64_with_base::lldb_xmm13,
+    x86_64_with_base::lldb_xmm14, x86_64_with_base::lldb_xmm15,
+    LLDB_INVALID_REGNUM // Register sets must be terminated with
+                        // LLDB_INVALID_REGNUM.
+};
+static_assert(
+    (sizeof(g_lldb_regnums_x86_64) / sizeof(g_lldb_regnums_x86_64[0])) - 1 ==
+        x86_64_with_base::k_num_fpr_registers,
+    "g_lldb_regnums_x86_64 has wrong number of register infos");
+
+static const uint32_t g_avx_regnums_x86_64[] = {
+    x86_64_with_base::lldb_ymm0,  x86_64_with_base::lldb_ymm1,
+    x86_64_with_base::lldb_ymm2,  x86_64_with_base::lldb_ymm3,
+    x86_64_with_base::lldb_ymm4,  x86_64_with_base::lldb_ymm5,
+    x86_64_with_base::lldb_ymm6,  x86_64_with_base::lldb_ymm7,
+    x86_64_with_base::lldb_ymm8,  x86_64_with_base::lldb_ymm9,
+    x86_64_with_base::lldb_ymm10, x86_64_with_base::lldb_ymm11,
+    x86_64_with_base::lldb_ymm12, x86_64_with_base::lldb_ymm13,
+    x86_64_with_base::lldb_ymm14, x86_64_with_base::lldb_ymm15,
+    LLDB_INVALID_REGNUM // Register sets must be terminated with
+                        // LLDB_INVALID_REGNUM.
+};
+static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) -
+                      1 ==
+                  x86_64_with_base::k_num_avx_registers,
+              "g_avx_regnums_x86_64 has wrong number of register infos");
+
+static const RegisterSet g_reg_sets_i386[] = {
+    {"General Purpose Registers", "gpr", k_num_gpr_registers_i386,
+     g_gpr_regnums_i386},
+    {"Floating Point Registers", "fpu", k_num_fpr_registers_i386,
+     g_lldb_regnums_i386},
+    {"Advanced Vector Extensions", "avx", k_num_avx_registers_i386,
+     g_avx_regnums_i386}};
+
+static const RegisterSet g_reg_sets_x86_64[] = {
+    {"General Purpose Registers", "gpr", x86_64_with_base::k_num_gpr_registers,
+     g_gpr_regnums_x86_64},
+    {"Floating Point Registers", "fpu", x86_64_with_base::k_num_fpr_registers,
+     g_lldb_regnums_x86_64},
+    {"Advanced Vector Extensions", "avx", x86_64_with_base::k_num_avx_registers,
+     g_avx_regnums_x86_64}};
+
+RegisterContextLinuxCore_x86_64::RegisterContextLinuxCore_x86_64(
+    Thread &thread, RegisterInfoInterface *register_info,
+    const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes)
+    : RegisterContextCorePOSIX_x86_64(thread, register_info, gpregset, notes) {}
+
+const RegisterSet *RegisterContextLinuxCore_x86_64::GetRegisterSet(size_t set) {
+  if (IsRegisterSetAvailable(set)) {
+    switch (m_register_info_up->GetTargetArchitecture().GetMachine()) {
+    case llvm::Triple::x86:
+      return &g_reg_sets_i386[set];
+    case llvm::Triple::x86_64:
+      return &g_reg_sets_x86_64[set];
+    default:
+      assert(false && "Unhandled target architecture.");
+      return nullptr;
+    }
+  }
+  return nullptr;
+}
+
+RegInfo &RegisterContextLinuxCore_x86_64::GetRegInfo() {
+  return GetRegInfoShared(
+      m_register_info_up->GetTargetArchitecture().GetMachine(),
+      /*with_base=*/true);
+}

diff  --git a/lldb/source/Plugins/Process/elf-core/RegisterContextLinuxCore_x86_64.h b/lldb/source/Plugins/Process/elf-core/RegisterContextLinuxCore_x86_64.h
new file mode 100644
index 00000000000000..a68ed82d718c37
--- /dev/null
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextLinuxCore_x86_64.h
@@ -0,0 +1,28 @@
+//===-- RegisterContextLinuxCore_x86_64.h -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTLINUXCORE_X86_64_H
+#define LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTLINUXCORE_X86_64_H
+
+#include "Plugins/Process/elf-core/RegisterUtilities.h"
+#include "RegisterContextPOSIXCore_x86_64.h"
+
+class RegisterContextLinuxCore_x86_64 : public RegisterContextCorePOSIX_x86_64 {
+public:
+  RegisterContextLinuxCore_x86_64(
+      lldb_private::Thread &thread,
+      lldb_private::RegisterInfoInterface *register_info,
+      const lldb_private::DataExtractor &gpregset,
+      llvm::ArrayRef<lldb_private::CoreNote> notes);
+
+  const lldb_private::RegisterSet *GetRegisterSet(size_t set) override;
+
+  lldb_private::RegInfo &GetRegInfo() override;
+};
+
+#endif // LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTLINUXCORE_X86_64_H

diff  --git a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
index 0191562d72230c..3ce2a4a5c3fa46 100644
--- a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
@@ -29,6 +29,7 @@
 #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
 #include "Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h"
 #include "ProcessElfCore.h"
+#include "RegisterContextLinuxCore_x86_64.h"
 #include "RegisterContextPOSIXCore_arm.h"
 #include "RegisterContextPOSIXCore_arm64.h"
 #include "RegisterContextPOSIXCore_mips64.h"
@@ -71,6 +72,7 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
   if (frame)
     concrete_frame_idx = frame->GetConcreteFrameIndex();
 
+  bool is_linux = false;
   if (concrete_frame_idx == 0) {
     if (m_thread_reg_ctx_sp)
       return m_thread_reg_ctx_sp;
@@ -123,6 +125,7 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
     }
 
     case llvm::Triple::Linux: {
+      is_linux = true;
       switch (arch.GetMachine()) {
       case llvm::Triple::aarch64:
         break;
@@ -206,8 +209,13 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
       break;
     case llvm::Triple::x86:
     case llvm::Triple::x86_64:
-      m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_x86_64>(
-          *this, reg_interface, m_gpregset_data, m_notes);
+      if (is_linux) {
+        m_thread_reg_ctx_sp = std::make_shared<RegisterContextLinuxCore_x86_64>(
+              *this, reg_interface, m_gpregset_data, m_notes);
+      } else {
+        m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_x86_64>(
+              *this, reg_interface, m_gpregset_data, m_notes);
+      }
       break;
     default:
       break;

diff  --git a/lldb/test/API/commands/register/register/register_command/TestRegisters.py b/lldb/test/API/commands/register/register/register_command/TestRegisters.py
index 9dfbd0dd84083b..e0edc8b60683da 100644
--- a/lldb/test/API/commands/register/register/register_command/TestRegisters.py
+++ b/lldb/test/API/commands/register/register/register_command/TestRegisters.py
@@ -606,3 +606,47 @@ def test_info_register(self):
 
         # This has an alternative name according to the ABI.
         self.expect("register info x30", substrs=["Name: lr (x30)"])
+
+    @skipUnlessPlatform(["linux"])
+    @skipIf(archs=no_match(["x86_64"]))
+    def test_fs_gs_base(self):
+        """
+        Tests fs_base register can be read and equals to pthread_self() return value
+        and gs_base register equals zero.
+        """
+        self.build()
+        target = self.createTestTarget()
+        # Launch the process and stop.
+        self.expect("run", PROCESS_STOPPED, substrs=["stopped"])
+
+        process = target.GetProcess()
+
+        thread = process.GetThreadAtIndex(0)
+        self.assertTrue(thread.IsValid(), "current thread is valid")
+
+        current_frame = thread.GetFrameAtIndex(0)
+        self.assertTrue(current_frame.IsValid(), "current frame is valid")
+
+        reg_fs_base = current_frame.FindRegister("fs_base")
+        self.assertTrue(reg_fs_base.IsValid(), "fs_base is not available")
+        reg_gs_base = current_frame.FindRegister("gs_base")
+        self.assertTrue(reg_gs_base.IsValid(), "gs_base is not available")
+        self.assertEqual(
+            reg_gs_base.GetValueAsSigned(-1), 0, f"gs_base should be zero"
+        )
+
+        # Evaluate pthread_self() and compare against fs_base register read.
+        pthread_self_code = "(uint64_t)pthread_self()"
+        pthread_self_val = current_frame.EvaluateExpression(pthread_self_code)
+        self.assertTrue(
+            pthread_self_val.IsValid(), f"{pthread_self_code} evaluation has failed"
+        )
+        self.assertNotEqual(
+            reg_fs_base.GetValueAsSigned(-1), -1, f"fs_base returned -1 which is wrong"
+        )
+
+        self.assertEqual(
+            reg_fs_base.GetValueAsUnsigned(0),
+            pthread_self_val.GetValueAsUnsigned(0),
+            "fs_base does not equal to pthread_self() value.",
+        )

diff  --git a/lldb/test/API/functionalities/postmortem/elf-core/thread_crash/TestLinuxCoreThreads.py b/lldb/test/API/functionalities/postmortem/elf-core/thread_crash/TestLinuxCoreThreads.py
index 5d79e5a9fc9963..a2c3b1f644f1cc 100644
--- a/lldb/test/API/functionalities/postmortem/elf-core/thread_crash/TestLinuxCoreThreads.py
+++ b/lldb/test/API/functionalities/postmortem/elf-core/thread_crash/TestLinuxCoreThreads.py
@@ -31,6 +31,41 @@ def test_x86_64(self):
         """Test that lldb can read the process information from an x86_64 linux core file."""
         self.do_test("linux-x86_64", self._x86_64_pid, self._x86_64_tid)
 
+    @skipIf(oslist=["windows"])
+    @skipIf(triple="^mips")
+    def test_fs_gs_base(self):
+        """Tests fs_base/gs_base registers can be read from linux coredump."""
+        target = self.dbg.CreateTarget(None)
+        process = target.LoadCore("linux-x86_64.core")
+        self.assertTrue(process, PROCESS_IS_VALID)
+
+        # The fs_base/gs_base registers in linux-x86_64.core are parsed by
+        # using "eu-readelf -n linux-x86_64.core" to verify.
+        fs_base_values = [0x00007fc295017700, 0x00007fc294fff740, 0x00007fc29501f700]
+        gs_base_values = [0, 0, 0]
+
+        for i in range(process.GetNumThreads()):
+            thread = process.GetThreadAtIndex(i)
+            self.assertTrue(thread.IsValid(), "current thread is valid")
+
+            current_frame = thread.GetFrameAtIndex(0)
+            self.assertTrue(current_frame.IsValid(), "current frame is valid")
+
+            reg_fs_base = current_frame.FindRegister("fs_base")
+            reg_gs_base = current_frame.FindRegister("gs_base")
+            self.assertTrue(reg_fs_base.IsValid(), "fs_base is not available")
+            self.assertTrue(reg_gs_base.IsValid(), "gs_base is not available")
+
+            self.assertEqual(
+                reg_fs_base.GetValueAsSigned(-1), fs_base_values[i], f"fs_base read is 
diff erent from expected"
+            )
+
+            self.assertEqual(
+                reg_gs_base.GetValueAsSigned(-1), gs_base_values[i], f"gs_base read is 
diff erent from expected"
+            )
+        self.dbg.DeleteTarget(target)
+
+
     def do_test(self, filename, pid, tid):
         target = self.dbg.CreateTarget("")
         process = target.LoadCore(filename + ".core")


        


More information about the lldb-commits mailing list