DWARF の行情報を読む

DWARF の行情報を読むのをWindowsでやってみた。ELFをPEにしただけ。
http://github.com/firewood/test/blob/master/addr2line.cpp

今のMinGW-GCCデバッグ情報はDWARF2がデフォルトのようで*1、-gをつけると.debug_lineが付加されるようになる。*2

PEだとIMAGE_SECTION_HEADER内のセクション名には8文字しか入らず、ポインタらしき名前がついている。バイナリの末尾に文字列テーブルがあるが、そこのオフセット値がどこに格納されてるかわからなかったので、とりあえずきめうちで/61をダンプするようにした。

これの実行結果は

extern int printf(const char *, ...);
int main(int argc, char *argv[]) 
{
    printf("Hello, world.\n");
    return 0;
}

こんな感じになった。

hello.c:3: 004013F0
hello.c:3: 00401401
hello.c:4: 00401406
hello.c:5: 00401412
hello.c:6: 00401417
hello.c:6: 00401420

ちょっとがんばればVC++の「混合モードを表示」みたいなのができる。超がんばればデバッガも作れる…かもしれない。

*1:以前はstabsのみサポートだった気がする

*2:例外のスタック巻き戻し方式でSJLJとDWARF2があるが、いずれもデフォルトは-gdwarf2のようである

SICP自習

SICP Lite #9に行かなかったので自習。
DrSchemeにてある範囲の素数を求めて、結果(個数)と実行時間を表示する。divides?とprime?はあるとして

(define (search-for-primes start end)
  (define (next n)
    (+ n (if (divides? 2 n) 1 2)))
  (define (loop start end result)
    (if (> start end)
        result
        (loop (next start) end (+ result (if (prime? start) 1 0)))))
  (loop start end 0))

(define (timed-search start end)
  (define (print-result result time)
    (print (string-append "prime count: " (number->string result)))
    (newline)
    (print (string-append "exec time: " (number->string time))))
  (define (loop start end start-tick)
    (print-result (search-for-primes start end) (- (current-process-milliseconds) start-tick)))
  (loop start end (current-process-milliseconds)))

ちょうどリーマン予想NHKスペシャルを見たところで、級数からπを求めるとかいうタイムリーなトピックがあって楽しい。(習ったのかもしれないが完全に忘れてる)

情報科学苦手の会

twitterで見かけて参加。

  • 具体的なプログラムは組まずに
  • 参加者各自が苦手な事について自由に雑談や議論を交わしたり
  • 苦手なことについて自習したり
  • 教えられる人が居れば積極的に教えてあげてください。
  • 今勉強していることをスライドで発表する

というイベントとのことで、その場で聞くというスタイルは良いと思った。
以下時系列イベント

自己紹介

せっかくnyaxtさんがいたのに3Dが苦手と言うのを忘れた。しかしながら、知りたいことが漠然としすぎていて、もう少し何か書いてみようと思った。

C++の話 shinh

G++が吐くアセンブリコードの話。多重継承したときのvtableの内容とか、virtual関数のポインタを取ると中身がただのindex値とか(VCはポインタとのこと)。例外(SjljとDWARF)でどうやってスタックを巻き戻すのかとか。
○○になってますよ、という説明で、はいそうですかと納得するのは騙されやすいタイプ(探究心が足りないという意味だと思われ)。

ホワイトハウスへの道 yuyarin

まずCDNの話。ホワイトハウスのwebサーバにアクセスすると、最も近いAkamaiのサーバを見てるだけかもとか。次にGoogle Public DNSとIP Anycastについて。物理的に別のサーバに同じアドレスを振り、最も近いところにアクセスするという点ではCDNに似てると思った。
以前DNS応答時間を調べたことがあって、結構な頻度で数十msくらいかかっており、自前でキャッシュしたらそこそこ速くなったりした。Google Public DNS使うと劇速というのは納得できる話。
ネタ的には、ホワイトハウス内にはwebサーバは一台もないから「本物」には到達不能ではないかとか。

diffのアルゴリズム cubicdaiya

編集距離について。図でなんとなくわかった気になったけど対角線の距離のところで挫折。最悪値が全削除→全追加で、そこから最も遠い点を求めていくみたいな感じなのかな。
WinDiffは追加・削除のほかに移動も教えてくれるのだが、これは質問したら「hunk(差分)に対してdiffを取ればわかる」との答え。なるほど。

expornentialの実装 herumi

floatのe^xの高速実行について。floatの内部形式が(1+n)の形なので、それをうまく変形するとテーブル引きできるようになったという話。
doubleだと表が爆発するんじゃ?という質問に対しては、e(a+b)=e(a)e(b)であり、上位ビット群のみのテーブル、中位ビット群のみのテーブル、下位ビット群のみのテーブルみたいに分割していけるので実装可能とのこと。
あとx86のdoubleは内部で80bitで扱ってる云々の話が出てWikipedia見てみたところ、8087はIEEE754の原型になり、80387で完全準拠とのことだ。ただしSSEの命令の一部の誤差は非準拠らしい。あと改定されてIEEE754Rになるぽい。

MVCの次は? NetPenguin

MVCの解釈が人により違うとか、じゃあなぜMVCが誤解されてるのかとか、誤解されなければよいだけでは?とか色々突っ込みが入ってこれは地雷(みんなMVCの話が好きすぎる)ということに落ち着いた。

SMPカーネル syuu1228

カーネルをSMP対応するときの作業内容など。スケジューラは、Hyper-threadingやNUMAなど固有の特性を知っておかないとロックしたりするとか。

goのアセンブラ ucq

見た目はx86っぽいアセンブラだけどビルドするとわけわからんことになっているらしい。コマンドが8a。

L3以下のIPの話 yuyarin

1000BASE-TXの変調方式の話など。素晴らしき低レイヤの世界。

FPGAとは何ぞや firewood

Google GroupでshinhさんがFPGAわからんと書いてたので、プレゼン聞きながらその場で書いた。はよピザ食わせろという殺伐とした雰囲気の中、ThinkPadが固まり再起動してさらに待たせることになった。HDLは10行くらいしか書いたことなくて嘘を言ってないかどきどきしながら発表した。学校の演習でCPUを書いた人とかいて釈迦に説法感ばりばりではあった。

個人的にはFLTVの時もそうだったけど微妙にカオスな感じがクラブ活動みたいで面白かった。
開催前は小さいQ→Aを繰り返す会みたいな感じにしようという思惑があったのかもしれないのだけど、始まってみると個々のトピックでは得意な人もいるために、苦手な人は埋もれて得意な人が前に出るみたいな感じになってしまった面はあったかと思う。(どこが苦手なんだみたいな突っ込みが何回かあった)ただ、会のタイトルが苦手ということで、素朴な質問でもOKという雰囲気ではあったと思う。そこは特に良かった。開催感謝です。

ONE PIECEの新聞広告

新聞の朝刊にONE PIECEの全面広告が9面が載っていたのだが、家庭用スキャナを使ったのかと思うくらいの画質で驚いた。
スキャニングのジャギーがくっくり印刷されてて、線の力が削がれてる。

それにしても広告の比率高いなあ。紙面の6割は広告って感じ。

スパコン

wikipediaによると

だそうな。

スパコンの開発能力が重要なのか、スパコンの利用能力が重要なのかは自明でないのだが、どうせ1位を取ったところで数ヶ月しか持たないレベルなわけだし、無理してシステム全体の開発技術をがんばるよりは、半導体製造技術とか要素技術に特化して底上げを図ったほうが国際競争力の維持につながるんじゃなかろうか。
汎用京速計算機のメインプロセッサは45nmプロセスとのことだが、PC向けプロセッサではすでに旧世代であり、開発中から時代遅れという悲しさだ。富士通にしても先端プロセスはTSMCに委託とかいうありさまなわけで、世界との差を埋めるために国が支援するのはありだと思う。半導体産業は博打だと言われているが、現行プロセスだと1チップ作るのに何億もかかったりして、博打に参加すらできない状態になっている。アイディアがあってもチップを作れない人たちがたくさんいるはずで、仮に最先端のプロセスを数百万のオーダーで利用できるようにしたりすれば半導体百花繚乱時代が来るのは間違いない。何やってもどうせ赤字なんだから出血大サービスすればよいんじゃなかろうか。

ThinkPadのBIOS書き換え

ThinkPadBIOSで内蔵無線LANカードのベンダチェック(特定のカードのホワイトリストを持っていてそれ以外を拒否する)をしていて、純正品でないと1802というPOSTエラーが発生して起動しないようになっている。
ある世代(X31とか)はno-1802.comというプログラムでBIOSCMOSデータを書き換えることでこのエラーを回避できるのだが、そのあとの世代(T60とか)ではプログラムを書き換えれば可能という感じ。で、解析してる人とかツールを開発している人がいたので試してみた。

手順としては

  1. Phoenixのサイトからデモ版のPhoenix BIOS Editorをダウンロードしてインストールする(上記サイトにリンクあり)。
  2. Cygwinを入れる。
  3. 上のサイトからphcompなどのツールをダウンロードする。
  4. phcomp /D $01A3000.FL1 で圧縮を解除する。$01A3000.FLH ができる。
  5. phnxdeco $01A3000.FLH でモジュールに分解する。いっぱいファイルができる。
  6. 書き換えたい部分のファイルを見つける(T60の場合、phoenix_.B5)。
  7. Phoenix BIOS Editorを起動したままにして、プログラムフォルダにあるPREPARE.EXEを適当なフォルダにコピーする。
  8. テキストファイルROM.SCRを以下の内容で作成する。
    COMPRESS LZINT
    BIOSCODE phoenix_.B5
  9. PREPARE ROM.SCR で圧縮する。できたPHOENIX_.MODをold.MODとかにリネームする。
  10. phoenix_.B5を書き換える。
  11. PREPARE ROM.SCR で圧縮する。(念のため、どこを書き換えたのか元のファイルとdiffを取って確認すべき)
  12. 書き換え前とファイルサイズが違ったら書き換えに戻る(PhnxPatchを適用した場合ホワイトリストは使用しないので、そこを適当なデータで埋めて調整する)。
  13. phnxmod $01A3000.FLH old.MOD PHOENIX_.MOD でモジュールを差し替える(ファイルサイズが違うと失敗する)。
  14. phnxcksm $01A3000.FLH でチェックサムを再計算して埋め込む(重要)。
  15. phcomp $01A3000.FLH で再圧縮する。
  16. $01A3000.FL2 とかいうのができるので、元のFL1と差し替える。元のファイルとだいたい同じサイズなのを確認しておく。
  17. IBM/LenovoBIOS Updateユーティリティーで書き換える(同じバージョンだと書き換えられないので、いったん古いのにしてから更新する)。
  18. 運が良いと起動ロゴが出る。

久々に16bitのアセンブラ見てにやにやした(なんかeaxとか使ってて邪道だけど)。書き換え間違うと二度と起動しないので多少のスリリング感がある。ThinkPadには復旧手段はないので注意。

ドメイン名つきでプロキシを通す

昨日、SICPの勉強会でお会いした人と「http_proxy の指定方法で困っている」の件で少し話をしたので、ちょっと試してみた。
ローカルにプロキシをたてて、

# export http_proxy="http://hoge\\fuga:password@127.0.0.1:8001/"
# gem install rails

とかやってみたところ、URI::InvalidURIErrorというエラーになった。これを出しているのはuri/common.rbで、該当する表現USERINFOは(?:[#{UNRESERVED};:&=+$,]|#{ESCAPED})*となっており、バックスラッシュが含まれていない。
ESCAPEDが入っているので試しにhoge%5cfuga:password@にしてみたところ、InvalidURIErrorは出なくなったが、HTTPヘッダをダンプしたらhoge%5cfuga:password(をbase64エンコードしたもの)がそのまま入っていた。


ではUSERINFOでバックスラッシュを許容するように変えてみたら、ということで

USERINFO = "(?:[#{UNRESERVED};:&=+$,\\\\]|#{ESCAPED})*"

に変更してみたところ、これだとヘッダを見る限りでは動作しているようだ。


RFC的には、http_proxyにはパーセントエンコーディングしたものを設定して、Proxy-Authorizationを送信する際にパーセントデコードしてからbase64エンコードするのが正しいんじゃなかろうか。
ユーザー名はともかく、パスワードには記号を入れるケースはありそうなので、パーセントデコードしなければならない気もするが…。そういやIEではuser:password@の形式がサポートされなくなってたのだった。フィッシング詐欺対策だったのか。