LibDisassembly: Allow disassembler to disassemble any architecture

We can easily detect the architecture from a given ELF file or just use
the native architecture. Importantly, this allows every implemented
target architecture to be disassembled on every host architecture.
This commit is contained in:
kleines Filmröllchen
2023-10-16 15:45:15 +02:00
committed by Tim Schumacher
parent 9430a6c336
commit 276655b4ce
7 changed files with 74 additions and 12 deletions

View File

@@ -15,6 +15,7 @@
#include <LibCore/System.h>
#include <LibDebug/DebugInfo.h>
#include <LibDebug/DebugSession.h>
#include <LibDisassembly/Architecture.h>
#include <LibDisassembly/Disassembler.h>
#include <LibDisassembly/x86/Instruction.h>
#include <LibLine/Editor.h>
@@ -83,7 +84,7 @@ static bool handle_disassemble_command(ByteString const& command, FlatPtr first_
}
Disassembly::SimpleInstructionStream stream(code.data(), code.size());
Disassembly::Disassembler disassembler(stream);
Disassembly::Disassembler disassembler(stream, Disassembly::host_architecture());
for (size_t i = 0; i < number_of_instructions_to_disassemble; ++i) {
auto offset = stream.offset();

View File

@@ -52,7 +52,7 @@ DisassemblyModel::DisassemblyModel(Debug::DebugSession const& debug_session, Ptr
Disassembly::ELFSymbolProvider symbol_provider(*elf);
Disassembly::SimpleInstructionStream stream((u8 const*)view.characters_without_null_termination(), view.length());
Disassembly::Disassembler disassembler(stream);
Disassembly::Disassembler disassembler(stream, Disassembly::architecture_from_elf_machine(elf->machine()).value_or(Disassembly::host_architecture()));
size_t offset_into_symbol = 0;
for (;;) {

View File

@@ -12,6 +12,7 @@
#include "Profile.h"
#include <LibCore/MappedFile.h>
#include <LibDebug/DebugInfo.h>
#include <LibDisassembly/Architecture.h>
#include <LibDisassembly/Disassembler.h>
#include <LibDisassembly/ELFSymbolProvider.h>
#include <LibELF/Image.h>
@@ -95,7 +96,7 @@ DisassemblyModel::DisassemblyModel(Profile& profile, ProfileNode& node)
Disassembly::ELFSymbolProvider symbol_provider(*elf, base_address);
Disassembly::SimpleInstructionStream stream((u8 const*)view.characters_without_null_termination(), view.length());
Disassembly::Disassembler disassembler(stream);
Disassembly::Disassembler disassembler(stream, Disassembly::architecture_from_elf_machine(elf->machine()).value_or(Disassembly::host_architecture()));
size_t offset_into_symbol = 0;
FlatPtr last_instruction_offset = 0;

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2023, kleines Filmröllchen <filmroellchen@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Optional.h>
#include <AK/Platform.h>
#include <LibELF/ELFABI.h>
namespace Disassembly {
enum class Architecture {
Aarch64,
RISCV64,
Wasm32,
X86,
};
constexpr Architecture host_architecture()
{
#if ARCH(AARCH64)
return Architecture::Aarch64;
#elif ARCH(RISCV64)
return Architecture::RISCV64;
#elif ARCH(WASM32)
return Architecture::Wasm32;
#elif ARCH(X86_64)
return Architecture::X86;
#else
# error "Unknown architecture"
#endif
}
ALWAYS_INLINE Optional<Architecture> architecture_from_elf_machine(Elf64_Quarter e_machine)
{
switch (e_machine) {
case EM_AARCH64:
return Architecture::Aarch64;
case EM_RISCV:
return Architecture::RISCV64;
case EM_X86_64:
return Architecture::X86;
default:
return {};
}
}
}

View File

@@ -8,6 +8,7 @@
#include <AK/NonnullOwnPtr.h>
#include <AK/Optional.h>
#include <LibDisassembly/Architecture.h>
#include <LibDisassembly/Instruction.h>
#include <LibDisassembly/InstructionStream.h>
#include <LibDisassembly/x86/Instruction.h>
@@ -16,8 +17,9 @@ namespace Disassembly {
class Disassembler {
public:
explicit Disassembler(InstructionStream& stream)
explicit Disassembler(InstructionStream& stream, Architecture arch)
: m_stream(stream)
, m_arch(arch)
{
}
@@ -25,16 +27,18 @@ public:
{
if (!m_stream.can_read())
return {};
#if ARCH(X86_64)
return make<X86::Instruction>(X86::Instruction::from_stream(m_stream, X86::ProcessorMode::Long));
#else
dbgln("Unsupported platform");
return {};
#endif
switch (m_arch) {
case Architecture::X86:
return make<X86::Instruction>(X86::Instruction::from_stream(m_stream, X86::ProcessorMode::Long));
default:
dbgln("Unsupported platform");
return {};
}
}
private:
InstructionStream& m_stream;
Architecture m_arch;
};
}

View File

@@ -15,6 +15,7 @@
#include <LibCore/ArgsParser.h>
#include <LibCore/MappedFile.h>
#include <LibCore/System.h>
#include <LibDisassembly/Architecture.h>
#include <LibDisassembly/Disassembler.h>
#include <LibDisassembly/ELFSymbolProvider.h>
#include <LibELF/Image.h>
@@ -69,9 +70,13 @@ ErrorOr<int> serenity_main(Main::Arguments args)
size_t file_offset = 0;
OwnPtr<Disassembly::ELFSymbolProvider> symbol_provider; // nullptr for non-ELF disassembly.
OwnPtr<ELF::Image> elf;
auto architecture = Disassembly::host_architecture();
if (asm_size >= 4 && strncmp(reinterpret_cast<char const*>(asm_data), "\u007fELF", 4) == 0) {
elf = make<ELF::Image>(asm_data, asm_size);
if (elf->is_valid()) {
if (auto elf_architecture = Disassembly::architecture_from_elf_machine(elf->machine()); elf_architecture.has_value())
architecture = elf_architecture.release_value();
symbol_provider = make<Disassembly::ELFSymbolProvider>(*elf);
elf->for_each_section_of_type(SHT_PROGBITS, [&](ELF::Image::Section const& section) {
// FIXME: Disassemble all SHT_PROGBITS sections, not just .text.
@@ -117,7 +122,7 @@ ErrorOr<int> serenity_main(Main::Arguments args)
}
Disassembly::SimpleInstructionStream stream(asm_data, asm_size);
Disassembly::Disassembler disassembler(stream);
Disassembly::Disassembler disassembler(stream, architecture);
Vector<Symbol>::Iterator current_ranged_symbol = ranged_symbols.begin();
Vector<Symbol>::Iterator current_zero_size_symbol = zero_size_symbols.begin();

View File

@@ -84,7 +84,7 @@ static NonnullOwnPtr<HashMap<FlatPtr, NonnullOwnPtr<Disassembly::Instruction>>>
return IterationDecision::Continue;
Disassembly::SimpleInstructionStream stream((u8 const*)((uintptr_t)lib.file->data() + section.offset()), section.size());
Disassembly::Disassembler disassembler(stream);
Disassembly::Disassembler disassembler(stream, Disassembly::architecture_from_elf_machine(lib.debug_info->elf().machine()).value_or(Disassembly::host_architecture()));
for (;;) {
auto offset = stream.offset();
auto instruction_address = section.address() + offset + lib.base_address;