Hatena::ブログ(Diary)

IGINブルネイ/syasudaの日記

2011-02-09

フルパスからの解放その5

だらだらと続きますなぁ。


前にさりげなく書いたことです。

フルパスからの解放その4

http://d.hatena.ne.jp/syasuda/20101129/1291028477

ですが、Makefileの書き方によっては、フルパスでgccに渡している場面も散見しますから、その場合はなかなか良いのではないでしょうか。

すでにばかでかいMakefileがある場合、サクっとフルパス指定に切り替えられないと、意味がありません。

gccに渡すソースファイル名をフルパスにすることで、コンパイル時の標準出力/エラー出力からデバッグ情報に記録されるフルパスを手軽に確認することが出来ます。さらに、-fdebug-prefix-map=old=newオプションを運用することができます。

いいことずくめですね。

同じ事を考える人は簡単に見つかります。

Re: Full path in compiler warning/error messages

http://www.spinics.net/lists/gcchelp/msg18738.html

So, it has apparently nothing to do with compiler options, it's just a matter how you invoke the compiler...

そう。gccのオプションを探し回る人はセンスが悪いのです。サフィックスルールで指定するのがスマートなやり方です。Makefileの書き方によっては1行の修正でフルパス<-->相対パスを切り替えることが出来ます。


エラー/ウォーニングに表示されるヘッダはいつもフルパスですが、ソースは相対だったりフルパスだったりします。細かいことを気にしない人は、そんなことを気にも留めないわけですが、そんな人が書いたプログラムはたぶんバグがいっぱいです。

1文字間違えたら爆発するかもしれないソフトウェア製品を取り扱う場合は細心の注意が必要なのです。

結局、Error行にフルパスを出すために必要なのは、

gccに渡すファイル名をフルパスにすればよい

ということです。例えばこんな風に説明されます。明確ですね。

Can gcc be configured to not print out a full path in warning/error messages?

http://stackoverflow.com/questions/1282392/can-gcc-be-configured-to-not-print-out-a-full-path-in-warning-error-messages


GNU Make 第3版

GNU Make 第3版

2010-11-29

フルパスからの解放その4

うひょひょ。gcc/gasにもオプションがあったぜよ。

これで今後は、デバッグ用バイナリ配布するときに、恥ずかしいディレクトリ名を晒さずに住むわけですな。(ピコーン)

3.9 Options for Debugging Your Program or GCC

http://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html#Debugging-Options

-fdebug-prefix-map=old=new
When compiling files in directory old, record debugging information describing them as in new instead. 
<超訳>ディレクトリ「old」でコンパイルして、「new」でコンパイルしたような内容のデバッグ情報を記録する。

さっそく手元で試すと・・・

$ g++ -g -fdebug-prefix-map=/home/syasuda/src/sandbox/placec/=/home/syasuda/src/sandbox/placea/ -o placea main.cpp
# placecでコンパイルしつつ、placeaのパスを記録したい
$ addr2line -e placea 0x80484f4
/home/syasuda/src/sandbox/placec/main.cpp:4
# あかんやんorz...

これってもしかして、文字列置換してるだけ?

ということは・・・

$ g++ -g -fdebug-prefix-map=/home/syasuda/src/sandbox/placec/=/home/syasuda/src/sandbox/placea/ -o placea /home/syasuda/src/sandbox/placec/main.cpp
# placecでコンパイルしつつ、placeaのパスを記録したい
$ addr2line -e placea 0x80484f4
/home/syasuda/src/sandbox/placea/main.cpp:4

お〜。なんともイマイチな機能。イマサンくらいですかねこりゃ。

ですが、Makefileの書き方によっては、フルパスでgccに渡している場面も散見しますから、その場合はなかなか良いのではないでしょうか。

バージョン:

$ gcc --version
gcc (Ubuntu 4.4.3-4ubuntu5) 4.4.3

というわけでめずらしくまとめです。

gdbでデバッグするときにソースのパスでハマる関係のまとめ

  • gdbでデバッグするときにはset substitute-pathでソースのパスをfakeできる
    • コンパイル時と違うルートにあるソースツリーをソース表示に使える
      • コマンドファイルにdirectoryコマンドの羅列すると今後、赤恥(gdb6.6以降なら)になる予定
        • 「コンパイル時とおなじディレクトリ構成」を強制したりする間抜けルールも滅亡予定
  • gcc -gでデバッグ情報に記録されるソースのパスはフルパスがデフォルトである
    • 理由はよく分からない
  • バイナリに記録されているパスをbinutilsのaddr2lineで確認できる
  • gcc -fdebug-prefix-map=old=newで、デバッグ情報に記録されるソースのディレクトリをfakeすることができる
    • gasに--with-debug-prefix-map=がある
    • 自分が作ったバイナリを人に渡して、「恥ずかしい」パス((例えば「kaihatsu」とか(笑)))が表示されて「こいつローカルで、こんなパス名使ってるんだ・・・」と思われないで済む

gdbのコマンドファイルで、directoryコマンドの羅列を見て、辟易してからもう4年ですか。

長かった。というかgdbの仕事がなかった・・・

参考リンク:

gccのML Re: Debug info path remapping

http://sourceware.org/ml/binutils/2007-07/msg00134.html

(追記)

フルパスからの解放は、コンパイルマシンとデバッグマシンが異なる場合にも効果を発揮します。

2010-10-08

make depend

makeコマンドに「depend」というオプションがあるわけではないですよ。


「depend」というターゲットを書いておくだけのことです。

そのターゲットが、

#makefileに以下を追加

depend:

makedepend -- $(CFLAGS) -- $(ALL_C_FILES)

こんな感じなら、依存関係はmakedependが洗い出してくれるというわけです。makedependに頼らずに手で書いたって良いですがね。

imakeについてもっと知れば、Makefileを書くにも、計画と設計が必要だとわかると思うんですがね。


リンク:

-Mとmakedepend

http://d.hatena.ne.jp/syasuda/20071222/1198305960


GNU Make 第3版

GNU Make 第3版

2008-09-26

ゲームメーカのソース肥大化対策?

繰り返しアクセスがあるようです。


検索結果をブックマークに入れていて、ときどきそれを眺めているのでしょうか。

SCEIさんが、このリンクにやたらとアクセスしてきます。

リンク高速化

http://d.hatena.ne.jp/syasuda/20070421/1177140983

はやく、成果を公開してほしいものですな。(ターリキーホンガン)

■eさんは、gdbのsubstituteコマンドに興味があるようです。

フルパスからの解放

http://d.hatena.ne.jp/syasuda/20071208/1197116413

2008-02-02

prelinkで高速化する前にやるべきことがあるんじゃないか

共有オブジェクトのprelinkをご存知でしょうか。Windowsでいえば、DLLのrebaseです。

共有オブジェクトは、同じアドレス空間にロードされますので、アドレスが被ってはいけないのです。なので、複数の共有オブジェクトをロードする場合、アドレスをずらしてロードすることになります。

で、その処理が重いので、あらかじめやっておいたらええじゃないかというのがprelinkだというわけです。

これによって、多数の共有オブジェクトをリンクする実行バイナリの起動時間が短縮される効果があると言われています。


さて、短縮される時間はアドレスをずらす”リロケーション(再配置)”とシンボルの突合せの2つの合計と考えられます。


シンボルの突合せは、共有オブジェクト特有の話ではありません。スタティックリンクでも、同じ処理が実行されます。つまり普段"リンク"と呼んでいる処理です。

そうすると思い出すのが、ldの高速化パッチです。場合によってはリンクにかかる時間が10分の1になるというのなら、共有オブジェクトのリンクも同じように高速化されるはずです。

例えば、リロケーションとシンボルの突合せにかかる時間が半分ずつだとしたら、実行バイナリのロードにかかる時間が、高速化パッチで半分強5分の1になるということではないでしょうか。

少なくともどちらもシンボル数に比例しそう(うまいこと実装してもO(log n))なので、余程特殊な場合で無い限り、効果が期待できると思うのですが。

逆に言うと、prelinkなどという面倒なものを導入する前に、ld-linux.soを高速化する方が汎用性があるような気がしてなりません。prelinkはバイナリをいじるので、いくら可逆な処理でいつでも元に戻せるとは言っても、心配な場合は心配です。


で、binutilsの最新版のソース(2.18)を眺めて2.16と見比べて、パッチを嘗め回しているのですが、すでに取り込まれているのかどうかさえ、さっぱり分かりません。たぶん気合が足りないのでしょう。ちなみに、2.16のelfc.はどうやら2.18のelflink.cに相当するようです。


リンク

prelinkの初心者用説明資料

CE Linux JapanTechnicalJamboree16

Summarizing Dynamic linking, part 3

Session for beginers

by Tetsuyuki Kobayashi (Aplix)

MIPSもprelinkに対応しておられるようで。

LD_DEBUGによるロード処理のデバッグなどについても説明があります。

挙げられている参考図書

Linkers & Loaders

Linkers & Loaders

Binary Hacks ―ハッカー秘伝のテクニック100選

Binary Hacks ―ハッカー秘伝のテクニック100選

俺のフッター

検索

日記の検索

トラバとコメ

最近のコメント

カウンタ

ページビュー
785898

トップハテナー

syasudaのトップハテナー