.dylibファイルを作成してコンパイルします。
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
static void* (*real_malloc)(size_t);
void *malloc(size_t size)
{
void *p = NULL;
fprintf(stderr, "malloc(%zd) = ", size);
p = real_malloc(size);
fprintf(stderr, "%p\n", p);
return p;
}
void __attribute((constructor))init()
{
real_malloc = (decltype(real_malloc))dlsym(RTLD_NEXT, "malloc");
if (NULL == real_malloc) {
fprintf(stderr, "Error in `dlsym`: %s\n", dlerror());
return;
}
}
次に、malloc
を呼び出すテストプログラムを作成します。 mallocへの呼び出しが最適化されていないことを確認しました。
次に、私は以下を実行しました:
DYLD_PRINT_LIBRARIES=1 X=1 DYLD_INSERT_LIBRARIES=./libTestHook.dylib ./malloctest
それはそれをロードしますが、それは関数をまったくフックしません..何かアイデアはありますか? El Capitanをアップグレードする前にこのコードを試しましたが、以前は機能していました。また、mallocに例外をスローさせて、呼び出されているかどうかを確認しました。そうではありません。
何が足りないのですか?
結果は次のとおりです。
sh-3.2# DYLD_PRINT_LIBRARIES=1 X=1 DYLD_INSERT_LIBRARIES=./libTestHook.dylib ./malloctest clear
dyld: loaded: /Users/Brandon/Desktop/./malloctest
dyld: loaded: ./libTestHook.dylib
dyld: loaded: /usr/lib/libc++.1.dylib
dyld: loaded: /usr/lib/libSystem.B.dylib
dyld: loaded: /usr/lib/libc++abi.dylib
dyld: loaded: /usr/lib/system/libcache.dylib
dyld: loaded: /usr/lib/system/libcommonCrypto.dylib
dyld: loaded: /usr/lib/system/libcompiler_rt.dylib
dyld: loaded: /usr/lib/system/libcopyfile.dylib
dyld: loaded: /usr/lib/system/libcorecrypto.dylib
dyld: loaded: /usr/lib/system/libdispatch.dylib
dyld: loaded: /usr/lib/system/libdyld.dylib
dyld: loaded: /usr/lib/system/libkeymgr.dylib
dyld: loaded: /usr/lib/system/liblaunch.dylib
dyld: loaded: /usr/lib/system/libmacho.dylib
dyld: loaded: /usr/lib/system/libquarantine.dylib
dyld: loaded: /usr/lib/system/libremovefile.dylib
dyld: loaded: /usr/lib/system/libsystem_asl.dylib
dyld: loaded: /usr/lib/system/libsystem_blocks.dylib
dyld: loaded: /usr/lib/system/libsystem_c.dylib
dyld: loaded: /usr/lib/system/libsystem_configuration.dylib
dyld: loaded: /usr/lib/system/libsystem_coreservices.dylib
dyld: loaded: /usr/lib/system/libsystem_coretls.dylib
dyld: loaded: /usr/lib/system/libsystem_dnssd.dylib
dyld: loaded: /usr/lib/system/libsystem_info.dylib
dyld: loaded: /usr/lib/system/libsystem_kernel.dylib
dyld: loaded: /usr/lib/system/libsystem_m.dylib
dyld: loaded: /usr/lib/system/libsystem_malloc.dylib
dyld: loaded: /usr/lib/system/libsystem_network.dylib
dyld: loaded: /usr/lib/system/libsystem_networkextension.dylib
dyld: loaded: /usr/lib/system/libsystem_notify.dylib
dyld: loaded: /usr/lib/system/libsystem_platform.dylib
dyld: loaded: /usr/lib/system/libsystem_pthread.dylib
dyld: loaded: /usr/lib/system/libsystem_sandbox.dylib
dyld: loaded: /usr/lib/system/libsystem_secinit.dylib
dyld: loaded: /usr/lib/system/libsystem_trace.dylib
dyld: loaded: /usr/lib/system/libunc.dylib
dyld: loaded: /usr/lib/system/libunwind.dylib
dyld: loaded: /usr/lib/system/libxpc.dylib
dyld: loaded: /usr/lib/libobjc.A.dylib
dyld: loaded: /usr/lib/libauto.dylib
dyld: loaded: /usr/lib/libDiagnosticMessagesClient.dylib
A
B
C
D
私の元の投稿のコードは、Yosemiteで機能していました。エルキャピタンでは機能しません。私は次のアプローチをすることになりました(DYLD_INTERPOSE
+ DYLD_INSERT_LIBRARIES
):
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#define DYLD_INTERPOSE(_replacment,_replacee) \
__attribute__((used)) static struct{ const void* replacment; const void* replacee; } _interpose_##_replacee \
__attribute__ ((section ("__DATA,__interpose"))) = { (const void*)(unsigned long)&_replacment, (const void*)(unsigned long)&_replacee };
void* pMalloc(size_t size) //would be Nice if I didn't have to rename my function..
{
printf("Allocated: %zu\n", size);
return malloc(size);
}
DYLD_INTERPOSE(pMalloc, malloc);
フックされている実行可能ファイルを再コンパイルできる場合、より簡単な解決策は-force_flat_namespace
を使用して実行可能ファイルを再コンパイルすることだと思います。
➜ clang slow_leak.c -force_flat_namespace -o slow_leak
➜ DYLD_INSERT_LIBRARIES=malloc_hook.dylib ./slow_leak
leaking
in hooked malloc
詳細 。これはOSX10.12.2 MacOSSierraにあります。
HNに関するコメント (2年後)DYLD_FORCE_FLAT_NAMESPACE=1
は、再コンパイルが不可能な場合に役立ちます。まだ試したことがないので、YMMV。
dyld
docsから:
DYLD_INSERT_LIBRARIESこれは、プログラムで指定されたものの前にロードするダイナミックライブラリのコロンで区切られたリストです。これにより、新しいモジュールのみを使用して一時的な動的共有ライブラリをロードすることにより、フラット名前空間イメージで使用される既存の動的共有ライブラリの新しいモジュールをテストできます。 DYLD_FORCE_FLAT_NAMESPACEも使用されていない限り、これは動的共有ライブラリを使用して2レベルの名前空間イメージを構築したイメージには影響しないことに注意してください。
DYLD_FORCE_FLAT_NAMESPACEプログラム内のすべての画像を強制的にフラット名前空間画像としてリンクし、2レベルの名前空間バインディングを無視します。これにより、2レベルの名前空間イメージを使用してイメージに複数定義のシンボルを含めることができる場合、プログラムが複数定義のシンボルエラーで実行に失敗する可能性があります。
したがって、コードにはDYLD_FORCE_FLAT_NAMESPACE = 1が必要でした。とにかく、 私の実装 はこのオプションを有効にした場合にのみ/usr/local/bin/git
で機能します。
DYLD環境変数をエクスポートしてみてください。例:
export DYLD_LIBRARY_PATH=.
環境を確認してください:
env
変数がエクスポートされなかった場合は、次のことを試してください システム整合性保護を無効にする (また、 このリンク MacOS仮想マシンで実行している場合に役立つことがあります)