2 // BUILD: $CC foo.c -dynamiclib -install_name /cant/find/me.dylib -o $BUILD_DIR/libmissing.dylib
3 // BUILD: $CC foo.c -dynamiclib $BUILD_DIR/libmissing.dylib -install_name $RUN_DIR/libMissingDylib.dylib -o $BUILD_DIR/libMissingDylib.dylib
4 // BUILD: $CC emptyMain.c $BUILD_DIR/libMissingDylib.dylib -o $BUILD_DIR/prog_missing_dylib.exe
5 // BUILD: $CC defSymbol.c -dynamiclib -install_name $RUN_DIR/libMissingSymbols.dylib -o $BUILD_DIR/libMissingSymbols.dylib
6 // BUILD: $CC defSymbol.c -dynamiclib -install_name $RUN_DIR/libMissingSymbols.dylib -o $BUILD_DIR/libHasSymbols.dylib -DHAS_SYMBOL
7 // BUILD: $CC useSymbol.c $BUILD_DIR/libHasSymbols.dylib -o $BUILD_DIR/prog_missing_symbol.exe
8 // BUILD: $CXX main.cpp -o $BUILD_DIR/dyld_abort_tests.exe
10 // NO_CRASH_LOG: prog_missing_dylib.exe
11 // NO_CRASH_LOG: prog_missing_symbol.exe
13 // RUN: ./dyld_abort_tests.exe
22 #include <mach/mach.h>
23 #include <mach/machine.h>
25 #include <System/sys/reason.h>
26 #include <System/sys/proc_info.h>
27 #include <System/kern/kern_cdata.h>
29 #include <mach-o/dyld_priv.h>
31 #include "test_support.h"
34 void runTest(const char* prog
, uint64_t dyldReason
, const char* expectedDylibPath
, const char* expectedSymbol
) {
36 process
.set_executable_path(prog
);
37 process
.set_crash_handler(^(task_t task
) {
38 LOG("Crash for task=%u", task
);
39 vm_address_t corpse_data
;
41 if (task_map_corpse_info(mach_task_self(), task
, &corpse_data
, &corpse_size
) != KERN_SUCCESS
) {
42 FAIL("Could not read corpse data");
44 kcdata_iter_t autopsyData
= kcdata_iter((void*)corpse_data
, corpse_size
);
45 if (!kcdata_iter_valid(autopsyData
)) {
46 FAIL("Corpse Data Invalid");
48 kcdata_iter_t exitReasonData
= kcdata_iter_find_type(autopsyData
, EXIT_REASON_SNAPSHOT
);
49 if (!kcdata_iter_valid(exitReasonData
)) {
50 FAIL("Could not find exit data");
52 struct exit_reason_snapshot
*ers
= (struct exit_reason_snapshot
*)kcdata_iter_payload(exitReasonData
);
54 if ( ers
->ers_namespace
!= OS_REASON_DYLD
) {
55 FAIL("eri_namespace (%d) != OS_REASON_DYLD", ers
->ers_namespace
);
57 if ( ers
->ers_code
!= dyldReason
) {
58 FAIL("eri_code (%llu) != dyldReason (%lld)", ers
->ers_code
, dyldReason
);
60 kcdata_iter_t iter
= kcdata_iter((void*)corpse_data
, corpse_size
);
62 KCDATA_ITER_FOREACH(iter
) {
63 if (kcdata_iter_type(iter
) == KCDATA_TYPE_NESTED_KCDATA
) {
64 kcdata_iter_t nestedIter
= kcdata_iter(kcdata_iter_payload(iter
), kcdata_iter_size(iter
));
65 if ( kcdata_iter_type(nestedIter
) != KCDATA_BUFFER_BEGIN_OS_REASON
){
68 kcdata_iter_t payloadIter
= kcdata_iter_find_type(nestedIter
, EXIT_REASON_USER_PAYLOAD
);
69 if ( !kcdata_iter_valid(payloadIter
) ) {
70 FAIL("invalid kcdata payload iterator from payload data");
72 const dyld_abort_payload
* dyldInfo
= (dyld_abort_payload
*)kcdata_iter_payload(payloadIter
);
74 if ( dyldInfo
->version
!= 1 ) {
75 FAIL("dyld payload is not version 1");
78 if ( (dyldInfo
->flags
& 1) == 0 ) {
79 FAIL("dyld flags should have low bit set to indicate process terminated during launch");
82 if ( expectedDylibPath
!= NULL
) {
83 if ( dyldInfo
->targetDylibPathOffset
!= 0 ) {
84 const char* targetDylib
= (char*)dyldInfo
+ dyldInfo
->targetDylibPathOffset
;
85 if ( strstr(targetDylib
, expectedDylibPath
) == NULL
) {
86 FAIL("dylib path (%s) not what expected (%s)", targetDylib
, expectedDylibPath
);
89 FAIL("dylib path (%s) not provided by dyld", expectedDylibPath
);
93 if ( expectedSymbol
!= NULL
) {
94 if ( dyldInfo
->targetDylibPathOffset
!= 0 ) {
95 const char* missingSymbol
= (char*)dyldInfo
+ dyldInfo
->symbolOffset
;
96 if ( strcmp(expectedSymbol
, missingSymbol
) != 0 ) {
97 FAIL("symbol (%s) not what expected (%s)", missingSymbol
, expectedSymbol
);
100 FAIL("symbol (%s) not provided by dyld", expectedSymbol
);
106 FAIL("Did not find EXIT_REASON_USER_PAYLOAD");
112 int main(int argc
, const char* argv
[], const char* envp
[], const char* apple
[]) {
113 // test launch program with missing library
114 runTest("./prog_missing_dylib.exe", DYLD_EXIT_REASON_DYLIB_MISSING
, "/cant/find/me.dylib", NULL
);
115 // runTest("./prog_missing_symbol.exe", DYLD_EXIT_REASON_SYMBOL_MISSING, "libMissingSymbols.dylib", "_slipperySymbol");