Skip to content

Commit

Permalink
i#4567: Handle instructions with a single source operand that's an AV…
Browse files Browse the repository at this point in the history
…X-512 mask register in AT&T style disassembly (#4568)

The mask register is always the first source operand. i here is stale, the result of previous loop. The `instr_get_src` correctly uses a hardcoded zero. But instr_info_opnd_type reuses i and dies if the instruction has a single source operand (because i is always out of range). is_evex_mask_pending is not ever set for Intel style disassembly which is why this bug only affects AT&T syntax.

drdisas -syntax att 62 f2 fe 48 28 c9 will trigger this bug.

This is tested in the (currently ifdefed out) binutils AVX-512 tests.

Also changes usage errors to actually show up (on this error the message is not visible) by printing to stderr and adding a trailing \n so they are not caught up in any output buffering glibc is doing.

Fixes #4567
  • Loading branch information
khuey authored Dec 1, 2020
1 parent 322d8d5 commit 0d6a8d0
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 4 deletions.
2 changes: 1 addition & 1 deletion core/ir/decodelib.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ get_thread_private_dcontext(void)
void
external_error(const char *file, int line, const char *msg)
{
printf("Usage error: %s (%s, line %d)", msg, file, line);
fprintf(stderr, "Usage error: %s (%s, line %d)\n", msg, file, line);
abort();
}

Expand Down
7 changes: 4 additions & 3 deletions core/ir/disassemble_shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -966,15 +966,16 @@ instr_disassemble_opnds_noimplicit(char *buf, size_t bufsz, size_t *sofar INOUT,
}
}
if (is_evex_mask_pending) {
opnd = instr_get_src(instr, 0);
int mask_index = 0;
opnd = instr_get_src(instr, mask_index);
CLIENT_ASSERT(IF_X86_ELSE(true, false), "evex mask can only exist for x86.");
optype = instr_info_opnd_type(info, !dsts_first(), i);
optype = instr_info_opnd_type(info, !dsts_first(), mask_index);
CLIENT_ASSERT(!instr_is_opmask(instr) && opnd_is_reg(opnd) &&
reg_is_opmask(opnd_get_reg(opnd)) && opmask_with_dsts(),
"evex mask must always be the first source.");
print_to_buffer(buf, bufsz, sofar, " {");
opnd_disassemble_noimplicit(buf, bufsz, sofar, dcontext, instr, optype, opnd,
false, multiple_encodings, dsts_first(), &i);
false, multiple_encodings, dsts_first(), &mask_index);
print_to_buffer(buf, bufsz, sofar, "}");
}
}
Expand Down

0 comments on commit 0d6a8d0

Please sign in to comment.