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