mirror of
https://github.com/SerenityOS/serenity
synced 2026-04-25 17:15:42 +02:00
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:
committed by
Tim Schumacher
parent
9430a6c336
commit
276655b4ce
@@ -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();
|
||||
|
||||
@@ -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 (;;) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
51
Userland/Libraries/LibDisassembly/Architecture.h
Normal file
51
Userland/Libraries/LibDisassembly/Architecture.h
Normal 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 {};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user