diff options
| author | WeiN76LQh <WeiN76LQh@github.com> | 2025-01-03 17:55:10 +0000 |
|---|---|---|
| committer | Mason Reed <mason@vector35.com> | 2025-04-02 05:36:54 -0400 |
| commit | ee500220baa1a46f3d7ca1486fa43dc1587f20d0 (patch) | |
| tree | ee3e1549997e60849f040f5745cdac8840f25303 /view/sharedcache/core/ObjC.h | |
| parent | 90e9ff91f02f2cb902bf0564de1f403e23172f36 (diff) | |
[ObjC] Create a shared ObjC processor for Macho and DSC views
Both the Macho and DSC views need to process Objective-C but have separate processor classes. It would appear that the DSC version was largely a copy and paste of the Macho view one, with some modifications. The majority of code overlaps between the 2 so it doesn't make sense to maintain 2 and copy and paste improvements/fixes between them.
This commit fixes that by creating a base Objective-C processor that contains the shared code. View specific code is implemented in the respective subclasses for the views. Although there is very little view specific code for each.
Diffstat (limited to 'view/sharedcache/core/ObjC.h')
| -rw-r--r-- | view/sharedcache/core/ObjC.h | 242 |
1 files changed, 28 insertions, 214 deletions
diff --git a/view/sharedcache/core/ObjC.h b/view/sharedcache/core/ObjC.h index a308c23a..13790364 100644 --- a/view/sharedcache/core/ObjC.h +++ b/view/sharedcache/core/ObjC.h @@ -6,233 +6,47 @@ #define SHAREDCACHE_OBJC_H #include <binaryninjaapi.h> -#include "VM.h" +#include <objectivec/objc.h> #include "SharedCache.h" -using namespace BinaryNinja; - - namespace DSCObjC { + class DSCObjCReader : public ObjCReader { + private: + VMReader m_reader; + size_t m_addressSize; - // This set of structs is based on the objc4 source, - // however pointers have been replaced with view_ptr_t - - // Used for pointers within BinaryView, primarily to make it far more clear in typedefs - // whether the size of a field can vary between architectures. - // These should _not_ be used in sizeof or direct Read() calls. - typedef uint64_t view_ptr_t; - - typedef struct { - view_ptr_t name; - view_ptr_t types; - view_ptr_t imp; - } method_t; - typedef struct { - uint32_t name; - uint32_t types; - uint32_t imp; - } method_entry_t; - typedef struct { - view_ptr_t offset; - view_ptr_t name; - view_ptr_t type; - uint32_t alignmentRaw; - uint32_t size; - } ivar_t; - typedef struct { - view_ptr_t name; - view_ptr_t attributes; - } property_t; - typedef struct { - uint32_t entsizeAndFlags; - uint32_t count; - } method_list_t; - typedef struct { - uint32_t entsizeAndFlags; - uint32_t count; - } ivar_list_t; - typedef struct { - uint32_t entsizeAndFlags; - uint32_t count; - } property_list_t; - typedef struct { - uint64_t count; - } protocol_list_t; - struct relative_list_list_entry_t { - uint64_t imageIndex: 16; - int64_t listOffset: 48; - }; - typedef struct { - view_ptr_t isa; - view_ptr_t mangledName; - view_ptr_t protocols; - view_ptr_t instanceMethods; - view_ptr_t classMethods; - view_ptr_t optionalInstanceMethods; - view_ptr_t optionalClassMethods; - view_ptr_t instanceProperties; - uint32_t size; - uint32_t flags; - } protocol_t; - typedef struct { - uint32_t flags; - uint32_t instanceStart; - uint32_t instanceSize; - uint32_t reserved; - view_ptr_t ivarLayout; - view_ptr_t name; - view_ptr_t baseMethods; - view_ptr_t baseProtocols; - view_ptr_t ivars; - view_ptr_t weakIvarLayout; - view_ptr_t baseProperties; - } class_ro_t; - typedef struct { - view_ptr_t isa; - view_ptr_t super; - view_ptr_t cache; - view_ptr_t vtable; - view_ptr_t data; - } class_t; - typedef struct { - view_ptr_t name; - view_ptr_t cls; - view_ptr_t instanceMethods; - view_ptr_t classMethods; - view_ptr_t protocols; - view_ptr_t instanceProperties; - } category_t; - typedef struct { - view_ptr_t receiver; - view_ptr_t current_class; - } objc_super2; - typedef struct { - view_ptr_t imp; - view_ptr_t sel; - } message_ref_t; - - struct Method { - std::string name; - std::string types; - view_ptr_t imp; - }; - - struct Ivar { - uint32_t offset; - std::string name; - std::string type; - uint32_t alignment; - uint32_t size; - }; - - struct Property { - std::string name; - std::string attributes; - }; - - struct ClassBase { - std::map<uint64_t, Method> methodList; - std::map<uint64_t, Ivar> ivarList; - }; - - struct Class { - std::string name; - ClassBase instanceClass; - ClassBase metaClass; - - // Loaded by type processing - QualifiedName associatedName; - }; - - class Protocol { public: - std::string name; - std::vector<QualifiedName> protocols; - ClassBase instanceMethods; - ClassBase classMethods; - ClassBase optionalInstanceMethods; - ClassBase optionalClassMethods; - }; - - struct QualifiedNameOrType { - BinaryNinja::Ref<BinaryNinja::Type> type = nullptr; - BinaryNinja::QualifiedName name; - size_t ptrCount = 0; - }; + void Read(void* dest, size_t len) override; + std::string ReadCString() override; + uint8_t Read8() override; + uint16_t Read16() override; + uint32_t Read32() override; + uint64_t Read64() override; + int8_t ReadS8() override; + int16_t ReadS16() override; + int32_t ReadS32() override; + int64_t ReadS64() override; + uint64_t ReadPointer() override; + uint64_t GetOffset() const override; + void Seek(uint64_t offset) override; + void SeekRelative(int64_t offset) override; - class DSCObjCProcessor { - struct Types { - // QualifiedName relativePtr; - // QualifiedName id; - // QualifiedName sel; - // QualifiedName BOOL; - // QualifiedName nsInteger; - // QualifiedName nsuInteger; - // QualifiedName cgFloat; - QualifiedName cfStringFlag; - QualifiedName cfString; - QualifiedName cfStringUTF16; - QualifiedName imageInfoFlags; - QualifiedName imageInfoSwiftVersion; - QualifiedName imageInfo; - QualifiedName methodEntry; - QualifiedName method; - QualifiedName methodList; - QualifiedName classRO; - QualifiedName cls; - QualifiedName category; - QualifiedName protocol; - QualifiedName protocolList; - QualifiedName ivar; - QualifiedName ivarList; - } m_typeNames; - - bool m_isBackedByDatabase; - - BinaryView* m_data; - SymbolQueue* m_symbolQueue = nullptr; - Ref<Logger> m_logger; - std::map<uint64_t, Class> m_classes; - std::map<uint64_t, Class> m_categories; - std::map<uint64_t, Protocol> m_protocols; - std::unordered_map<uint64_t, std::string> m_selectorCache; - std::unordered_map<uint64_t, Method> m_localMethods; - - // Required for workflow_objc type heuristics, should be removed when that is no longer a thing. - std::map<uint64_t, std::string> m_selRefToName; - std::map<uint64_t, std::vector<uint64_t>> m_selRefToImplementations; - std::map<uint64_t, std::vector<uint64_t>> m_selToImplementations; - // -- + VMReader& GetVMReader(); + DSCObjCReader(SharedCacheCore::SharedCache* cache, size_t addressSize); + }; + class DSCObjCProcessor : public ObjCProcessor { std::optional<uint64_t> m_customRelativeMethodSelectorBase = std::nullopt; SharedCacheCore::SharedCache* m_cache; - uint64_t ReadPointerAccountingForRelocations(VMReader* reader); - std::unordered_map<uint64_t, uint64_t> m_relocationPointerRewrites; - - static Ref<Metadata> SerializeMethod(uint64_t loc, const Method& method); - static Ref<Metadata> SerializeClass(uint64_t loc, const Class& cls); - - Ref<Metadata> SerializeMetadata(); - std::vector<QualifiedNameOrType> ParseEncodedType(const std::string& type); - void DefineObjCSymbol(BNSymbolType symbolType, QualifiedName typeName, const std::string& name, uint64_t addr, bool deferred); - void DefineObjCSymbol(BNSymbolType symbolType, Ref<Type> type, const std::string& name, uint64_t addr, bool deferred); - void ReadIvarList(VMReader* reader, ClassBase& cls, std::string_view name, view_ptr_t start); - void ReadMethodList(VMReader* reader, ClassBase& cls, std::string_view name, view_ptr_t start); - void ReadListOfMethodLists(VMReader* reader, ClassBase& cls, std::string_view name, view_ptr_t start); - void LoadClasses(VMReader* reader, Ref<Section> listSection); - void LoadCategories(VMReader* reader, Ref<Section> listSection); - void LoadProtocols(VMReader* reader, Ref<Section> listSection); - void GenerateClassTypes(); - bool ApplyMethodType(Class& cls, Method& method, bool isInstanceMethod); - void ApplyMethodTypes(Class& cls); - void PostProcessObjCSections(VMReader* reader, std::string baseName); + std::shared_ptr<ObjCReader> GetReader() override; + void GetRelativeMethod(ObjCReader* reader, method_t& meth) override; + public: DSCObjCProcessor(BinaryView* data, SharedCacheCore::SharedCache* cache, bool isBackedByDatabase); - void ProcessObjCData(std::shared_ptr<VM> vm, std::string baseName); - void ProcessCFStrings(std::shared_ptr<VM> vm, std::string baseName); - void AddRelocatedPointer(uint64_t location, uint64_t rewrite); + + uint64_t GetObjCRelativeMethodBaseAddress(ObjCReader* reader) override; }; } #endif //SHAREDCACHE_OBJC_H |
