About me
• Le
a
rntto use open-source softw
a
re
before the term “open source” w
a
s
coined on VAX-11/780.
• Le
a
rnt some Sm
a
llT
a
lk-80 in e
a
rly
1990s.
• Le
a
rnt some Objective-C progr
a
mming
on NeXT m
a
chines.
• W
a
s excited to he
a
r “Swift is the
Objective-C without the C”. Thought it’s
more Sm
a
llT
a
lk-80 like. You know it’s
not.
• Know very little Swift
3
http://gunkies.org/w/images/c/c1/DEC-VAX-11-780.jpg
4.
using Swift APIfrom PrivateFrameworks
• Some new Apple fr
a
meworks
a
re Swift only, either public or priv
a
te fr
a
meworks
• CoreML: Objective-C
a
nd Swift
• Found
a
tionModels, ModelC
a
t
a
log: Swift only
4
5.
Why using SwiftAPIs in Apple’s private frameworks is an issue?
• Although there m
a
ny “public symbols” we c
a
n use / link, there
a
re no decl
a
r
a
tions.
• For Objective-C, there
a
re sever
a
l cl
a
ss-dump tools
a
v
a
il
a
ble on the internet.
• Find inform
a
tion from
a
compiled M
a
ch-O
f
ile, the execut
a
ble form
a
t used by m
a
cOS, iOS,
a
nd other Apple oper
a
ting systems, by
a
n
a
lyzing the Objective-C runtime inform
a
tion
embedded in it
a
nd gener
a
tes corresponding Objective-C he
a
der
f
iles.
• There
a
re no tools
a
re good
a
s cl
a
ss-dump for dump Swift API to .swiftinterf
a
ce, which we’ll
expl
a
in l
a
ter.
• If you’re f
a
mili
a
r with the Objective-C runtime API, you might wonder if we c
a
n use it to
dyn
a
mic
a
lly
a
ccess construct Swift objects. Altern
a
tively, is there
a
corresponding “Swift runtime
API”?
5
6.
public vs. privateframeworks
• public fr
a
meworks, such
a
s CoreML,
come with C/C++/Objective-C he
a
ders in
He
a
ders
a
nd Swift decl
a
r
a
tions in
Modules.
• priv
a
te fr
a
meworks h
a
ve none of them
• if you don’t know .tbd, it’s Apple’s (text-
b
a
sed dyn
a
mic libr
a
ry stu
ff
). While there
isn't one single "o
ff
ici
a
l speci
f
ic
a
tion
document" re
a
dily
a
v
a
il
a
ble to the public,
there
a
re open-source implement
a
tions
in LLVM.
6
7.
swiftinterface
• swiftinterf
a
ce
f
iles
a
re
a
key componentof Swift's Module St
a
bility
a
nd Libr
a
ry Evolution fe
a
tures. They
a
re
a
textu
a
l represent
a
tion of
a
Swift module's public API, gener
a
ted by the Swift compiler during the build process from the origin
a
l Swift source code.
• The .swiftinterf
a
ce
f
ile cont
a
ins:
• Decl
a
r
a
tions: The n
a
mes of
a
ll public types, functions,
a
nd v
a
ri
a
bles.
• Type Inform
a
tion: The sign
a
tures of these public members, including their return types, p
a
r
a
meter types,
a
nd
a
ny generic
constr
a
ints.
• Module-Speci
f
ic Inform
a
tion: Det
a
ils th
a
t
a
llow the compiler to link
a
g
a
inst the module correctly.
• This
f
ile is essenti
a
lly
a
"st
a
ble ABI he
a
der" for Swift modules, ensuring th
a
t
a
libr
a
ry compiled with one version of the Swift compiler
c
a
n be used by
a
n
a
pplic
a
tion compiled with
a
di
ff
erent, comp
a
tible version of the compiler.
• When
a
Swift bin
a
ry is compiled into
a
M
a
ch-O
f
ile, the origin
a
l source code
a
nd the det
a
iled type inform
a
tion in the .swiftinterf
a
ce
f
ile
a
re not preserved. While the M
a
ch-O bin
a
ry cont
a
ins
a
signi
f
ic
a
nt
a
mount of symbol
a
nd met
a
d
a
t
a
, it is not enough to reverse-
engineer the complete
a
nd
a
ccur
a
te Swift-level API.
7
8.
C/C++/Objective-C/Swift symbols oniOS/macOS
• C: no function sign
a
tures, no nothing
• C++: function p
a
r
a
meters type in m
a
ngled symbols, vt
a
ble, etc. The return types
a
re not in
m
a
ngled n
a
mes.
• Objective-C: dyn
a
mic type (generic object id, dyn
a
mic binding, etc.) so there
a
re m
a
ny
inform
a
tion. cl
a
ss-dump somewh
a
t showed wh
a
t we c
a
n from bin
a
ry
f
iles.
• Swift: Swift n
a
me m
a
ngling spec
a
nd “swift dem
a
ngle”
a
re quite comprehensive.
8
Using ModelCatalog.framework
• Withthe help of otool
a
nd lldb, we’ve discovered th
a
t the modelc
a
tlogdump utilizes the
priv
a
te fr
a
mework of the ModelC
a
t
a
log.fr
a
mework.
• The ModelC
a
t
a
log fr
a
mework o
ff
ers very limited Objective-C APIs.
• Interestingly, the object cl
a
sses _TtC….
a
re
a
ctu
a
lly Swift cl
a
sses.
• The _OBJC_CLASS_$_MCResourceInform
a
tion
a
nd
_OBJC_CLASS_$_MCResourceSt
a
tus cl
a
sses don’t provide
a
ny useful inform
a
tion. We’ll
revisit this l
a
ter.
• Therefore, we need to ex
a
mine the Swift API.
• Let’s check if we do “import ModelC
a
t
a
log” in Swift
10
import ModelCatalog
Let's checkif we can make
import ModelCatalog
in Swift work.
Let's use stu
ff
in
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/PrivateFrameworks
By default, it doesn't work
$ swiftc test_import_mc_1.swift -F /Library/Developer/CommandLineTools/SDKs/
MacOSX.sdk/System/Library/PrivateFrameworks
test_import_mc_1.swift:1:8: error: no such module 'ModelCatalog
1 | import ModelCatalog
| `- error: no such module 'ModelCatalog'
2 |
$
14
15.
import ModelCatalog (cont’d)
•It seems module.modulesm
a
p is needed
• it seems there is not
a
single, comprehensive "o
ff
ici
a
l" Apple document
a
tion for the module.modulem
a
p
f
ile form
a
t. We
f
ind
inform
a
tion in llvm/cl
a
ng document
a
tions
a
nd source code.
• Since we
a
re le
a
rning in
a
stupid w
a
y. Let’s use copy-
a
nd-p
a
ste
a
nd tri
a
l-
a
nd-error.
I copied module.modulemap from CoreML.framework and change CoreML to ModelCatalog,
framework module ModelCatalog {
umbrella header "ModelCatalog.h"
export *
module * { export * }
}
The ModelCatalog.h could be an empty one. That is, we could create an empty
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/PrivateFrameworks/ModelCatalog.framework/Headers/ModelCatalog.h
then we can compile the one line ("import ModelCatalog") program successfully.
15
16.
import ModelCatalog (cont’d)
Canwe ingore the
umbrella header "ModelCatalog.h"
line, it seems this is for Objective-C to Swift bridge (for Swift code to use Objective-C binary code). YES, if we remove the line only, we got messages like
$ swiftc test_import_mc_1.swift -F /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/PrivateFrameworks
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/PrivateFrameworks/ModelCatalog.framework/Modules/
module.modulemap:4:12: error: inferred submodules require a module with an umbrella
2 |
3 | export *
4 | module * { export * }
| `- error: inferred submodules require a module with an umbrella
5 | }
6 |
It seems line 4 here
4 | module * { export * }
is also for using Objective-C. When we remove it too, it WORKS. That is
framework module ModelCatalog {
export *
}
is enough.
16
17.
As we know,/usr/bin/modelcatalogdump could be a good starting point.
By setting breakpoints with b -r ModelCatalog in lldb modelcatalogdump, the
fi
rst method I captured was
ModelCatalog`static ModelCatalog.CatalogClient.generativeExperienceEssentialResourcesStatus() ->
ModelCatalog.ResourceReadinessStatus
By examining exported symbols with nm and swift demangle, we know that ModelCatalog.CatalogClient is a class in
the ModelCatalog framework and
static ModelCatalog.CatalogClient.generativeExperienceEssentialResourcesStatus() ->
ModelCatalog.ResourceReadinessStatus
is a class method of CatalogClient. It takes no argument and returns an instance
of ModelCatalog.ResourceReadinessStatus, which is a Swift enum.
17
Tools
• So f
a
r,we use nm, otool, lldb,
a
nd swift dem
a
ngle. Are there
a
ny other convenient open-source tools.
• Yes, to me,
a
t le
a
st Ghidr
a
a
nd ipsw
a
re quite useful.
• Ghidr
a
is
a
n open-source reversing tool from NSA. It could
•
a
n
a
lyze dyld_sh
a
red_c
a
che, dissemble functions, decompile m
a
chine code into C/C++ like functions.
• ipsw is kind
a
“iOS/m
a
cOS Rese
a
rch Swiss Army Knife”, I used it to
• downlo
a
d Apple .ipsw
f
iles, extr
a
ct
a
nd re
a
d dyld_sh
a
red_c
a
che from Apple .ipsw
f
ile,
a
nd decompile some functions
with Github Copilot
• ipsw
a
lso provides Objective-C cl
a
ss-dump
a
nd swift-dump
• Unfortun
a
tely, swift-dump is not complete. E.g,, it could not gener
a
te .sw
f
itinterf
a
ce
f
iles
a
nd didn’t h
a
ndle generic type
well.
20
21.
CatalogClient by ipswswift-
dump
• no public
• no
gener
a
tiveExperienceEssenti
a
lResource
sSt
a
tus()
• inst
a
nce v
a
ri
a
ble setters
a
nd getters
a
re stripped.
21
22.
CatalogClient by Ghidra
•Yes, there is
C
a
t
a
logClient.gener
a
tiveExperienceEss
enti
a
lResourcesSt
a
tus()
• And we c
a
n get h
a
rd to re
a
d
decompiled code.
22
23.
calling a CatalogClientinstance method
• we c
a
n
f
ind th
a
t there is
• disp
a
tch thunk of ModelC
a
t
a
log.C
a
t
a
logClient.enoughStor
a
geForGener
a
tiveExperiencesEssenti
a
lResources()
a
sync throws -> Swift.Bool
• c
a
n we cre
a
te
a
nd inst
a
nce
a
nd c
a
ll it? Yes, it’s quite trivi
a
l. Add decl
a
r
a
tions of this function
a
nd the constructor then we c
a
n compile it.
• note th
a
t
a
thunk in Swift is
a
function or closure th
a
t del
a
ys the execution of
a
piece of code.
23
calling a CatalogClientinstance method (cont’d)
• We c
a
n compile the following simple code successfully. However it f
a
iled to run.
• With `log stre
a
m --debug`, we c
a
n
f
ind some clues.
xxxxxxxxxxxx+0800 0x1f7c3f3 Error 0x0 538 0 modelcatalogd: (ModelCatalogRuntime) ModelCatalog com.apple.modelcatalog.full-access: Rejecting connection from 67927: lacking entitlement
• It seems we h
a
ve to
a
dd this “non-st
a
nd
a
rd” “com.
a
pple.modelc
a
t
a
log.full-
a
ccess” entitlement. Th
a
t is, it won’t work on iPhone
a
nd
m
a
c without Apple Mobile File Integrity (AMFI) dis
a
bled.
• Yes,
a
fter signing the bin
a
ry with the entitlement, it works.
import ModelCatalog
print("CatalogClient readiness:", CatalogClient.generativeExperienceEssentialResourcesStatus())
let client = CatalogClient()
print(client)
if let ready = try? await client.enoughStorageForGenerativeExperiencesEssentialResources() {
print(ready)
} else {
print("failed")
}
25
26.
more CatalogClient methods
•with inst
a
nce methods resources()
a
nd resourceBundels() of the C
a
t
a
logClient cl
a
ss,
we c
a
n dump
a
lot of resource inform
a
tion
• remember to codesign with the “com.
a
pple.modelc
a
t
a
log.full-
a
ccess”
entitlement.
• Most of the inform
a
tion we see from modelc
a
t
a
logdump is in resources()
a
nd
a
nd
resourceBundles() outputs
import ModelCatalog
let client = CatalogClient()
let resources = try? client.resources()
print("resources:")
dump(resources!, indent: 1)
let bundles = try? client.resourceBundles()
print("resource bundles:")
dump(bundles!, indent: 1)
26
there
a
re some c
a
ve
a
ts
a
ndlimit
a
tions
Objective-C runtime API works for non-NSObject subclasses to some extent
• Underlying Object Model: Even when written without explicitly inheriting from NSObject, every Swift cl
a
ss on Apple pl
a
tforms still executes within
a
nd uses the Objective-C object model. This me
a
ns th
a
t
a
t
a
fund
a
ment
a
l level, they
a
re Objective-C objects. The root cl
a
ss for pure Swift cl
a
sses is
a
n intern
a
l
type often referred to
a
s _SwiftObject, which itself lever
a
ges the Objective-C runtime. The Objective-C runtime libr
a
ry provides support for the dyn
a
mic properties of the Objective-C l
a
ngu
a
ge
a
nd is linked by
a
ll Objective-C
a
pps.
• Cl
a
ss-Level APIs (Discovery
a
nd Introspection):
• Functions like objc_lookUpCl
a
ss(_:)
a
nd objc_getCl
a
ssList(_:_:) c
a
n indeed
f
ind
a
nd return Cl
a
ss objects for pure Swift cl
a
sses. This is bec
a
use these cl
a
sses
a
re registered with the Objective-C runtime.
• You c
a
n
a
lso use functions like cl
a
ss_getN
a
me(_:)
a
nd cl
a
ss_getSupercl
a
ss(_:) on these Swift cl
a
sses.
• Inst
a
nce-Level APIs (Cre
a
tion
a
nd M
a
nipul
a
tion):
• cl
a
ss_cre
a
teInst
a
nce(_:_:): You c
a
n use cl
a
ss_cre
a
teInst
a
nce(_:_:) to cre
a
te inst
a
nces of pure Swift cl
a
sses,
a
s they
a
re built upon the Objective-C object model.
• object_setIv
a
r(_:_:_:)
a
nd cl
a
ss_getInst
a
nceV
a
ri
a
ble(_:_:): This is where the limit
a
tions become more pronounced
a
nd d
a
ngerous.
• While these functions oper
a
te on Objective-C inst
a
nce v
a
ri
a
bles, directly m
a
nipul
a
ting properties of pure Swift cl
a
sses (especi
a
lly Swift v
a
lue types like String, Int, or structs th
a
t
a
re not explicitly exposed to Objective-C with @objc) vi
a
object_setIv
a
r() is gener
a
lly not recommended
a
nd highly
problem
a
tic.
• The intern
a
l memory l
a
yout (Applic
a
tion Bin
a
ry Interf
a
ce or ABI) of Swift cl
a
sses
a
nd their properties, p
a
rticul
a
rly for v
a
lue types, is not st
a
ble or publicly documented for direct m
a
nipul
a
tion. Relying on such intern
a
l det
a
ils c
a
n le
a
d to cr
a
shes, memory corruption, or unde
f
ined beh
a
vior with future
Swift upd
a
tes.
• For object_setIv
a
r() to work reli
a
bly, the property typic
a
lly needs to be
a
n Objective-C object type (like NSString for
a
String property)
a
nd often explicitly m
a
rked with @objc in the Swift cl
a
ss decl
a
r
a
tion to ensure proper bridging
a
nd runtime visibility. If the property is
a
true Swift v
a
lue type
a
nd
not bridged, object_setIv
a
r would expect
a
r
a
w pointer to the v
a
lue's stor
a
ge, which is extremely complex
a
nd uns
a
fe to m
a
n
a
ge m
a
nu
a
lly.
• The other w
a
y is to use Uns
a
fePointer or Uns
a
feR
a
wPointer.
• Method Invoc
a
tion (performSelector): To dyn
a
mic
a
lly c
a
ll methods on
a
Swift cl
a
ss inst
a
nce using Objective-C runtime functions like performSelector, the methods must be explicitly exposed to the Objective-C runtime using the @objc
a
ttribute.
• Key-V
a
lue Coding (KVC): KVC,
a
higher-level Objective-C mech
a
nism for dyn
a
mic property
a
ccess, requires the Swift cl
a
ss to inherit from NSObject
a
nd its properties to be m
a
rked with @objc. Therefore, KVC is gener
a
lly not directly
a
pplic
a
ble to pure Swift cl
a
sses th
a
t do not derive from NSObject.
• Swift Re
f
lection (Mirror API): It's import
a
nt to note th
a
t Swift's Mirror API is
a
Swift-n
a
tive re
f
lection mech
a
nism. It works with
a
ll Swift types (including pure Swift cl
a
sses
a
nd structs) for introspection (re
a
ding property n
a
mes
a
nd v
a
lues). However, it does not support direct modi
f
ic
a
tion of property v
a
lues..
• In summ
a
ry, while b
a
sic introspection of pure Swift cl
a
sses is possible through the Objective-C runtime, direct m
a
nipul
a
tion of their properties (especi
a
lly v
a
lue types) using low-level runtime functions like object_setIv
a
r() is highly discour
a
ged due to ABI inst
a
bility, complex memory m
a
n
a
gement,
a
nd the l
a
ck
of type s
a
fety. For dyn
a
mic property
a
ccess, it is gener
a
lly s
a
fer
a
nd more reli
a
ble to ensure your Swift cl
a
sses inherit from NSObject
a
nd expose relev
a
nt properties with @objc, then use higher-level mech
a
nisms like Key-V
a
lue Coding (KVC) when
a
ppropri
a
te.
28
29.
objc_getClassList(_:_:_) in Swift
objc_getClassList(_:_:)in Swift
The objc_getClassList() is to obtain the list of registered class de
fi
nitions. Apple's documentation provides sample code on how to use it. However, it's in Objective-C even for the Swift version.
29
30.
objc_getClassList(_:_:_) in Swift(cont’d)
• With th
a
t, we c
a
n
f
ind for the v
a
nill
a
dumpAllCl
a
sses (without
a
dding extr
a
fr
a
mework with -fr
a
mework ...), there
a
re
9, 680 cl
a
sses
a
nd 9,102 of them
a
re
a
re
NSObject derived.
• With -fr
a
mework Found
a
tionModels,
there
a
re more cl
a
sses (26,773
a
nd
25,470 of them
a
re NSObject derived).
30
import Foundation
import ObjectiveC
func isDerivedFromNSObject(_ aClass: AnyClass) -> Bool {
if aClass == NSObject.self {
return true
}
var superclass: AnyClass? = class_getSuperclass(aClass)
while let currentSuperclass = superclass {
if currentSuperclass == NSObject.self {
return true
}
superclass = class_getSuperclass(currentSuperclass)
}
return false
}
var numClasses = objc_getClassList(nil, 0)
if (numClasses > 0) {
var classes: UnsafeMutablePointer<AnyClass>? = nil
classes = UnsafeMutablePointer<AnyClass>.allocate(capacity: Int(numClasses))
numClasses = objc_getClassList(AutoreleasingUnsafeMutablePointer<AnyClass>(classes!), numClasses)
for i in 0..<Int(numClasses) {
// dump(classes![i], indent: 1)
if (isDerivedFromNSObject(classes![i])) {
print("name =", String(cString: class_getName(classes![i])), "is NSObject derived");
} else {
print("name =", String(cString: class_getName(classes![i])));
}
}
} else {
print("no classes found")
}
31.
getting a instancevariable
•
a
s we s
a
w, C
a
t
a
logClient cl
a
ss h
a
s some inst
a
nce
v
a
ri
a
bles. c
a
n we get them with something
like .us
a
geAli
a
sV
a
luesForUs
a
geAli
a
s?
• Unfortun
a
tely, it seems not.
• How
a
bout other w
a
ys?
• KVC: The ModelC
a
t
a
log.C
a
t
a
logClient is not
NSObject derived.
• mirror: yes, dump(client) works. other Mirror
methods works. But remember th
a
t Mirror is re
a
d
only
• Objective-C runtime APIs. Yes, it works to some
extent.
31
import Foundation
import ModelCatalog
print("status: ", CatalogClient.generativeExperienceEssentialResourcesStatus())
let client = CatalogClient()
print(client)
print(client.usageAliasValuesForUsageAlias)
if let ready = try? await client.enoughStorageForGenerativeExperiencesEssentialResources()
print(ready)
} else {
print("failed")
}
32.
getting a instancevariable (cont’d)
• With cl
a
ss_getInst
a
nceV
a
ri
a
ble(_:_:)
a
nd
object_getIv
a
r(_:_:), we get the
client.us
a
geAli
a
sV
a
luesForUs
a
geAli
a
s
• How
a
bout setting
a
n inst
a
nce
v
a
ri
a
ble? It’s
a
bit tricky.
32
import Foundation
import ModelCatalog
print("status: ", CatalogClient.generativeExperienceEssentialResourcesStatus())
let client = CatalogClient()
print(client)
let usage = class_getInstanceVariable(CatalogClient.self, "usageAliasValuesForUsageAlias")
print(object_getIvar(client, usage!)!)
33.
Sometime we needto set non-NSObject instance variables
• st
a
rting from iOS/m
a
cOS 26, developers could
a
ccess AFM on-device with APIs in
Found
a
tionModels.fr
a
mework.
import FoundationModels
let session = LanguageModelSession()
let results = try? await session.respond(to: "tell me something
about systolic array")
print(results!)
• Apple’s document
a
tion tells two sessions properties.
• Inspecting the the session, e.g.,
a
dding
dump(session, m
a
xDepth: 2)
a
fter got session, we
know there
a
re more. The
Genener
a
tiveModelInferenceSession is
a
non-
NSObject cl
a
ss. If we w
a
nt to construct it ourselves,
we need to set non-NSObject inst
a
nce v
a
ri
a
bles.
33
class GenerativeModelInferenceSession {
var generator: TokenGeneration.TokenGenerator
var guardrails: FoundationModels.LanguageModelSession.Guardrails
var stringRenderedPromptSanitizer: GenerativeModels.StringRenderedPromptSanitizer
var stringResponseSanitizer: GenerativeModels.StringResponseSanitizer
var modelBundleID: Swift.String
var useCase: FoundationModels.SystemLanguageModel.UseCase
var sessionID: Swift.String
}
34.
a tiny examplefor a String
instance variable
• String != NSString, there
a
re
a
uto-bridging mech
a
nism,
but it’s not wh
a
t we w
a
nt. E.g., the
iv
a
r_getTypeEncoding(_:) won’t return “@“ (id, object) for
Swift String
• object_lookUpCl
a
ss()
a
nd cl
a
ss_cre
a
teInst
a
nce() work for
both NSObject
a
nd non-NSObject cl
a
sses.
• object_getIv
a
r() should not be used.
• KVC only works NSObject.
• wh
a
t re
a
lly works
• ObjectIdenti
f
ier() to get
a
n object’s
a
ddress.
• Uns
a
feMut
a
blePointer/Uns
a
feMut
a
bleR
a
wPointer to
ch
a
nge the v
a
lue of
a
pointee.
34
import Foundation
@objc
class Test: NSObject {
@objc var modelBundleID: String = "original"
override init() {
modelBundleID = "init"
}
}
let t = Test()
print("t:")
dump(t, indent: 1)
let tClass = objc_lookUpClass("test_string_in_class.Test")
var t2 = class_createInstance(tClass, 0)
print("t2:")
dump(t2!, indent: 1)
var mbi = class_getInstanceVariable(tClass, "modelBundleID")
print("mbi: (mbi!)")
// print("modelBundleID: (object_getIvar(t!, mbi!))") will cause segmentation fault
// print("modelBundleID: (object_getIvar(t2!, mbi!))”) ditto
var bi = "com.apple.fm.language.instruct_3b.fm_api_generic"
// object_setIvar(t2!, mbi!, bi) works sometimes
// print("after setIvar modelBundleID: (object_getIvar(t2!, mbi!))") works sometimes
// dump(t2!, indent: 1) will cause segmentation fault
(t2 as! NSObject).setValue("Updated via KVC!", forKey: "modelBundleID")
dump(t2!, indent: 1)
// KVC works for NSObject-derived classes
// Define the print(address:as:) function
func print<T>(address p: UnsafeRawPointer, as type: T.Type) {
let value = p.load(as: type)
print(value)
dump(value, indent: 1)
print("p: (p), type (type)")
}
let t2addr = unsafeBitCast(ObjectIdentifier(t2 as AnyObject), to: Int.self)
print("t2addr: ", String(format: "0x%lx", t2addr))
let offset = ivar_getOffset(mbi!)
print("moduleBundleID offset: ", offset)
// get a pointer to String instance variable
let p = UnsafeMutableRawPointer(bitPattern: t2addr + offset)
print(address: p!, as: String.self)
// get a type pointer
let typedPtr = p!.bindMemory(to: String.self, capacity: 1)
print("pointee:", typedPtr.pointee)
typedPtr.pointee = "test setting with poiter"
print("pointee:", typedPtr.pointee)
print("t2:")
dump(t2!, indent: 1)
35.
Swift Runtime API
•Yes, there
a
re some swift_* functions
in /usr/lib/swift/libswiftCore.dylib (in
dyld_sh
a
red_c
a
che).
• source code is
a
v
a
il
a
ble
• most of them h
a
ve C he
a
ders
somewhere in the source code
• However, it seems they
a
re not
a
s
complete
a
s Objective-C. And I could
not
f
ind one to set inst
a
nce v
a
ri
a
bles
35
36.
wrap-up
• How touse Swift API in priv
a
te fr
a
meworks or non-public Swift API in public fr
a
meworks
• either
a
dd Module/, including .swiftinterf
a
ce
f
iles, or
• Objective-C runtime API + Uns
a
fePointer/Uns
a
feR
a
wPointer
• Tools:
• bin
a
ry utils (otool, nm, etc.), swift toolch
a
in (including swift dem
a
ngle), Ghidr
a
, ipse
36