1 #pragma once
2
3 #include "../disassembler/disassemblerapi.h"
4 #include "../disassembler/types/symboltable.h"
5 #include "../disassembler/listing/listingdocument.h"
6 #include "../analyzer/analyzer.h"
7 #include "../types/endianness/endianness.h"
8 #include "base.h"
9
10 #define DECLARE_LOADER_PLUGIN_BASE(T, id) inline bool id##_plugin_loader_test(const LoadRequest& request) { return REDasm::testLoaderPlugin<T>(request); } \
11 inline LoaderPlugin* id##_plugin_loader_init(const LoadRequest& request) { return REDasm::initLoaderPlugin<T>(request, #id); } \
12 inline std::string id##_plugin_loader_name() { return T::Name; } \
13 inline std::string id##_plugin_loader_id() { return #id; }
14
15 #define DECLARE_LOADER_PLUGIN(T, id) DECLARE_LOADER_PLUGIN_BASE(T, id) \
16 inline u32 id##_plugin_loader_flags() { return LoaderFlags::None; }
17
18 #define DECLARE_LOADER_PLUGIN_FLAGS(T, id, flags) DECLARE_LOADER_PLUGIN_BASE(T, id) \
19 inline u32 id##_plugin_loader_flags() { return flags; }
20
21
22 #define DECLARE_LOADER_PLUGIN_TEST(T) public: static bool test(const LoadRequest& request, const T* header); private:
23 #define LOADER_PLUGIN_TEST(T, H) bool T::test(const LoadRequest& request, const H* header)
24
25 #define LOADER_PLUGIN_ENTRY(id) { &id##_plugin_loader_test, &id##_plugin_loader_init, &id##_plugin_loader_name, &id##_plugin_loader_flags, &id##_plugin_loader_id }
26
27 #define LOADER_CTOR AbstractBuffer* buffer
28 #define LOADER_ARGS buffer
29 #define LOADER_INHERIT(classname, basename, name) PLUGIN_INHERIT(classname, basename, name, LOADER_CTOR, LOADER_ARGS)
30
31 namespace REDasm {
32
33 typedef std::unordered_set<std::string> SignatureIdentifiers;
34
35 namespace LoaderFlags {
36 enum: u32 { None = 0, CustomAssembler = 1, CustomAddressing = 2, Binary = 0xFFFFFFFF };
37 }
38
39 struct LoadRequest
40 {
LoadRequestLoadRequest41 LoadRequest(const std::string& filepath, AbstractBuffer* buffer): filepath(filepath), buffer(buffer), view(buffer->view()) { }
42 std::string id, filepath;
43 AbstractBuffer* buffer;
44 BufferView view;
45 };
46
testLoaderPlugin(const LoadRequest & request)47 template<typename T> bool testLoaderPlugin(const LoadRequest& request)
48 {
49 const typename T::HeaderType* header = reinterpret_cast<const typename T::HeaderType*>(request.buffer->data());
50
51 if((sizeof(typename T::HeaderType) > request.buffer->size()) || !T::test(request, header))
52 return false;
53
54 return true;
55 }
56
initLoaderPlugin(const LoadRequest & request,const std::string & id)57 template<typename T> LoaderPlugin* initLoaderPlugin(const LoadRequest& request, const std::string& id)
58 {
59 T* loaderplugin = new T(request.buffer);
60 loaderplugin->setId(id);
61 loaderplugin->load();
62 return loaderplugin;
63 }
64
65 class LoaderPlugin: public Plugin
66 {
67 public:
68 LoaderPlugin(AbstractBuffer *buffer);
69 AbstractBuffer* buffer() const;
70 BufferView viewOffset(offset_t offset) const;
71 BufferView view(address_t address) const;
72 BufferView viewSegment(const Segment* segment) const;
73 ListingDocument& createDocument();
74 const ListingDocument& document() const;
75 ListingDocument& document();
76 SignatureIdentifiers &signatures();
77
78 public:
79 virtual offset_location offset(address_t address) const;
80 virtual address_location address(offset_t offset) const;
81 virtual void build(const std::string& assembler, offset_t offset, address_t baseaddress, address_t entrypoint);
82 virtual Analyzer *createAnalyzer(DisassemblerAPI* disassembler) const;
83 virtual std::string assembler() const;
84 virtual void load() = 0;
85
86 public:
fileoffset(const U * ptr)87 template<typename U> inline offset_location fileoffset(const U* ptr) const { return REDasm::make_location<offset_t>(reinterpret_cast<const u8*>(ptr) - reinterpret_cast<const u8*>(m_buffer->data()), m_view.inRange(ptr)); }
addressof(const U * ptr)88 template<typename U> inline address_location addressof(const U* ptr) const { return m_view.inRange(ptr) ? this->address(this->fileoffset(ptr)) : REDasm::invalid_location<address_t>(); }
pointer(O offset)89 template<typename U, typename O> inline U* pointer(O offset) const { return m_view.inRange(offset) ? reinterpret_cast<U*>(reinterpret_cast<u8*>(m_buffer->data()) + offset) : nullptr; }
addrpointer(A address)90 template<typename U, typename A> inline U* addrpointer(A address) const { auto o = offset(address); return o ? reinterpret_cast<U*>(reinterpret_cast<u8*>(m_buffer->data()) + o) : nullptr; }
relpointer(const V * base,O offset)91 template<typename U, typename V, typename O> inline static const U* relpointer(const V* base, O offset) { return reinterpret_cast<const U*>(reinterpret_cast<const u8*>(base) + offset); }
relpointer(V * base,O offset)92 template<typename U, typename V, typename O> inline static U* relpointer(V* base, O offset) { return reinterpret_cast<U*>(reinterpret_cast<u8*>(base) + offset); }
93
94 protected:
95 std::unique_ptr<AbstractBuffer> m_buffer;
96 BufferView m_view;
97 ListingDocument m_document;
98 SignatureIdentifiers m_signatures;
99 };
100
101 template<typename T> class LoaderPluginT: public LoaderPlugin
102 {
103 public:
104 typedef T HeaderType;
105
106 public:
LoaderPluginT(AbstractBuffer * buffer)107 LoaderPluginT(AbstractBuffer* buffer): LoaderPlugin(buffer) { m_header = reinterpret_cast<T*>(m_buffer->data()); }
test(const T * loader,const AbstractBuffer * buffer)108 static bool test(const T* loader, const AbstractBuffer* buffer) { RE_UNUSED(loader); RE_UNUSED(buffer); return false; }
109
110 protected:
111 T* m_header;
112 };
113
114 class LoaderPluginB: public LoaderPluginT<u8>
115 {
DECLARE_LOADER_PLUGIN_TEST(u8)116 DECLARE_LOADER_PLUGIN_TEST(u8)
117
118 public:
119 LoaderPluginB(AbstractBuffer* buffer): LoaderPluginT<u8>(buffer) { }
120 };
121
122 struct LoaderPlugin_Entry
123 {
124 std::function<bool(const LoadRequest&)> test;
125 std::function<LoaderPlugin*(const LoadRequest&)> init;
126 std::function<std::string()> name;
127 std::function<u32()> flags;
128 std::function<std::string()> id;
129 };
130
131 }
132