Exploring Swift Binary Structure and Dynamic Method Invocation in Mach-O
This article examines Swift's binary representation in Mach-O files, compares it with Objective‑C storage, demonstrates runtime dynamic method calls, and analyzes class metadata, VTable construction, and related flags to reveal how Swift functions are located and invoked at runtime.
The article introduces the differences between Swift and Objective‑C binaries from a binary perspective, focusing on function table storage structures and providing a demo repository for further exploration.
Background : With Swift's ABI now stable, 58.com initiated the "Mixed Sky" project to improve Swift integration across mixed‑language architectures, toolchains, and UI components, and this write‑up presents the toolchain team's findings.
Dynamic Invocation : An example Swift class MyClass is shown, followed by an Objective‑C version that can be inspected via runtime to list methods and invoke them using IMP . The Objective‑C output demonstrates successful method discovery.
class MyClass {
var p:Int = 0
init() {
print("init")
}
func helloSwift() -> Int {
print("helloSwift")
return 100
}
func helloSwift1() -> Int {
print("helloSwift1")
return 100
}
func helloSwift2() -> Int {
print("helloSwift2")
return 100
}
}When attempting the same with a pure Swift class, runtime fails to retrieve method information, showing a count of zero.
Class class = NSClassFromString(@"SwiftDynamicRun.MyClass");
unsigned int count = 0;
Method *list = class_copyMethodList(class,&count);
for (int i = 0; i < count; i++) {
Method method = list[i];
NSLog(@"- [%@ %@]",class,NSStringFromSelector(method_getName(method)));
}OC Storage : Objective‑C classes are stored in the __objc_classlist section of Mach‑O. The class64 struct layout is presented, and address‑to‑file‑offset conversion is explained.
struct class64 {
unsigned long long isa;
unsigned long long superClass;
unsigned long long cache;
unsigned long long vtable;
unsigned long long data;
};By examining class64Info , one can locate class names, method lists, and function entry points.
Swift Storage : Swift also retains the __objc_classlist layout, but its method tables are not stored in class64Info . Instead, Swift uses sections such as __swift5_types , which contain 4‑byte relative offsets rather than full 8‑byte addresses, reducing binary size.
type ClassDescriptor struct {
Flags uint32
Parent int32
Name int32
AccessFunction int32
FieldDescriptor int32
SuperclassType int32
MetadataNegativeSizeInWords uint32
MetadataPositiveSizeInWords uint32
NumImmediateMembers uint32
NumFields uint32
}Further analysis shows that Swift’s ClassContextDescriptorBuilder adds a VTable and other metadata via overridden layout methods.
class ClassContextDescriptorBuilder {
void layout() {
super::layout();
addVTable();
addOverrideTable();
addObjCResilientClassStubInfo();
maybeAddCanonicalMetadataPrespecializations();
}
}The VTable size is stored as a 4‑byte count followed by method descriptors. Flags such as Class_HasVTable (bit 15) indicate the presence of a VTable; for example, a flag value of 0x80000050 denotes a class with a VTable.
// Flag layout example
| TypeFlag(16bit) | version(8bit) | generic(1bit) | unique(1bit) | unknown(1bit) | Kind(5bit) |How to Implement Dynamic Calls : A demo repository ( SwiftMachODemo ) illustrates runtime method enumeration and invocation. The demo also shows that extra compiler‑generated functions appear in the VTable.
// Function flag explanation
enum class Kind {
Method,
Init,
Getter,
Setter,
ModifyCoroutine,
ReadCoroutine,
};An OverrideTable structure is described, though not implemented in the demo.
struct SwiftOverrideMethod {
struct SwiftClassType *OverrideClass;
struct SwiftMethod *OverrideMethod;
struct SwiftMethod *Method;
};Summary : Starting from dynamic invocation, the article delves into Swift’s binary storage, highlighting limitations such as reliance on VTable indices and the impact of code changes on VTable layout. It encourages further exploration of Swift’s advanced runtime features.
Author : Deng Zhuli, iOS Development Engineer, User Value Growth Center, 58.com.
References :
https://knight.sc/reverse%20engineering/2019/07/17/swift-metadata.html
https://juejin.im/post/6844903783449755655
https://github.com/apple/swift/blob/5c59babfebb1603c8fd95bf04e1a33c8e074c7ca/lib/IRGen/GenMeta.cpp
https://www.jianshu.com/p/158574ab8809
https://github.com/neil-wu/SwiftDump/blob/master/README_zh.md
58 Tech
Official tech channel of 58, a platform for tech innovation, sharing, and communication.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.