前回の最後で dysymの undef extsymbolのほうがImport関数の情報として正しそうと感じていましたが、どうやらそれは間違っていたようです。正しくはIndirectテーブルから求めていくのが正解のようです。
このIndirectテーブルは struct dysymtab_command の indirectsymoff で示される場所に配置されています。
そしてこのテーブルのエントリ数は nindirectsyms となっています。
ではこのエントリ数分のnindirectsymsがインポート関数かと言われるとそうでもないようで、この中の一部分となっているようです。
セクション __la_symbol_ptr で示される reserved1メンバがこのIndirectテーブルでの開始点を示すことになっているようです。
そこで、エントリのreserved1から nindirectsymsまでの中身を確認してみます。
このエントリは uint32_t の配列となっているので取り出すと単なる整数です。
これはシンボルテーブルのエントリのインデックスとなっています。情報表示をするにはシンボルテーブルの情報にアクセスする必要があります。
これらの処理を以下のようにコードにしてみました。割と自明なところのコードは省きます。
void listupImportFunc() { mach_header_64* mh; symtab_command* symtab = (symtab_command*)getLoadCommand( mh, LC_SYMTAB ); dysymtab_command* dysymtab = (dysymtab_command*)getLoadCommand(mh, LC_DYSYMTAB ); nlist_64* nlist = (nlist_64*)( (uint8_t*)mh + symtab->symoff ); uint32_t* indtab = (uint32_t*) ((uint8_t*)mh + dysymtab->indirectsymoff); uint32_t indoff = getIndirectTableOffset( mh ); char* strtab = (char*)mh + symtab->stroff; printf( "Indirect Syms = %u\n", dysymtab->nindirectsyms ); for( int i = indoff; i < dysymtab->nindirectsyms; ++i ) { uint32_t index = indtab[ i ]; nlist_64* nl = &nlist[index]; const char* name = strtab + nl->n_un.n_strx; printf( " %u : %s\n", index, name ); } }
この実行結果の一部を公開するとこんな感じになります。
256 : __ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE6sentryD1Ev 257 : __ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEi 258 : __ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEm 261 : __ZNSt3__16localeD1Ev 262 : __ZNSt3__18ios_base33__set_badbit_and_consider_rethrowEv 263 : __ZNSt3__18ios_base5clearEj 264 : __ZSt9terminatev 265 : __ZdlPv 266 : __Znwm 268 : ___cxa_begin_catch 269 : ___cxa_end_catch 245 : __Unwind_Resume 267 : ___cxa_atexit 271 : ___stack_chk_fail 273 : __dyld_get_image_header 274 : __dyld_get_image_name 275 : __dyld_get_image_vmaddr_slide 276 : __dyld_image_count 277 : _getpid 278 : _mach_port_deallocate 280 : _mach_vm_region 281 : _printf 282 : _strcmp 283 : _strlen 284 : _sysctl
それっぽいものが出力されるようになりました!