Print this page
libdisasm: disassembly of strex may cause SIGSEGV
To make things confusing enough, the names of bitfields between ldrex and
strex are not totally consistent so this commit makes it easier on future
readers.

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libdisasm/common/dis_arm.c
          +++ new/usr/src/lib/libdisasm/common/dis_arm.c
↓ open down ↓ 1268 lines elided ↑ open up ↑
1269 1269          return (0);
1270 1270  }
1271 1271  
1272 1272  /*
1273 1273   * Handle LDREX and STREX out of the extra loads/stores extensions.
1274 1274   */
1275 1275  static int
1276 1276  arm_dis_lsexcl(uint32_t in, char *buf, size_t buflen)
1277 1277  {
1278 1278          arm_cond_code_t cc;
1279      -        arm_reg_t rn, rd, rm;
     1279 +        arm_reg_t rx, ry, rz;
1280 1280          int lbit;
1281 1281          size_t len;
1282 1282  
     1283 +        /*
     1284 +         * To make things confusing enough, the names of bitfields between
     1285 +         * ldrex and strex are not totally consistent.  Specifically,
     1286 +         *    STREX rd, rt, [rn]
     1287 +         *       rn = 19:16
     1288 +         *       rd = 15:12
     1289 +         *       rt = 3:0
     1290 +         *
     1291 +         *    LDREX rt, [rn]
     1292 +         *       rn = 19:16
     1293 +         *       rt = 15:12
     1294 +         *
     1295 +         * To avoid having to do too many mental gymnastics, let's just
     1296 +         * think of the bitfields as:
     1297 +         *
     1298 +         *       rx = 19:16
     1299 +         *       ry = 15:12
     1300 +         *       rz = 3:0
     1301 +         *
     1302 +         * And so we print the instructions as:
     1303 +         *    STREX ry, rz, [rx]
     1304 +         *    LDREX ry, [rx]
     1305 +         */
     1306 +
1283 1307          cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
1284      -        rn = (in & ARM_ELS_RN_MASK) >> ARM_ELS_RN_SHIFT;
1285      -        rd = (in & ARM_ELS_RD_MASK) >> ARM_ELS_RD_SHIFT;
1286      -        rm = in & ARM_ELS_RN_MASK;
     1308 +        rx = (in & ARM_ELS_RN_MASK) >> ARM_ELS_RN_SHIFT;
     1309 +        ry = (in & ARM_ELS_RD_MASK) >> ARM_ELS_RD_SHIFT;
     1310 +        rz = (in & ARM_ELS_LOW_AM_MASK);
1287 1311          lbit = in & ARM_ELS_LBIT_MASK;
1288 1312  
1289 1313          len = snprintf(buf, buflen, "%s%sex %s, ",
1290 1314              lbit != 0 ? "ldr" : "str",
1291      -            arm_cond_names[cc], arm_reg_names[rd]);
     1315 +            arm_cond_names[cc], arm_reg_names[ry]);
1292 1316          if (len >= buflen)
1293 1317                  return (-1);
1294 1318  
1295 1319          if (lbit)
1296 1320                  len += snprintf(buf + len, buflen - len, "[%s]",
1297      -                    arm_reg_names[rn]);
     1321 +                    arm_reg_names[rx]);
1298 1322          else
1299 1323                  len += snprintf(buf + len, buflen - len, "%s, [%s]",
1300      -                    arm_reg_names[rm], arm_reg_names[rn]);
     1324 +                    arm_reg_names[rz], arm_reg_names[rx]);
1301 1325          return (len >= buflen ? -1 : 0);
1302 1326  }
1303 1327  
1304 1328  /*
1305 1329   * This is designed to handle the multiplication instruction extension space.
1306 1330   * Note that this doesn't actually cover all of the multiplication instructions
1307 1331   * available in ARM, but all of the ones that are in this space. This includes
1308 1332   * the following instructions:
1309 1333   *
1310 1334   *
↓ open down ↓ 1307 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX