Parsing Symbol Table for SafariSharedUI: An Introduction

When you inspect an iOS binary (or framework) like SafariSharedUI.framework
(hypothetical naming), the symbol table holds mappings between addresses and function / method names, class names, selectors, file offsets, etc. By parsing that symbol table, you can reverse engineer names, understand call graphs, and reconstruct high-level structure from a stripped binary.
Parsing Symbol Table for SafariSharedUI: In iOS / macOS, many system frameworks are built with symbols hidden or stripped (for release builds). To study them, security researchers or reverse engineers often extract symbol tables from the dyld shared cache, or use symbol files (dSYMs), or re-inject or restore symbols.
This article walks through the key concepts, steps, tools, and caveats for parsing the symbol table of something like SafariSharedUI.
What Is a Symbol Table & Why Parse It
A symbol table is a data structure embedded in binaries / object files (e.g. Mach-O on iOS) mapping symbol names (like -[MyClass doSomething:]
) to addresses or offsets in memory or the code section. It may also include metadata, file names, line numbers (if debug info exists), and relocation entries.
Why parse a symbol table?
-
To recover function / method names even in stripped binaries
-
To map crash reports (address traces) to human-readable symbols (symbolication)
-
To understand class / selector relationships (especially for Objective-C frameworks)
-
To analyze call graphs, hooking points, or potential private API use
-
To assist in forensic or security research, e.g. detecting backdoors or hidden features
Symbol parsing is central to reverse engineering or forensic toolchains.
In Apple’s ecosystem, the process of symbolication converts raw addresses in crash logs back to names and line numbers via dSYM / symbol files
But for internal system or UI frameworks like SafariSharedUI, you may not have full debug info—so you must work with what’s in the dyld cache or other extracted Mach-O slices.
Where Symbols Reside in iOS / macOS & SafariSharedUI Context
Understanding where symbols come from is vital before parsing:
In iOS, many built-in frameworks are packaged into a dyld shared cache which aggregates system dylibs for performance. Reverse engineers often extract individual Mach-O slices from that cache to parse their symbols.
Frameworks like SafariSharedUI
(if treated like a “shared UI” module for Safari) would live under /System/Library/Frameworks
or inside the dyld cache; they may not carry full symbol tables in production builds, but may retain some Objective-C metadata (class names, selectors).
Symbol stripping: Official builds often strip symbol tables or use minimal exports to hide internals. So you might see only exported symbols or stubs, not all internal ones.
Thus, when you parse “SafariSharedUI” you may only regain partial symbol visibility; your tools and strategies must take that into account.
Methods & Tools to Parse the Symbol Table
Below is a step-by-step outline of how to parse or recover the symbol table, using typical reverse engineering workflows:
1. Extract the Mach-O slice / dylib
-
Use tools or scripts (e.g.
dyld_shared_cache_util
, oripsw dyld extract
) to extract the relevant framework’s Mach-O from the dyld cache. -
For example:
This yields a standalone dylib or binary with symbol sections.
2. Read symbol tables using nm / objdump / mach tools
-
Run
nm -g <MachO_file>
orotool -Iv <file>
to list global symbols, undefined symbols, etc. -
Use
llvm-nm
ornm-classic
variants if working in modern iOS toolchain. -
For Objective-C metadata (classes, selectors), use
class-dump
orr2 ida
hooks.
3. Restore stripped symbols or embed additional metadata
-
Use community tools that restore stripped symbol tables (e.g.
restore-symbol
) for Mach-O / Objective-C binaries. -
These tools may re-inject method names, selector names, or function names into a cleaned / new Mach-O so debugging is easier.
4. Parse / index symbols programmatically
-
After getting a list of symbols, feed into a symbol parser / database (e.g. in Python, or within IDA, Ghidra).
-
Build data structures:
{ address → symbol_name }
, perhaps cross-referenced with Objective-C class names and selectors.
5. Resolve relocations, stubs and imports
-
Many symbols are stubs that call into other dylibs. You must resolve indirect symbols / relocations to get actual call targets.
-
For Objective-C, selectors are often forwarded or resolved at runtime; mapping between selector names and method addresses is done via class metadata.
6. Cross-reference with crash reports or runtime logs
-
Use the parsed symbol database to translate uninterpreted crash logs: addresses → human-readable symbols.
-
This is the core of symbolication for system / private frameworks.
These combined steps let you restore as much of the symbol table as possible.
Challenges, Limitations & Best Practices
Parsing symbol tables for frameworks like SafariSharedUI is not trivial. Here are common pitfalls and how to address them:
🔍 Stripped / minimal export symbols
-
Many internal (private) functions aren’t exported, so you won’t see their names.
-
To mitigate: rely on Objective-C runtime metadata (class lists, method lists) which may still be intact even if symbols are stripped.
🧩 Stub islands / trampoline logic
-
Some symbols may point to stubs or jump islands — small helper wrappers inserted by the runtime.
-
You might need to symbolicate stub pointers or patch through to real implementations. Tools like
--stubs
flag inipsw dyld extract
help include stub symbols.
⚠ Address slide / ASLR
-
In a loaded binary, addresses may be slid due to ASLR (Address Space Layout Randomization).
-
When parsing offline, you must apply the slide offset to map symbol addresses correctly.
🔐 Obfuscation / symbol hiding
-
Some frameworks may deliberately obfuscate or rename symbols to avoid easy reverse engineering.
-
Certain methods may be stripped entirely or replaced with generic labels (e.g.
_objc_msgSend$shim
) which lacks clarity.
📚 Partial / inconsistent metadata
-
Some symbols may lack file/line info (because debug sections are removed).
-
Class metadata or selector tables may be incomplete or fragmented, making name resolution partial.
🧠 Performance / scale
-
Large frameworks may hold thousands of symbols; indexing and querying must be efficient (e.g. use B-trees, hashed maps).
-
Merging multiple symbol sources (exports, Obj-C metadata, restored symbols) must resolve conflicts.
By anticipating these, you can design workflows that maximize recovery and clarity.
Example: Hypothetical Walkthrough for SafariSharedUI
To ground this in a concrete example, here’s a hypothetical walkthrough:
-
Extract the
SafariSharedUI.dylib
from iOS’s dyld_shared_cache usingipsw dyld extract
. -
Run nm / llvm-nm:
You’ll get exported function names like
-[SUIController initWithWebView:]
etc. -
Run class-dump or runtime introspection to list Objective-C classes and selectors in that framework:
-
Use restore-symbol to try to re-inject missing method names or Objective-C symbols back into an internal Mach-O version.
-
Load into disassembler / decompiler (Ghidra, IDA) and map symbol database so that function bodies show meaningful names instead of
sub_10123456
. -
Relocate / apply slide offset so that the addresses align with the running system (for use in crash logs).
-
Cross-check with crash logs: when a crash backtrace shows an address
0x1F234AB0
withinSafariSharedUI
, map that to a known symbol via your table and annotate it.
After this, SafariSharedUI
becomes much more readable for security analysis, vulnerability hunting, or understanding internal UI behavior.