runtime/disassembler.cpp (108 lines of code) (raw):
// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
// Copyright (c) 2013, the Dart project authors and Facebook, Inc. and its
// affiliates. Please see the AUTHORS-Dart 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-Dart file.
#include "disassembler.h"
#include <cinttypes>
#include <cstdarg>
#include "assembler-utils.h"
namespace py {
static const int kHexColumnWidth = 23;
void DisassembleToStdout::consumeInstruction(char* hex_buffer,
intptr_t hex_size,
char* human_buffer,
intptr_t human_size, uword pc) {
(void)hex_size;
(void)human_size;
std::fprintf(stdout, "0x%" PRIX64 " %s", static_cast<uint64_t>(pc),
hex_buffer);
int hex_length = strlen(hex_buffer);
if (hex_length < kHexColumnWidth) {
for (int i = kHexColumnWidth - hex_length; i > 0; i--) {
std::fprintf(stdout, " ");
}
}
std::fprintf(stdout, "%s", human_buffer);
std::fprintf(stdout, "\n");
}
void DisassembleToStdout::print(const char* format, ...) {
va_list args;
va_start(args, format);
std::vprintf(format, args);
va_end(args);
}
void DisassembleToMemory::consumeInstruction(char* hex_buffer,
intptr_t hex_size,
char* human_buffer,
intptr_t human_size, uword pc) {
(void)human_size;
(void)hex_buffer;
(void)hex_size;
(void)pc;
if (overflowed_) {
return;
}
intptr_t len = strlen(human_buffer);
if (remaining_ < len + 100) {
*buffer_++ = '.';
*buffer_++ = '.';
*buffer_++ = '.';
*buffer_++ = '\n';
*buffer_++ = '\0';
overflowed_ = true;
return;
}
memmove(buffer_, human_buffer, len);
buffer_ += len;
remaining_ -= len;
*buffer_++ = '\n';
remaining_--;
*buffer_ = '\0';
}
void DisassembleToMemory::print(const char* format, ...) {
if (overflowed_) {
return;
}
va_list args;
va_start(args, format);
intptr_t len = std::vsnprintf(nullptr, 0, format, args);
va_end(args);
if (remaining_ < len + 100) {
*buffer_++ = '.';
*buffer_++ = '.';
*buffer_++ = '.';
*buffer_++ = '\n';
*buffer_++ = '\0';
overflowed_ = true;
return;
}
va_start(args, format);
intptr_t len2 = std::vsnprintf(buffer_, len, format, args);
va_end(args);
DCHECK(len == len2, "");
buffer_ += len;
remaining_ -= len;
*buffer_++ = '\n';
remaining_--;
*buffer_ = '\0';
}
void Disassembler::disassemble(uword start, uword end,
DisassemblyFormatter* formatter,
const CodeComments* comments) {
DCHECK(formatter != nullptr, "");
char hex_buffer[kHexadecimalBufferSize]; // Instruction in hexadecimal form.
char human_buffer[kUserReadableBufferSize]; // Human-readable instruction.
uword pc = start;
intptr_t comment_finger = 0;
while (pc < end) {
const intptr_t offset = pc - start;
while (comments && comment_finger < comments->length() &&
comments->offsetAt(comment_finger) <= offset) {
formatter->print(" ;; %s\n", comments->commentAt(comment_finger));
comment_finger++;
}
int instruction_length;
decodeInstruction(hex_buffer, sizeof(hex_buffer), human_buffer,
sizeof(human_buffer), &instruction_length, pc);
// TODO(emacs): Add flag to disassemble relative? Then use offset instead
// of pc.
formatter->consumeInstruction(hex_buffer, sizeof(hex_buffer), human_buffer,
sizeof(human_buffer), pc);
pc += instruction_length;
}
}
} // namespace py