2017-12-31 23:49:35 +00:00
|
|
|
//
|
|
|
|
// Kernel.hpp
|
|
|
|
// Clock Signal
|
|
|
|
//
|
|
|
|
// Created by Thomas Harte on 31/12/2017.
|
2018-05-13 19:19:52 +00:00
|
|
|
// Copyright 2017 Thomas Harte. All rights reserved.
|
2017-12-31 23:49:35 +00:00
|
|
|
//
|
|
|
|
|
2024-01-17 04:34:46 +00:00
|
|
|
#pragma once
|
2017-12-31 23:49:35 +00:00
|
|
|
|
2023-05-10 21:02:18 +00:00
|
|
|
namespace Analyser::Static::Disassembly {
|
2017-12-31 23:49:35 +00:00
|
|
|
|
|
|
|
template <typename D, typename S> struct PartialDisassembly {
|
|
|
|
D disassembly;
|
|
|
|
std::vector<S> remaining_entry_points;
|
2023-09-10 18:25:28 +00:00
|
|
|
std::vector<S> implicit_entry_points;
|
2017-12-31 23:49:35 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template <typename D, typename S, typename Disassembler> D Disassemble(
|
|
|
|
const std::vector<uint8_t> &memory,
|
|
|
|
const std::function<std::size_t(S)> &address_mapper,
|
2023-09-04 19:13:06 +00:00
|
|
|
std::vector<S> entry_points,
|
2023-09-07 02:26:15 +00:00
|
|
|
bool exhaustive)
|
|
|
|
{
|
2017-12-31 23:49:35 +00:00
|
|
|
PartialDisassembly<D, S> partial_disassembly;
|
|
|
|
partial_disassembly.remaining_entry_points = entry_points;
|
|
|
|
|
2023-09-07 02:26:15 +00:00
|
|
|
while(!partial_disassembly.remaining_entry_points.empty()) {
|
2023-09-04 19:13:06 +00:00
|
|
|
// Do a recursive-style disassembly for all current entry points.
|
|
|
|
while(!partial_disassembly.remaining_entry_points.empty()) {
|
|
|
|
// Pull the next entry point from the back of the vector.
|
2023-09-07 02:26:15 +00:00
|
|
|
const S next_entry_point = partial_disassembly.remaining_entry_points.back();
|
2023-09-04 19:13:06 +00:00
|
|
|
partial_disassembly.remaining_entry_points.pop_back();
|
|
|
|
|
|
|
|
// If that address has already been visited, forget about it.
|
|
|
|
if( partial_disassembly.disassembly.instructions_by_address.find(next_entry_point)
|
|
|
|
!= partial_disassembly.disassembly.instructions_by_address.end()) continue;
|
|
|
|
|
|
|
|
// If it's outgoing, log it as such and forget about it; otherwise disassemble.
|
|
|
|
std::size_t mapped_entry_point = address_mapper(next_entry_point);
|
|
|
|
if(mapped_entry_point >= memory.size())
|
|
|
|
partial_disassembly.disassembly.outward_calls.insert(next_entry_point);
|
|
|
|
else
|
|
|
|
Disassembler::AddToDisassembly(partial_disassembly, memory, address_mapper, next_entry_point);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this is not an exhaustive disassembly, that's your lot.
|
|
|
|
if(!exhaustive) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2023-09-10 18:25:28 +00:00
|
|
|
// Otherwise, copy in the new 'implicit entry points' (i.e. all locations that are one after
|
|
|
|
// a disassembled region). There's a test above that'll ignore any which have already been
|
|
|
|
// disassembled from.
|
|
|
|
std::move(
|
|
|
|
partial_disassembly.implicit_entry_points.begin(),
|
|
|
|
partial_disassembly.implicit_entry_points.end(),
|
|
|
|
std::back_inserter(partial_disassembly.remaining_entry_points)
|
|
|
|
);
|
|
|
|
partial_disassembly.implicit_entry_points.clear();
|
2017-12-31 23:49:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return partial_disassembly.disassembly;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|