私は、プロセスやスレッドがターミナル信号(SIGSEGV、SIGABRTなど)を受信したときにトレースをエクスポートするようにLinuxで実行されるアプリケーションを強化しています。
backtrace(3)
コードはbacktrace_symbols(3)
、を使用してうまく機能し、バックトレースdladdr(3)
にabi::__cxa_demangle
役立つ情報を生成します。
addr2line
それ以外にも、ソースファイル名と行番号を生成しようとしたときに提供されたアドレスを使用して実行可能ファイルを送信するとうまく機能することがわかりましたが、最近は共有オブジェクト内にシンボルがある限りbacktrace(3)
生成するのは簡単です??:0
。backtrace
友達が報告した住所がASLRの影響を受けたようです。この問題は私のスタックトレースの大部分(すべてではありません)に影響を与え、現在のフォーキングの価値を減らしていますaddr2line
。
問題を解決し、ファイルと行番号を取得する方法に関するインターネットの結果がまれになり始めました。しかし、私は最近、次の問題を解決するためにメモリマッピングがどのように機能するかを十分に学びました。
backtrace_symbols(3)
共有オブジェクトにこのアドレスとオフセットを追加して送信するときに、指定されたシンボルを見つけるためにこの共有オブジェクトで使用できる共有オブジェクトへのパスを含む文字列を指定しますdladdr(3)
。ファイルと行番号が正しく生成されました。dli_fname
nm
backtrace_symbols
addr2line -e <sharedobjectpath>
/proc/<pid>/maps
共有オブジェクトパスでマッピングされたアドレスを検索し、報告されたアドレスからその値を減算すると、上記の共有オブジェクトr-xp
とbacktrace(3)
まったく同じアドレスを取得できます。- 共有オブジェクトマップアドレスを直接取得すると(まだテストしていませんが直感的に)、
dladdr1(3)
アクセスをスキップできます/proc/<pid>/maps
。
addr2line
とにかく、ここではファイルと行番号を取得するために分岐する必要があるようです。これは少し痛みがあり(数百ミリ秒かかります)、libbfd
私のアプリケーションに依存関係を導入せずに必要なようです。
修正する:詳しくは見ていないが、 で見つけたアドレスが の/proc/<pid>/maps
値と同じであることがわかりました。それはすべてです。まったく上を見る必要はありません。dli_fbase
dladdr(3)
/proc/<pid>/maps
これを行うよりクリーンで直接的な方法はありますか? 3番目の箇条書きのためaddr2line
。 (編集する:住所を教えてもらえますか?私の言及は無視してください/proc/<pid>/maps
。 )2番目の箇条書きはすでに必要なフォークを取得するために読み取ることができることを示して/proc/<pid>/maps
addr2line
います。 3番目の箇条書きは実行不可能であることがわかります)私のプログラムからのアクセスに関連するセキュリティ/アクセス/セキュリティの問題はありますランニング/proc/<pid>/maps
か?はどうですかaddr2line
?