d7a57a5df4
Option --write_code_comments_as_synthetic_source_to=file tells AOT compiler to create a file which contains code comments for all code objects written into an ELF snapshot and then emit a DWARF line number program into .debug_line section which attributes code to code comments in a way similar to how our own disassembler does it. This enables tools like objdump to display our code comments as part of the disassembly. This CL also tweaks ifdefs in such a way that IL printer and code comments facilities is now included into PRODUCT gen_snapshot binary. TEST=manually run product build with --print-flow-graph and --write_code_comments_as_synthetic_source_to Change-Id: Id6741013d43e1733b4ddeb34891a4d2fc06b9313 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/181380 Commit-Queue: Vyacheslav Egorov <vegorov@google.com> Reviewed-by: Tess Strickland <sstrickl@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
206 lines
6.8 KiB
C++
206 lines
6.8 KiB
C++
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#ifndef RUNTIME_VM_COMPILER_ASSEMBLER_DISASSEMBLER_H_
|
|
#define RUNTIME_VM_COMPILER_ASSEMBLER_DISASSEMBLER_H_
|
|
|
|
#include "vm/allocation.h"
|
|
#include "vm/globals.h"
|
|
#include "vm/log.h"
|
|
#include "vm/object.h"
|
|
|
|
#if !defined(DART_PRECOMPILED_RUNTIME)
|
|
#include "vm/compiler/assembler/assembler.h"
|
|
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
|
|
|
namespace dart {
|
|
|
|
// Forward declaration.
|
|
class CodeComments;
|
|
class JSONArray;
|
|
class MemoryRegion;
|
|
|
|
// Disassembly formatter interface, which consumes the
|
|
// disassembled instructions in any desired form.
|
|
class DisassemblyFormatter {
|
|
public:
|
|
DisassemblyFormatter() {}
|
|
virtual ~DisassemblyFormatter() {}
|
|
|
|
// Consume the decoded instruction at the given pc.
|
|
virtual void ConsumeInstruction(char* hex_buffer,
|
|
intptr_t hex_size,
|
|
char* human_buffer,
|
|
intptr_t human_size,
|
|
Object* object,
|
|
uword pc) = 0;
|
|
|
|
// Print a formatted message.
|
|
virtual void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3) = 0;
|
|
};
|
|
|
|
// Basic disassembly formatter that outputs the disassembled instruction
|
|
// to stdout.
|
|
class DisassembleToStdout : public DisassemblyFormatter {
|
|
public:
|
|
DisassembleToStdout() : DisassemblyFormatter() {}
|
|
~DisassembleToStdout() {}
|
|
|
|
virtual void ConsumeInstruction(char* hex_buffer,
|
|
intptr_t hex_size,
|
|
char* human_buffer,
|
|
intptr_t human_size,
|
|
Object* object,
|
|
uword pc);
|
|
|
|
virtual void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
|
|
|
|
private:
|
|
DISALLOW_ALLOCATION()
|
|
DISALLOW_COPY_AND_ASSIGN(DisassembleToStdout);
|
|
};
|
|
|
|
// Disassemble into a JSONStream.
|
|
class DisassembleToJSONStream : public DisassemblyFormatter {
|
|
public:
|
|
explicit DisassembleToJSONStream(const JSONArray& jsarr)
|
|
: DisassemblyFormatter(), jsarr_(jsarr) {}
|
|
~DisassembleToJSONStream() {}
|
|
|
|
virtual void ConsumeInstruction(char* hex_buffer,
|
|
intptr_t hex_size,
|
|
char* human_buffer,
|
|
intptr_t human_size,
|
|
Object* object,
|
|
uword pc);
|
|
|
|
virtual void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
|
|
|
|
private:
|
|
const JSONArray& jsarr_;
|
|
DISALLOW_ALLOCATION();
|
|
DISALLOW_COPY_AND_ASSIGN(DisassembleToJSONStream);
|
|
};
|
|
|
|
#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
|
|
// Basic disassembly formatter that outputs the disassembled instruction
|
|
// to a memory buffer. This is only intended for test writing.
|
|
class DisassembleToMemory : public DisassemblyFormatter {
|
|
public:
|
|
DisassembleToMemory(char* buffer, uintptr_t length)
|
|
: DisassemblyFormatter(),
|
|
buffer_(buffer),
|
|
remaining_(length),
|
|
overflowed_(false) {}
|
|
~DisassembleToMemory() {}
|
|
|
|
virtual void ConsumeInstruction(char* hex_buffer,
|
|
intptr_t hex_size,
|
|
char* human_buffer,
|
|
intptr_t human_size,
|
|
Object* object,
|
|
uword pc);
|
|
|
|
virtual void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
|
|
|
|
private:
|
|
char* buffer_;
|
|
int remaining_;
|
|
bool overflowed_;
|
|
DISALLOW_ALLOCATION();
|
|
DISALLOW_COPY_AND_ASSIGN(DisassembleToMemory);
|
|
};
|
|
#endif
|
|
|
|
// Disassemble instructions.
|
|
class Disassembler : public AllStatic {
|
|
public:
|
|
// Disassemble instructions between start and end.
|
|
// (The assumption is that start is at a valid instruction).
|
|
// Return true if all instructions were successfully decoded, false otherwise.
|
|
static void Disassemble(uword start,
|
|
uword end,
|
|
DisassemblyFormatter* formatter,
|
|
const Code& code,
|
|
const CodeComments* comments = nullptr);
|
|
|
|
static void Disassemble(uword start,
|
|
uword end,
|
|
DisassemblyFormatter* formatter) {
|
|
Disassemble(start, end, formatter, Code::Handle());
|
|
}
|
|
|
|
static void Disassemble(uword start,
|
|
uword end,
|
|
DisassemblyFormatter* formatter,
|
|
const CodeComments* comments) {
|
|
Disassemble(start, end, formatter, Code::Handle(), comments);
|
|
}
|
|
|
|
static void Disassemble(uword start, uword end, const Code& code) {
|
|
#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
|
|
DisassembleToStdout stdout_formatter;
|
|
LogBlock lb;
|
|
Disassemble(start, end, &stdout_formatter, code);
|
|
#else
|
|
UNREACHABLE();
|
|
#endif
|
|
}
|
|
|
|
static void Disassemble(uword start, uword end) {
|
|
#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
|
|
DisassembleToStdout stdout_formatter;
|
|
LogBlock lb;
|
|
Disassemble(start, end, &stdout_formatter);
|
|
#else
|
|
UNREACHABLE();
|
|
#endif
|
|
}
|
|
|
|
static void Disassemble(uword start,
|
|
uword end,
|
|
char* buffer,
|
|
uintptr_t buffer_size) {
|
|
#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
|
|
DisassembleToMemory memory_formatter(buffer, buffer_size);
|
|
LogBlock lb;
|
|
Disassemble(start, end, &memory_formatter);
|
|
#else
|
|
UNREACHABLE();
|
|
#endif
|
|
}
|
|
|
|
// Decodes one instruction.
|
|
// Writes a hexadecimal representation into the hex_buffer and a
|
|
// human-readable representation into the human_buffer.
|
|
// Writes the length of the decoded instruction in bytes in out_instr_len.
|
|
static void DecodeInstruction(char* hex_buffer,
|
|
intptr_t hex_size,
|
|
char* human_buffer,
|
|
intptr_t human_size,
|
|
int* out_instr_len,
|
|
const Code& code,
|
|
Object** object,
|
|
uword pc);
|
|
|
|
static void DisassembleCode(const Function& function,
|
|
const Code& code,
|
|
bool optimized);
|
|
|
|
static void DisassembleStub(const char* name, const Code& code);
|
|
|
|
private:
|
|
static void DisassembleCodeHelper(const char* function_fullname,
|
|
const char* function_info,
|
|
const Code& code,
|
|
bool optimized);
|
|
|
|
static const int kHexadecimalBufferSize = 32;
|
|
static const int kUserReadableBufferSize = 256;
|
|
};
|
|
|
|
} // namespace dart
|
|
|
|
#endif // RUNTIME_VM_COMPILER_ASSEMBLER_DISASSEMBLER_H_
|