From 46009de0fa9dc458931cf259bd2deff26032eb12 Mon Sep 17 00:00:00 2001 From: Giovanni <561184+wargio@users.noreply.github.com> Date: Wed, 10 Sep 2025 23:12:53 +0800 Subject: [PATCH] librz/bin: add corefile support for Linux MIPS 32/64 (#5355) --- librz/arch/p/analysis/analysis_mips_cs.c | 220 +++++++++++++++-------- librz/bin/format/elf/elf_notes.c | 53 +++++- test/db/abi/platforms/reg_profile | 14 +- test/db/analysis/mips | 46 ----- test/db/formats/elf/core | 96 ++++++++++ 5 files changed, 305 insertions(+), 124 deletions(-) diff --git a/librz/arch/p/analysis/analysis_mips_cs.c b/librz/arch/p/analysis/analysis_mips_cs.c index c971bd8877..6f822c9c6f 100644 --- a/librz/arch/p/analysis/analysis_mips_cs.c +++ b/librz/arch/p/analysis/analysis_mips_cs.c @@ -931,42 +931,80 @@ static char *mips_get_reg_profile(RzAnalysis *analysis) { "=A3 a3\n" "=R0 v0\n" "=R1 v1\n" - "gpr zero .32 ? 0\n" - "gpr at .32 4 0\n" - "gpr v0 .32 8 0\n" - "gpr v1 .32 12 0\n" - "gpr a0 .32 16 0\n" - "gpr a1 .32 20 0\n" - "gpr a2 .32 24 0\n" - "gpr a3 .32 28 0\n" - "gpr t0 .32 32 0\n" - "gpr t1 .32 36 0\n" - "gpr t2 .32 40 0\n" - "gpr t3 .32 44 0\n" - "gpr t4 .32 48 0\n" - "gpr t5 .32 52 0\n" - "gpr t6 .32 56 0\n" - "gpr t7 .32 60 0\n" - "gpr s0 .32 64 0\n" - "gpr s1 .32 68 0\n" - "gpr s2 .32 72 0\n" - "gpr s3 .32 76 0\n" - "gpr s4 .32 80 0\n" - "gpr s5 .32 84 0\n" - "gpr s6 .32 88 0\n" - "gpr s7 .32 92 0\n" - "gpr t8 .32 96 0\n" - "gpr t9 .32 100 0\n" - "gpr k0 .32 104 0\n" - "gpr k1 .32 108 0\n" - "gpr gp .32 112 0\n" - "gpr sp .32 116 0\n" - "gpr fp .32 120 0\n" - "gpr ra .32 124 0\n" - "gpr pc .32 128 0\n" - "gpr hi .32 132 0\n" - "gpr lo .32 136 0\n" - "gpr t .32 140 0\n"; + "gpr zero .32 ? 0\n" + "gpr at .32 4 0\n" + "gpr v0 .32 8 0\n" + "gpr v1 .32 12 0\n" + "gpr a0 .32 16 0\n" + "gpr a1 .32 20 0\n" + "gpr a2 .32 24 0\n" + "gpr a3 .32 28 0\n" + "gpr t0 .32 32 0\n" + "gpr t1 .32 36 0\n" + "gpr t2 .32 40 0\n" + "gpr t3 .32 44 0\n" + "gpr t4 .32 48 0\n" + "gpr t5 .32 52 0\n" + "gpr t6 .32 56 0\n" + "gpr t7 .32 60 0\n" + "gpr s0 .32 64 0\n" + "gpr s1 .32 68 0\n" + "gpr s2 .32 72 0\n" + "gpr s3 .32 76 0\n" + "gpr s4 .32 80 0\n" + "gpr s5 .32 84 0\n" + "gpr s6 .32 88 0\n" + "gpr s7 .32 92 0\n" + "gpr t8 .32 96 0\n" + "gpr t9 .32 100 0\n" + "gpr k0 .32 104 0\n" + "gpr k1 .32 108 0\n" + "gpr gp .32 112 0\n" + "gpr sp .32 116 0\n" + "gpr fp .32 120 0\n" + "gpr ra .32 124 0\n" + "gpr lo .32 128 0\n" + "gpr hi .32 132 0\n" + "gpr pc .32 136 0\n" + "gpr badvaddr .32 140 0\n" + "gpr status .32 144 0\n" + "gpr cause .32 148 0\n" + "fpu f0 .32 152 0\n" + "fpu f1 .32 156 0\n" + "fpu f2 .32 160 0\n" + "fpu f3 .32 164 0\n" + "fpu f4 .32 168 0\n" + "fpu f5 .32 172 0\n" + "fpu f6 .32 176 0\n" + "fpu f7 .32 180 0\n" + "fpu f8 .32 184 0\n" + "fpu f9 .32 188 0\n" + "fpu f10 .32 192 0\n" + "fpu f11 .32 196 0\n" + "fpu f12 .32 200 0\n" + "fpu f13 .32 204 0\n" + "fpu f14 .32 208 0\n" + "fpu f15 .32 212 0\n" + "fpu f16 .32 216 0\n" + "fpu f17 .32 220 0\n" + "fpu f18 .32 224 0\n" + "fpu f19 .32 228 0\n" + "fpu f20 .32 232 0\n" + "fpu f21 .32 236 0\n" + "fpu f22 .32 240 0\n" + "fpu f23 .32 244 0\n" + "fpu f24 .32 248 0\n" + "fpu f25 .32 252 0\n" + "fpu f26 .32 256 0\n" + "fpu f27 .32 260 0\n" + "fpu f28 .32 264 0\n" + "fpu f29 .32 268 0\n" + "fpu f30 .32 272 0\n" + "fpu f31 .32 276 0\n" + "fpu fcsr .32 280 0\n" + "fpu fir .32 284 0\n" + "fpu restart .32 288 0\n" + "gpr t .32 292 0\n"; break; case 64: p = @@ -980,42 +1018,80 @@ static char *mips_get_reg_profile(RzAnalysis *analysis) { "=SN v0\n" "=R0 v0\n" "=R1 v1\n" - "gpr zero .64 ? 0\n" - "gpr at .64 8 0\n" - "gpr v0 .64 16 0\n" - "gpr v1 .64 24 0\n" - "gpr a0 .64 32 0\n" - "gpr a1 .64 40 0\n" - "gpr a2 .64 48 0\n" - "gpr a3 .64 56 0\n" - "gpr t0 .64 64 0\n" - "gpr t1 .64 72 0\n" - "gpr t2 .64 80 0\n" - "gpr t3 .64 88 0\n" - "gpr t4 .64 96 0\n" - "gpr t5 .64 104 0\n" - "gpr t6 .64 112 0\n" - "gpr t7 .64 120 0\n" - "gpr s0 .64 128 0\n" - "gpr s1 .64 136 0\n" - "gpr s2 .64 144 0\n" - "gpr s3 .64 152 0\n" - "gpr s4 .64 160 0\n" - "gpr s5 .64 168 0\n" - "gpr s6 .64 176 0\n" - "gpr s7 .64 184 0\n" - "gpr t8 .64 192 0\n" - "gpr t9 .64 200 0\n" - "gpr k0 .64 208 0\n" - "gpr k1 .64 216 0\n" - "gpr gp .64 224 0\n" - "gpr sp .64 232 0\n" - "gpr fp .64 240 0\n" - "gpr ra .64 248 0\n" - "gpr pc .64 256 0\n" - "gpr hi .64 264 0\n" - "gpr lo .64 272 0\n" - "gpr t .64 280 0\n"; + "gpr zero .64 ? 0\n" + "gpr at .64 8 0\n" + "gpr v0 .64 16 0\n" + "gpr v1 .64 24 0\n" + "gpr a0 .64 32 0\n" + "gpr a1 .64 40 0\n" + "gpr a2 .64 48 0\n" + "gpr a3 .64 56 0\n" + "gpr t0 .64 64 0\n" + "gpr t1 .64 72 0\n" + "gpr t2 .64 80 0\n" + "gpr t3 .64 88 0\n" + "gpr t4 .64 96 0\n" + "gpr t5 .64 104 0\n" + "gpr t6 .64 112 0\n" + "gpr t7 .64 120 0\n" + "gpr s0 .64 128 0\n" + "gpr s1 .64 136 0\n" + "gpr s2 .64 144 0\n" + "gpr s3 .64 152 0\n" + "gpr s4 .64 160 0\n" + "gpr s5 .64 168 0\n" + "gpr s6 .64 176 0\n" + "gpr s7 .64 184 0\n" + "gpr t8 .64 192 0\n" + "gpr t9 .64 200 0\n" + "gpr k0 .64 208 0\n" + "gpr k1 .64 216 0\n" + "gpr gp .64 224 0\n" + "gpr sp .64 232 0\n" + "gpr fp .64 240 0\n" + "gpr ra .64 248 0\n" + "gpr lo .64 256 0\n" + "gpr hi .64 264 0\n" + "gpr pc .64 272 0\n" + "gpr badvaddr .64 280 0\n" + "gpr status .64 288 0\n" + "gpr cause .64 296 0\n" + "fpu f0 .64 304 0\n" + "fpu f1 .64 312 0\n" + "fpu f2 .64 320 0\n" + "fpu f3 .64 328 0\n" + "fpu f4 .64 336 0\n" + "fpu f5 .64 344 0\n" + "fpu f6 .64 352 0\n" + "fpu f7 .64 360 0\n" + "fpu f8 .64 368 0\n" + "fpu f9 .64 376 0\n" + "fpu f10 .64 384 0\n" + "fpu f11 .64 392 0\n" + "fpu f12 .64 400 0\n" + "fpu f13 .64 408 0\n" + "fpu f14 .64 416 0\n" + "fpu f15 .64 424 0\n" + "fpu f16 .64 432 0\n" + "fpu f17 .64 440 0\n" + "fpu f18 .64 448 0\n" + "fpu f19 .64 456 0\n" + "fpu f20 .64 464 0\n" + "fpu f21 .64 472 0\n" + "fpu f22 .64 480 0\n" + "fpu f23 .64 488 0\n" + "fpu f24 .64 496 0\n" + "fpu f25 .64 504 0\n" + "fpu f26 .64 512 0\n" + "fpu f27 .64 520 0\n" + "fpu f28 .64 528 0\n" + "fpu f29 .64 536 0\n" + "fpu f30 .64 544 0\n" + "fpu f31 .64 552 0\n" + "fpu fcsr .32 560 0\n" // 32 bit long + "fpu fir .32 564 0\n" // 32 bit long + "fpu restart .64 568 0\n" + "gpr t .64 576 0\n"; break; } return rz_str_dup(p); diff --git a/librz/bin/format/elf/elf_notes.c b/librz/bin/format/elf/elf_notes.c index 5cb092fc5d..6d36692277 100644 --- a/librz/bin/format/elf/elf_notes.c +++ b/librz/bin/format/elf/elf_notes.c @@ -8,6 +8,8 @@ #define ROUND_UP_4(x) ((x) + (4 - 1)) / 4 * 4 +#define FP_LAYOUT 0x10 + #define X86 0 #define X86_64 1 #define ARM 2 @@ -21,9 +23,14 @@ // They are only for registers and store no other information. #define OPENBSD_SPARC_V9 7 #define OPENBSD_SPARC_V9_FP (FP_LAYOUT | OPENBSD_SPARC_V9) +// MIPS related constants. +// The size of the pr status depends on the ABI +#define MIPS_32 8 +#define MIPS_64 9 +#define MIPS_FP32 (FP_LAYOUT | MIPS_32) +#define MIPS_FP64 (FP_LAYOUT | MIPS_64) // Floating point register layout. -#define FP_LAYOUT 0x10 -#define ARCH_LEN (FP_LAYOUT | 0xf) +#define ARCH_LEN (FP_LAYOUT | 0xf) // See elf.c::elfcore_grok_solaris_note_impl() of binutil's bfd // https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=bfd/elf.c;h=6ef603010918f14eda69f0d0dc1637b4d51e8157;hb=HEAD#l11777 @@ -93,6 +100,16 @@ #define SPARC32_PR_STATUS_REG_OFFSET_SP (4 * 14) #define SPARC64_PR_STATUS_REG_OFFSET_SP (8 * 14) +// MIPS number of registers. +#define MIPS_N_GPR_REGS 45 +#define MIPS_N_FP_REGS 33 +#define MIPS32_REGS_SIZE (4 * MIPS_N_GPR_REGS) // int32 +#define MIPS64_REGS_SIZE (8 * MIPS_N_GPR_REGS) // int64 +#define MIPS_FP32_REGS_SIZE (4 * MIPS_N_FP_REGS) // float32 +#define MIPS_FP64_REGS_SIZE (8 * MIPS_N_FP_REGS) // float64 +#define MIPS_GPR32_STATUS_OFFSET (96) +#define MIPS_GPR64_STATUS_OFFSET (112) + static RzBinElfPrStatusLayout prstatus_layouts[ARCH_LEN] = { [X86] = { 160, 0x48, 32, 0x3c }, [X86_64] = { 216, 0x70, 64, 0x98 }, @@ -104,9 +121,15 @@ static RzBinElfPrStatusLayout prstatus_layouts[ARCH_LEN] = { [SPARC_V9] = { SPARC64_REGS_SIZE, SPARC64_PR_STATUS_REG_OFFSET, 64, SPARC64_PR_STATUS_REG_OFFSET_SP }, [OPENBSD_SPARC_V9] = { SPARC64_REGS_SIZE, SPARC64_OPENBSD_REG_OFFSET, 64, SPARC64_PR_STATUS_REG_OFFSET_SP }, + [MIPS_32] = { MIPS32_REGS_SIZE, MIPS_GPR32_STATUS_OFFSET, 0, 0 }, + [MIPS_64] = { MIPS64_REGS_SIZE, MIPS_GPR64_STATUS_OFFSET, 0, 0 }, + [SPARC32_FP] = { SPARC32_FPREGS_SIZE, SPARC32_FPREG_OFFSET, 0, 0 }, [SPARC64_FP] = { SPARC64_FPREGS_SIZE, SPARC32_FPREG_OFFSET, 0, 0 }, [OPENBSD_SPARC_V9_FP] = { SPARC64_OPENBSD_FPREGS_SIZE, SPARC64_OPENBSD_FPREG_OFFSET, 0, 0 }, + + [MIPS_FP32] = { MIPS_FP32_REGS_SIZE, 4, 0, 0 }, + [MIPS_FP64] = { MIPS_FP64_REGS_SIZE, 8, 0, 0 }, }; static bool parse_register_note(ELFOBJ *bin, RzVector /**/ *notes, Elf_(Nhdr) * note_segment_header, ut64 offset, size_t n_type) { @@ -310,6 +333,14 @@ static void note_segment_free(void *e, RZ_UNUSED void *user) { rz_vector_fini(ptr); } +static const size_t elf_get_prstatus_layout_mips(const ELFOBJ *bin, bool is_fp) { + size_t fp = is_fp ? FP_LAYOUT : 0; + if (bin->ehdr.e_ident[EI_CLASS] == ELFCLASS64) { + return fp | MIPS_64; + } + return fp | MIPS_32; +} + RZ_BORROW RzBinElfPrStatusLayout *Elf_(rz_bin_elf_get_prstatus_layout)(RZ_NONNULL ELFOBJ *bin) { rz_return_val_if_fail(bin, NULL); @@ -328,6 +359,12 @@ RZ_BORROW RzBinElfPrStatusLayout *Elf_(rz_bin_elf_get_prstatus_layout)(RZ_NONNUL return prstatus_layouts + SPARC_V8PLUS; case EM_SPARCV9: return prstatus_layouts + SPARC_V9; + case EM_MIPS: + /* fall-thru */ + case EM_MIPS_RS3_LE: + /* fall-thru */ + case EM_MIPS_X: + return prstatus_layouts + elf_get_prstatus_layout_mips(bin, false); } return NULL; @@ -352,6 +389,18 @@ RZ_BORROW RzBinElfPrStatusLayout *Elf_(rz_bin_elf_get_regset_layout)(RZ_NONNULL switch (bin->ehdr.e_machine) { default: return NULL; + case EM_MIPS: + /* fall-thru */ + case EM_MIPS_RS3_LE: + /* fall-thru */ + case EM_MIPS_X: + if (n_type == NT_FPREGSET) { + off = elf_get_prstatus_layout_mips(bin, true); + } else { + rz_warn_if_reached(); + return NULL; + } + break; case EM_SPARC: if (n_type == NT_FPREGSET) { off = FP_LAYOUT | SPARC; diff --git a/test/db/abi/platforms/reg_profile b/test/db/abi/platforms/reg_profile index 0b8760ac78..7d9b6f4898 100644 --- a/test/db/abi/platforms/reg_profile +++ b/test/db/abi/platforms/reg_profile @@ -101,9 +101,12 @@ gp = 0x00000000 sp = 0x00000000 fp = 0x00000000 ra = 0x00000000 -pc = 0x00000000 -hi = 0x00000000 lo = 0x00000000 +hi = 0x00000000 +pc = 0x00000000 +badvaddr = 0x00000000 +status = 0x00000000 +cause = 0x00000000 t = 0x00000000 EOF RUN @@ -145,9 +148,12 @@ gp = 0x0000000000000000 sp = 0x0000000000000000 fp = 0x0000000000000000 ra = 0x0000000000000000 -pc = 0x0000000000000000 -hi = 0x0000000000000000 lo = 0x0000000000000000 +hi = 0x0000000000000000 +pc = 0x0000000000000000 +badvaddr = 0x0000000000000000 +status = 0x0000000000000000 +cause = 0x0000000000000000 t = 0x0000000000000000 EOF RUN diff --git a/test/db/analysis/mips b/test/db/analysis/mips index 0cbc065984..899eeebaf3 100644 --- a/test/db/analysis/mips +++ b/test/db/analysis/mips @@ -821,52 +821,6 @@ EXPECT=<