From 9007cde56ed024136ec832496d139f20b9205164 Mon Sep 17 00:00:00 2001 From: Mohammed Muqeet Us Salam Date: Fri, 1 May 2026 09:37:59 +0530 Subject: [PATCH] librz/bin: fix regstate load in ELF corefiles for x86_64 (#6195) * regstate retrieval in ELF corefiles * remove rzbin call from cmd_debug * increase FP_LAYOUT to 128 --- librz/bin/format/elf/elf_notes.c | 29 +++++++++++++++++++++++++++- librz/core/cfile.c | 6 ++++++ librz/debug/dreg.c | 33 +++++++++++++++++++++++++++++--- test/db/formats/elf/core | 19 ++++++++++++++++++ 4 files changed, 83 insertions(+), 4 deletions(-) diff --git a/librz/bin/format/elf/elf_notes.c b/librz/bin/format/elf/elf_notes.c index d200e93e28..59300268af 100644 --- a/librz/bin/format/elf/elf_notes.c +++ b/librz/bin/format/elf/elf_notes.c @@ -8,7 +8,7 @@ #define ROUND_UP_4(x) ((x) + (4 - 1)) / 4 * 4 -#define FP_LAYOUT 0x10 +#define FP_LAYOUT 0x80 #define X86 0 #define X86_64 1 @@ -154,6 +154,13 @@ #define SPARC64_OPENBSD_FPREGS_SIZE ((4 * 64) + 8 + 4) #define SPARC64_OPENBSD_FPREG_OFFSET 0x0 +// Linux x86/x86_64 NT_FPREGSET layouts. +// For both, the FP state begins at the start of the note description. +#define X86_FPREGS_SIZE 108 +#define X86_64_FPREGS_SIZE 512 +#define X86_FPREG_OFFSET 0x0 +#define X86_64_FPREG_OFFSET 0x0 + // o6 is the stack pointer. So g0-g7,o0-5 come before it. // Same for OpenBSD and Linux. #define SPARC32_PR_STATUS_REG_OFFSET_SP (4 * 14) @@ -214,6 +221,10 @@ static RzBinElfPrStatusLayout prstatus_layouts[ARCH_LEN] = { [RISCV_32] = { RISCV_32_REGS_SIZE, RISCV_32_REG_OFFSET, 32, RISCV_32_REG_OFFSET_SP }, [RISCV_64] = { RISCV_64_REGS_SIZE, RISCV_64_REG_OFFSET, 64, RISCV_64_REG_OFFSET_SP }, + + [X86 | FP_LAYOUT] = { X86_FPREGS_SIZE, X86_FPREG_OFFSET, 0, 0 }, + [X86_64 | + FP_LAYOUT] = { X86_64_FPREGS_SIZE, X86_64_FPREG_OFFSET, 0, 0 }, }; static bool parse_register_note(ELFOBJ *bin, RzVector /**/ *notes, Elf_(Nhdr) * note_segment_header, ut64 offset, size_t n_type) { @@ -500,6 +511,22 @@ RZ_BORROW RzBinElfPrStatusLayout *Elf_(rz_bin_elf_get_regset_layout)(RZ_NONNULL switch (bin->ehdr.e_machine) { default: return NULL; + case EM_386: + if (n_type == NT_FPREGSET) { + off = FP_LAYOUT | X86; + } else { + rz_warn_if_reached(); + return NULL; + } + break; + case EM_X86_64: + if (n_type == NT_FPREGSET) { + off = FP_LAYOUT | X86_64; + } else { + rz_warn_if_reached(); + return NULL; + } + break; case EM_MIPS: /* fall-thru */ case EM_MIPS_RS3_LE: diff --git a/librz/core/cfile.c b/librz/core/cfile.c index 62c3cd0cf7..b987a2323e 100644 --- a/librz/core/cfile.c +++ b/librz/core/cfile.c @@ -1163,6 +1163,12 @@ RZ_API bool rz_core_bin_load(RZ_NONNULL RzCore *r, RZ_NULLABLE const char *filen } else { RZ_LOG_INFO("Setting up coredump: Registers have been set\n"); } + if (!RZ_STR_ISEMPTY(rreg->reg_profile_str)) { + rz_reg_set_profile_string(r->dbg->reg, rreg->reg_profile_str); + if (binfile->o->regstate && rz_reg_arena_set_bytes(r->dbg->reg, binfile->o->regstate)) { + RZ_LOG_WARN("Setting up coredump: Problem while setting debug registers\n"); + } + } } } return true; diff --git a/librz/debug/dreg.c b/librz/debug/dreg.c index 5782b487ad..6eb2332438 100644 --- a/librz/debug/dreg.c +++ b/librz/debug/dreg.c @@ -6,15 +6,42 @@ #include #include -RZ_API int rz_debug_reg_sync(RzDebug *dbg, int type, int write) { - int i, n, size; - if (!dbg || !dbg->reg || !dbg->cur) { +static bool rz_debug_reg_sync_from_regstate(RzDebug *dbg) { + if (!dbg || !dbg->corebind.core) { return false; } + RzCore *core = (RzCore *)dbg->corebind.core; + RzBinFile *bf = rz_bin_cur(core->bin); + if (!bf || !bf->o || !bf->o->regstate) { + return false; + } + RzReg *areg = core->analysis ? rz_analysis_get_reg(core->analysis) : NULL; + const char *profile = areg ? areg->reg_profile_str : NULL; + if (!RZ_STR_ISEMPTY(profile)) { + rz_reg_set_profile_string(dbg->reg, profile); + } + return rz_reg_arena_set_bytes(dbg->reg, bf->o->regstate) == 0; +} + +RZ_API int rz_debug_reg_sync(RzDebug *dbg, int type, int write) { + int i, n, size; + if (!dbg || !dbg->reg) { + return false; + } + + if (!write && (!dbg->cur || (!dbg->cur->reg_read && !dbg->cur->sync_registers) || rz_debug_is_dead(dbg))) { + if (rz_debug_reg_sync_from_regstate(dbg)) { + return true; + } + } + // There's no point in syncing a dead target if (rz_debug_is_dead(dbg)) { return false; } + if (!dbg->cur) { + return false; + } // Check if the functions needed are available if (write && !dbg->cur->reg_write && !dbg->cur->sync_registers) { return false; diff --git a/test/db/formats/elf/core b/test/db/formats/elf/core index d8bf250041..3fcbf4475e 100644 --- a/test/db/formats/elf/core +++ b/test/db/formats/elf/core @@ -145,6 +145,7 @@ NAME=core regs linux x86_64 FILE=bins/elf/core/core-linux-x86_64 CMDS=<