* Essen開発メモ(1) -(by [[K]], 2018.03.05) ** 2018.03.05(月) #00 JITBで遊ぶ -JITBというのは、即興で考えた造語。JITコンパイラはJITC。じゃあもしJITで動くアセンブラがあったらJITA。そして16進数を直接入力してそれがいきなり動くプログラミング言語があったらJITBかなー、というそれだけのこと。 -そのJITBを作って、コンソールから入力した16進数がすぐに実行されるのを眺めて、最初は面白かったんだけど、すぐに飽きた(笑)。まあ実行ファイルをいちいち作らなくてもいいっていうのは、新鮮と言えば新鮮。 -やっぱりJITAくらいじゃないと、結構大変である。16進数を全部覚えているわけじゃないので・・・。 ** 2018.03.06(火) #00 次はどうしようか -とりあえず[[page0002]]でJITBについては遊びつくしたので、次はJITAかなあ。そうやって少しずつ言語を低級から高級にしていけば、いつかはEssenができそうな気がする。 ** 2018.03.08(木) #00 JITA -ひとまずJITAを作り始めた。オペコードのみの命令ならアセンブルして実行できる。16進数を直接入力しなくていいのは快適だ。あとRDTSCが例外を出さずに実行できたので、win32ではCR4によって禁じられていないのだなと分かった。 -今は238行で5.0KB。 ** 2018.03.19(月) #00 -もはやのんびりと作って壊してまた作って・・・をやっている暇はない。確実に積み上げられるやり方で作っていかなければいけない。となると、やはりアセンブラレイヤを作り、必要に応じて最適化ができるようにしておいて、その上に高級言語レイヤを載せなければならない。 ** 2018.04.01(日) #00 -さて、年度も変わったことだし、明日からちょっとずつ再開しよう。 ** 2018.04.11(水) #00 -EssenRev4のJITコンパイルでは、浮動小数点演算でFP命令を使わずに、SSEスカラ命令を使おうと思っている。FP命令のほうが対応CPUが多いけれど、SSEのほうがレジスタ番号で管理できてわかりやすそうだから。 -ということで、参考になりそうなサイトを探しておいたので、忘れないうちにメモしておく。 --SSE2による浮動小数演算の仕組みと検証 https://codezine.jp/article/detail/458 --x86/x64 SIMD命令一覧表 (SSE~AVX2) http://www.officedaytime.com/tips/simd.html --PAND (Logical AND) https://cmpsb.net/asm/x86/instr/view/264/PAND ** 2018.04.17(火) #00 -昨日C言語でちょっとしたプログラムを書いていて、まあこんなものかなと思った関数があったのだけど、果たしてこの関数はちゃんと期待通りに動いているのか、と心配になって、適当に値を入れてみて計算してみた。するとまあ全然期待通りに動いてくれない。・・・おお、これぞまさに私が根絶したい現象そのものではないか! -もちろんプログラムはその後あっさりと直ったわけだけど、どうすればこういうのにもっと早く気付けるだろう。チェックしたいという気持ちにさせるにはどうしたらいいのだろう。 -まあ「どこまでテストするかはプログラマの自由です」としかできないかもしれないけど、テストしやすい仕組みを提供することはできるはずだよね、っていうか提供したい。 -ユニットテストがしたいのかというと、まあそれでもいいかもしれないけど、でもちょっと違うような気もする。「テスト」だと、これこれを入力したらこれが出力されるはずっていうのがあるわけだけど、そういう想定される結果がある状況より前に、とりあえず0を入力してみよう、何が出てくるかな?・・・あれ??・・・みたいなのが気楽でいい。つまり何が出てくるはずだっていうのをしっかり予想するのはそれなりに大変だけど、適当に入れてみて出てきた結果を見て、「えっ?」ってなるのは簡単なので。 ** 2018.04.17(火) #01 -とりあえず、230行くらいはできた。といってもメモリ管理部分だけだけど。 -いやその、セキュアな言語を作るためには、まず言語を作りやすい環境を整備したほうがその後ははかどるわけで、だからまずはそういう基準で作っている。 -そしてC言語はメモリ管理が大変なので、まずはメモリ管理を簡単にするためのライブラリを作った。ひとまず自分の気が済む程度のものはできた。これでソースコードのパーサーを簡単に作れるはず!(いや、まともなメモリを管理しないで雑なものならすぐに作れたけど、やっぱりメモリは無駄にしたくないわけで、そうするとメモリ管理をしなければならず、だからそういう自前ライブラリを作っていたのだ)。 ** 2018.04.23(月) #00 -とりあえず、以下の程度なら実行できた。 >exec asm386 { PUSH 13 POP EAX } 6a 0d 58 // これはデバッグ用の表示 sz=3 ec=0 // これはデバッグ用の表示 >regs <regs> eax:0000000d ecx:00000000 edx:00000000 ebx:00000000 esp:00840000 ebp:00000000 esi:00000000 edi:00000000 <stack> > -さらにちょっとだけ頑張って、 >exec asm386 { PUSH 1+2*3-4 } -こういうのもできるようにした。・・・あんまり使わないかもしれないけど。もちろん演算子の優先順位は真面目にやっているよー。 -ここまでやって実行ファイルの大きさは9.0KB(ソースコードの行数とかだと、コメントなどに左右されてしまうので私はあまり使わない)。 ** 2018.04.24(火) #00 -ADD, OR, ADC, SBB, AND, SUB, XOR, CMPをちょっとだけ実装。 >exec asm386 { ADD AL,2; SUB EAX,1; AND EAX,0xffff} 04 02 83 e8 01 25 ff ff 00 00 // これはデバッグ用の表示 sz=10 ec=0 // これはデバッグ用の表示 -よしよし、ちゃんと動いているな。 -実行ファイルの大きさは10.0KBになりました。 -この調子で4月中に高級言語に行けるかどうかは分からないけど、まあ地道に頑張ろう。とにかくアセンブラをSecHack365やセキュリティキャンプの受講生に使えというのは無理な話なので。 -まあこの調子ならもうすぐアセンブラは終わるので、そしたら次は中間言語で、それができたらEssen本体が作れるんじゃないかなあ。連休明けくらいまではかかるかも。 ** 2018.04.27(金) #00 -油断していると大規模な開発になりそうになる。落ち着け川合。 -できるだけシンプルに最短で目的を達成する方法を考えるのだ。そうしなければ間に合わないし、本質を見失う。 -そしてMOV命令もできた。まあ難しくないからできて当たり前だけどね。 -メモリ関係の命令はまだ全然できていないけれど。 -次は何にしようか。お、Jccを作ればレジスタだけで簡単なループはできるなー。 ** 2018.05.01(火) #00 -セキュリティチェックのためのコードをどうしようかと検討中。・・・とりあえず高速にすることはわきに置いて、作りやすい構造を選ぶことにしようと思う。最初から難しい構造にしてしまうと、手に負えなくなってしまうかもしれないから。 ** 2018.05.01(火) #01 -セキュリティだけを考えたら、なんでもチェックすればいいのは間違いないだろうけど、そんなに何でもかんでもチェックされたら、当然だけど遅くなる。それで何をチェックすべきかを考えた。 -まず初期化されていない変数へのアクセスは検出できるべきだ。不定になっているのである時はうまく行き、ある時はうまくいかない、みたいになって再現性の問題が生じて、きっとデバッグを困難にするから。 -ポインタがおかしくなって予期せぬ場所を上書きするケースもブロックするべきだ。 -逆に、以下のケースはそれほど深刻ではないと思われる。ポインタがおかしくなって読んではいけないところが読めてしまうというケース。これは悪意あるプログラムが保護されたデータを読むことを阻止するためには防止しなければいけないかもしれないけど、今回はプログラマが自分で書いているプログラムだけを考えているので、わざと読みたいのなら読ませてやればいいと思う(とはいえ、完全にノーチェックで読まれると結局はOS側のアクセス権例外で落ちてしまうので、それを避けるためにチェックは必要だな・・・)。 -プログラムは、ポインタのアクセス域などを自由に設定できるけど、その設定する権限とかは設計する必要がないと思う。つまりプログラムは自分にかかっているセキュリティ機能を自分で解除することもできる。たとえば、ある限られた範囲にしかアクセスできないポインタのリミットを変更して、メモリ域を自由にアクセスできるようにもできる。 -当初、オーバーフローの検出も積極的に考えていたけど、オーバーフローしても値がおかしいだけで、誤動作はしないかもしれない。むしろ問題は、適切ではない値を受け取ったときに誤動作するほうがまずいのではないか?・・・つまりすべての命令は、不適切な値を渡されても、大事故が起きないように設計されていなければいけない。 ** 2018.05.02(水) #00 -なんかさっき、一瞬だけ全体が見えたぞ。これは行けるという感じがした! -構造体: --メンバのオフセットと構造体のサイズを内部で計算しておけば、あとはabc->defを[abc+offsetof(def)]にすればいいだけだろうと思われる。 -配列: --とりあえず1次元配列だけを考える。要素のサイズをsとすれば、a[i]っていうのは[a+i*s]に展開するだけのことなんじゃないかな? -配列と構造体さえなんとかなれば、それ以外はOSECPU-VMのときにやったことあるから、きっとなんとかなりそう。 ** 2018.05.10(木) #00 -今日はEssenで使う[[blaライブラリ>page0010]]のMacOS版の開発をしています。こちらには今はMacがないので、SecHack365の受講生に実行してもらうという、なかなかひどいことをやっています。しかしそれでも、ちょっとずつ進んでいます。 -そしてなんと移植に成功してしまいました。おお、なんて運がいいんだ。SecHack365の人たちもうまくいかないときに自発的にスクリーンショットを見せてくれて、すごくはかどりました。みんな優秀だな・・・。 ** 2018.06.08(金) #00 -[[page0013]]に書いたjck0ライブラリの実力(というか限界)を探るために、いくつかのプログラムでアセンブラで書いたりC言語で書いたりした場合と比較しているのだけど、jck0ライブラリは結構強力で十分な速さのバイナリを出力できているっぽい。C言語やアセンブラに負けてない。CPUに依存しない仕様でここまでできるっていうのは我ながらたいしたものだと思う。 ** 2018.07.01(日) #00 -TJ08が「こんな簡単な仕組みでもここまでできる」的な意味では結構な完成度で、なんか山を一つ越えた感じがある。・・・さて次はどうしようか。演算子の優先順位をやろうかと最初は思っていたけど、jck0の一般メモリアクセスも楽しいかもしれない。・・・まあ適当に両方やればいいか。 * こめんと欄 #comment