8

FreeType のFT_Load_GlyphandFT_Render_Glyph関数への引数を変更する共有オブジェクトを作成しましたが、現在はLD_PRELOADandで挿入していdlsymます。

これはうまくいきますが、これらの変更を行う方法があるかどうか知りたいです:

  • 特定のホスト (Debian などを実行) で FreeType を使用するすべてのプログラム。
  • FreeType に実際にリンクされていないプログラムを壊すことなく。
  • LD_PRELOADホスト上のすべてのプログラムに単純に適用するのではなく、
  • FreeType の soname が変更されない限り、メンテナンスは必要ありません。と
  • FreeType のファイルやホスト上のプログラムのファイルを変更する必要はありません。

私が思いついた唯一の「解決策」は、醜いハックです。

  • LD_PRELOADすべてのプログラムに対して、常に、遅くて壊れやすいように見えます。また
  • にコピーlibfreetype.so.6.12.3libxxxxtype.so.6.12.3ます。それから
    • soname を にパッチlibxxxxtype.so.6.12.3libxxxxtype.so.6ます。
    • 介在する共有オブジェクトを に対してリンクしますlibxxxxtype.so.6。と
    • たとえば、共有オブジェクトをインストールしますlibfreetype.so.6.999

基本的に、共有オブジェクトのソースまたはそれを使用するプログラムに必ずしもアクセスすることなく、残りの関数を通過させながら、共有オブジェクト内のいくつかの関数に透過的にパッチを適用したいのですが、偽の共有オブジェクトを作成するとsoname では、それを実際の にリンクする (または)libfreetype.so.6きれいな方法がわかりません。dlopenlibfreetype.so.6

これは共有ライブラリを使った最初の実際の実験なので、この質問が間違った仮定をしていたり​​、単に意味をなさない場合はご容赦ください。

4

3 に答える 3

3

uprobesいくつかの関数から動的に制御を盗むために使用できますか?

http://www.brendangregg.com/blog/2015-06-28/linux-ftrace-uprobe.html を確認してください

uprobes: Linux 3.5 に追加され、Linux 3.14 で改善されたユーザーレベルの動的トレース。ユーザーレベルの関数をトレースできます。たとえば、実行中のすべての bash シェルからの readline() 関数の戻り値には、次の文字列が返されます。

# ./uprobe 'r:bash:readline +0($retval):string'
Tracing uprobe readline (r:readline /bin/bash:0x8db60 +0($retval):string). Ctrl-C to end.
 bash-11886 [003] d... 19601837.001935: readline: (0x41e876 <- 0x48db60) arg1="ls -l"
 bash-11886 [002] d... 19601851.008409: readline: (0x41e876 <- 0x48db60) arg1="echo "hello world""
 bash-11886 [002] d... 19601854.099730: readline: (0x41e876 <- 0x48db60) arg1="df -h"
 bash-11886 [002] d... 19601858.805740: readline: (0x41e876 <- 0x48db60) arg1="cd .."
 bash-11886 [003] d... 19601898.378753: readline: (0x41e876 <- 0x48db60) arg1="foo bar"
^C
Ending tracing...

そしてhttp://www.brendangregg.com/blog/2015-07-03/hacking-linux-usdt-ftrace.html

ftrace、systemtap、dtrace、lttng など、ユーザー空間関数をトレースする他のソリューションもありました。それらのいくつかは、再コンパイルし、プログラムで静的にトレース ポイントを定義する必要があります。アップローブは「ユーザーレベルの動的トレース」です。

uprobes に関するいくつかのリンク:

handlerを持ったアップローブがありますpt_regs。最後のリンクで述べたように、「アップローブは、プロセスが特定の命令の場所を実行するたびにカーネル関数を呼び出すことができるメカニズムを実装しています。」そして、アップローブがいくつかのptrace / gdbベースのソリューションを置き換える可能性があることを示唆しています。そのため、eip/rip (PC) レジスタを変更することで、アクティブな uprobe にヒットするプログラムの実行を変更する可能性があります。

pinまたはdyninst;などの他の動的計測ツールを試すことができます。ただし、プロセスごとに使用するように設計されています。

于 2016-06-29T02:54:37.240 に答える
2

もう 1 つの解決策は、カスタム libfreetype を使用して lib のシステム全体の「オーバーレイ」を作成し、変更されていないメソッドを実際の lib にプロキシすることです。

カスタム lib を実際の lib と互換性を持たせる必要があります。これには、絶対パス(例: )を使用dlopenし、実際のエクスポートされた関数の定義をコピーし、それらを でプロキシします。メンテナンスを容易にするために、プロキシ引数タイプを simple に置き換えることができると考えています。freetype 関数 (引数の数、関数名) が変更された場合にのみ、変更を加える必要があります。dlopen("/usr/lib64/libfreetype.so.6")dlsymvoid*

lib「オーバーレイ」を作成するには、カスタム lib を例にインストールします。"/opt/myapp/lib64/libfreetype.so.6" の場合、このパスを動的リンカーのランタイム パスに追加します。元の実装が変更された場合は、他のバージョンのシンボリック リンクを作成するか、新しいカスタム ライブラリをコンパイルする必要がある場合があります。実際のライブラリをシャドーし、他のアプリの動作を維持するために必要なものは何でも:)

Google によると、Debian で実行時のロード パスを変更するには、単に編集する必要があります/etc/ld.so.conf。先頭にパスを追加/opt/myapp/lib64して、最初にチェックされるようにします。これで、freetype を検索するすべてのアプリがライブラリをロードするはずですldd <path to app>

このソリューションが機能しないケースを 1 つだけ考えることができます。アプリがバンドルされた libfreetype をロードしているか、名前ではなくフル パスでロードしている場合です。

于 2016-06-28T10:02:46.390 に答える