1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 04:27:44 +00:00

LibX86: Add a way for Instruction::to_string() to symbolicate addresses

This patch adds a pure virtual X86::SymbolProvider that can be passed
to Instruction::to_string(). If the instruction contains what appears
to be a program address, stringification will try to symbolicate that
address via the SymbolProvider.

This makes it possible (and very flexible) to add symbolication to
clients of the disassembler. :^)
This commit is contained in:
Andreas Kling 2020-04-12 13:57:44 +02:00
parent 5390d53a80
commit e880e4c2d2
2 changed files with 29 additions and 9 deletions

View file

@ -1253,7 +1253,7 @@ static String relative_address(u32 origin, bool x32, i32 imm)
return String::format("%#04x", w + si); return String::format("%#04x", w + si);
} }
String Instruction::to_string(u32 origin, bool x32) const String Instruction::to_string(u32 origin, const SymbolProvider* symbol_provider, bool x32) const
{ {
String segment_prefix; String segment_prefix;
String asize_prefix; String asize_prefix;
@ -1281,11 +1281,11 @@ String Instruction::to_string(u32 origin, bool x32) const
builder.append(osize_prefix); builder.append(osize_prefix);
builder.append(lock_prefix); builder.append(lock_prefix);
builder.append(rep_prefix); builder.append(rep_prefix);
builder.append(to_string_internal(origin, x32)); builder.append(to_string_internal(origin, symbol_provider, x32));
return builder.to_string(); return builder.to_string();
} }
String Instruction::to_string_internal(u32 origin, bool x32) const String Instruction::to_string_internal(u32 origin, const SymbolProvider* symbol_provider, bool x32) const
{ {
if (!m_descriptor) if (!m_descriptor)
return String::format("db %#02x", m_op); return String::format("db %#02x", m_op);
@ -1297,6 +1297,21 @@ String Instruction::to_string_internal(u32 origin, bool x32) const
builder.append(mnemonic); builder.append(mnemonic);
builder.append(' '); builder.append(' ');
auto formatted_address = [&](FlatPtr origin, bool x32, auto offset) {
StringBuilder builder;
builder.append(relative_address(origin, x32, offset));
if (symbol_provider) {
u32 symbol_offset = 0;
auto symbol = symbol_provider->symbolicate(origin + offset, &symbol_offset);
builder.append(" <");
builder.append(symbol);
if (symbol_offset)
builder.appendf("+%u", symbol_offset);
builder.append('>');
}
return builder.to_string();
};
auto append_rm8 = [&] { builder.append(m_modrm.to_string_o8()); }; auto append_rm8 = [&] { builder.append(m_modrm.to_string_o8()); };
auto append_rm16 = [&] { builder.append(m_modrm.to_string_o16()); }; auto append_rm16 = [&] { builder.append(m_modrm.to_string_o16()); };
auto append_rm32 = [&] { builder.append(m_modrm.to_string_o32()); }; auto append_rm32 = [&] { builder.append(m_modrm.to_string_o32()); };
@ -1313,10 +1328,10 @@ String Instruction::to_string_internal(u32 origin, bool x32) const
auto append_seg = [&] { builder.append(register_name(segment_register())); }; auto append_seg = [&] { builder.append(register_name(segment_register())); };
auto append_creg = [&] { builder.appendf("cr%u", register_index()); }; auto append_creg = [&] { builder.appendf("cr%u", register_index()); };
auto append_dreg = [&] { builder.appendf("dr%u", register_index()); }; auto append_dreg = [&] { builder.appendf("dr%u", register_index()); };
auto append_relative_addr = [&] { builder.append(relative_address(origin + (m_a32 ? 6 : 4), x32, i32(m_a32 ? imm32() : imm16()))); }; auto append_relative_addr = [&] { builder.append(formatted_address(origin + (m_a32 ? 6 : 4), x32, i32(m_a32 ? imm32() : imm16()))); };
auto append_relative_imm8 = [&] { builder.append(relative_address(origin + 2, x32, i8(imm8()))); }; auto append_relative_imm8 = [&] { builder.append(formatted_address(origin + 2, x32, i8(imm8()))); };
auto append_relative_imm16 = [&] { builder.append(relative_address(origin + 3, x32, i16(imm16()))); }; auto append_relative_imm16 = [&] { builder.append(formatted_address(origin + 3, x32, i16(imm16()))); };
auto append_relative_imm32 = [&] { builder.append(relative_address(origin + 5, x32, i32(imm32()))); }; auto append_relative_imm32 = [&] { builder.append(formatted_address(origin + 5, x32, i32(imm32()))); };
auto append_mm = [&] { builder.appendf("mm%u", register_index()); }; auto append_mm = [&] { builder.appendf("mm%u", register_index()); };
auto append_mmrm64 = [&] { builder.append(m_modrm.to_string_mm()); }; auto append_mmrm64 = [&] { builder.append(m_modrm.to_string_mm()); };

View file

@ -34,6 +34,11 @@ namespace X86 {
class Instruction; class Instruction;
struct InstructionDescriptor; struct InstructionDescriptor;
class SymbolProvider {
public:
virtual String symbolicate(FlatPtr, u32* offset = nullptr) const = 0;
};
template<typename T> template<typename T>
struct MakeUnsigned { struct MakeUnsigned {
typedef T type; typedef T type;
@ -333,12 +338,12 @@ public:
u8 cc() const { return m_has_sub_op ? m_sub_op & 0xf : m_op & 0xf; } u8 cc() const { return m_has_sub_op ? m_sub_op & 0xf : m_op & 0xf; }
String to_string(u32 origin, bool x32 = true) const; String to_string(u32 origin, const SymbolProvider* = nullptr, bool x32 = true) const;
private: private:
Instruction(InstructionStream&, bool o32, bool a32); Instruction(InstructionStream&, bool o32, bool a32);
String to_string_internal(u32 origin, bool x32) const; String to_string_internal(u32 origin, const SymbolProvider*, bool x32) const;
const char* reg8_name() const; const char* reg8_name() const;
const char* reg16_name() const; const char* reg16_name() const;