lldb: Fix empty register set when trying to get size of register

The register set information is stored as a singleton in
GetRegisterInfo_i386. However, other functions later access this
information assuming it is stored in GetSharedRegisterInfoVector. To
resolve this inconsistency, we remove the original construction logic
and instead initialize the singleton using llvm::call_once within the
appropriate function (GetSharedRegisterInfoVector_i386).

PR:		289945
Obtained from:	llvm-project 41859c27842eeda1ef6ff18f3b2fb269388c0857
This commit is contained in:
ShengYi Hung
2025-11-21 13:30:25 -05:00
committed by Ed Maste
parent fa1c56b3af
commit 1d1a2e6932
@@ -9,6 +9,7 @@
#include "RegisterContextFreeBSD_x86_64.h"
#include "RegisterContextFreeBSD_i386.h"
#include "RegisterContextPOSIX_x86.h"
#include "llvm/Support/Threading.h"
#include <vector>
using namespace lldb_private;
@@ -69,40 +70,34 @@ struct UserArea {
#include "RegisterInfos_x86_64.h"
#undef DECLARE_REGISTER_INFOS_X86_64_STRUCT
static std::vector<lldb_private::RegisterInfo> &GetSharedRegisterInfoVector() {
static std::vector<lldb_private::RegisterInfo> register_infos;
return register_infos;
}
static const RegisterInfo *
GetRegisterInfo_i386(const lldb_private::ArchSpec &arch) {
static std::vector<lldb_private::RegisterInfo> g_register_infos(
GetSharedRegisterInfoVector());
// Allocate RegisterInfo only once
if (g_register_infos.empty()) {
// Copy the register information from base class
std::unique_ptr<RegisterContextFreeBSD_i386> reg_interface(
new RegisterContextFreeBSD_i386(arch));
const RegisterInfo *base_info = reg_interface->GetRegisterInfo();
g_register_infos.insert(g_register_infos.end(), &base_info[0],
&base_info[k_num_registers_i386]);
static std::vector<lldb_private::RegisterInfo> &
GetSharedRegisterInfoVector_i386(const lldb_private::ArchSpec &arch) {
static std::vector<lldb_private::RegisterInfo> g_register_infos;
static llvm::once_flag g_initialized;
llvm::call_once(g_initialized, [&]() {
if (g_register_infos.empty()) {
// Copy the register information from base class
std::unique_ptr<RegisterContextFreeBSD_i386> reg_interface(
new RegisterContextFreeBSD_i386(arch));
const RegisterInfo *base_info = reg_interface->GetRegisterInfo();
g_register_infos.insert(g_register_infos.end(), &base_info[0],
&base_info[k_num_registers_i386]);
// 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"
#undef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
}
return &g_register_infos[0];
}
});
return g_register_infos;
}
static const RegisterInfo *
PrivateGetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) {
switch (target_arch.GetMachine()) {
case llvm::Triple::x86:
return GetRegisterInfo_i386(target_arch);
return &GetSharedRegisterInfoVector_i386(target_arch)[0];
case llvm::Triple::x86_64:
return g_register_infos_x86_64;
default:
@@ -116,9 +111,10 @@ PrivateGetRegisterCount(const lldb_private::ArchSpec &target_arch) {
switch (target_arch.GetMachine()) {
case llvm::Triple::x86:
// This vector should have already been filled.
assert(!GetSharedRegisterInfoVector().empty() &&
assert(!GetSharedRegisterInfoVector_i386(target_arch).empty() &&
"i386 register info vector not filled.");
return static_cast<uint32_t>(GetSharedRegisterInfoVector().size());
return static_cast<uint32_t>(
GetSharedRegisterInfoVector_i386(target_arch).size());
case llvm::Triple::x86_64:
return static_cast<uint32_t>(sizeof(g_register_infos_x86_64) /
sizeof(g_register_infos_x86_64[0]));