我向您介绍Darling Project博客中我文章的翻译。 对所用概念的帮助不大:Darwin-一种基于macOS,iOS和Apple的其他操作系统的开源操作系统; Mach-O是达尔文使用的可执行文件和库的二进制格式; dyld-达尔文用于下载Mach-O文件的动态引导程序; dylib是一个可动态加载的库(通常具有扩展名.dylib
)。

Darling Project的目标是使macOS应用程序能够在Linux上运行,并且能够以Mach-O格式下载二进制文件的能力是实现该目标的关键步骤之一。
最初,Darling围绕其自身的Mach-O加载器实现以及在高级Darwin API与Linux对应对象之间广播调用的想法而构建。 从那时起,我们的重点已转移到在越来越孤立的Darwin容器中运行代码。 自从我们改用Darling的内部组件使用Mach-O以来,我们已经能够使用Apple的原始模型,并构建了许多其他开源的Darwin组件。 我们仍然需要一个简单的Mach-O引导程序来引导dyld本身。
Mach-O和Mach本身可能是达尔文最著名的标志,Apple提供的各种库和框架广泛使用了Mach-O格式的许多晦涩功能。 这使得与Mach-O一起工作成为开发Darling时最重要和值得注意的任务之一。 从实施本地Mach-O加载程序到组装达尔文组件(首先以特殊的ELF文件的形式,现在以真正的Mach-O的形式)-我们需要比普通人更深入地了解Mach-O的内部结构。达尔文平台的开发人员。
我们完成了本介绍,然后继续讨论Mach-O格式可以为我们提供的一些技巧。
安装名称
在Windows和Linux上,动态库由它们的名称(例如libc.so
)引用,此后,动态链接程序的任务是在标准库目录之一中查找具有匹配名称的库。 达尔文立即改为使用库文件的(几乎)完整路径,该路径称为该库的安装名称。 大概是这样做是为了防止dylib [dylib劫持]的替代 -一种攻击,其中将伪造的dylib放置在目录中,动态链接程序将在比实际真实目录早的位置找到它,从而允许伪造的dylib代表程序执行任意代码,因此确信了这一点。 dylib下载。
不仅可执行文件和库存储了其依赖项的完整安装名,而且Mach-O依赖项本身也“知道”了自己的安装名。 实际上,链接器就是通过这种方式来了解要用于依赖项的安装名称:它从依赖项本身中读取它们。
链接dylib时,可以使用选项ld -install_name
或-dylib_install_name
来指定其安装名称:
$ ld -o libfoo.dylib foo.o -install_name /usr/local/lib/libfoo.dylib
现在,当您将另一个Mach-O文件(例如libbar.dylib
)链接到libfoo.dylib
,ld将在libbar
依赖项libbar
写入libfoo安装名称- /usr/local/lib/libfoo.dylib
libbar
/usr/local/lib/libfoo.dylib
libbar
/usr/local/lib/libfoo.dylib
libbar
,这就是dyld所在的位置。会在运行时查找libfoo
。
对于系统库而言,使用完整路径已经足够好了,事实上,这些系统库已安装在文件系统中以前已知的位置。 但是使用库作为应用程序捆绑包的一部分时,就会出现问题。 尽管每个应用程序都可以假定将其安装在/Applications/AppName.app
,但是一般来说,这意味着应用程序程序集是可移植的,并且可以在文件系统中自由移动,因此此类程序集中的特定库路径无法提前知道。
为了解决此问题,达尔文允许安装名称以@executable_path
, @loader_path
或@rpath
-不是绝对的,而是指示相对于主要可执行文件路径,“加载”路径(可执行文件或库,分别直接取决于此库)或相对于主要可执行文件定义的路径列表。 @executable_path
和@loader_path
工作没有其他复杂性,但是如果至少一个依赖项(或它们的传递性依赖项)具有使用@rpath
的设置名称, @rpath
在使用ld -rpath
选项链接可执行文件时,必须显式设置@rpath
。倍您需要多少:
$ ld -o runme -rpath @executable_path/../Frameworks -rpath @executable_path/../bin/lib
(rpath概念在某种程度上破坏了众所周知的库路径的原始概念,并打开了 dylib欺骗攻击的可能性。我们可以假设这会使与安装名称相关的所有事情都变得毫无用处。)
循环依赖
当一个项目的源代码占用多个文件时,如果这些文件相互依赖是完全正常的。 只要将所有这些文件编译为单个二进制文件(可执行文件或库),此方法就可以正常工作。 当几个动态库相互依赖时,不起作用。
您可能会争辩说,与其重新使用动态库之间的循环依赖关系,不如重新设计项目体系结构,这一点我同意。 但是,如果有苹果公司的典型代表,那就是他们永远不会停止思考并正确地做事。 取而代之的是,他们把拐杖和把戏摆在彼此之上。 在这种情况下,对于Darling,我们需要使循环依赖项起作用,因为各种libSystem libSystem
(例如libsystem_dyld
, libsystem_kernel
和libsystem_pthread
)都相互依赖。 (直到最近,由于在Cocotron中实现了Core OpenGL的方式,我们还不得不循环链接诸如AppKit,Core Graphics和Core OpenGL之类的Cocoa框架,但是我们重新设计了 Core OpenGL的实现架构,并且能够摆脱这种循环依赖项。)
原则上,循环依赖项应该可以正常工作:动态链接器已经知道如何仅加载一次每个库,因此无限递归不会有问题。 问题是不能简单地链接这样的库,因为每个链接程序调用仅创建一个库,并且在链接任何二进制文件时,必须将已链接的所有依赖项都转移到链接器。 我们必须首先链接我们的一个库,目前其他库还没有准备好,因此我们将无法将它们传输到链接器。
这里的技巧是将这些库的某些(或为简单起见,全部)链接两次 。 第一次,告诉链接程序忽略缺少的依赖关系,实际上,不要传递依赖关系:
$ ld -o libfoo.dylib foo.o -flat_namespace -undefined suppress $ ld -o libbar.dylib bar.o -flat_namespace -undefined suppress
(有关-flat_namespace
请参见下文。)
当然,如果尝试直接使用生成的dylib,则会在运行时出现动态链接错误。 相反,请再次链接这些库,并将生成的dylib作为依赖项传递:
$ ld -o libfoo.dylib foo.o libbar.dylib $ ld -o libbar.dylib bar.o libfoo.dylib
这次,链接器会看到所有字符,因此我们不会告诉他忽略错误(如果确实丢失了某些字符,则会出现错误)。
尽管某些(如果不是全部)库链接到其依赖项的“错误”副本,则dyld将在运行时看到正确的版本。 为此,请确保每个库的两个副本都具有相同的安装名称。
这里的另一个细节是初始化顺序。 任何代码都可以使用__attribute__((constructor))
编译器magic命令声明初始化程序函数(此类初始化程序的列表位于Mach-O文件的__mod_init_func
节中)。 当在调用main()
之前加载它们所在的二进制文件时,dyld会调用这些函数。 通常,每个库的初始化器在其依赖项的初始化器之后执行,因此每个初始化器都可以期望依赖项库已被初始化并可以使用。 当然,对于循环依赖性不能保证。 dyld将以某种顺序执行其初始化程序。 您可以将依赖性标记为向上依赖性以自定义此顺序。 dyld将最后初始化某人已将其标记为依赖项的库。 因此,要使libfoo
在libbar
之后初始化,请像这样链接它们:
$ ld -o libfoo.dylib foo.o libbar.dylib $ ld -o libbar.dylib bar.o -upward_library libfoo.dylib
为了使一切更方便,我们有一个名为add_circular
的Darling CMake函数,它可以解决所有困难,并允许您像这样简单且声明性地使用它:
set(DYLIB_INSTALL_NAME "/usr/lib/system/libdispatch.dylib") add_circular(libdispatch_shared FAT SOURCES ${dispatch_SRCS} SIBLINGS system_c system_kernel system_malloc system_blocks system_pthread system_dyld system_duct unwind platform compiler_rt UPWARD objc )
两级字符名称空间
Mach-O中的符号表不仅存储符号名称,它们还“记住”从哪个库(或可执行文件)中提取符号。 换句话说,符号名称存在于由二进制定义它们的名称空间中。 因此,“二级命名空间”(另一级表示符号名称本身)。
引入了两级名称空间,以防止符号名称冲突。 通常,如果多个库用相同的名称定义字符,则在链接期间会出现错误; 但是,如果您在运行时加载库(例如插件),或者在链接时和运行时库的版本不同时,这可能不起作用。 对于使用两级名称空间的库而言,这不是问题-它允许多个库以相同的名称定义字符而不会产生冲突。
可以通过恢复使用“平面名称空间”来关闭两级名称空间(原因之一是,使用两级名称空间意味着在链接期间必须允许每个字符,因此-undefined_suppress
需要平面名称空间,例如我们在上面看到)。 Ld具有两个标志,这些标志使您可以在链接期间禁用两级名称空间: -flat_namespace
仅影响一个Mach-O文件; -force_flat_namespace
仅适用于可执行文件,而不是库,并强制整个过程使用flat命名空间。 另外,您可以通过设置环境变量DYLD_FORCE_FLAT_NAMESPACE
来强制dyld在运行时使用平面名称空间。
使用两层名称空间的一个功能是,您始终必须将每个Mach-O显式链接到它所依赖的所有库和框架。 例如,如果链接到AppKit,则不能仅使用Foundation。 您必须明确链接到她。 另一个功能是,作为库或框架的作者,您不能像习惯那样随意地沿依赖关系链自由移动符号“ down”的实现(例如,不能将代码从AppKit移至Foundation)。 为此,Mach-O,ld和dyld具有几个附加功能,即子库 , 字符的 重新导出和元字符 。
子库
子库-允许一个库(称为立面库[umbrella库]或伞形库[umbrella库])将其部分功能的实现委派给另一个库(称为子库[sub-library])的机制; 或者,如果您从另一侧看,则允许该库公开重新导出另一个库提供的符号。
再次使用它的主要地方是libSystem
及其在/usr/lib/system
子库; 但是它可以与任何一对库一起使用:
$ ld -o libfoo.dylib foo.o -lobjc -sub_library libobjc
与仅链接到该库相比,影响此操作的唯一因素是将LC_REEXPORT_DYLIB
命令写入到生成的文件中,而不是通常的LC_LOAD_DYLIB
(包括链接期间来自子库的符号不会复制到伞状库,因此它甚至不必如果以后将新字符添加到子库,请链接)。 在运行时, LC_REEXPORT_DYLIB
工作LC_REEXPORT_DYLIB
也类似于LC_LOAD_DYLIB
:dyld将加载子库并使其余字符可用(但与LC_LOAD_DYLIB
不同,就两级命名空间而言,字符将来自伞形库)。
LC_REEXPORT_DYLIB
真正区别在于,当您将另一个库链接到libfoo
时ld会做什么:ld不仅会在传递给它的所有对象和dylib文件中查找符号,还会打开并查看重新导出的子库(在此示例中) libobjc
示例)。
他怎么知道在哪里找她? 保存在libfoo.dylib
的唯一东西是安装名称libobjc.dylib
,因此ld希望找到它。 这意味着必须将该库安装到位,然后才能用作其他任何子库。 这对于像libobjc
这样的系统库来说效果libobjc
,但是如果您尝试重新导出自己的子库,可能会非常不便或完全不可能。
为了解决此问题,ld提供了-dylib_file
选项,该选项允许您指定在链接期间要使用的其他dylib路径:
$ ld -o libfoo.dylib foo.o -reexport_library /path/to/libsubfoo.dylib $ ld -o libbar.dylib bar.o libfoo.dylib -dylib_file @executable_path/lib/foo/libsubfoo.dylib:/path/to/libsubfoo.dylib
尽管libSystem
和其他一些系统库重新导出了它们的子库, -dylib_file
当链接macOS上的每个可执行文件时,您不必使用-dylib_file
。 这是因为已经根据系统库的安装名称安装了系统库。 但是,在Linux上构建Darling时,我们必须向每个ld调用传递一些-dylib_file
选项(以及其他公共参数)。 我们通过使用add_darling_library
, add_darling_executable
以及其他函数时会自动应用的特殊功能来执行此操作。
重新导出字符
有时一个库可能需要从另一个库中重新导出某些字符,但不是一次全部导出。 例如,Core Foundation正在NSObject
,出于兼容性的考虑, NSObject
在最新版本中是在Objective-C运行时内部实现的。
(如果您对为什么NSObject
曾经在Core Foundation中而不是在Foundation中感兴趣,那是因为免费转换 [免费电话桥接,直接在对应的Core Foundation和Foundation类型之间进行转换的能力, [额外的转换],要求在Core Foundation中实现Core Foundation上类型的私有包装类(例如__NSCFString
);作为Objective-C对象,它们必须从NSObject
继承。到另一个,将NSObject
及其所有继承人留在Foundation和循环中 esky将Core Foundation和Foundation链接在一起,但是Apple决定将这些帮助程序私有类与NSObject
一起迁移到Core Foundation,在Darling中,我们以相同的方式维护兼容性。)
您可以使用ld的-reexported_symbols_list
选项传递要-reexported_symbols_list
的字符列表:
$ echo .objc_class_name_NSObject > reexport_list.exp $ ld -o CoreFoundation CFFiles.o -lobjc -reexported_symbols_list reexport_list.exp
尽管重新导出某些符号听起来与重新导出所有符号非常相似,但是实现此符号的机制与子库的工作方式非常不同。 不使用特殊的LC_*_DYLIB
命令; 而是在名称表中插入一个特殊的间接符号 (由N_INDIR
标志指示),其行为类似于该库中定义的符号。 如果库本身使用此符号,则该符号的第二个 “不确定”副本将出现在名称表中(因为它发生时没有任何重新导出)。
使用字符的显式重新导出时要记住的一件重要的小事情是,您很可能需要针对不同的体系结构重新导出具有不同名称的字符。 确实,Objective-C的[名称处理约定]命名约定和i386和x86-64的Objective-C二进制接口[ABI]是不同的,因此在i386上,您只需要.objc_class_name_NSObject
,在x86-64上- _OBJC_CLASS_$_NSObject
, _OBJC_IVAR_$_NSObject.isa
和_OBJC_METACLASS_$_NSObject
。 使用子库时无需考虑,因为每种架构的所有自动可用符号都会自动重新导出。
大多数用于Mach-O的工具都透明地处理“厚”或通用二进制文件(Mach-O文件包含用于多个体系结构的多个sub-Mach-O)。 Clang可以编译具有所有请求的体系结构的通用二进制文件,dyld从dylib选择要加载的体系结构,查看可执行文件支持的体系结构,并且ld,otool和nm之类的工具与对应于计算机体系结构的体系结构一起工作(即(x86-64),除非您明确要求使用特殊标志的其他体系结构。 , - , – , , .
. ld , , dylib- lipo:
$ ld -o CF_i386.dylib CFFiles.o -arch i386 -lobjc -reexported_symbols_list reexport_i386.exp $ ld -o CF_x86-64.dylib CFFiles.o -arch x86_64 -lobjc -reexported_symbols_list reexport_x86_64.exp $ lipo -arch i386 CF_i386.dylib -arch x86_64 CF_x86-64.dylib -create -output CoreFoundation
Darling CMake- add_separated_framework
, lipo, CMake- Core Foundation :
add_separated_framework(CoreFoundation CURRENT_VERSION SOURCES ${cf_sources} VERSION "A" DEPENDENCIES objc system icucore LINK_FLAGS
- – , , Apple , .
Mach-O- macOS, , -mmacosx-version-min=10.x
( iOS, tvOS, watchOS , Apple ). ; , AVAILABLE_MAC_OS_X_VERSION_10_13_AND_LATER
C++ libstdc++
( GNU) libc++
( LLVM). , Mach-O. , ld -macosx_version_min
( m
), Mach-O- LC_VERSION_MIN_MACOSX
( dyld, , ).
, ld -macosx_version_min
, - Mach-O- . - – , $ld$
, ld, , : , . $ld$$$
.
os10.5
, - – , Mach-O- , ;
add
, hide
, install_name
compatibility_version
, ld ,
,
( ) , .
, , , ; , -, libobjc
, NSObject
, macOS:
$ld$hide$os10.0$_OBJC_CLASS_$_NSObject $ld$hide$os10.0$_OBJC_IVAR_$_NSObject.isa $ld$hide$os10.0$_OBJC_METACLASS_$_NSObject $ld$hide$os10.1$_OBJC_CLASS_$_NSObject $ld$hide$os10.1$_OBJC_IVAR_$_NSObject.isa $ld$hide$os10.1$_OBJC_METACLASS_$_NSObject $ld$hide$os10.2$_OBJC_CLASS_$_NSObject $ld$hide$os10.2$_OBJC_IVAR_$_NSObject.isa $ld$hide$os10.2$_OBJC_METACLASS_$_NSObject $ld$hide$os10.3$_OBJC_CLASS_$_NSObject $ld$hide$os10.3$_OBJC_IVAR_$_NSObject.isa $ld$hide$os10.3$_OBJC_METACLASS_$_NSObject $ld$hide$os10.4$_OBJC_CLASS_$_NSObject $ld$hide$os10.4$_OBJC_IVAR_$_NSObject.isa $ld$hide$os10.4$_OBJC_METACLASS_$_NSObject $ld$hide$os10.5$_OBJC_CLASS_$_NSObject $ld$hide$os10.5$_OBJC_IVAR_$_NSObject.isa $ld$hide$os10.5$_OBJC_METACLASS_$_NSObject $ld$hide$os10.6$_OBJC_CLASS_$_NSObject $ld$hide$os10.6$_OBJC_IVAR_$_NSObject.isa $ld$hide$os10.6$_OBJC_METACLASS_$_NSObject $ld$hide$os10.7$_OBJC_CLASS_$_NSObject $ld$hide$os10.7$_OBJC_IVAR_$_NSObject.isa $ld$hide$os10.7$_OBJC_METACLASS_$_NSObject
, , , , .
dyld – [symbol resolvers], . , , , dyld , .
ld, . .symbol_resolver
:
; foo _foo1: movl 1, %eax ret _foo2: movl 2, %eax ret .symbol_resolver _foo ; - call _condition jz .ret_foo2 movq _foo1, %rax ret .ret_foo2: movq _foo2, %rax ret ; , _foo ; , , ; . .global _foo _foo:
C , , C:
static int foo1() { return 1; } static int foo2() { return 2; } int foo() {
( _foo
foo
, Darwin C, . , Mach-O Darling, ELF-, .)
_foo
, ( ), foo()
foo_resolver()
, :
void *foo() { __asm__(".symbol_resolver _foo"); return condition() ? &foo1 : &foo2; }
, – - , foo()
, ( int
-). , , : dlsym("_foo")
_foo
– , , , – . , , , foo()
_foo
.
. Apple libplatform
:
#define _OS_VARIANT_RESOLVER(s, v, ...) \ __attribute__((visibility(OS_STRINGIFY(v)))) extern void* s(void); \ void* s(void) { \ __asm__(".symbol_resolver _" OS_STRINGIFY(s)); \ __VA_ARGS__ \ } #define _OS_VARIANT_UPMP_RESOLVER(s, v) \ _OS_VARIANT_RESOLVER(s, v, \ uint32_t *_c = (void*)(uintptr_t)_COMM_PAGE_CPU_CAPABILITIES; \ if (*_c & kUP) { \ extern void OS_VARIANT(s, up)(void); \ return &OS_VARIANT(s, up); \ } else { \ extern void OS_VARIANT(s, mp)(void); \ return &OS_VARIANT(s, mp); \ })
, – – ( kUP
, commpage ), , , [spinlock]. , .
Darling : Mach-O- ELF- Linux, [host, , Darling] – , libX11
libcairo
.
ELF- – libelfloader
, ELF, , ld-linux, dyld Linux, ld-linux ELF-. libelfloader
Mach-O /usr/lib/darling/libelfloader.dylib
Darwin-chroot-; , Darwin-.
, libelfloader
Mach-O ELF. ( _elfcalls
), libSystem
, Darwin , ELF- Linux. «» Darwin Linux – , C ( libSystem_c
glibc
, ).
ELF- Darwin, - libelfloader
API _elfcalls->dlsym_fatal(_elfcalls->dlopen_fatal("libX11.so"), "XOpenDisplay")
. , wrapgen , ELF- , , The Cocotron – Linux – . wrapgen ELF- (, libX11.so
), :
#include <elfcalls.h> extern struct elf_calls* _elfcalls; static void* lib_handle; __attribute__((constructor)) static void initializer() __attribute__((destructor)) static void destructor() void* XOpenDisplay()
Mach-O- /usr/lib/native/libX11.dylib
, Mach-O- , libX11.so
, Mach-O. , CMake- wrap_elf
, wrapgen, Mach-O- /usr/lib/native
: wrap_elf(X11 libX11.so)
libX11
, Mach-O-.
Linux . , Darling , Darwin Linux, . Darling – Darwin ( , Darwin); , , , Darwin, libSystem
, dyld, XNU launchd, , , commpage. , libsystem_kernel
, , Linux, «» Darwin- – Linux GNU/Linux . Linux- , Linux ( X server) , [witnessing a magic trick] – libelfloader
, wrapgen, , . , , , , , .
- , Mach-O-, ld . ( , – , Apple, , .)
, , , , [order file], ld :
$ ld -o libfoo.dylib foo.o -order_file foo.order
-reexported_symbols_list
, , -order_file
, :
symbol1 symbol2 # . # # , , # ( C) # . foo.o: _static_function3 # , , # ; # # lipo, # . i386:symbol4
( , , ) «» . , , , , .subsections_via_symbols
, Mach-O- , , , , .
, Apple – libdispatch
. libdispatch
, «OS object», , . Objective-C, libdispatch
( Core Foundation), libdispatch
- Objective-C- , Objective-C-. , dispatch_data_t
NSData *
API Cocoa ( ).
, , Objective-C- OS object vtables . , DISPATCH_OBJECT_TFB
, , Objective-C libdispatch
-, isa
vtable
- dispatch_object
object
:
#define DISPATCH_OBJECT_TFB(f, o, ...) \ if (slowpath((uintptr_t)((o)._os_obj->os_obj_isa) & 1) || \ slowpath((Class)((o)._os_obj->os_obj_isa) < \ (Class)OS_OBJECT_VTABLE(dispatch_object)) || \ slowpath((Class)((o)._os_obj->os_obj_isa) >= \ (Class)OS_OBJECT_VTABLE(object))) { \ return f((o), ##__VA_ARGS__); \ }
, , libdispatch
.
( ) – DYLD_INSERT_LIBRARIES
, dyld Mach-O- . , , , DYLD_FORCE_FLAT_NAMESPACE
.
, , - . ( ), dlsym()
RTLD_NEXT
, :
int open(const char* path, int flags, mode_t mode) { printf(" open(%s)\n", path); // " " if (strcmp(path, "foo") == 0) { path = "bar"; } int (*original_open)(const char *, int, mode_t); original_open = dlsym(RTLD_NEXT, "open"); return original_open(path, flags, mode); }
, dyld , dyld- [dyld iterposing]. Mach-O- __interpose
, dyld , – .
, – , __interpose
– [implicit interposing]. , __interpose
( ), dyld . , dyld- , - . , dyld , - , - ( Mach-O-):
static int my_open(const char* path, int flags, mode_t mode) { printf("Called open(%s)\n", path); // " " if (strcmp(path, "foo") == 0) { path = "bar"; } // , // open() my_open(). return open(path, flags, mode); } // __interpose __attribute__ ((section ("__DATA,__interpose"))) static struct { void *replacement, *replacee; } replace_pair = { my_open, open };
, – – Mach-O- - [relocation table]. , dyld ( ), .
, dyld_dynamic_interpose
, :
typedef struct { void *replacement, *replacee; } replacement_tuple; extern const struct mach_header __dso_handle; extern void dyld_dynamic_interpose(const struct mach_header*, const replacement_tuple replacements[], size_t count); void interpose() { replacement_tuple replace_pair = { my_open, open }; dyld_dynamic_interpose(&__dso_handle, &replace_pair, 1); }
, , , .
DYLD_INSERT_LIBRARIES
dyld- Objective-C, C, - , Objective-C- ( IMP
), Objective-C , method swizzling ( isa swizzling ).
Darling xtrace, .
Darwin Darwin ( – BSD Mach- [Mach traps]). libsystem_kernel
, ABI userspace. Darling, libsystem_kernel
Darwin Linux Darling-Mach , Linux, Mach .
strace, Linux, , Linux-; strace Darwin, Darling, Linux, Darwin ( Linux, ELF- ). , Darwin Linux , , Darwin – , – .
, xtrace . strace, , ptrace()
API, xtrace . DYLD_INSERT_LIBRARIES=/usr/lib/darling/libxtrace.dylib
, - [trampoline functions] , . xtrace , strace, , , :
Darling [~]$ xtrace arch <......> [223] mach_timebase_info_trap (...) [223] mach_timebase_info_trap () -> KERN_SUCCESS [223] issetugid (...) [223] issetugid () -> 0 [223] host_self_trap () [223] host_self_trap () -> port right 2563 [223] mach_msg_trap (...) [223] mach_msg_trap () -> KERN_SUCCESS [223] _kernelrpc_mach_port_deallocate_trap (task=2563, name=-6) [223] _kernelrpc_mach_port_deallocate_trap () -> KERN_SUCCESS [223] ioctl (...) [223] ioctl () -> 0 [223] fstat64 (...) [223] fstat64 () -> 0 [223] ioctl (...) [223] ioctl () -> 0 [223] write_nocancel (...) i386 [223] write_nocancel () -> 5 [223] exit (...)
, BSD Mach. , write()
exit()
, Linux-, . , Mach- ioctl
- /dev/mach
, ; BSD- ioctl()
, stdio , stdin stdout ( tty) readlink()
/proc/self/fd/
.
Mach-O, , dyld. :
- , , dylib, , . ld
-bundle_loader
. - ,
LC_LOAD_DYLIB
, LC_REEXPORT_DYLIB
LC_DYLIB_ID
, [compatibility version, current version] , – , . ld -current_version
-compatibility_version
, . dyld , , , . - , Mach-O [source version]. ,
LC_SOURCE_VERSION
. ld -source_version
, , Mach-O- – -add_source_version
-no_source_version
. Info.plist
__info_plist
Mach-O- [codesign] , Info.plist
. ad-hoc Security.framework, , CFBundle
/ NSBundle
API, , , .
, , , ld dyld , « », libSystem
, -. /usr/lib/
.