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.


1259         rd = (in & ARM_ELS_RD_MASK) >> ARM_ELS_RD_SHIFT;
1260         rm = in & ARM_ELS_RN_MASK;
1261 
1262         if (snprintf(buf, buflen, "swp%s%s %s, %s, [%s]",
1263             arm_cond_names[cc],
1264             (in & ARM_ELS_SWAP_BYTE_MASK) ? "b" : "",
1265             arm_reg_names[rd], arm_reg_names[rm], arm_reg_names[rn]) >=
1266             buflen)
1267                 return (-1);
1268 
1269         return (0);
1270 }
1271 
1272 /*
1273  * Handle LDREX and STREX out of the extra loads/stores extensions.
1274  */
1275 static int
1276 arm_dis_lsexcl(uint32_t in, char *buf, size_t buflen)
1277 {
1278         arm_cond_code_t cc;
1279         arm_reg_t rn, rd, rm;
1280         int lbit;
1281         size_t len;
1282 
























1283         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;
1287         lbit = in & ARM_ELS_LBIT_MASK;
1288 
1289         len = snprintf(buf, buflen, "%s%sex %s, ",
1290             lbit != 0 ? "ldr" : "str",
1291             arm_cond_names[cc], arm_reg_names[rd]);
1292         if (len >= buflen)
1293                 return (-1);
1294 
1295         if (lbit)
1296                 len += snprintf(buf + len, buflen - len, "[%s]",
1297                     arm_reg_names[rn]);
1298         else
1299                 len += snprintf(buf + len, buflen - len, "%s, [%s]",
1300                     arm_reg_names[rm], arm_reg_names[rn]);
1301         return (len >= buflen ? -1 : 0);
1302 }
1303 
1304 /*
1305  * This is designed to handle the multiplication instruction extension space.
1306  * Note that this doesn't actually cover all of the multiplication instructions
1307  * available in ARM, but all of the ones that are in this space. This includes
1308  * the following instructions:
1309  *
1310  *
1311  * There are three basic encoding formats:
1312  *
1313  * Multipy (acc):
1314  * 31 - 28|27 - 24|23|22|21|20|19-16|15-12|11-8 |7|6|5|4|3-0
1315  * [ cond |   0   |0 |0 | A |S |Rn  | Rd   |Rs   |1|0|0|1|Rm ]
1316  *
1317  * Unsigned multipy acc acc long
1318  * 31 - 28|27 - 24|23|22|21|20|19-16|15-12|11-8 |7|6|5|4|3-0
1319  * [ cond |   0   |0 |1 |0 |0 |RdHi |RdLo  |Rs   |1|0|0|1|Rm ]
1320  *




1259         rd = (in & ARM_ELS_RD_MASK) >> ARM_ELS_RD_SHIFT;
1260         rm = in & ARM_ELS_RN_MASK;
1261 
1262         if (snprintf(buf, buflen, "swp%s%s %s, %s, [%s]",
1263             arm_cond_names[cc],
1264             (in & ARM_ELS_SWAP_BYTE_MASK) ? "b" : "",
1265             arm_reg_names[rd], arm_reg_names[rm], arm_reg_names[rn]) >=
1266             buflen)
1267                 return (-1);
1268 
1269         return (0);
1270 }
1271 
1272 /*
1273  * Handle LDREX and STREX out of the extra loads/stores extensions.
1274  */
1275 static int
1276 arm_dis_lsexcl(uint32_t in, char *buf, size_t buflen)
1277 {
1278         arm_cond_code_t cc;
1279         arm_reg_t rx, ry, rz;
1280         int lbit;
1281         size_t len;
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 
1307         cc = (in & ARM_CC_MASK) >> ARM_CC_SHIFT;
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);
1311         lbit = in & ARM_ELS_LBIT_MASK;
1312 
1313         len = snprintf(buf, buflen, "%s%sex %s, ",
1314             lbit != 0 ? "ldr" : "str",
1315             arm_cond_names[cc], arm_reg_names[ry]);
1316         if (len >= buflen)
1317                 return (-1);
1318 
1319         if (lbit)
1320                 len += snprintf(buf + len, buflen - len, "[%s]",
1321                     arm_reg_names[rx]);
1322         else
1323                 len += snprintf(buf + len, buflen - len, "%s, [%s]",
1324                     arm_reg_names[rz], arm_reg_names[rx]);
1325         return (len >= buflen ? -1 : 0);
1326 }
1327 
1328 /*
1329  * This is designed to handle the multiplication instruction extension space.
1330  * Note that this doesn't actually cover all of the multiplication instructions
1331  * available in ARM, but all of the ones that are in this space. This includes
1332  * the following instructions:
1333  *
1334  *
1335  * There are three basic encoding formats:
1336  *
1337  * Multipy (acc):
1338  * 31 - 28|27 - 24|23|22|21|20|19-16|15-12|11-8 |7|6|5|4|3-0
1339  * [ cond |   0   |0 |0 | A |S |Rn  | Rd   |Rs   |1|0|0|1|Rm ]
1340  *
1341  * Unsigned multipy acc acc long
1342  * 31 - 28|27 - 24|23|22|21|20|19-16|15-12|11-8 |7|6|5|4|3-0
1343  * [ cond |   0   |0 |1 |0 |0 |RdHi |RdLo  |Rs   |1|0|0|1|Rm ]
1344  *