1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "jit/Disassemble.h"
9 #include <stddef.h> // size_t
10 #include <stdint.h> // uint8_t, int32_t
12 #include "js/Printf.h" // JS_smprintf
13 #include "js/Utility.h" // JS::UniqueChars
15 #if defined(JS_JITSPEW)
16 # if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
17 # include "zydis/ZydisAPI.h" // zydisDisassemble
18 # elif defined(JS_CODEGEN_ARM64)
19 # include "jit/arm/disasm/Disasm-arm.h" // js::jit::disasm::*
20 # include "jit/arm64/vixl/Decoder-vixl.h" // vixl::Decoder
21 # include "jit/arm64/vixl/Disasm-vixl.h" // vixl::Disassembler
22 # include "jit/arm64/vixl/Instructions-vixl.h" // vixl::Instruction
23 # elif defined(JS_CODEGEN_ARM)
24 # include "jit/arm/disasm/Disasm-arm.h" // js::jit::disasm::*
31 #if defined(JS_JITSPEW) && (defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64))
33 bool HasDisassembler() { return true; }
35 void Disassemble(uint8_t* code
, size_t length
, InstrCallback callback
) {
36 zydisDisassemble(code
, length
, callback
);
39 #elif defined(JS_JITSPEW) && defined(JS_CODEGEN_ARM64)
41 class ARM64Disassembler
: public vixl::Disassembler
{
43 explicit ARM64Disassembler(InstrCallback callback
) : callback_(callback
) {}
46 void ProcessOutput(const vixl::Instruction
* instr
) override
{
47 JS::UniqueChars formatted
= JS_smprintf(
48 "0x%p %08x %s", instr
, instr
->InstructionBits(), GetOutput());
49 callback_(formatted
.get());
53 InstrCallback callback_
;
56 bool HasDisassembler() { return true; }
58 void Disassemble(uint8_t* code
, size_t length
, InstrCallback callback
) {
59 ARM64Disassembler
dis(callback
);
60 vixl::Decoder decoder
;
61 decoder
.AppendVisitor(&dis
);
63 uint8_t* instr
= code
;
64 uint8_t* end
= code
+ length
;
67 decoder
.Decode(reinterpret_cast<vixl::Instruction
*>(instr
));
69 instr
+= sizeof(vixl::Instr
);
73 #elif defined(JS_JITSPEW) && defined(JS_CODEGEN_ARM)
75 bool HasDisassembler() { return true; }
77 void Disassemble(uint8_t* code
, size_t length
, InstrCallback callback
) {
78 disasm::NameConverter converter
;
79 disasm::Disassembler
d(converter
);
81 uint8_t* instr
= code
;
82 uint8_t* end
= code
+ length
;
85 disasm::EmbeddedVector
<char, disasm::ReasonableBufferSize
> buffer
;
87 uint8_t* next_instr
= instr
+ d
.InstructionDecode(buffer
, instr
);
89 JS::UniqueChars formatted
=
90 JS_smprintf("0x%p %08x %s", instr
, *reinterpret_cast<int32_t*>(instr
),
92 callback(formatted
.get());
100 bool HasDisassembler() { return false; }
102 void Disassemble(uint8_t* code
, size_t length
, InstrCallback callback
) {
103 callback("*** No disassembly available ***\n");