TL;DR
macOS Big Sur 11.0.1 以降だと、ダイナミックリンクライブラリがキャッシュされていてファイルシステムから見えなくなっている(Finder.appから見えない)
ことの発端
Ghidraを使ってバイナリを見ていたところ、ダイナミックリンクライブラリが見つからないとエラーが出た。
----- Loading /Users/XXXXXXXXXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXX -----
Linking external programs to XXXXXXXXXXXXXXXXXXXXX...
[/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation] -> not found
[/System/Library/Frameworks/CFNetwork.framework/Versions/A/CFNetwork] -> not found
[/usr/lib/libresolv.9.dylib] -> not found
[/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation] -> not found
[/System/Library/Frameworks/ServiceManagement.framework/Versions/A/ServiceManagement] -> not found
[/System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration] -> not found
[/System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices] -> not found
[/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit] -> not found
[/usr/lib/libobjc.A.dylib] -> not found
[/System/Library/Frameworks/Security.framework/Versions/A/Security] -> not found
[/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit] -> not found
[/System/Library/Frameworks/Virtualization.framework/Versions/A/Virtualization] -> not found
[/System/Library/Frameworks/Hypervisor.framework/Versions/A/Hypervisor] -> not found
[/usr/lib/libSystem.B.dylib] -> not found
/usr/lib/libSystem.B.dylib
とかは明らかにシステムに無くてはならないものなのに、見つからないのはおかしい。
cha84rakanal@ ~ % ls /usr/lib/libSystem.B.dylib
ls: /usr/lib/libSystem.B.dylib: No such file or directory
cha84rakanal@ ~ %
公式ドキュメントより
New in macOS Big Sur 11.0.1, the system ships with a built-in dynamic linker cache of all system-provided libraries. As part of this change, copies of dynamic libraries are no longer present on the filesystem. Code that attempts to check for dynamic library presence by looking for a file at a path or enumerating a directory will fail. Instead, check for library presence by attempting to dlopen() the path, which will correctly check for the library in the cache. (62986286)
macOS Big Sur 11.0.1 よりダイナミックリンクライブラリはファイルシステム上に存在しなくなりました。と書いてありました。プログラムの実行時、OS側がよしなに取り扱っているわけですね。ちなみに、ダイナミックリンクライブラリのキャッシュの実体は、 /System/Library/dyld
においてあります。
dlopenは動作する
ファイルシステム上に存在しないパスに対して、ダイナミックリンクライブラリを動的にロードする dlopen
関数が動作するか確認してみる。確認には、次のプログラムを使った。
#include <mach-o/dyld.h>
#include <dlfcn.h>
#include <stdio.h>
int library_exists(const char* path) {
void* handle = dlopen(path, RTLD_LAZY);
if (handle == NULL) return 0;
dlclose(handle);
return 1;
}
int main(void) {
int result;
char* path = "/System/Library/Frameworks/Virtualization.framework/Versions/A/Virtualization";
result = library_exists(path);
printf("library_exists(%s) == %d", path, result);
}
cha84rakanal % ls /System/Library/Frameworks/Virtualization.framework/Versions/A/Virtualization
ls: /System/Library/Frameworks/Virtualization.framework/Versions/A/Virtualization: No such file or directory
cha84rakanal % cc -g dltest.c && ./a.out
library_exists(/System/Library/Frameworks/Virtualization.framework/Versions/A/Virtualization) == 1
cha84rakanal %
ファイルが無いので、 0
を期待しましたが1
が帰ってきてるのでdlopen
関数が動作していますね。
dyldの dlopen
関数の解剖については、WIPです。