1// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_COMPILER_ASSEMBLER_DISASSEMBLER_H_
6#define RUNTIME_VM_COMPILER_ASSEMBLER_DISASSEMBLER_H_
7
8#include "vm/allocation.h"
9#include "vm/globals.h"
10#include "vm/log.h"
11#include "vm/object.h"
12
13#if !defined(DART_PRECOMPILED_RUNTIME)
14#include "vm/compiler/assembler/assembler.h"
15#endif // !defined(DART_PRECOMPILED_RUNTIME)
16
17namespace dart {
18
19// Forward declaration.
20class MemoryRegion;
21class JSONArray;
22
23// Disassembly formatter interface, which consumes the
24// disassembled instructions in any desired form.
25class DisassemblyFormatter {
26 public:
27 DisassemblyFormatter() {}
28 virtual ~DisassemblyFormatter() {}
29
30 // Consume the decoded instruction at the given pc.
31 virtual void ConsumeInstruction(char* hex_buffer,
32 intptr_t hex_size,
33 char* human_buffer,
34 intptr_t human_size,
35 Object* object,
36 uword pc) = 0;
37
38 // Print a formatted message.
39 virtual void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3) = 0;
40};
41
42// Basic disassembly formatter that outputs the disassembled instruction
43// to stdout.
44class DisassembleToStdout : public DisassemblyFormatter {
45 public:
46 DisassembleToStdout() : DisassemblyFormatter() {}
47 ~DisassembleToStdout() {}
48
49 virtual void ConsumeInstruction(char* hex_buffer,
50 intptr_t hex_size,
51 char* human_buffer,
52 intptr_t human_size,
53 Object* object,
54 uword pc);
55
56 virtual void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
57
58 private:
59 DISALLOW_ALLOCATION()
60 DISALLOW_COPY_AND_ASSIGN(DisassembleToStdout);
61};
62
63// Disassemble into a JSONStream.
64class DisassembleToJSONStream : public DisassemblyFormatter {
65 public:
66 explicit DisassembleToJSONStream(const JSONArray& jsarr)
67 : DisassemblyFormatter(), jsarr_(jsarr) {}
68 ~DisassembleToJSONStream() {}
69
70 virtual void ConsumeInstruction(char* hex_buffer,
71 intptr_t hex_size,
72 char* human_buffer,
73 intptr_t human_size,
74 Object* object,
75 uword pc);
76
77 virtual void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
78
79 private:
80 const JSONArray& jsarr_;
81 DISALLOW_ALLOCATION();
82 DISALLOW_COPY_AND_ASSIGN(DisassembleToJSONStream);
83};
84
85#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
86// Basic disassembly formatter that outputs the disassembled instruction
87// to a memory buffer. This is only intended for test writing.
88class DisassembleToMemory : public DisassemblyFormatter {
89 public:
90 DisassembleToMemory(char* buffer, uintptr_t length)
91 : DisassemblyFormatter(),
92 buffer_(buffer),
93 remaining_(length),
94 overflowed_(false) {}
95 ~DisassembleToMemory() {}
96
97 virtual void ConsumeInstruction(char* hex_buffer,
98 intptr_t hex_size,
99 char* human_buffer,
100 intptr_t human_size,
101 Object* object,
102 uword pc);
103
104 virtual void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
105
106 private:
107 char* buffer_;
108 int remaining_;
109 bool overflowed_;
110 DISALLOW_ALLOCATION();
111 DISALLOW_COPY_AND_ASSIGN(DisassembleToMemory);
112};
113#endif
114
115// Disassemble instructions.
116class Disassembler : public AllStatic {
117 public:
118 // Disassemble instructions between start and end.
119 // (The assumption is that start is at a valid instruction).
120 // Return true if all instructions were successfully decoded, false otherwise.
121 static void Disassemble(uword start,
122 uword end,
123 DisassemblyFormatter* formatter,
124 const Code& code,
125 const Code::Comments* comments = nullptr);
126
127 static void Disassemble(uword start,
128 uword end,
129 DisassemblyFormatter* formatter) {
130 Disassemble(start, end, formatter, Code::Handle());
131 }
132
133 static void Disassemble(uword start,
134 uword end,
135 DisassemblyFormatter* formatter,
136 const Code::Comments* comments) {
137 Disassemble(start, end, formatter, Code::Handle(), comments);
138 }
139
140 static void Disassemble(uword start, uword end, const Code& code) {
141#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
142 DisassembleToStdout stdout_formatter;
143 LogBlock lb;
144 Disassemble(start, end, &stdout_formatter, code);
145#else
146 UNREACHABLE();
147#endif
148 }
149
150 static void Disassemble(uword start, uword end) {
151#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
152 DisassembleToStdout stdout_formatter;
153 LogBlock lb;
154 Disassemble(start, end, &stdout_formatter);
155#else
156 UNREACHABLE();
157#endif
158 }
159
160 static void Disassemble(uword start,
161 uword end,
162 char* buffer,
163 uintptr_t buffer_size) {
164#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
165 DisassembleToMemory memory_formatter(buffer, buffer_size);
166 LogBlock lb;
167 Disassemble(start, end, &memory_formatter);
168#else
169 UNREACHABLE();
170#endif
171 }
172
173 // Decodes one instruction.
174 // Writes a hexadecimal representation into the hex_buffer and a
175 // human-readable representation into the human_buffer.
176 // Writes the length of the decoded instruction in bytes in out_instr_len.
177 static void DecodeInstruction(char* hex_buffer,
178 intptr_t hex_size,
179 char* human_buffer,
180 intptr_t human_size,
181 int* out_instr_len,
182 const Code& code,
183 Object** object,
184 uword pc);
185
186 static void DisassembleCode(const Function& function,
187 const Code& code,
188 bool optimized);
189
190 static void DisassembleStub(const char* name, const Code& code);
191
192 private:
193 static void DisassembleCodeHelper(const char* function_fullname,
194 const char* function_info,
195 const Code& code,
196 bool optimized);
197
198 static const int kHexadecimalBufferSize = 32;
199 static const int kUserReadableBufferSize = 256;
200};
201
202} // namespace dart
203
204#endif // RUNTIME_VM_COMPILER_ASSEMBLER_DISASSEMBLER_H_
205