Commit 0f5c0d6b authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

Make disassembler tests abort on unimplemented opcode

This ensures that tests actually abort on unimplemented opcodes instead
of just printing them as "Unimplemented Instruction". If used to
disassemble a code region though, we want to ignore unimplemented
opcodes to keep printing remaining valid instructions.

The tests were previously fixed by Deepti in
8fa509d3, but this got partly reverted
on the "Address" refactoring in
2459046c.

R=titzer@chromium.org

Change-Id: I802dda2b0f45ee77c4f9b244ed984b1c4679bac3
Reviewed-on: https://chromium-review.googlesource.com/1146649
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54726}
parent 34f6b5fb
...@@ -2693,13 +2693,6 @@ const char* NameConverter::NameInCode(byte* addr) const { ...@@ -2693,13 +2693,6 @@ const char* NameConverter::NameInCode(byte* addr) const {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Disassembler::Disassembler(const NameConverter& converter)
: converter_(converter) {}
Disassembler::~Disassembler() {}
int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
byte* instruction) { byte* instruction) {
v8::internal::Decoder d(converter_, buffer); v8::internal::Decoder d(converter_, buffer);
...@@ -2711,10 +2704,10 @@ int Disassembler::ConstantPoolSizeAt(byte* instruction) { ...@@ -2711,10 +2704,10 @@ int Disassembler::ConstantPoolSizeAt(byte* instruction) {
return v8::internal::Decoder::ConstantPoolSizeAt(instruction); return v8::internal::Decoder::ConstantPoolSizeAt(instruction);
} }
void Disassembler::Disassemble(FILE* f, byte* begin, byte* end,
void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { UnimplementedOpcodeAction unimplemented_action) {
NameConverter converter; NameConverter converter;
Disassembler d(converter); Disassembler d(converter, unimplemented_action);
for (byte* pc = begin; pc < end;) { for (byte* pc = begin; pc < end;) {
v8::internal::EmbeddedVector<char, 128> buffer; v8::internal::EmbeddedVector<char, 128> buffer;
buffer[0] = '\0'; buffer[0] = '\0';
...@@ -2725,7 +2718,6 @@ void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { ...@@ -2725,7 +2718,6 @@ void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
} }
} }
} // namespace disasm } // namespace disasm
#endif // V8_TARGET_ARCH_ARM #endif // V8_TARGET_ARCH_ARM
...@@ -4106,15 +4106,9 @@ class BufferDisassembler : public v8::internal::DisassemblingDecoder { ...@@ -4106,15 +4106,9 @@ class BufferDisassembler : public v8::internal::DisassemblingDecoder {
v8::internal::Vector<char> out_buffer_; v8::internal::Vector<char> out_buffer_;
}; };
Disassembler::Disassembler(const NameConverter& converter)
: converter_(converter) {}
Disassembler::~Disassembler() { USE(converter_); }
int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
byte* instr) { byte* instr) {
USE(converter_); // avoid unused field warning
v8::internal::Decoder<v8::internal::DispatchingDecoderVisitor> decoder; v8::internal::Decoder<v8::internal::DispatchingDecoderVisitor> decoder;
BufferDisassembler disasm(buffer); BufferDisassembler disasm(buffer);
decoder.AppendVisitor(&disasm); decoder.AppendVisitor(&disasm);
...@@ -4129,8 +4123,8 @@ int Disassembler::ConstantPoolSizeAt(byte* instr) { ...@@ -4129,8 +4123,8 @@ int Disassembler::ConstantPoolSizeAt(byte* instr) {
reinterpret_cast<v8::internal::Instruction*>(instr)); reinterpret_cast<v8::internal::Instruction*>(instr));
} }
void Disassembler::Disassemble(FILE* file, byte* start, byte* end,
void Disassembler::Disassemble(FILE* file, byte* start, byte* end) { UnimplementedOpcodeAction) {
v8::internal::Decoder<v8::internal::DispatchingDecoderVisitor> decoder; v8::internal::Decoder<v8::internal::DispatchingDecoderVisitor> decoder;
v8::internal::PrintDisassembler disasm(file); v8::internal::PrintDisassembler disasm(file);
decoder.AppendVisitor(&disasm); decoder.AppendVisitor(&disasm);
......
...@@ -32,32 +32,39 @@ class NameConverter { ...@@ -32,32 +32,39 @@ class NameConverter {
// A generic Disassembler interface // A generic Disassembler interface
class Disassembler { class Disassembler {
public: public:
enum UnimplementedOpcodeAction : int8_t {
kContinueOnUnimplementedOpcode,
kAbortOnUnimplementedOpcode
};
// Caller deallocates converter. // Caller deallocates converter.
explicit Disassembler(const NameConverter& converter); explicit Disassembler(const NameConverter& converter,
UnimplementedOpcodeAction unimplemented_opcode_action =
kAbortOnUnimplementedOpcode)
: converter_(converter),
unimplemented_opcode_action_(unimplemented_opcode_action) {}
virtual ~Disassembler(); UnimplementedOpcodeAction unimplemented_opcode_action() const {
return unimplemented_opcode_action_;
}
// Writes one disassembled instruction into 'buffer' (0-terminated). // Writes one disassembled instruction into 'buffer' (0-terminated).
// Returns the length of the disassembled machine instruction in bytes. // Returns the length of the disassembled machine instruction in bytes.
int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction); int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction);
// Disassemblers on ia32/x64 need a separate method for testing, as
// instruction decode method above continues on unimplemented opcodes, and
// does not test the disassemblers. Basic functionality of the method remains
// the same.
int InstructionDecodeForTesting(v8::internal::Vector<char> buffer,
byte* instruction);
// Returns -1 if instruction does not mark the beginning of a constant pool, // Returns -1 if instruction does not mark the beginning of a constant pool,
// or the number of entries in the constant pool beginning here. // or the number of entries in the constant pool beginning here.
int ConstantPoolSizeAt(byte* instruction); int ConstantPoolSizeAt(byte* instruction);
// Write disassembly into specified file 'f' using specified NameConverter // Write disassembly into specified file 'f' using specified NameConverter
// (see constructor). // (see constructor).
static void Disassemble(FILE* f, byte* begin, byte* end); static void Disassemble(FILE* f, byte* begin, byte* end,
UnimplementedOpcodeAction unimplemented_action =
kAbortOnUnimplementedOpcode);
private: private:
const NameConverter& converter_; const NameConverter& converter_;
const UnimplementedOpcodeAction unimplemented_opcode_action_;
DISALLOW_IMPLICIT_CONSTRUCTORS(Disassembler); DISALLOW_IMPLICIT_CONSTRUCTORS(Disassembler);
}; };
......
...@@ -175,7 +175,8 @@ static int DecodeIt(Isolate* isolate, ExternalReferenceEncoder* ref_encoder, ...@@ -175,7 +175,8 @@ static int DecodeIt(Isolate* isolate, ExternalReferenceEncoder* ref_encoder,
v8::internal::EmbeddedVector<char, kOutBufferSize> out_buffer; v8::internal::EmbeddedVector<char, kOutBufferSize> out_buffer;
StringBuilder out(out_buffer.start(), out_buffer.length()); StringBuilder out(out_buffer.start(), out_buffer.length());
byte* pc = begin; byte* pc = begin;
disasm::Disassembler d(converter); disasm::Disassembler d(converter,
disasm::Disassembler::kContinueOnUnimplementedOpcode);
RelocIterator* it = nullptr; RelocIterator* it = nullptr;
if (!converter.code().is_null()) { if (!converter.code().is_null()) {
it = new RelocIterator(converter.code()); it = new RelocIterator(converter.code());
......
...@@ -16,6 +16,8 @@ class Disassembler : public AllStatic { ...@@ -16,6 +16,8 @@ class Disassembler : public AllStatic {
// Decode instructions in the the interval [begin, end) and print the // Decode instructions in the the interval [begin, end) and print the
// code into os. Returns the number of bytes disassembled or 1 if no // code into os. Returns the number of bytes disassembled or 1 if no
// instruction could be decoded. // instruction could be decoded.
// Does not abort on unimplemented opcodes, but prints them as 'Unimplemented
// Instruction'.
// the code object is used for name resolution and may be null. // the code object is used for name resolution and may be null.
// TODO(titzer): accept a {WasmCodeManager*} if {isolate} is null // TODO(titzer): accept a {WasmCodeManager*} if {isolate} is null
static int Decode(Isolate* isolate, std::ostream* os, byte* begin, byte* end, static int Decode(Isolate* isolate, std::ostream* os, byte* begin, byte* end,
......
...@@ -228,15 +228,16 @@ void InstructionTable::AddJumpConditionalShort() { ...@@ -228,15 +228,16 @@ void InstructionTable::AddJumpConditionalShort() {
// The IA32 disassembler implementation. // The IA32 disassembler implementation.
class DisassemblerIA32 { class DisassemblerIA32 {
public: public:
DisassemblerIA32(const NameConverter& converter, DisassemblerIA32(
bool abort_on_unimplemented = true) const NameConverter& converter,
Disassembler::UnimplementedOpcodeAction unimplemented_opcode_action)
: converter_(converter), : converter_(converter),
vex_byte0_(0), vex_byte0_(0),
vex_byte1_(0), vex_byte1_(0),
vex_byte2_(0), vex_byte2_(0),
instruction_table_(InstructionTable::get_instance()), instruction_table_(InstructionTable::get_instance()),
tmp_buffer_pos_(0), tmp_buffer_pos_(0),
abort_on_unimplemented_(abort_on_unimplemented) { unimplemented_opcode_action_(unimplemented_opcode_action) {
tmp_buffer_[0] = '\0'; tmp_buffer_[0] = '\0';
} }
...@@ -254,7 +255,7 @@ class DisassemblerIA32 { ...@@ -254,7 +255,7 @@ class DisassemblerIA32 {
InstructionTable* instruction_table_; InstructionTable* instruction_table_;
v8::internal::EmbeddedVector<char, 128> tmp_buffer_; v8::internal::EmbeddedVector<char, 128> tmp_buffer_;
unsigned int tmp_buffer_pos_; unsigned int tmp_buffer_pos_;
bool abort_on_unimplemented_; Disassembler::UnimplementedOpcodeAction unimplemented_opcode_action_;
enum { enum {
eax = 0, eax = 0,
...@@ -392,8 +393,9 @@ class DisassemblerIA32 { ...@@ -392,8 +393,9 @@ class DisassemblerIA32 {
PRINTF_FORMAT(2, 3) void AppendToBuffer(const char* format, ...); PRINTF_FORMAT(2, 3) void AppendToBuffer(const char* format, ...);
void UnimplementedInstruction() { void UnimplementedInstruction() {
if (abort_on_unimplemented_) { if (unimplemented_opcode_action_ ==
UNIMPLEMENTED(); Disassembler::kAbortOnUnimplementedOpcode) {
FATAL("Unimplemented instruction in disassembler");
} else { } else {
AppendToBuffer("'Unimplemented Instruction'"); AppendToBuffer("'Unimplemented Instruction'");
} }
...@@ -2628,32 +2630,20 @@ const char* NameConverter::NameInCode(byte* addr) const { ...@@ -2628,32 +2630,20 @@ const char* NameConverter::NameInCode(byte* addr) const {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Disassembler::Disassembler(const NameConverter& converter)
: converter_(converter) {}
Disassembler::~Disassembler() {}
int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
byte* instruction) { byte* instruction) {
DisassemblerIA32 d(converter_, false /*do not crash if unimplemented*/); DisassemblerIA32 d(converter_, unimplemented_opcode_action());
return d.InstructionDecode(buffer, instruction);
}
int Disassembler::InstructionDecodeForTesting(v8::internal::Vector<char> buffer,
byte* instruction) {
DisassemblerIA32 d(converter_, true /*crash if unimplemented*/);
return d.InstructionDecode(buffer, instruction); return d.InstructionDecode(buffer, instruction);
} }
// The IA-32 assembler does not currently use constant pools. // The IA-32 assembler does not currently use constant pools.
int Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; } int Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; }
// static
/*static*/ void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { void Disassembler::Disassemble(FILE* f, byte* begin, byte* end,
UnimplementedOpcodeAction unimplemented_action) {
NameConverter converter; NameConverter converter;
Disassembler d(converter); Disassembler d(converter, unimplemented_action);
for (byte* pc = begin; pc < end;) { for (byte* pc = begin; pc < end;) {
v8::internal::EmbeddedVector<char, 128> buffer; v8::internal::EmbeddedVector<char, 128> buffer;
buffer[0] = '\0'; buffer[0] = '\0';
......
...@@ -2752,13 +2752,6 @@ const char* NameConverter::NameInCode(byte* addr) const { ...@@ -2752,13 +2752,6 @@ const char* NameConverter::NameInCode(byte* addr) const {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Disassembler::Disassembler(const NameConverter& converter)
: converter_(converter) {}
Disassembler::~Disassembler() {}
int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
byte* instruction) { byte* instruction) {
v8::internal::Decoder d(converter_, buffer); v8::internal::Decoder d(converter_, buffer);
...@@ -2771,10 +2764,10 @@ int Disassembler::ConstantPoolSizeAt(byte* instruction) { ...@@ -2771,10 +2764,10 @@ int Disassembler::ConstantPoolSizeAt(byte* instruction) {
return -1; return -1;
} }
void Disassembler::Disassemble(FILE* f, byte* begin, byte* end,
void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { UnimplementedOpcodeAction unimplemented_action) {
NameConverter converter; NameConverter converter;
Disassembler d(converter); Disassembler d(converter, unimplemented_action);
for (byte* pc = begin; pc < end;) { for (byte* pc = begin; pc < end;) {
v8::internal::EmbeddedVector<char, 128> buffer; v8::internal::EmbeddedVector<char, 128> buffer;
buffer[0] = '\0'; buffer[0] = '\0';
......
...@@ -3071,13 +3071,6 @@ const char* NameConverter::NameInCode(byte* addr) const { ...@@ -3071,13 +3071,6 @@ const char* NameConverter::NameInCode(byte* addr) const {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Disassembler::Disassembler(const NameConverter& converter)
: converter_(converter) {}
Disassembler::~Disassembler() {}
int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
byte* instruction) { byte* instruction) {
v8::internal::Decoder d(converter_, buffer); v8::internal::Decoder d(converter_, buffer);
...@@ -3090,10 +3083,10 @@ int Disassembler::ConstantPoolSizeAt(byte* instruction) { ...@@ -3090,10 +3083,10 @@ int Disassembler::ConstantPoolSizeAt(byte* instruction) {
return -1; return -1;
} }
void Disassembler::Disassemble(FILE* f, byte* begin, byte* end,
void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { UnimplementedOpcodeAction unimplemented_action) {
NameConverter converter; NameConverter converter;
Disassembler d(converter); Disassembler d(converter, unimplemented_action);
for (byte* pc = begin; pc < end;) { for (byte* pc = begin; pc < end;) {
v8::internal::EmbeddedVector<char, 128> buffer; v8::internal::EmbeddedVector<char, 128> buffer;
buffer[0] = '\0'; buffer[0] = '\0';
......
...@@ -1512,13 +1512,6 @@ const char* NameConverter::NameInCode(byte* addr) const { ...@@ -1512,13 +1512,6 @@ const char* NameConverter::NameInCode(byte* addr) const {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Disassembler::Disassembler(const NameConverter& converter)
: converter_(converter) {}
Disassembler::~Disassembler() {}
int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
byte* instruction) { byte* instruction) {
v8::internal::Decoder d(converter_, buffer); v8::internal::Decoder d(converter_, buffer);
...@@ -1529,10 +1522,10 @@ int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, ...@@ -1529,10 +1522,10 @@ int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
// The PPC assembler does not currently use constant pools. // The PPC assembler does not currently use constant pools.
int Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; } int Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; }
void Disassembler::Disassemble(FILE* f, byte* begin, byte* end,
void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { UnimplementedOpcodeAction unimplemented_action) {
NameConverter converter; NameConverter converter;
Disassembler d(converter); Disassembler d(converter, unimplemented_action);
for (byte* pc = begin; pc < end;) { for (byte* pc = begin; pc < end;) {
v8::internal::EmbeddedVector<char, 128> buffer; v8::internal::EmbeddedVector<char, 128> buffer;
buffer[0] = '\0'; buffer[0] = '\0';
......
...@@ -960,11 +960,6 @@ const char* NameConverter::NameInCode(byte* addr) const { ...@@ -960,11 +960,6 @@ const char* NameConverter::NameInCode(byte* addr) const {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Disassembler::Disassembler(const NameConverter& converter)
: converter_(converter) {}
Disassembler::~Disassembler() {}
int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
byte* instruction) { byte* instruction) {
v8::internal::Decoder d(converter_, buffer); v8::internal::Decoder d(converter_, buffer);
...@@ -974,9 +969,10 @@ int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, ...@@ -974,9 +969,10 @@ int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
// The S390 assembler does not currently use constant pools. // The S390 assembler does not currently use constant pools.
int Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; } int Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; }
void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { void Disassembler::Disassemble(FILE* f, byte* begin, byte* end,
UnimplementedOpcodeAction unimplemented_action) {
NameConverter converter; NameConverter converter;
Disassembler d(converter); Disassembler d(converter, unimplemented_action);
for (byte* pc = begin; pc < end;) { for (byte* pc = begin; pc < end;) {
v8::internal::EmbeddedVector<char, 128> buffer; v8::internal::EmbeddedVector<char, 128> buffer;
buffer[0] = '\0'; buffer[0] = '\0';
......
...@@ -277,23 +277,17 @@ static const InstructionDesc cmov_instructions[16] = { ...@@ -277,23 +277,17 @@ static const InstructionDesc cmov_instructions[16] = {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// DisassemblerX64 implementation. // DisassemblerX64 implementation.
enum UnimplementedOpcodeAction {
CONTINUE_ON_UNIMPLEMENTED_OPCODE,
ABORT_ON_UNIMPLEMENTED_OPCODE
};
// A new DisassemblerX64 object is created to disassemble each instruction. // A new DisassemblerX64 object is created to disassemble each instruction.
// The object can only disassemble a single instruction. // The object can only disassemble a single instruction.
class DisassemblerX64 { class DisassemblerX64 {
public: public:
DisassemblerX64(const NameConverter& converter, DisassemblerX64(const NameConverter& converter,
UnimplementedOpcodeAction unimplemented_action = Disassembler::UnimplementedOpcodeAction unimplemented_action)
ABORT_ON_UNIMPLEMENTED_OPCODE)
: converter_(converter), : converter_(converter),
tmp_buffer_pos_(0), tmp_buffer_pos_(0),
abort_on_unimplemented_(unimplemented_action == abort_on_unimplemented_(unimplemented_action ==
ABORT_ON_UNIMPLEMENTED_OPCODE), Disassembler::kAbortOnUnimplementedOpcode),
rex_(0), rex_(0),
operand_size_(0), operand_size_(0),
group_1_prefix_(0), group_1_prefix_(0),
...@@ -305,9 +299,6 @@ class DisassemblerX64 { ...@@ -305,9 +299,6 @@ class DisassemblerX64 {
tmp_buffer_[0] = '\0'; tmp_buffer_[0] = '\0';
} }
virtual ~DisassemblerX64() {
}
// Writes one disassembled instruction into 'buffer' (0-terminated). // Writes one disassembled instruction into 'buffer' (0-terminated).
// Returns the length of the disassembled machine instruction in bytes. // Returns the length of the disassembled machine instruction in bytes.
int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction); int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction);
...@@ -2820,21 +2811,9 @@ const char* NameConverter::NameInCode(byte* addr) const { ...@@ -2820,21 +2811,9 @@ const char* NameConverter::NameInCode(byte* addr) const {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Disassembler::Disassembler(const NameConverter& converter)
: converter_(converter) { }
Disassembler::~Disassembler() { }
int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
byte* instruction) { byte* instruction) {
DisassemblerX64 d(converter_, CONTINUE_ON_UNIMPLEMENTED_OPCODE); DisassemblerX64 d(converter_, unimplemented_opcode_action());
return d.InstructionDecode(buffer, instruction);
}
int Disassembler::InstructionDecodeForTesting(v8::internal::Vector<char> buffer,
byte* instruction) {
DisassemblerX64 d(converter_, ABORT_ON_UNIMPLEMENTED_OPCODE);
return d.InstructionDecode(buffer, instruction); return d.InstructionDecode(buffer, instruction);
} }
...@@ -2843,10 +2822,10 @@ int Disassembler::ConstantPoolSizeAt(byte* instruction) { ...@@ -2843,10 +2822,10 @@ int Disassembler::ConstantPoolSizeAt(byte* instruction) {
return -1; return -1;
} }
void Disassembler::Disassemble(FILE* f, byte* begin, byte* end,
void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { UnimplementedOpcodeAction unimplemented_action) {
NameConverter converter; NameConverter converter;
Disassembler d(converter); Disassembler d(converter, unimplemented_action);
for (byte* pc = begin; pc < end;) { for (byte* pc = begin; pc < end;) {
v8::internal::EmbeddedVector<char, 128> buffer; v8::internal::EmbeddedVector<char, 128> buffer;
buffer[0] = '\0'; buffer[0] = '\0';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment