From: Florian Krohm Date: Wed, 4 Dec 2024 15:53:17 +0000 (+0100) Subject: Bug 495816 - s390x: Fix disassembler segfault for C[G]RT and CL[G]RT X-Git-Tag: VALGRIND_3_25_0~211 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1e694434a5cd2a0352e97f872ebd6922129c0282;p=thirdparty%2Fvalgrind.git Bug 495816 - s390x: Fix disassembler segfault for C[G]RT and CL[G]RT The function s390_format_RRF_U0RR() is called with one of the following xmnm_kind parameters: S390_XMNM_CAB when constructing IR for C[G]RT or CL[G]RT S390_XMNM_LOCFHR for LOCFHR S390_XMNM_LOCGR for LOCGR S390_XMNM_LOCR for LOCR In all cases it invokes the disassembler without providing a mnemonic: if (UNLIKELY(vex_traceflags & VEX_TRACE_FE)) s390_disasm(ENC3(XMNM, GPR, GPR), xmnm_kind, m3, r1, r2); But in the first case s390_disasm() processes these arguments as if there was one: case S390_XMNM_CAB: mnm = va_arg(args, HChar *); // <--- m3 mask = va_arg(args, UInt); // <--- r1 p += vex_sprintf(p, "%s", mnemonic(cab_operand(mnm, mask))); Thus, m3 is interpreted as a string which then causes the segfault. Fix this by (1) replacing all of S390_XMNM_LOC* and S390_XMNM_STOC* by S390_XMNM_CLS, (2) passing down the mnemonic to s390_disasm, and (3) changing function cls_operand() to be symmetric with cab_operand() by also taking in the base mnemonic. Apart from s390_format_RRF_U0RR(), further "load/store on condition" instructions are handled via s390_format_RIE_RUPIX() and s390_format_RSY_RDRM(). Adjust these functions accordingly as well. --- diff --git a/VEX/priv/guest_s390_toIR.c b/VEX/priv/guest_s390_toIR.c index 2e0f6bb28..b0468cdc8 100644 --- a/VEX/priv/guest_s390_toIR.c +++ b/VEX/priv/guest_s390_toIR.c @@ -2843,12 +2843,13 @@ s390_format_RIE_RUPI(const HChar *(*irgen)(UChar r1, UChar m3, UShort i4, static void s390_format_RIE_RUPIX(const HChar *(*irgen)(UChar r1, UChar m3, UShort i2), - UChar r1, UChar m3, UShort i2, Int xmnm_kind) + UChar r1, UChar m3, UShort i2) { - irgen(r1, m3, i2); + const HChar *mnm = irgen(r1, m3, i2); if (UNLIKELY(vex_traceflags & VEX_TRACE_FE)) - s390_disasm(ENC3(XMNM, GPR, INT), xmnm_kind, m3, r1, (Int)(Short)i2); + s390_disasm(ENC3(XMNM, GPR, INT), S390_XMNM_CLS, mnm, m3, r1, + (Int)(Short)i2); } static void @@ -3106,10 +3107,10 @@ static void s390_format_RRF_U0RR(const HChar *(*irgen)(UChar m3, UChar r1, UChar r2), UChar m3, UChar r1, UChar r2, Int xmnm_kind) { - irgen(m3, r1, r2); + const HChar *mnm = irgen(m3, r1, r2); if (UNLIKELY(vex_traceflags & VEX_TRACE_FE)) - s390_disasm(ENC3(XMNM, GPR, GPR), xmnm_kind, m3, r1, r2); + s390_disasm(ENC3(XMNM, GPR, GPR), xmnm_kind, mnm, m3, r1, r2); } static void @@ -3334,8 +3335,7 @@ s390_format_RSY_RURD(const HChar *(*irgen)(UChar r1, UChar r3, IRTemp op2addr), static void s390_format_RSY_RDRM(const HChar *(*irgen)(UChar r1, IRTemp op2addr), - UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2, - Int xmnm_kind) + UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2) { IRTemp op2addr = newTemp(Ity_I64); IRTemp d2 = newTemp(Ity_I64); @@ -3346,12 +3346,13 @@ s390_format_RSY_RDRM(const HChar *(*irgen)(UChar r1, IRTemp op2addr), assign(op2addr, binop(Iop_Add64, mkexpr(d2), b2 != 0 ? get_gpr_dw0(b2) : mkU64(0))); - irgen(r1, op2addr); + const HChar *mnm = irgen(r1, op2addr); vassert(dis_res->whatNext == Dis_Continue); if (UNLIKELY(vex_traceflags & VEX_TRACE_FE)) - s390_disasm(ENC3(XMNM, GPR, SDXB), xmnm_kind, m3, r1, dh2, dl2, 0, b2); + s390_disasm(ENC3(XMNM, GPR, SDXB), S390_XMNM_CLS, mnm, m3, r1, + dh2, dl2, 0, b2); } static void @@ -20763,12 +20764,12 @@ s390_decode_4byte_and_irgen(const UChar *bytes) RRE_r2(ovl)); goto ok; case 0xb9e0: s390_format_RRF_U0RR(s390_irgen_LOCFHR, RRF3_r3(ovl), RRF3_r1(ovl), RRF3_r2(ovl), - S390_XMNM_LOCFHR); goto ok; + S390_XMNM_CLS); goto ok; case 0xb9e1: s390_format_RRFa_U0RR(s390_irgen_POPCNT, RRF3_r3(ovl), RRF3_r1(ovl), RRF3_r2(ovl)); goto ok; case 0xb9e2: s390_format_RRF_U0RR(s390_irgen_LOCGR, RRF3_r3(ovl), RRF3_r1(ovl), RRF3_r2(ovl), - S390_XMNM_LOCGR); goto ok; + S390_XMNM_CLS); goto ok; case 0xb9e3: s390_format_RRF_RURR(s390_irgen_SELGR, RRF4_r3(ovl), RRF4_m4(ovl), RRF4_r1(ovl), RRF4_r2(ovl)); goto ok; @@ -20807,7 +20808,7 @@ s390_decode_4byte_and_irgen(const UChar *bytes) RRF4_r2(ovl)); goto ok; case 0xb9f2: s390_format_RRF_U0RR(s390_irgen_LOCR, RRF3_r3(ovl), RRF3_r1(ovl), RRF3_r2(ovl), - S390_XMNM_LOCR); goto ok; + S390_XMNM_CLS); goto ok; case 0xb9f4: s390_format_RRF_R0RR2(s390_irgen_NRK, RRF4_r3(ovl), RRF4_r1(ovl), RRF4_r2(ovl)); goto ok; @@ -22251,23 +22252,19 @@ s390_decode_6byte_and_irgen(const UChar *bytes) case 0xeb00000000e0ULL: s390_format_RSY_RDRM(s390_irgen_LOCFH, RSY_r1(ovl), RSY_r3(ovl), RSY_b2(ovl), RSY_dl2(ovl), - RSY_dh2(ovl), - S390_XMNM_LOCFH); goto ok; + RSY_dh2(ovl)); goto ok; case 0xeb00000000e1ULL: s390_format_RSY_RDRM(s390_irgen_STOCFH, RSY_r1(ovl), RSY_r3(ovl), RSY_b2(ovl), RSY_dl2(ovl), - RSY_dh2(ovl), - S390_XMNM_STOCFH); goto ok; + RSY_dh2(ovl)); goto ok; case 0xeb00000000e2ULL: s390_format_RSY_RDRM(s390_irgen_LOCG, RSY_r1(ovl), RSY_r3(ovl), RSY_b2(ovl), RSY_dl2(ovl), - RSY_dh2(ovl), - S390_XMNM_LOCG); goto ok; + RSY_dh2(ovl)); goto ok; case 0xeb00000000e3ULL: s390_format_RSY_RDRM(s390_irgen_STOCG, RSY_r1(ovl), RSY_r3(ovl), RSY_b2(ovl), RSY_dl2(ovl), - RSY_dh2(ovl), - S390_XMNM_STOCG); goto ok; + RSY_dh2(ovl)); goto ok; case 0xeb00000000e4ULL: s390_format_RSY_RRRD(s390_irgen_LANG, RSY_r1(ovl), RSY_r3(ovl), RSY_b2(ovl), RSY_dl2(ovl), @@ -22291,13 +22288,11 @@ s390_decode_6byte_and_irgen(const UChar *bytes) case 0xeb00000000f2ULL: s390_format_RSY_RDRM(s390_irgen_LOC, RSY_r1(ovl), RSY_r3(ovl), RSY_b2(ovl), RSY_dl2(ovl), - RSY_dh2(ovl), S390_XMNM_LOC); - goto ok; + RSY_dh2(ovl)); goto ok; case 0xeb00000000f3ULL: s390_format_RSY_RDRM(s390_irgen_STOC, RSY_r1(ovl), RSY_r3(ovl), RSY_b2(ovl), RSY_dl2(ovl), - RSY_dh2(ovl), - S390_XMNM_STOC); goto ok; + RSY_dh2(ovl)); goto ok; case 0xeb00000000f4ULL: s390_format_RSY_RRRD(s390_irgen_LAN, RSY_r1(ovl), RSY_r3(ovl), RSY_b2(ovl), RSY_dl2(ovl), @@ -22321,8 +22316,7 @@ s390_decode_6byte_and_irgen(const UChar *bytes) case 0xec0000000042ULL: s390_format_RIE_RUPIX(s390_irgen_LOCHI, RIEv3_r1(ovl), RIEv3_m3(ovl), - RIEv3_i4(ovl), - S390_XMNM_LOCHI); goto ok; + RIEv3_i4(ovl)); goto ok; case 0xec0000000044ULL: s390_format_RIE_RRP(s390_irgen_BRXHG, RIE_r1(ovl), RIE_r3(ovl), RIE_i2(ovl)); goto ok; @@ -22332,13 +22326,11 @@ s390_decode_6byte_and_irgen(const UChar *bytes) case 0xec0000000046ULL: s390_format_RIE_RUPIX(s390_irgen_LOCGHI, RIEv3_r1(ovl), RIEv3_m3(ovl), - RIEv3_i4(ovl), - S390_XMNM_LOCGHI); goto ok; + RIEv3_i4(ovl)); goto ok; case 0xec000000004eULL: s390_format_RIE_RUPIX(s390_irgen_LOCHHI, RIEv3_r1(ovl), RIEv3_m3(ovl), - RIEv3_i4(ovl), - S390_XMNM_LOCHHI); goto ok; + RIEv3_i4(ovl)); goto ok; case 0xec0000000051ULL: s390_format_RIE_RRUUU(s390_irgen_RISBLG, RIE_RRUUU_r1(ovl), RIE_RRUUU_r2(ovl), diff --git a/VEX/priv/s390_disasm.c b/VEX/priv/s390_disasm.c index a1cf61bb4..67b5c2bc3 100644 --- a/VEX/priv/s390_disasm.c +++ b/VEX/priv/s390_disasm.c @@ -239,27 +239,8 @@ brcl_operand(UInt m1) /* Return the special mnemonic for a conditional load/store opcode */ static const HChar * -cls_operand(Int kind, UInt mask) +cls_operand(const HChar *prefix, UInt mask) { - const HChar *prefix; - - switch (kind) { - case S390_XMNM_LOCR: prefix = "locr"; break; - case S390_XMNM_LOCGR: prefix = "locgr"; break; - case S390_XMNM_LOC: prefix = "loc"; break; - case S390_XMNM_LOCG: prefix = "locg"; break; - case S390_XMNM_STOC: prefix = "stoc"; break; - case S390_XMNM_STOCG: prefix = "stocg"; break; - case S390_XMNM_STOCFH: prefix = "stocfh"; break; - case S390_XMNM_LOCFH: prefix = "locfh"; break; - case S390_XMNM_LOCFHR: prefix = "locfhr"; break; - case S390_XMNM_LOCHI: prefix = "lochi"; break; - case S390_XMNM_LOCGHI: prefix = "locghi"; break; - case S390_XMNM_LOCHHI: prefix = "lochhi"; break; - default: - vpanic("cls_operand"); - } - return construct_mnemonic(prefix, "", mask); } @@ -415,25 +396,15 @@ s390_disasm(UInt command, ...) p += vex_sprintf(p, "%s", mnemonic(cab_operand(mnm, mask))); break; - case S390_XMNM_LOCR: - case S390_XMNM_LOCGR: - case S390_XMNM_LOC: - case S390_XMNM_LOCG: - case S390_XMNM_STOC: - case S390_XMNM_STOCG: - case S390_XMNM_STOCFH: - case S390_XMNM_LOCFH: - case S390_XMNM_LOCFHR: - case S390_XMNM_LOCHI: - case S390_XMNM_LOCGHI: - case S390_XMNM_LOCHHI: + case S390_XMNM_CLS: + mnm = va_arg(args, HChar *); mask = va_arg(args, UInt); - mnm = cls_operand(kind, mask); - p += vex_sprintf(p, "%s", mnemonic(mnm)); + p += vex_sprintf(p, "%s", mnemonic(cls_operand(mnm, mask))); /* There are no special opcodes when mask == 0 or 15. In that case the integer mask is appended as the final operand */ if (mask == 0 || mask == 15) mask_suffix = mask; break; + case S390_XMNM_BIC: mask = va_arg(args, UInt); if (mask == 0) { diff --git a/VEX/priv/s390_disasm.h b/VEX/priv/s390_disasm.h index eec41f8ac..d6b2fbc8e 100644 --- a/VEX/priv/s390_disasm.h +++ b/VEX/priv/s390_disasm.h @@ -80,19 +80,8 @@ enum { S390_XMNM_BC = 2, S390_XMNM_BRC = 3, S390_XMNM_BRCL = 4, - S390_XMNM_LOCR = 5, - S390_XMNM_LOCGR = 6, - S390_XMNM_LOC = 7, - S390_XMNM_LOCG = 8, - S390_XMNM_STOC = 9, - S390_XMNM_STOCG = 10, - S390_XMNM_STOCFH = 11, - S390_XMNM_LOCFH = 12, - S390_XMNM_LOCFHR = 13, - S390_XMNM_LOCHI = 14, - S390_XMNM_LOCGHI = 15, - S390_XMNM_LOCHHI = 16, - S390_XMNM_BIC = 17 + S390_XMNM_CLS = 5, + S390_XMNM_BIC = 6, }; void s390_disasm(UInt command, ...);