Skip to content

Commit c7d9dfc

Browse files
ptxed: fix xed address width
We currently supply XED_ADDRESS_WIDTH_INVALID to xed_state_init2(). This is fine for 64bit mode, but not for 16bit or 32bit mode. Derive the address width from the instruction mode. Also inline check_insn_decode() to not split initialization. Signed-off-by: Markus Metzger <markus.t.metzger@intel.com>
1 parent 17e0cd3 commit c7d9dfc

File tree

1 file changed

+87
-49
lines changed

1 file changed

+87
-49
lines changed

ptxed/src/ptxed.c

Lines changed: 87 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,7 @@ static int load_raw(struct pt_image_section_cache *iscache,
602602
return 0;
603603
}
604604

605-
static xed_machine_mode_enum_t translate_mode(enum pt_exec_mode mode)
605+
static xed_machine_mode_enum_t to_xed_mode(enum pt_exec_mode mode)
606606
{
607607
switch (mode) {
608608
case ptem_unknown:
@@ -621,6 +621,25 @@ static xed_machine_mode_enum_t translate_mode(enum pt_exec_mode mode)
621621
return XED_MACHINE_MODE_INVALID;
622622
}
623623

624+
static xed_address_width_enum_t to_xed_addr_width(enum pt_exec_mode mode)
625+
{
626+
switch (mode) {
627+
case ptem_unknown:
628+
return XED_ADDRESS_WIDTH_INVALID;
629+
630+
case ptem_16bit:
631+
return XED_ADDRESS_WIDTH_16b;
632+
633+
case ptem_32bit:
634+
return XED_ADDRESS_WIDTH_32b;
635+
636+
case ptem_64bit:
637+
return XED_ADDRESS_WIDTH_64b;
638+
}
639+
640+
return XED_ADDRESS_WIDTH_INVALID;
641+
}
642+
624643
static const char *visualize_iclass(enum pt_insn_class iclass)
625644
{
626645
switch (iclass) {
@@ -808,18 +827,27 @@ static void check_insn_iclass(const xed_decoded_inst_t *inst,
808827
visualize_iclass(insn->iclass), xed_iclass_enum_t2str(iclass));
809828
}
810829

811-
static void check_insn_decode(xed_decoded_inst_t *inst,
812-
const struct pt_insn *insn, uint64_t offset)
830+
static void check_insn(const struct pt_insn *insn, uint64_t offset)
813831
{
832+
xed_address_width_enum_t addr_width;
833+
xed_machine_mode_enum_t mode;
834+
xed_decoded_inst_t inst;
814835
xed_error_enum_t errcode;
836+
xed_state_t xed;
815837

816-
if (!inst || !insn) {
838+
if (!insn) {
817839
printf("[internal error]\n");
818840
return;
819841
}
820842

821-
xed_decoded_inst_set_mode(inst, translate_mode(insn->mode),
822-
XED_ADDRESS_WIDTH_INVALID);
843+
if (insn->isid <= 0)
844+
printf("[%" PRIx64 ", %" PRIx64 ": check error: "
845+
"bad isid]\n", offset, insn->ip);
846+
847+
addr_width = to_xed_addr_width(insn->mode);
848+
mode = to_xed_mode(insn->mode);
849+
xed_state_init2(&xed, mode, addr_width);
850+
xed_decoded_inst_zero_set_mode(&inst, &xed);
823851

824852
/* Decode the instruction (again).
825853
*
@@ -830,43 +858,19 @@ static void check_insn_decode(xed_decoded_inst_t *inst,
830858
* while not printing instructions since the latter is too expensive for
831859
* regular use with long traces.
832860
*/
833-
errcode = xed_decode(inst, insn->raw, insn->size);
861+
errcode = xed_decode(&inst, insn->raw, insn->size);
834862
if (errcode != XED_ERROR_NONE) {
835863
printf("[%" PRIx64 ", %" PRIx64 ": xed error: (%u) %s]\n",
836864
offset, insn->ip, errcode,
837865
xed_error_enum_t2str(errcode));
838866
return;
839867
}
840868

841-
if (!xed_decoded_inst_valid(inst)) {
869+
if (!xed_decoded_inst_valid(&inst)) {
842870
printf("[%" PRIx64 ", %" PRIx64 ": xed error: "
843871
"invalid instruction]\n", offset, insn->ip);
844872
return;
845873
}
846-
}
847-
848-
static void check_insn(const struct pt_insn *insn, uint64_t offset)
849-
{
850-
xed_decoded_inst_t inst;
851-
852-
if (!insn) {
853-
printf("[internal error]\n");
854-
return;
855-
}
856-
857-
if (insn->isid <= 0)
858-
printf("[%" PRIx64 ", %" PRIx64 ": check error: "
859-
"bad isid]\n", offset, insn->ip);
860-
861-
xed_decoded_inst_zero(&inst);
862-
check_insn_decode(&inst, insn, offset);
863-
864-
/* We need a valid instruction in order to do further checks.
865-
*
866-
* Invalid instructions have already been diagnosed.
867-
*/
868-
if (!xed_decoded_inst_valid(&inst))
869-
return;
870874

871875
check_insn_iclass(&inst, insn, offset);
872876
}
@@ -953,13 +957,15 @@ static void print_insn(const struct pt_insn *insn,
953957
printf("%016" PRIx64, insn->ip);
954958

955959
if (!options->dont_print_insn) {
960+
xed_address_width_enum_t addr_width;
956961
xed_machine_mode_enum_t mode;
957962
xed_decoded_inst_t inst;
958963
xed_error_enum_t errcode;
959964
xed_state_t xed;
960965

961-
mode = translate_mode(insn->mode);
962-
xed_state_init2(&xed, mode, XED_ADDRESS_WIDTH_INVALID);
966+
addr_width = to_xed_addr_width(insn->mode);
967+
mode = to_xed_mode(insn->mode);
968+
xed_state_init2(&xed, mode, addr_width);
963969
xed_decoded_inst_zero_set_mode(&inst, &xed);
964970

965971
errcode = xed_decode(&inst, insn->raw, insn->size);
@@ -1388,8 +1394,11 @@ static void diagnose_insn(struct ptxed_decoder *decoder,
13881394
const char *errtype, int errcode,
13891395
const struct pt_insn *insn)
13901396
{
1397+
xed_address_width_enum_t addr_width;
1398+
xed_machine_mode_enum_t mode;
13911399
xed_decoded_inst_t inst;
13921400
xed_error_enum_t xederr;
1401+
xed_state_t xed;
13931402
uint64_t ip;
13941403

13951404
if (!decoder || !insn) {
@@ -1424,10 +1433,10 @@ static void diagnose_insn(struct ptxed_decoder *decoder,
14241433
if (insn.iclass == ptic_error)
14251434
break;
14261435
#endif
1427-
xed_decoded_inst_zero(&inst);
1428-
xed_decoded_inst_set_mode(&inst,
1429-
translate_mode(insn->mode),
1430-
XED_ADDRESS_WIDTH_INVALID);
1436+
addr_width = to_xed_addr_width(insn->mode);
1437+
mode = to_xed_mode(insn->mode);
1438+
xed_state_init2(&xed, mode, addr_width);
1439+
xed_decoded_inst_zero_set_mode(&inst, &xed);
14311440

14321441
xederr = xed_decode(&inst, insn->raw, insn->size);
14331442
if (xederr == XED_ERROR_NONE)
@@ -1664,8 +1673,11 @@ static void diagnose_block(struct ptxed_decoder *decoder,
16641673
const struct pt_block *block)
16651674
{
16661675
struct pt_insn insn;
1676+
xed_address_width_enum_t addr_width;
1677+
xed_machine_mode_enum_t mode;
16671678
xed_decoded_inst_t inst;
16681679
xed_error_enum_t xederr;
1680+
xed_state_t xed;
16691681
uint64_t ip;
16701682
int err;
16711683

@@ -1702,10 +1714,10 @@ static void diagnose_block(struct ptxed_decoder *decoder,
17021714
if (err < 0)
17031715
break;
17041716

1705-
xed_decoded_inst_zero(&inst);
1706-
xed_decoded_inst_set_mode(&inst,
1707-
translate_mode(insn.mode),
1708-
XED_ADDRESS_WIDTH_INVALID);
1717+
addr_width = to_xed_addr_width(block->mode);
1718+
mode = to_xed_mode(block->mode);
1719+
xed_state_init2(&xed, mode, addr_width);
1720+
xed_decoded_inst_zero_set_mode(&inst, &xed);
17091721

17101722
xederr = xed_decode(&inst, insn.raw, insn.size);
17111723
if (xederr == XED_ERROR_NONE)
@@ -1724,6 +1736,7 @@ static void print_block(struct ptxed_decoder *decoder,
17241736
const struct ptxed_stats *stats,
17251737
uint64_t offset, uint64_t time)
17261738
{
1739+
xed_address_width_enum_t addr_width;
17271740
xed_machine_mode_enum_t mode;
17281741
xed_state_t xed;
17291742
uint64_t ip;
@@ -1741,8 +1754,9 @@ static void print_block(struct ptxed_decoder *decoder,
17411754
printf("]\n");
17421755
}
17431756

1744-
mode = translate_mode(block->mode);
1745-
xed_state_init2(&xed, mode, XED_ADDRESS_WIDTH_INVALID);
1757+
addr_width = to_xed_addr_width(block->mode);
1758+
mode = to_xed_mode(block->mode);
1759+
xed_state_init2(&xed, mode, addr_width);
17461760

17471761
/* There's nothing to do for empty blocks. */
17481762
ninsn = block->ninsn;
@@ -1811,7 +1825,11 @@ static void check_block(const struct pt_block *block,
18111825
uint64_t offset)
18121826
{
18131827
struct pt_insn insn;
1828+
xed_address_width_enum_t addr_width;
1829+
xed_machine_mode_enum_t mode;
18141830
xed_decoded_inst_t inst;
1831+
xed_error_enum_t xederr;
1832+
xed_state_t xed;
18151833
uint64_t ip;
18161834
uint16_t ninsn;
18171835
int errcode;
@@ -1830,6 +1848,10 @@ static void check_block(const struct pt_block *block,
18301848
printf("[%" PRIx64 ", %" PRIx64 ": check error: "
18311849
"bad isid]\n", offset, block->ip);
18321850

1851+
addr_width = to_xed_addr_width(block->mode);
1852+
mode = to_xed_mode(block->mode);
1853+
xed_state_init2(&xed, mode, addr_width);
1854+
18331855
ip = block->ip;
18341856
do {
18351857
errcode = block_fetch_insn(&insn, block, ip, iscache);
@@ -1839,15 +1861,31 @@ static void check_block(const struct pt_block *block,
18391861
return;
18401862
}
18411863

1842-
xed_decoded_inst_zero(&inst);
1843-
check_insn_decode(&inst, &insn, offset);
1864+
xed_decoded_inst_zero_set_mode(&inst, &xed);
18441865

1845-
/* We need a valid instruction in order to do further checks.
1866+
/* Decode the instruction (again).
18461867
*
1847-
* Invalid instructions have already been diagnosed.
1868+
* We may have decoded the instruction already for printing.
1869+
* In this case, we will decode it twice.
1870+
*
1871+
* The more common use-case, however, is to check the
1872+
* instruction class while not printing instructions since the
1873+
* latter is too expensive for regular use with long traces.
18481874
*/
1849-
if (!xed_decoded_inst_valid(&inst))
1875+
xederr = xed_decode(&inst, insn.raw, insn.size);
1876+
if (xederr != XED_ERROR_NONE) {
1877+
printf("[%" PRIx64 ", %" PRIx64
1878+
": xed error: (%u) %s]\n",
1879+
offset, insn.ip, xederr,
1880+
xed_error_enum_t2str(xederr));
18501881
return;
1882+
}
1883+
1884+
if (!xed_decoded_inst_valid(&inst)) {
1885+
printf("[%" PRIx64 ", %" PRIx64 ": xed error: "
1886+
"invalid instruction]\n", offset, insn.ip);
1887+
return;
1888+
}
18511889

18521890
errcode = xed_next_ip(&ip, &inst, ip);
18531891
if (errcode < 0) {

0 commit comments

Comments
 (0)