質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.35%

  • C++

    3745questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Mac上のC++で行番号付きスタック・トレースは可能でしょうか?

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 433

Chironian

C++総合1位

Mac上のQtにて開発しているのですが、スタック・トレースでハマっています。
boostのStackTraceでは関数名までしか表示されず、ソース・ファイル名と行番号が表示されません。addr2lineがないためと思います。
BOOST_STACKTRACE_USE_BACKTRACEを使ってlibbacktraceも試してみたのですがlibbacktrace.laのビルドがうまく行きません。(libbacktrace.laはできますが945バイトと小さくリンクしても_backtrace_create_state等のシンボル無しエラーになる)

Posixのbacktraceも大差ないです。(マングルされた関数名とオフセットが表示されます。)

アプリが落ちた後、システムが表示するダイアログで「レポート」を押すとソース・ファイルと行番号もでるので何らかの方法で表示することは可能と思うのですが、その方法を見つけることができません。

Mac上のC++プログラムでソース名と行番号を表示するには何をすればよいでしょうか?
もしくは、Mac(High Sierra 64bit)上でlibbacktraceをビルドする方法をご存知の方はいらっしゃいませんか?(現在は、単純に./configure後にmakeしているだけです。)

次に、SIGSEGV発生時のスタック・トレースも表示したく、boostのこのページの手順でトライしています。
しかし、Macの場合、起動する度にアプリがロードされるアドレスが変わるようで、前回保存したダンプ・ファイルの関数名さえ適切に表示されません。あさってのシンボルになったり、変換されなかったりです。これに対処する方法は存在するでしょうか?


Macについては不慣れなので、多少馬鹿なことを聞いているかも知れません。ご容赦頂けると幸いです。


【追記】
記載漏れがありました。binutilsのgaddr2lineは試しています。
homebrewでインストールし、インストールされたパスをBOOST_STACKTRACE_ADDR2LINE_LOCATIONでboost stack traceへ指示してみました。
結果は変わらず、関数名までしか表示されませんでした。


【更に追記】
Twitterで拾った情報からlibbacktraceのissue Mach-O support #2を辿れました。
どうも残念ながらlibbacktraceは未だMac OSはサポートしていない様子です。

英語のニュアンスがうまく読み取れないので、誤読しているかもしれませんが、需要が少ないことと苦労が凄まじいことが原因っぽいです。このプルリク主の JohnColanduoni さんはかなり粘り強く頑張っている(Add libbacktrace support for Apple platformsAdd libbacktrace support for Apple platforms (resubmitted))ようですが、結局難易度が高すぎていまだうまく行っていないと読み取れました。

Macはクローズド・システムだから、Appleがスタックトレースを取得するAPIを公開しない限りかなり厳しいことになります。そして、このように公開の場で苦労し続けている人がいるということは、Appleはスタックトレースを取得するAPIを公開していないということかも?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+1

libbacktraceのビルドがうまくいかないというのはもう少し具体的にお願いいたします。
ビルド自体はエラーを吐かずに成功するのですか?

ロードされるアドレスが変わるのはASLRが有効になってるんだと思います。
以下のサイトをもとにASLRを無効にしたプログラムを作成できませんか?

ASLR

追記:
addr2lineがないのであればportでaddr2line相当のgaddr2lineがbinutilsで入れられるそうですが、入れたあとエイリアス等でaddr2lineと置き換えられませんか?
homebrewが使えるならそちらでも。

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib: file: .libs/libbacktrace.a(atomic.o) has no symbols

これは多分、

→#if !defined (HAVE_ATOMIC_FUNCTIONS) && defined (HAVE_SYNC_FUNCTIONS)

これによってatmic.oの中身がないんだと思います。
nmでシンボルが全く存在しないのか確認できますでしょうか。
多分途中抜けてる感じでも中身はあると思うのですが。

エラーで落ちるのであればリリースビルドとしてではなくデバッグビルドとして検証したほうがよろしい気がしますが・・・。
addr2lineはコンパイル時の最適化オプションはどうだか知りませんがデバッグ情報はどちらにしろ付加しないといけないみたいなので、ただ単にリリースビルドとしてビルドしただけ(デバッグ情報を付加していないのであれば)では使えないそうですが、デバッグビルドとしてビルドすることを再考したほうがよろしいかと。。。
リリースビルドで起きるエラーなのでしょうか?
最適化かかっていたらどちらにしろエラー時の情報の有用性(スタックトレースが読みにくい気がします)が低くなってしまいますが、リリースビルドじゃないとだめでしょうか・・・。

addr2lineはPIEもしくはPICでコンパイルしても駄目らしいのでどちらにしろコンパイルし直さないと正しい情報が得られないと思います。
ASLRは対象のプログラムだけ無効といった形でも駄目でしょうか?
コンパイル時にこんな感じで無効化できるかもしれません。

追記:

atmic.oをnmでみてみました。全く何も出てきませんでしたので空です。ちょっと気になってリンク・エラーになるシンボル _backtrace_create_state を探してみたところ、state.cにあり、state.oをnmでみると入ってました。

.libsにlibbacktrace.soができると思うのですが、こちらに_backtrace_create_stateはありませんか?
libbacktrace.la自体はテキストファイルでlibtoolが見るやつなので無視していいです。
こちらにあるならlibbacktraceのビルドは正常にできており、リンクが間違っているかaddr2lineが正常にデータを拾えてないことになります。

addr2lineが正常に動いているかどうかは確認いたしましたでしょうか?
該当のファイルにgccなら-no-pieをつけてコンパイルしないとaddr2lineに相対アドレスを渡すことになり、計算する必要がございます。
boostの内部の実装がどうなってるかわかりませんが、PIEで実行すると正常にデータが得られないのではないでしょうか?

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/21 00:46

    ご回答ありがとうございます。
    libbacktrace.laができていて、かつ、error: やwarning: はでていないのでlibbacktraceのビルド自体は成功しているように見えます。
    ただ、次のようなメッセージがでていますので、適切にはビルドできないと思います。
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib: file: .libs/libbacktrace.a(atomic.o) has no symbols
    そのままboost stack trace経由でアプリとリンクするとシンボル無しエラーとなります。

    ASLRについては理解しています。これを解除するということはセキュリティ的に弱くなるのでこれは解除しない方針です。お客様のPCで稼働中に万が一不具合が発生した時のデバッグ用ログ取得が目的なので、セキュリティ上のリスクを上げてまでやることではないと考えています。

    キャンセル

  • 2018/06/21 13:07 編集

    追記ありがとうございます。gaddr2lineは実はトライしています。記載せずすいません。BOOST_STACKTRACE_ADDR2LINE_LOCATIONにgaddr2lineのフルパスを定義してトライしました。残念ながら結果は変わらずでした。

    atmic.oをnmでみてみました。全く何も出てきませんでしたので空です。ちょっと気になってリンク・エラーになるシンボル _backtrace_create_state を探してみたところ、state.cにあり、state.oをnmでみると入ってました。何故にこれがリンクされないのか謎です。

    最終系はリリースビルドしますが、現時点ではデバッグビルドでトライしています。現在は、スタックトレースを取得するコードをデバッグしている状態なのです。これに成功してからリリースビルドにトライ予定です。

    addr2lineのビルドはそれなりに手間がかかるので、希望が見えてからトライしたいです。
    アSLRの解除は厳しいです。内部にWebBrowserコントロールを抱えていますし、セキュリティ上のリスクが上がる以外の手段がない場合は、スタック・トレースを断念する方向です。

    キャンセル

  • 2018/06/21 15:37

    更に追記ありがとうございます。
    おおっ、.libsにlibbacktrace.dylibがありました!!(Macなので.soではなく.dylib)
    同じところに、libbacktrace.aも有ったので、こちらとリンクしてみます。(ただ、質問に追記したようにlibbacktraceがMacをサポートしているかどうか怪しいです。でも、.dylibがあるならできてもよさそうですし。)

    なお、addr2lineとlibbacktraceは排他です。2つの仕組みをboostがサポートしていてどちらかを選択します。

    キャンセル

  • 2018/06/21 16:06

    やってみましたが、結論としてはダメでした。
    libbacktraceの方はリンクし、起動することにも成功しました。しかし、関数名さえ表示されなくなりました。
    gaddr2lineは、直接コマンドラインにて、「gaddr2line -e 実行ファイル 0x上記で表示されたアドレス」としても ??:0 と表示されるだけでした。
    やはり無理っぽいですね。

    ところで、m_yoko さんは、MacにてC++プログラムでスタックトレースのファイル名と行番号を獲得するのに成功されたことがある、もしくは、成功したとの話を聞いたことはございますか?
    質問に追記した内容から、安定して使える方法はないのではないかと疑っています。

    キャンセル

  • 2018/06/21 16:55

    PIEで実行しているならば自分で計算し直さないとaddr2lineは使えないですが、アドレスは再計算したでしょうか?
    objdumpして実際に該当のアドレスは見てみましたか?
    少なくともobjdumpで出力されるアドレスに該当の箇所がないと出力されないはずです。
    相対のアドレスの方を入力すると出ます。
    こちらではLinuxマシンしかないため、Linux上でやってますが、セグフォしたときの+0x65eとかのアドレスを打ち込むと出ました。右側のメモリ上のアドレスは毎回変わるんで打ち込んでも駄目です。
    Backtrace:
    ./main(+0x65e)[0x55899d56465e]
    ./main(+0x6a6)[0x55899d5646a6]
    /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf1)[0x7f22d57f11c1]
    ./main(+0x56a)[0x55899d56456a]

    一度PIEでコンパイルするのをやめて試してみたらどうでしょうか?

    周りはSwiftの開発者はいるのですがC++でやってる人が居ないので聞いたことないですね。。。

    キャンセル

  • 2018/06/21 18:11

    「アドレスは再計算」はしていないというか、再計算方法は把握していません。
    といいますか、私がgaddr2lineに与えた数値はboost stack traceの出力ですので、ASLRやPIC/PIEを想定した場合、これがそもそも相対アドレスでないとソース名と行番号へ変換できる筈がないですね。
    ということは、boostの出力が相対アドレスでない、もしくは、boostのスタックトレースはgaddr2lineと非互換ということになります。ASLR絡みの動作から前者と思います。どちらにせよ、この問題は私が対処できる気がしません。

    > 一度PIEでコンパイルするのをやめて試してみたらどうでしょうか?

    そもそもMacで非位置独立コードって可能なのでしょうか?(結構難易度高そうな印象です。)
    https://stackoverflow.com/questions/26647563/is-it-possible-to-make-non-fpic-dylib-in-mac
    http://wwweic.eri.u-tokyo.ac.jp/computer/manual/altixuv/doc/Compiler/fort/jp_lnx_fortdocs11.1.tar/Documentation/ja_JP/compiler_f/main_for/copts/common_options/option_fpie.htm

    そして、またまたすいません。明記しておくべきでしたが、boost stack traceは、Windowsとlinuxではソース名と行番号まで表示できます。Macだけダメなのです。
    質問の追記に簡単ですが記載しましたように、libbacktraceに2年前にプルリクが投げられて採用されず、そこでrust専用としてプルリクされ、それも結局採用されていないという事実は重いです。(Appleが必要なAPIを公開していないのではないか?と私は感じています。)
    Macでソース名と行番号をプログラムにて獲得できるとの情報をお持ちでないのであれば、この辺で終了させて頂ければ幸いです。

    キャンセル

  • 2018/06/21 18:59

    最新のMacではデフォルトでPIEが有効になっているそうですよ。
    https://jp.xlsoft.com/documents/intel/compiler/18/cpp_18_win_lin/GUID-EFCC2954-F3C9-4A85-A227-62B30A077109.html
    http://www.oversea-pub.com/category/free/c
    https://stackoverflow.com/questions/23897963/documented-way-to-disable-aslr-on-os-x
    https://stackoverflow.com/questions/10562280/line-number-in-google-perftools-cpu-profiler-on-macosx
    実際にPIEが有効になっているかはotoolを使ってフラグを見てみればわかると思いますが・・・。

    有用な情報を提供できず申し訳ございません・・・。

    キャンセル

  • 2018/06/21 21:54 編集

    追加情報ありがとうございます.非位置独立コード(非PIE)ってできるのですね。ALSRがディセーブルされるので本番では使えないですが、試しにやってみました。
    が、ダメでした。libbacktraceはアドレスしか表示されず、デフォルトとgaddr2lineは関数名までしか表示されませんでした。
    残念な結果でしたが、お付き合いありがとうございました。

    キャンセル

+1

詳しくはないんですが、LLVMって使えないんですかね?
LLVM 3.1 リリースノートの訳
mac osでLLVMの環境を構築してみる
標準のLLDBでも可能なのかもしれませんが。
的外れだったらご容赦下さい。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/21 12:12

    ご回答ありがとうございます。
    Macの標準の開発環境(Xcode)のコンパイラはllvmですので、あまりかわらない可能性が高いと思います。
    私が使っている環境の__VERSION__マクロは、"4.2.1 Compatible Apple LLVM 9.1.0 (clang-902.0.39.2)"と定義されていました。

    lldb調べてみましたがコアダンプが生成されず断念しました。生成される場合でもストレージ圧迫の大きな原因の1つのようですので生成するのは厳しいですが。https://goo.gl/PkicP5

    キャンセル

check解決した方法

0

この件、少なくともメジャーな解決方法は存在しないという結論になると思います。
無いものの証明はできないので、「メジャーな方法は存在しない」にてクローズとさせて頂きます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

同じタグがついた質問を見る

  • C++

    3745questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。