2017-06-15 11 views
1

systemへの呼び出しをラップして引数に前処理を追加するために、linuxでLD_PRELOADを使用しようとしています。ここに私のsystem.cppです:LD_PRELOAD'edライブラリからsystem()関数が呼び出されていません

#define _GNU_SOURCE 
#include <dlfcn.h> 
#include <string> 
#include <iostream> 

typedef int (*orig_system_type)(const char *command); 

int system(const char *command) 
{ 
    std::string new_cmd = std::string("set -f;") + command; 
    // next line is for debuggin only 
    std::cout << new_cmd << std::endl; 

    orig_system_type orig_system; 
    orig_system = (orig_system_type)dlsym(RTLD_NEXT,"system"); 
    return orig_system(new_cmd.c_str()); 
} 

私は.soのオブジェクトを生成

g++ -shared -fPIC -ldl -o libsystem.so system.cpp 

でそれを構築します。一見、私のsystem関数が呼び出されていない - 私はその後、私はすべてのエラーを得ることはありません

$ LD_PRELOAD=/path/to/libsystem.so ./myprogram 

で私のプログラムを実行します。 LD_DEBUG=libsを実行すると、自分の.soがロードされているのがわかりますが、私のsystem関数は呼び出されておらず、代わりに標準ライブラリの関数が呼び出されています。

コード/ビルドを変更するには何が必要ですか?

答えて

2

それはCの関数によって呼び出されるので、あなたが

extern "C" int system ... 

を必要としています。 C++バージョンの名前は変更されているため認識できません。

+0

はい!それはそれだった。 'string libsystem.so |のように名前のマングリングについて不思議でした。 grep system'は 'system'関数名の周りにいくつかのmanglingを持っていました。 'extern" C "で、正しく動作します! –

0

コードは完全に正常に動作するはずです。ドライバプログラムは、このようなものであると仮定すると:

#include <cstdlib> 

int main() { 
    system("find -name *.cpp"); 
} 

その後env LD_PRELOAD=$PWD/libsystem.so ./a.outすることは私にこの出力を与える:

set -f;find -name *.cpp 
./system.cpp 
./test.cpp 

デバッグ文が表示されているが、そのグロブはそのコマンドのために無効になっているだけでなく、ことを示しています。

+0

@rici答えを参照してください - あなたは正しいです、それは正しくドライバプログラムがC言語であれば、私の場合はC++であり、名前のマングリングは途中で起こります。 –

1

また、毎回dlsymを呼び出さないように、「orig_system」ポインタを保存することを検討することもできます。あなたは

extern "C" { 

typedef int (*orig_system_type)(const char *command); 

static orig_system_type orig_system; 

static void myInit() __attribute__((constructor)); 

void myInit() 
{ 
    orig_system = (orig_system_type)dlsym(RTLD_NEXT,"system"); 
} 

int system(const char *command) 
{ 
    std::string new_cmd = std::string("set -f;") + command; 
    // next line is for debuggin only 
    std::cout << new_cmd << std::endl; 
    return orig_system(new_cmd.c_str()); 
} 

} 

のようなものを持っているでしょうので、あなたは(このコードはテストされていませんが、私は過去にこの技術を使用している)、constructor/init機能でこれを行うことができます。

GNU ldの--wrapオプションを使用する方法もあります。

あなたは

-Wl、とあなたの共有ライブラリをコンパイルする場合 - ラップシステム

、あなたのコード内であなたが

extern "C" { 

void* __real_system(const char* command); 
void* __wrap_system(const char* command) 
{ 
    std::string new_cmd = std::string("set -f;") + command; 
    // next line is for debuggin only 
    std::cout << new_cmd << std::endl; 
    return __real_system(new_cmd.c_str()); 
} 

} 

を書く(私はこれを使ったことがないことに注意してください)。

関連する問題