diff options
| -rw-r--r-- | view/macho/machoview.cpp | 7 | ||||
| -rw-r--r-- | view/macho/machoview.h | 129 | ||||
| -rw-r--r-- | view/sharedcache/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | view/sharedcache/api/python/sharedcache.py | 13 | ||||
| -rw-r--r-- | view/sharedcache/api/python/sharedcache_enums.py | 6 | ||||
| -rw-r--r-- | view/sharedcache/api/sharedcache.cpp | 2 | ||||
| -rw-r--r-- | view/sharedcache/api/sharedcacheapi.h | 2 | ||||
| -rw-r--r-- | view/sharedcache/api/sharedcachecore.h | 8 | ||||
| -rw-r--r-- | view/sharedcache/core/SharedCache.cpp | 26 | ||||
| -rw-r--r-- | view/sharedcache/core/SharedCache.h | 2 |
10 files changed, 163 insertions, 34 deletions
diff --git a/view/macho/machoview.cpp b/view/macho/machoview.cpp index 9ee393e8..ec0ea4d5 100644 --- a/view/macho/machoview.cpp +++ b/view/macho/machoview.cpp @@ -14,13 +14,6 @@ #include "lowlevelilinstruction.h" #include "rapidjsonwrapper.h" -enum { - N_STAB = 0xe0, - N_PEXT = 0x10, - N_TYPE = 0x0e, - N_EXT = 0x01 -}; - using namespace BinaryNinja; using namespace std; diff --git a/view/macho/machoview.h b/view/macho/machoview.h index 6a5e80ae..74508559 100644 --- a/view/macho/machoview.h +++ b/view/macho/machoview.h @@ -268,14 +268,129 @@ typedef int vm_prot_t; #define SEG_UNIXSTACK "__UNIXSTACK" #define SEG_IMPORT "__IMPORT" -//Symbol Types (N_TYPE) -#define N_UNDF 0x0 -#define N_ABS 0x2 -#define N_SECT 0xe -#define N_PBUD 0xc -#define N_INDR 0xa +/* + * Symbols with a index into the string table of zero (n_un.n_strx == 0) are + * defined to have a null, "", name. Therefore all string indexes to non null + * names must not have a zero string index. This is bit historical information + * that has never been well documented. + */ + +/* + * The n_type field really contains four fields: + * unsigned char N_STAB:3, + * N_PEXT:1, + * N_TYPE:3, + * N_EXT:1; + * which are used via the following masks. + */ +#define N_STAB 0xe0 /* if any of these bits set, a symbolic debugging entry */ +#define N_PEXT 0x10 /* private external symbol bit */ +#define N_TYPE 0x0e /* mask for the type bits */ +#define N_EXT 0x01 /* external symbol bit, set for external symbols */ + +/* + * Only symbolic debugging entries have some of the N_STAB bits set and if any + * of these bits are set then it is a symbolic debugging entry (a stab). In + * which case then the values of the n_type field (the entire field) are given + * in <mach-o/stab.h> + */ + +/* + * Values for N_TYPE bits of the n_type field. + */ +#define N_UNDF 0x0 /* undefined, n_sect == NO_SECT */ +#define N_ABS 0x2 /* absolute, n_sect == NO_SECT */ +#define N_SECT 0xe /* defined in section number n_sect */ +#define N_PBUD 0xc /* prebound undefined (defined in a dylib) */ +#define N_INDR 0xa /* indirect */ -#define N_ARM_THUMB_DEF 0x0008 +/* + * If the type is N_INDR then the symbol is defined to be the same as another + * symbol. In this case the n_value field is an index into the string table + * of the other symbol's name. When the other symbol is defined then they both + * take on the defined type and value. + */ + +/* + * If the type is N_SECT then the n_sect field contains an ordinal of the + * section the symbol is defined in. The sections are numbered from 1 and + * refer to sections in order they appear in the load commands for the file + * they are in. This means the same ordinal may very well refer to different + * sections in different files. + * + * The n_value field for all symbol table entries (including N_STAB's) gets + * updated by the link editor based on the value of it's n_sect field and where + * the section n_sect references gets relocated. If the value of the n_sect + * field is NO_SECT then it's n_value field is not changed by the link editor. + */ +#define NO_SECT 0 /* symbol is not in any section */ +#define MAX_SECT 255 /* 1 thru 255 inclusive */ + +/* + * The bit 0x0020 of the n_desc field is used for two non-overlapping purposes + * and has two different symbolic names, N_NO_DEAD_STRIP and N_DESC_DISCARDED. + */ + +/* + * The N_NO_DEAD_STRIP bit of the n_desc field only ever appears in a + * relocatable .o file (MH_OBJECT filetype). And is used to indicate to the + * static link editor it is never to dead strip the symbol. + */ +#define N_NO_DEAD_STRIP 0x0020 /* symbol is not to be dead stripped */ + +/* + * The N_DESC_DISCARDED bit of the n_desc field never appears in linked image. + * But is used in very rare cases by the dynamic link editor to mark an in + * memory symbol as discared and longer used for linking. + */ +#define N_DESC_DISCARDED 0x0020 /* symbol is discarded */ + +/* + * The N_WEAK_REF bit of the n_desc field indicates to the dynamic linker that + * the undefined symbol is allowed to be missing and is to have the address of + * zero when missing. + */ +#define N_WEAK_REF 0x0040 /* symbol is weak referenced */ + +/* + * The N_WEAK_DEF bit of the n_desc field indicates to the static and dynamic + * linkers that the symbol definition is weak, allowing a non-weak symbol to + * also be used which causes the weak definition to be discared. Currently this + * is only supported for symbols in coalesed sections. + */ +#define N_WEAK_DEF 0x0080 /* coalesed symbol is a weak definition */ + +/* + * The N_REF_TO_WEAK bit of the n_desc field indicates to the dynamic linker + * that the undefined symbol should be resolved using flat namespace searching. + */ +#define N_REF_TO_WEAK 0x0080 /* reference to a weak symbol */ + +/* + * The N_ARM_THUMB_DEF bit of the n_desc field indicates that the symbol is + * a defintion of a Thumb function. + */ +#define N_ARM_THUMB_DEF 0x0008 /* symbol is a Thumb function (ARM) */ + +/* + * The N_SYMBOL_RESOLVER bit of the n_desc field indicates that the + * that the function is actually a resolver function and should + * be called to get the address of the real function to use. + * This bit is only available in .o files (MH_OBJECT filetype) + */ +#define N_SYMBOL_RESOLVER 0x0100 + +/* + * The N_ALT_ENTRY bit of the n_desc field indicates that the + * symbol is pinned to the previous content. + */ +#define N_ALT_ENTRY 0x0200 + +/* + * The N_COLD_FUNC bit of the n_desc field indicates that the symbol is used + * infrequently and the linker should order it towards the end of the section. + */ +#define N_COLD_FUNC 0x0400 /* * An indirect symbol table entry is simply a 32bit index into the symbol table diff --git a/view/sharedcache/CMakeLists.txt b/view/sharedcache/CMakeLists.txt index 07c58514..8620975c 100644 --- a/view/sharedcache/CMakeLists.txt +++ b/view/sharedcache/CMakeLists.txt @@ -33,7 +33,7 @@ endif() set(HARD_FAIL_MODE OFF CACHE BOOL "Enable hard fail mode") set(SLIDEINFO_DEBUG_TAGS OFF CACHE BOOL "Enable debug tags in slideinfo") set(VIEW_NAME "DSCView" CACHE STRING "Name of the view") -set(METADATA_VERSION 4 CACHE STRING "Version of the metadata") +set(METADATA_VERSION 5 CACHE STRING "Version of the metadata") add_subdirectory(core) add_subdirectory(api) diff --git a/view/sharedcache/api/python/sharedcache.py b/view/sharedcache/api/python/sharedcache.py index e0e18bde..e3ccbb9b 100644 --- a/view/sharedcache/api/python/sharedcache.py +++ b/view/sharedcache/api/python/sharedcache.py @@ -52,14 +52,21 @@ class DSCBackingCacheMapping: @dataclasses.dataclass class DSCBackingCache: path: str - isPrimary: bool + cacheType: BackingCacheType mappings: list[DSCBackingCacheMapping] def __str__(self): return repr(self) def __repr__(self): - return f"<DSCBackingCache {self.path} {'Primary' if self.isPrimary else 'Secondary'} | {len(self.mappings)} mappings>" + match self.cacheType: + case BackingCacheType.BackingCacheTypePrimary: + cacheTypeStr = 'Primary' + case BackingCacheType.BackingCacheTypeSecondary: + cacheTypeStr = 'Secondary' + case BackingCacheType.BackingCacheTypeSymbols: + cacheTypeStr = 'Symbols' + return f"<DSCBackingCache {self.path} {cacheTypeStr} | {len(self.mappings)} mappings>" @dataclasses.dataclass @@ -142,7 +149,7 @@ class SharedCache: mappings.append(mapping) result.append(DSCBackingCache( value[i].path, - value[i].isPrimary, + value[i].cacheType, mappings )) diff --git a/view/sharedcache/api/python/sharedcache_enums.py b/view/sharedcache/api/python/sharedcache_enums.py index 34668424..ea86b5c6 100644 --- a/view/sharedcache/api/python/sharedcache_enums.py +++ b/view/sharedcache/api/python/sharedcache_enums.py @@ -1,6 +1,12 @@ import enum +class BackingCacheType(enum.IntEnum): + BackingCacheTypePrimary = 0 + BackingCacheTypeSecondary = 1 + BackingCacheTypeSymbols = 2 + + class DSCViewLoadProgress(enum.IntEnum): LoadProgressNotStarted = 0 LoadProgressLoadingCaches = 1 diff --git a/view/sharedcache/api/sharedcache.cpp b/view/sharedcache/api/sharedcache.cpp index a0c4e961..d9838057 100644 --- a/view/sharedcache/api/sharedcache.cpp +++ b/view/sharedcache/api/sharedcache.cpp @@ -102,7 +102,7 @@ namespace SharedCacheAPI { { BackingCache cache; cache.path = value[i].path; - cache.isPrimary = value[i].isPrimary; + cache.cacheType = value[i].cacheType; for (size_t j = 0; j < value[i].mappingCount; j++) { BackingCacheMapping mapping; diff --git a/view/sharedcache/api/sharedcacheapi.h b/view/sharedcache/api/sharedcacheapi.h index 712cc98e..af82bb62 100644 --- a/view/sharedcache/api/sharedcacheapi.h +++ b/view/sharedcache/api/sharedcacheapi.h @@ -105,7 +105,7 @@ namespace SharedCacheAPI { struct BackingCache { std::string path; - bool isPrimary; + BNBackingCacheType cacheType; std::vector<BackingCacheMapping> mappings; }; diff --git a/view/sharedcache/api/sharedcachecore.h b/view/sharedcache/api/sharedcachecore.h index c2e1c7bd..54899919 100644 --- a/view/sharedcache/api/sharedcachecore.h +++ b/view/sharedcache/api/sharedcachecore.h @@ -64,6 +64,12 @@ extern "C" LoadProgressFinished, } BNDSCViewLoadProgress; + typedef enum BNBackingCacheType { + BackingCacheTypePrimary, + BackingCacheTypeSecondary, + BackingCacheTypeSymbols, + } BNBackingCacheType; + typedef struct BNBinaryView BNBinaryView; typedef struct BNSharedCache BNSharedCache; typedef struct BNStringRef BNStringRef; @@ -98,7 +104,7 @@ extern "C" typedef struct BNDSCBackingCache { char* path; - bool isPrimary; + BNBackingCacheType cacheType; BNDSCBackingCacheMapping* mappings; size_t mappingCount; } BNDSCBackingCache; diff --git a/view/sharedcache/core/SharedCache.cpp b/view/sharedcache/core/SharedCache.cpp index 9139d7ba..eae2e5b8 100644 --- a/view/sharedcache/core/SharedCache.cpp +++ b/view/sharedcache/core/SharedCache.cpp @@ -517,7 +517,7 @@ void SharedCache::PerformInitialLoad(std::lock_guard<std::mutex>& lock) { dyld_cache_mapping_info mapping {}; BackingCache cache; - cache.isPrimary = true; + cache.cacheType = BackingCacheTypePrimary; cache.path = path; for (size_t i = 0; i < primaryCacheHeader.mappingCount; i++) @@ -583,7 +583,7 @@ void SharedCache::PerformInitialLoad(std::lock_guard<std::mutex>& lock) // briefly. BackingCache cache; - cache.isPrimary = true; + cache.cacheType = BackingCacheTypePrimary; cache.path = path; for (size_t i = 0; i < primaryCacheHeader.mappingCount; i++) @@ -654,7 +654,7 @@ void SharedCache::PerformInitialLoad(std::lock_guard<std::mutex>& lock) dyld_cache_mapping_info subCacheMapping {}; BackingCache subCache; - subCache.isPrimary = false; + subCache.cacheType = BackingCacheTypeSecondary; subCache.path = subCachePath; for (size_t j = 0; j < subCacheHeader.mappingCount; j++) @@ -688,7 +688,7 @@ void SharedCache::PerformInitialLoad(std::lock_guard<std::mutex>& lock) dyld_cache_mapping_info mapping {}; // We're going to reuse this for all of the mappings. We only need it // briefly. BackingCache cache; - cache.isPrimary = true; + cache.cacheType = BackingCacheTypePrimary; cache.path = path; for (size_t i = 0; i < primaryCacheHeader.mappingCount; i++) @@ -740,7 +740,7 @@ void SharedCache::PerformInitialLoad(std::lock_guard<std::mutex>& lock) subCacheFile->Read(&subCacheHeader, 0, headerSize); BackingCache subCache; - subCache.isPrimary = false; + subCache.cacheType = BackingCacheTypeSecondary; subCache.path = subCachePath; dyld_cache_mapping_info subCacheMapping {}; @@ -808,7 +808,7 @@ void SharedCache::PerformInitialLoad(std::lock_guard<std::mutex>& lock) dyld_cache_mapping_info mapping {}; BackingCache cache; - cache.isPrimary = true; + cache.cacheType = BackingCacheTypePrimary; cache.path = path; for (size_t i = 0; i < primaryCacheHeader.mappingCount; i++) @@ -885,7 +885,7 @@ void SharedCache::PerformInitialLoad(std::lock_guard<std::mutex>& lock) dyld_cache_mapping_info subCacheMapping {}; BackingCache subCache; - subCache.isPrimary = false; + subCache.cacheType = BackingCacheTypeSecondary; subCache.path = subCachePath; for (size_t j = 0; j < subCacheHeader.mappingCount; j++) @@ -942,7 +942,7 @@ void SharedCache::PerformInitialLoad(std::lock_guard<std::mutex>& lock) subCacheFile->Read(&subCacheHeader, 0, headerSize); BackingCache subCache; - subCache.isPrimary = false; + subCache.cacheType = BackingCacheTypeSymbols; subCache.path = subCachePath; dyld_cache_mapping_info subCacheMapping {}; @@ -957,7 +957,9 @@ void SharedCache::PerformInitialLoad(std::lock_guard<std::mutex>& lock) initialState.backingCaches.push_back(std::move(subCache)); } catch (...) - {} + { + m_logger->LogWarn("Failed to load the symbols cache"); + } break; } } @@ -3370,7 +3372,7 @@ extern "C" for (size_t i = 0; i < viewCaches.size(); i++) { caches[i].path = BNAllocString(viewCaches[i].path.c_str()); - caches[i].isPrimary = viewCaches[i].isPrimary; + caches[i].cacheType = viewCaches[i].cacheType; BNDSCBackingCacheMapping* mappings; mappings = new BNDSCBackingCacheMapping[viewCaches[i].mappings.size()]; @@ -3750,7 +3752,7 @@ void SharedCache::ModifiedState::Merge(SharedCache::ModifiedState&& newer) void BackingCache::Store(SerializationContext& context) const { MSS(path); - MSS(isPrimary); + MSS_CAST(cacheType, uint32_t); MSS(mappings); } @@ -3758,7 +3760,7 @@ BackingCache BackingCache::Load(DeserializationContext& context) { BackingCache cache; cache.MSL(path); - cache.MSL(isPrimary); + cache.MSL_CAST(cacheType, uint32_t, BNBackingCacheType); cache.MSL(mappings); return cache; } diff --git a/view/sharedcache/core/SharedCache.h b/view/sharedcache/core/SharedCache.h index f5f63749..ee4228ef 100644 --- a/view/sharedcache/core/SharedCache.h +++ b/view/sharedcache/core/SharedCache.h @@ -104,7 +104,7 @@ namespace SharedCacheCore { struct BackingCache : public MetadataSerializable<BackingCache> { std::string path; - bool isPrimary = false; + BNBackingCacheType cacheType = BackingCacheTypeSecondary; std::vector<dyld_cache_mapping_info> mappings; void Store(SerializationContext& context) const; |
