深入解析MacOS和iOS 卷一 笔记
MacOS and iOS Internals, Volume I : User Mode.md
MacOS and iOS Internals, Volume I : User Mode
DarwinVer = 10.(MacOSVer + 4) = (iOSVer + 6) = (TvOSVer + 6) = (WatchOSVer + 13)
/System/Library/CoreServices/SystemVersion.plist
man what
what /bin/ls
what which what
strings /bin/ls | grep #
app nap / timer coalescing
应用睡眠 / 计时器合并
compressed memory
thread-level qos
10.11’s SIP
AppleScript –> JXA(JavaScript for Automation)
AMFI –> SIP
10.12
syslog -> os_log
HFS+ -> APFS
10.13
Metal2
Remote XPC
10.14
dark mode
app notarization
GCD(Grand Central Dispatcher)
10.15
Voice Control
SideCar
DriverKit
User Mode Kernel Extensions
KAuth -> EndpointSecurity
*OS Architecture
Application Layer -> Cocoa
Media Frameworks -> AVF, CoreAudio, CoreImage, CoreGraphic
Core Services -> Foundation, CoreFoundation
Core OS -> OpenDirectory, SystemConfiguration
Kernel and Device Drievers -> XNU and Kenerl Extensions
Resources
.car -> assetutil/cartool
XCode 7.1 tbd
1 | cd /usr/lib/system |
libsystem_kernel.dylib 1457
libsystem_platform.dylib 180
libsystem_pthread.dylib 201
libSystem_initializer
1 | enum init_func { |
1 | _libSystem_ktrace0 |
systemcall nocancel
check -> pthread_testcancel
Even if syscall() will eventually removed, there is no way to block
direct invocation of system calls through the system assembly instructions.
comm page
1 |
sudo launchctl hostinfo
UNIX-style system call/Mach Traps
IOKit – Windows’ NDIS
user mode c++
kexts
/System/Library/Extensions
kernelcaches
kextstat
chapter 3
FileSystem & Directory
FileSystem
mount/fsck
VFS -> BSD layer
/[System/]Library/FileSystems
1 | kextstat|grep filesystems |
- APFS 10.12
- NTFS
- Media FileSystem -> CD9660/UDF .iso
- Network FileSystem -> AC/AFP/FTP/NFS/SMB/WebDAV
- DMG -> hdiutil/hdik -> DiskImage.framework -> IOHDIXController.kext
- /usr/libexec/diskarbitrationd -> DiskArbitration.frameworkACLs & Attributes
1
2grep -A1 Program /System/Library/LaunchDaemons/*diskarb*
ps -ef | grep diskarbitration | head -n1Transparent file compression1
2
3
4
5
6
7
8
9touch test
chmod +a "admin allow write" test
ls -le test
ls -lOF /
# extended attributes
ls -l@
xattr -l
xattr -d com.apple.quarantine
sudo xattr -r -d com.apple.quarantine
ditto
File forks (MacOS)
Directory
1 | ls /usr/standalone/ |
CLI binary
1 | sudo taskinfo |
[/System]/Library
1 | ls /System/Library/Extensions | wc -l |
/Applications
1 | lsappinfo -> Running |
Guarded Descriptors
EXC_GUARD mach exception
mac_policy_syscall
File Ports
Mach port -> BSD’s file descriptors
chapter 4
UX and System Services
FSEvents’s main clients -> SpotLight/QuickLook
DUET/printing subsystem
kevent EVFILT_VNODE -> limited to individual vnodes
FSEvents[/dev/fsevents] -> filesystem-wide notification
/dev/fsevents root -> FSEvents.framework[fseventsd]
SpotLight -> mds
QuickLook -> qlmanage
sysctl -> POSIX interface
1 | sysctl hw |
AppleSystemInfo.framework[private]
system_profile/System Information.app -> SPSupport.framework[private]
MobileGestalt -> some ways better than its SystemProfiler plugins
Apple Event Manager
Feature Flags (Darwin 19) -> ls /System/Library/FeatureFlags/
/Library/Preferences/SystemConfiguration -> /usr/libexec/configd
/System/Library/SystemConfiguration
/usr/sbin/scuil ->
1 | scutil -dvr www.apple.com |
Duet -> /usr/libexec/coreduetd
Activity Scheduler /usr/libexec/dasd
NSPrintOperation and PrintCore.framework
–> CUPS -> IPP
/usr/sbin/cupsd
lpinfo -v
Voice Control -> Siri
loginwindow/windowserver
CGXServer and SLXServer
IOSurface [/usr/libexec/hidd -> CGEvent
-> Skylight/framework/Resources/WindowServer]
Revisiting touch -> MultitouchSupport.framework
chapter 5
Application Services
application installation
.pkg -> xar
installer -> Installer.app
[installd/system_installd]
App Store Receipts
Transparent Application Lifecycle (MacOS)
-> NSSupportSuddenTermination -> Info.plist
LaunchServices.framework
Ref:https://eclecticlight.co/2019/03/25/lsregister-a-valuable-undocumented-command-for-launchservices/
1 | /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -dump |
/usr/libexec/lsd
launchserviced
/usr/sbin/cfprefsd
Darwin Notifications(libsystem_notify)
/usr/sbin/notifyd
1 | -> _signal/_mach_port,file_descriptor,_diapatch |
https://zhuanlan.zhihu.com/p/317738443 iOS系统的底层通知框架库 观察者模式
lsmp -h
Lists information about mach ports
1 | ps -e -o pid,comm | grep notifyd |
Distributed Notification Center[/usr/sbin/distnoted]
Notification Proxying[/usr/libexec/notification_proxy] used by lockdownd
Apple Push Notifications(APN)[apsd]
Whereas the Local notification center was process-wide and the Distributed notification center
was system wide, APN is Internet-borne, and thus world-wide.
1 | ps -ef | grep apsd |
/Library/Application Support/ApplePushService -> aps.db
User Notifications -> must have a noticeable GUI presence
/sbin/emond (MacOS) -> useful for use-generated events
Apple Events (MacOS) -> similar to Windows’ DCOM
-> AppleScript
chapter 6
The Binary Format
/usr/lib/dyld
arch -> posix_spawnattr_setbinpref_np
MH_MAGIC_64
MH_CIGAM_64
__PAGEZERO exec onlyh
__TEXT both writable and executable, whereas *OS does not
__DATA/__DATA_CONST
__LINKEDIT
Mach-O FileTypes
MH_EXECUTABLE/MH_DYLINKER
MH_DYLIBD/MH_BUNDLE/MH_KEXT_BUNDLE
MH_OBJECT/MH_CORE/MH_DSYM
dsymutil
Header Flags
MH_ALLOW_STACK_EXECUTION/MH_NO_HEAP_EXECUTION
vm.allow_stack_exec/vm.allow_heap_exec
Load commands known to XNU
LC_SEGMENT[_64]
LC_UUID -> proc_uuid_poliy_lookup
LC_UNIXTHREAD/LC_MAIN
LC_LOAD_DYLINKER
LC_CODE_SIGNATURE
LC_ENCRYPTION_INFO[_64]
Load commands known to dyld
LC_SYMTAB/LC_DYSYMTAB
The library load commands and SUB_ commands
LC_LAZY_LOAD_DYLIB/LC_LOAD_WEAK_DYLIB/LC_LOAD_UPWARD_DYLIB/LC_REEXPORT_DYLIB
LC_RPATH/LC_DYLD_INFO/LC_DYLD_ENVIRONMENT
Load commands serving litte or no purpose
LC_VERSION_MIN_MACOSX/LC_BUILD_VERSION
LC_DATA_IN_CODE/LC_FUNCTION_STARTS
chapter 7
In the Darkness, Bind Them:dyld internals
CoreSymbolicaton.frameworkprivate]
__dyld_start -> dyldStartup.s
dyldbootstrap::start
-> mach_init/mach_task_self/pthread_set_self
1 | // envp[] extension, not standard |
exec_add_apple_strings()
dyld::_main()
csops(2) system call
dyld shared cache
DYLD_PRINT_LIBRARIES=1 is useful to display image loading
1 | # man dyld |
[not for restrited binary https://qa.1r1g.com/sf/ask/2773668061/]
_dyld_stub_binder -> __DATA.__nl_symbol_ptr
Bind Info:__DATA.__got and __DATA.__nl_symbol_ptr
Lazy Info: __DATA.__la_symbol_ptr
Weak Info
Rebasing Opcodes
ASLR
1 | <mach-o/loader.h> |
The CoreSymbolication.framework
1 | <mach-o/nlist.h> |
liblorgnette
man symbols
Interposing
DYLD_INTERPOSE
__DATA.__interpose
–> Linux LD_PRELOAD/dlsym(RTLD_NEXT, …)
MacOS’s libgmalloc(3)
DYLD_PRINT_INTERPOSING
dyld_dynamic_interpose
1 | _dyld_shared_cahce |
Overriding the SLC
DYLD_SHARED_REGION
Darwin17:dyldv3
macos 10.13
DYLD Closures
Programmatic manipulation of Mach-o objects
libmacho.dylib
1 | <mach-o/getsect.h> |
libdyld.dylib
dl* APIS dlopen/dladdr/dlsym/dlclose
dldl* specific APIs _dyld_image_count
libdscsym.dylib
machlibd
Remote inspection of dyld state
task_set_dyld_info()
Debugging and tracing dyld operations
1 | strings /usr/lib/dyld | grep ^DYLD_ | sort -u |
DYLD_PRINT_STATISTICS
undocumented
x DYLD_PRINT_APIS_APP
x DYLD_PRINT_WEAK_BINDINGS
x DYLD_PRINT_CODE_SIGNATURES
DYLD_PRINT_NOTIFICATIONS
DYLD_PRINT_INTERPOSING
x DYLD_PRINT_STATISTICS_DETAILS
x DYLD_PRINT_WARNINGS
x DYLD_PRINT_LIBRARIES_POST_LAUNCH
Kdebug codes
task_register_dyld_image_infos
task_unregister_dyld_image_infos
task_get_dyld_image_infos
task_register_dyld_shared_cache_image_info
task_register_dyld_set_dyld_state
task_register_dyld_get_process_state
chapter 8
Parts of the process: Threads and GCD
Processes
1 | top -H # Linux |
Process Lifecycle
system calls affecting the process lifecycle
exit/fork/vfork
wait4[_nocancel]
waitid[_nocancel]
posix_spawn
execve
mac_execve
vfork -> “quick fork” without any memory copying
POSIX has since been expanded to allow the more modern posix_spawn(2) system call,
which combines the vfork(2) and execve(2) call into one, more efficient operation.
posix_spawnattr_set* APIs
Process Identifiers and Grouping
getpid/getpgid/getpgrp/getppid
setpgrp/setpgid/setsid
Coalitions (Darwin 14+)
Credentials
uid/groups/tid
Personae (*OS
)
Signals
kill/sigaction
sigprocmask/sigpending
sigaltstack/sigsuspend/sigreturn
sigwait
pthread_kill -> pthread_cancel
Pthreads
Non-POSIX extensions _np
pthread_cond_signal_thread_np
pthread_create_suspended_np
Thread lifecycle
Introspection -> pthread_introspection_hook_install
Thread Specific Data (TSD)
Thread Local Variables
__DATA.__thread_vars/__DATA.__thread_bss
Thread Priorities and QoS Classees
Priority/IO Throughput/CPU Throughput
Timer Latency/Network Traffic
Process, Task & Thread Policies
Process Policies -> process_policy
proc_rlimit_control
iopolicysys
Task Policies -> task_policy
Thread Policy
THREAD_BACKGROUND_POLICY -> *OS
Thread level QoS -> bsdthread_ctl
psynch -> pthread synchronization
Ulocks(Darwin 17+) -> os_unfair_lock
os_atomic_cmpxchg2o/ulock_wait/ulock_wake
-> turnstile(Darwin 18)
Interiude: kevents and kqueues
Grand Central Dispatched
thread pool with scheduler
1 | DISPATCH_INVOKE_STEALING = 0x00000001, |
dispatch_queue_create
Blocks -> like coroutine?
Queues -> scheduler
dispatch_suspend/dispatch_resume
dispatch_sync/dispathc_async
Dispatch queues are well integrated into CFRunLoops.
Pure GCD programs,(no other CFRunLoop or UI main thread), call dispatch_main
Queue Attributes
Queue maintennace -> kernel work queues
Dispatching blocks
Continuations -> CPS? [https://www.zhihu.com/question/61222322 什么是「continuation」?]
A key concept driving GCD is coninuations.The term refers to a stateless function,
which can be resumed immmediatelt, and requires not stack space.
1 |
Dispatch objectsdispatch_object_create
block/data/group
io/mach/mach_msg
pthread_root_queue
queue/semaphore(sync)/source(event)
[https://github.com/apple-oss-distributions/WTF/blob/main/wtf/cocoa/WorkQueueCocoa.cpp]
os_mpsc_queue(Multi Producer Single Consumer)
#pragma mark os_mpsc_queue
Dispatch Sources
Dispatch sources hide their underlying implementation - kevents - from their callers.
DISPATCH_INTROSPECTION -> /usr/lib/system/introspection
dispatch_introspection_hooks_install
kdebug codes -> DBG_LIBDISPATCH
chapter 9
Process Virtual Memory
On the same page
Copy-on-Write(CoW)
Paging Free/Active/Inactive/Speculative/Wired
vm_stat(1) -> host_statistics64
Memory Management APIs
- POSIX Memory APIs
madvise/m[un]lock/msync[_nocanel]mprotect/m[un]map - Mach memory APIS
BSD system calls -> Mach-base impl [vm_region->mach_vm_region]
vm_region/vm_allocate/vm_deallocate/vm_protect
vm_read/vm_read_list/vm_write/vm_copy/vm_read_overwrite
vm_msync/vm_behavior_set/vm_map/vm_remap/vm_machine_attribute - Memory Tags
vmmap
libmalloc
The scalable (default) zone
Apple M1 Mac Mini
MALLOC_TINY 1024K 16B
MALLOC_SMALL 8192K 512B
MALLOC_MEDIUM 128M
MALLOC_NANO 512M
MALLOC_LARGE PAGE_SIZE
malloc_create_zone -> malloc_zone_t
-> mvm_allocate_pages -> mach_vm_map
malloc_register_zone/malloc_zone_malloc
[https://www.jianshu.com/p/f939cb8c4635 iOS底层系列08 – malloc与calloc源码分析]
Zone APIs
#include <malloc/malloc.h>
1 | extern malloc_zone_t *malloc_zone_from_ptr(const void *ptr); |
In the Zone
The Magazine layer
The Hoard allocator
Magazines
The Nanov2 Zone (Darwin 18+)
The Purgeable Zone
libcache
Debugging
MallocHelp=1
kdebug codes -> MallocTracing -> DBG_UMALLOC
SamplingTools
aots/filtercalltree
heap/leaks/malloc_history
sample/stringdups/symbols/vmmap
1 | MallocStackLogging=1 ./cpp20 |
libplatform(os_alloc_once)
Swap
Dynamic paging (MacOS)
swapfile_pager
Compressed memory
vm_stat(1) or memory_pressure(1)
1 | vm_stat | grep ompr |
Memory Pressure
MacOS:MemoryStatus*OS
:Jetsam
The JetsamEvent reports
1 | defaults read /System/Library/LaunchDaemons/com.apple.jetsamproperties.Mac.plist |
vm_pressure_monitor
EVFILT_VM -> kevent (util Darwin 16)
-> DISPATCH_SOURCE_TYPE_MEMORYPRESSURE
libMalloc pressure handlers (Darwin 16)
didReceiveMemoryWarning
iOS: mmaintenanced
chapter 10
CFRun, RunLoopRun: The Darwin Runtime Environments
[Core]Foundation
CF* objects
CFString/CFNumber/CFAllocator
CFMachPort/CFMessagePort
CFNotificationCenter
CFPasteboard/CFRunArray
CFRunLoop/CFRunLoopObserver
CFRunLoopSource/CFRunLoopTimer
CFSocket/CFURL/CFStringTokenizer
CFUUID/CFXMLParser/CFTree
-> CFRuntimeClass
Run Loops
The runtime provides one CFRunLoop object per thread.
CFRunLoopRun -> NSRunLoop
Run loop sources
CFFileDescriptor and CFSocket
CFMachPort/CFMessagePort
CFUserNotification
CFRunLoopTimer
Run Loop observers
CFRunLoopObserverCreate
Putting it all together - RunLoop,Run
Objective-C
Objective-C Library initialization
libSystem.B.initializer -> libdispatch_init
-> objc_init (environ_init/tls_init/lock_init/execption_init
Register dyld Handlers)
Type Encoding
Sending messages
objc_msgSend
Message Passing
Reflection -> class_getName/method_getName
Methid Swizzling
Using DTrace
1 | objc$target:::entry |
Swift
chapter 11
The Message is the Mediaum: Mach IPC
A litte history
XNU -> NeXTSTEP -> Mach -> Mach messaging
port -> port right [SEND/SEND_ONCE/RECEIVE/DEAD_NAME]
mach_port_allocate/
bootstrap_register/bootstrap_lookup/bootstrap_check_in
View Mach Port
Sending and receiving messages
mach_msg/mach_msg_overwrite
The Mach Interface Generator
The original SunRPC use rpcgen,
Windows’ RPC uses midl, Android use iadl -
and Mach uses the Mach Interface Generator, commonly referred to as MID.
1 | kdv all | grep MID |
_NDR_RECORD
chapter 12
Mach Primitives
Ports as object abstactions
- The Host port
host_info/host_kernel_version
host_processor_info
host_get_io_master
host_get_clock_service
host_statistics64
mach_zone_info
mach_memory_info
mach_zone_info_for_zone - The Host_Priv port
host_get_boot_info/host_reboot - Task ports
task_for_pid/pid_for_task
task_inspect (Darwin 17)
vm_map/mach_vm -> like Windows’ [Read/Write]ProcessMemory
-> ptrace Linux and other UNIX
With great power…
ps(1) top(1) com.apple.system-task-ports - Task special ports
- Thread Ports
task_threads/processor_set_threads
processor_info/processor_set_things
processor_set_statistics/processor_set_info
Execption Ports
ReportCrash(8)
Exception codes and subcodes
<mach/exception_types.h>
mach_msg_server
task_set_exception_ports/host_set_exception_ports
chapter 13
The Alpha and the Omega: Launchd
The daemon’s many roles - process launcher and reaper, system monitor,
job scheduler, and bootstrap server - make it a focal point for a large number of
system workflows, and thus important to understand.
Born Again
launchd 10.4 <- mach_init(Mach subsystem)/init(BSD subsystem)
atd(scheduled execution) at/atq/atrm/batch
crond (scheduled recurring execuution)
inetd/xinetd
Triggered execuation
WatchPaths
IOKit Notifications
Other (third paryt) events
Interlude: UserEventAgent
Agents and Daemons
Agents are daemons that are started only when a user logs on.
Unlike other daemons, they may interface with the user, and may in fact have a GUI.
launchctl
xpc_bootstrap_pipe
xpc_pipe_routine
The XPC bootstrap pipe
Service/Doamin/Event/Bootstrap/VProc/Launch/Jetsam
liblaunch.dylib -> launch_msg
ServiceManagement.framework deprecated
chapter 14
X is not Procedure Call: XPC Internals
Design Rationle
Apple touts XPC as providing “a lightweight mechnism for basic interprocess communcation
intergrated with Grand Central Dispatch(GCD) and launchd”.
XPC APIs
xpc* -> libxpc.dylib
NSXPCConnection/NSXPCListener
XPC Transport APIs
xpc_pipe
RemoteXPC.framework
-> libnetwork’s nw_connection
/usr/libexec/remotectl
netstat/nettop
- Tracing Remote XPC with XPoCe 2
XCP service -> xpc_main - Tracing xpcproxy with supraudit(j)
XPC caches -> XPC bundles - Tracing XPC
kdebug/dtrace/XPoCe
chapter 15
Follow Me: Tracing & Debugging
XCode’s Instruments.app provides a fine example of just how powerful
some of these (notablt, DTrace and Kdebug) are.
chapter 16
Het-work: Darwin Networking
- POSIX aio
aio_write - Native aio (Linux libaio)
io_submit
aio io_uring interface - Windows IOCP
- macOS GCD aio
sendfile
In Linux kernels before 2.6.33, out_fd must refer to a socket. Since
Linux 2.6.33 it can be any file. If it is a regular file, then send‐
file() changes the file offset appropriately.