@@ -1352,6 +1352,93 @@ static void diagnose(struct ptxed_decoder *decoder, uint64_t ip,
1352
1352
ip , errtype , pt_errstr (pt_errcode (errcode )));
1353
1353
}
1354
1354
1355
+ static int xed_next_ip (uint64_t * pip , const xed_decoded_inst_t * inst ,
1356
+ uint64_t ip )
1357
+ {
1358
+ xed_uint_t length , disp_width ;
1359
+
1360
+ if (!pip || !inst )
1361
+ return - pte_internal ;
1362
+
1363
+ length = xed_decoded_inst_get_length (inst );
1364
+ if (!length ) {
1365
+ printf ("[xed error: failed to determine instruction length]\n" );
1366
+ return - pte_bad_insn ;
1367
+ }
1368
+
1369
+ ip += length ;
1370
+
1371
+ /* If it got a branch displacement it must be a branch.
1372
+ *
1373
+ * This includes conditional branches for which we don't know whether
1374
+ * they were taken. The next IP won't be used in this case as a
1375
+ * conditional branch ends a block. The next block will start with the
1376
+ * correct IP.
1377
+ */
1378
+ disp_width = xed_decoded_inst_get_branch_displacement_width (inst );
1379
+ if (disp_width )
1380
+ ip += (uint64_t ) (int64_t )
1381
+ xed_decoded_inst_get_branch_displacement (inst );
1382
+
1383
+ * pip = ip ;
1384
+ return 0 ;
1385
+ }
1386
+
1387
+ static void diagnose_insn (struct ptxed_decoder * decoder ,
1388
+ const char * errtype , int errcode ,
1389
+ const struct pt_insn * insn )
1390
+ {
1391
+ xed_decoded_inst_t inst ;
1392
+ xed_error_enum_t xederr ;
1393
+ uint64_t ip ;
1394
+
1395
+ if (!decoder || !insn ) {
1396
+ printf ("ptxed: internal error" );
1397
+ return ;
1398
+ }
1399
+
1400
+ /* Determine the IP at which to report the error.
1401
+ *
1402
+ * When an error is reported by pt_insn_next(), the error may refer to
1403
+ * that instruction, e.g. it cannot be decoded, or it may refer to the
1404
+ * next instruction, e.g. cannot determine the next IP.
1405
+ *
1406
+ * As a general rule, if the instruction can be decoded and we can
1407
+ * determine the next IP, we attribute the error to the next IP.
1408
+ * Otherwise, we attribute it to the instruction's IP.
1409
+ *
1410
+ * There are exceptions, though, to make the IP we report more useful:
1411
+ *
1412
+ * -pte_bad_query applies to that instruction.
1413
+ */
1414
+ ip = insn -> ip ;
1415
+ switch (errcode ) {
1416
+ case - pte_bad_query :
1417
+ break ;
1418
+
1419
+ default :
1420
+ #if (LIBIPT_VERSION >= 0x201 )
1421
+ if (insn -> iclass == ptic_unknown )
1422
+ break ;
1423
+ #else
1424
+ if (insn .iclass == ptic_error )
1425
+ break ;
1426
+ #endif
1427
+ xed_decoded_inst_zero (& inst );
1428
+ xed_decoded_inst_set_mode (& inst ,
1429
+ translate_mode (insn -> mode ),
1430
+ XED_ADDRESS_WIDTH_INVALID );
1431
+
1432
+ xederr = xed_decode (& inst , insn -> raw , insn -> size );
1433
+ if (xederr == XED_ERROR_NONE )
1434
+ (void ) xed_next_ip (& ip , & inst , ip );
1435
+
1436
+ break ;
1437
+ }
1438
+
1439
+ diagnose (decoder , ip , errtype , errcode );
1440
+ }
1441
+
1355
1442
#if defined(FEATURE_SIDEBAND )
1356
1443
1357
1444
static int ptxed_sb_event (struct ptxed_decoder * decoder ,
@@ -1450,8 +1537,8 @@ static void decode_insn(struct ptxed_decoder *decoder,
1450
1537
struct pt_insn insn ;
1451
1538
int status ;
1452
1539
1453
- /* Initialize the IP - we use it for error reporting. */
1454
- insn . ip = 0ull ;
1540
+ /* Initialize @insn. We use it for error reporting. */
1541
+ memset ( & insn , 0 , sizeof ( insn )) ;
1455
1542
1456
1543
status = pt_insn_sync_forward (ptdec );
1457
1544
if (status < 0 ) {
@@ -1541,42 +1628,10 @@ static void decode_insn(struct ptxed_decoder *decoder,
1541
1628
if (status == - pte_eos )
1542
1629
break ;
1543
1630
1544
- diagnose (decoder , insn . ip , "error" , status );
1631
+ diagnose_insn (decoder , "error" , status , & insn );
1545
1632
}
1546
1633
}
1547
1634
1548
- static int xed_next_ip (uint64_t * pip , const xed_decoded_inst_t * inst ,
1549
- uint64_t ip )
1550
- {
1551
- xed_uint_t length , disp_width ;
1552
-
1553
- if (!pip || !inst )
1554
- return - pte_internal ;
1555
-
1556
- length = xed_decoded_inst_get_length (inst );
1557
- if (!length ) {
1558
- printf ("[xed error: failed to determine instruction length]\n" );
1559
- return - pte_bad_insn ;
1560
- }
1561
-
1562
- ip += length ;
1563
-
1564
- /* If it got a branch displacement it must be a branch.
1565
- *
1566
- * This includes conditional branches for which we don't know whether
1567
- * they were taken. The next IP won't be used in this case as a
1568
- * conditional branch ends a block. The next block will start with the
1569
- * correct IP.
1570
- */
1571
- disp_width = xed_decoded_inst_get_branch_displacement_width (inst );
1572
- if (disp_width )
1573
- ip += (uint64_t ) (int64_t )
1574
- xed_decoded_inst_get_branch_displacement (inst );
1575
-
1576
- * pip = ip ;
1577
- return 0 ;
1578
- }
1579
-
1580
1635
static int block_fetch_insn (struct pt_insn * insn , const struct pt_block * block ,
1581
1636
uint64_t ip , struct pt_image_section_cache * iscache )
1582
1637
{
@@ -1617,6 +1672,9 @@ static void diagnose_block(struct ptxed_decoder *decoder,
1617
1672
const char * errtype , int errcode ,
1618
1673
const struct pt_block * block )
1619
1674
{
1675
+ struct pt_insn insn ;
1676
+ xed_decoded_inst_t inst ;
1677
+ xed_error_enum_t xederr ;
1620
1678
uint64_t ip ;
1621
1679
int err ;
1622
1680
@@ -1627,33 +1685,27 @@ static void diagnose_block(struct ptxed_decoder *decoder,
1627
1685
1628
1686
/* Determine the IP at which to report the error.
1629
1687
*
1630
- * Depending on the type of error, the IP varies between that of the
1631
- * last instruction in @block or the next instruction outside of @block.
1688
+ * When an error is reported by pt_blk_next(), the error typically
1689
+ * refers to the first instruction after the block.
1690
+ *
1691
+ * As a general rule, if the last instruction in the block can be
1692
+ * decoded and we can determine the next IP, we attribute the error to
1693
+ * that IP. Otherwise, we attribute it to the instruction's IP.
1632
1694
*
1633
- * When the block is empty, we use the IP of the block itself,
1634
- * i.e. where the first instruction should have been.
1695
+ * There are exceptions, though, to make the IP we report more useful:
1696
+ *
1697
+ * -pte_bad_query applies to the last instruction.
1635
1698
*/
1636
1699
if (!block -> ninsn )
1637
1700
ip = block -> ip ;
1638
1701
else {
1639
1702
ip = block -> end_ip ;
1640
1703
1641
1704
switch (errcode ) {
1642
- case - pte_nomap :
1643
- case - pte_bad_insn : {
1644
- struct pt_insn insn ;
1645
- xed_decoded_inst_t inst ;
1646
- xed_error_enum_t xederr ;
1647
-
1648
- /* Decode failed when trying to fetch or decode the next
1649
- * instruction. Since indirect or conditional branches
1650
- * end a block and don't cause an additional fetch, we
1651
- * should be able to reach that IP from the last
1652
- * instruction in @block.
1653
- *
1654
- * We ignore errors and fall back to the IP of the last
1655
- * instruction.
1656
- */
1705
+ case - pte_bad_query :
1706
+ break ;
1707
+
1708
+ default :
1657
1709
err = block_fetch_insn (& insn , block , ip ,
1658
1710
decoder -> iscache );
1659
1711
if (err < 0 )
@@ -1665,14 +1717,9 @@ static void diagnose_block(struct ptxed_decoder *decoder,
1665
1717
XED_ADDRESS_WIDTH_INVALID );
1666
1718
1667
1719
xederr = xed_decode (& inst , insn .raw , insn .size );
1668
- if (xederr != XED_ERROR_NONE )
1669
- break ;
1670
-
1671
- (void ) xed_next_ip (& ip , & inst , insn .ip );
1672
- }
1673
- break ;
1720
+ if (xederr == XED_ERROR_NONE )
1721
+ (void ) xed_next_ip (& ip , & inst , insn .ip );
1674
1722
1675
- default :
1676
1723
break ;
1677
1724
}
1678
1725
}
0 commit comments