]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Bug 495816 - s390x: Fix disassembler segfault for C[G]RT and CL[G]RT
authorFlorian Krohm <flo2030@eich-krohm.de>
Wed, 4 Dec 2024 15:53:17 +0000 (16:53 +0100)
committerAndreas Arnez <arnez@linux.ibm.com>
Wed, 4 Dec 2024 15:53:17 +0000 (16:53 +0100)
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.

VEX/priv/guest_s390_toIR.c
VEX/priv/s390_disasm.c
VEX/priv/s390_disasm.h

index 2e0f6bb28d070c25016f561fc6431cb422054ae1..b0468cdc8d369fa6e752875e5f1da62bebb948a1 100644 (file)
@@ -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),
index a1cf61bb4d90f8b717ffac163b906fc22c7b2834..67b5c2bc3cb8319e7525412177e7562d86d66f59 100644 (file)
@@ -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) {
index eec41f8ac55f43de88283d22189640ecad8105f1..d6b2fbc8eb780f4bd3d9164197b9e171900f3b99 100644 (file)
@@ -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, ...);