.Net で動くちゃんぽんアセンブラー、予定: 1.「monのアセンブラこれ使いずれーな…   んじゃ作るかぁ。アセンブラをバイナリに落とすぐらい、   .NetFrameworkとかstdlib使えばすぐできそうじゃんw」 2.「どーせなら色んなCPUに対応するかー。スクリプトでCPUとか定義して…   それを実行すりゃいいか。   あーそいだとスクリプト実行は遅いから、直接ネイティブアセンブラを   RAMに用意して、スクリプトをネイティブアセンブラにしよう。   せっかくx86CPU勉強したばっかだしー。」 3.「そういやぁ自己ブレークポイントのコードの続き、未完成で   放置してたっけ。これをベースに発展させないと   スクリプト>ネイティブアセンブラコード出力は出来ないなぁ。   久々に続きちょっと調べてみるかー。」 4.「うおおおうごかねえ〜〜〜!!!なんでうごかねーんだ!!!」 5.「はぁはぁはぁ・・・   VirtualProtectはなんとか通るようになったぜ・・・   でもアドレス指定が・・・うう・・・・」 6.「オフセットアドレス、きちんと指定すりゃブレーク張れるんじゃねーの?」 7.「じゃ、関数の物理メモリアドレスを求めてみるかー。   どうやんだろ? 8.「どうやっても動かねぇ!!メモリ読み取れねぇ!!」 9.「パソコン壊れた!熱暴走の原因わかんねぇ!!」1年以上放置 10.「よしノート買った!・・・バックアップ・・・修理依頼・・・etcetcイソガシイ」 11.「そういや昔買ったゲーム機で続きやるか・・・おもすれー(^ω^)」 12.「FM音源コンバーターやろう!」「数学!」「家事w」「デバッガw」「いんたーねっつw」 13.「デバッガ直す時間ねぇ!」 14.先週発見した数式アップしとこっと。その前にホームページちょっと直しとこう。←イマココ VAlloc.vbはアセンブラだったんだよ!!! ナンダッテーーーーー System.Diagnostics.SymbolStore https://docs.microsoft.com/ja-jp/dotnet/api/system.diagnostics.symbolstore?view=netframework-3.5 https://tutorialmore.com/questions-1349930.htm ICorDebugCode::GetILToNativeMapping メソッド https://docs.microsoft.com/ja-jp/dotnet/framework/unmanaged-api/debugging/icordebugcode-getiltonativemapping-method MSIL > native オフセットを取得 により、自己exe, 自己セルフデバックモジュールを入れたいw こんな感じの設計図w 追記: 自己セルフデバッガ機能は諦めました。別プロセスから Win32API で 接続しないとソフトウェアブレーク機能が 使えない為です。 (自分でデバイスドライバを作ればそりゃ動くだろうけど) R2.8.27時点: 相変わらず、ソース行にブレークポイントをはろうとして そのMSILのコンパイル前のアドレスが取れずに困っています。 分かった点:  ・System.Diagnostics.SymbolStoreは単独では読み込みオブジェクトを   作れない。LCR Runtimeのメタデータ読み込みモジュールを呼び出さないと   シンボル等をアクセスできない。  ・CLR Runtime Engine を読み込むには MetaData Dispenserクラスを   ロードしないといけない。   が、コレはMS VC++ にしかないヘッダー、ライブラリ、DLLを使う必要がある。   C:\windows\system32\rometadata.dll MetaDataGetDispenser の呼び出しで   代替できるが、出来るのはWindows8以後。(これまたVC++なしで   本当に動くのかかなり怪しい)  ・VB.NETから呼び出すんだとInteface その他全部手で再定義して   あげないといけない。    ・上記でVBソースコード - MSIL - nativeOffsetを特定して、   そこのアセンブラを書き換えるw  ・ネット上にSystem.Diagnostics.SymbolStoreのソースが多少あるけど、   コピペで動かせるコードはない。   その上なぜかGUIDを打ち込んで呼ばないといけない、さっぱり訳わかめ。  ・System.Assembly.ReflectionにもMetaDataReaderとか   MetaDataReadProviderとかがある。多分デバッガ=VisualStudio   本体との通信用で、デバッグ行情報やシンボル情報の問い合わせとは関係ない。  ・MSILの仕様書がネットから発掘されました。ECMA-335という規格を   マイクロソフトが中心に、IBMその他各社と共同で策定したそうです。   わーい、MSILの内容読めるじゃん!   (それ以前にうちの環境ではMSILのダンプをする方法を確立していないw)   んーーーー、これPC88やファミコンとかと互換性持たせられるのかなー、   うーーーーーん。気になる。  ・GitHubにpdbファイルフォーマットの内容をMSの偉い人がアップしている!   もの凄くラッキー!   ソースはかなり分かりやすく、すごくきれい。NTFSやMemoryMappiedIO、その他   WindowsOS内部の機能に詳しい人だったら多分そんな難航しない気が。   バリバリOS依存コードです。長い。何やってるかよく分からない。   でもうちは単純テキストエディタで読んでるからすごい時間かかるw   しかもオールC++(notCLI)なので、動かすにはうちの場合VB.NETにコードを   全部書き直す必要があるw   1つのクラスがばかでっかいので、その境界を読み解くだけでも大変w   多分、Visual Studio等の高額なツールがあればスイスイ解析出来るんでしょう。   MST関係すら解析出来ないので終わっている!!!   ブレークアドレスをソース行から求めるのはやっぱり難しい!   こんだけ大変な物作ってもらっててしかも金払わないのは失礼だから、   こっちで実装するのは機能不全版にする予定w   (というか…同等機能を実装するのはどう考えても無理。全部VB.Netにコード置換する   なんてやってたら終わらないしwつかシンボルウォッチなんかどう考えても   実装無理)   上記コードから、何ヶ所か要点だけ抜き出してVB.Netでコードを組んで   動かせばいいかな…。とかいう非常に甘い見込みw   アセンブラ本体のコード、いつになったら出来るんだwパソコン買えよオレw R2.8.28時点:  ・oleからのdispencer呼び出しは諦め。やり方よく分からない。  ・pdbファイルの中身の解析。といってもぼけーーっとバイナリダンプ眺めて、   ネットで資料漁ってその文法が合ってるか調べるだけ。   「・・・全然分からん。この数字なんだろう・・・こうかな・・・こうかな・・・・。    ネットで資料漁ってみるかぁ。    あれ?こんなHPあるんだー!おお、合ってる!その通りだ!!!    あーここもそうなのかー、あーここもか〜〜・・・・・・・・・・    あれ?これ、資料通りにやっても全然合わないよ?・・・あれ?ここも合わないよ?    なんだだよぉぉぉ〜〜〜」      「API使ってデバッグ情報を見るのを強くお勧めします」ってハッキリ   書いてありました。      経験上で言えばですが。   デバッグ行情報はまぁだいたいなんとか取れます。(某社S〇f形式のをコンバータで(ピーーー))   なので強行してやってるんですけど・・・。   シンボルのうち構造体、構造体、共用体のネストや循環参照・自己参照、typedefなどがかなり難しい。   専門でやってる会社なら出来なくはないでしょうけど、日曜大工で出来る範囲を到底超えています。   デバッグ情報は、実は恐ろしくとてつもない巨大ソースになるのですw   でもこれやらんとシンボルウォッチできねーんだよな〜。   シンボルウォッチがマウスでスイスイ出来るか出来ないかで、デバッガの   使い勝手が全然違うんですもん。   今どき、変数を構造体やクラス等でカプセル化しないなんて   乱暴なコード書けないし。   (ラップし過ぎると中身が何やってるかサッパリ分からなくなる。   コードがどういう順序で動いてるのか分からなくなるw    この点でMS系の「コード部分隠し機能は凄い便利だと思います。    見えないから毎回開く羽目になったり、非表示表示の切り替えが    凄く面倒臭くなるけど。    ・・・がwカプセル化しなさ過ぎるとコードがグローバル化し過ぎてもっと訳が    分からなくなるw)   デバッガが軽いかとんでもなく重いかは、使い勝手の面からすると   すっごい大事な問題なのだと思います。   (たいがいのソフトのシンボルウォッチはまず100%バグがあって、    ちょっと複雑な使い方をするとアプリケーションエラーで落ちるw)   英語系のHPでは幾つか pdb ファイルフォーマットについて説明があり…。   さらに・・・pdbのバージョンによって中身の形式が全然違うようです。   どうやらwやだわーーー、どうりでテストファイルと形式全然合わない   訳だわw      呪われてるぅ〜〜〜〜。祟られてるぅ〜〜〜〜。呪われてるぅ〜〜〜。祟られてるぅ〜〜〜〜。 R2.8.30時点:   頭のヘッダ付近だけ何とか読めそうなのでそこだけコーディング中・・・。   最初のMSTなんちゃら、の文字を読み取って内容を定数と比較するだけで   オオハマリw   ・・・・ASCIIエンコーディングの文字列とシステムの既定のUnicodeエンコーディング   とで文字列比較しても一致しないのね・・・この人・・・ちょっと驚きw   改行も比較したかったけどなんか出来ないや。なんでだろ・・・面倒くさw   数字を読み取るだけでもハマるしw   1バイト読み取って4ビットシフトして・・・「あれーなんで読めないんだろ   このバイト・・・あれ・・・あれ・・・」・・・なぜ4ビットシフトではなく、   8ビットシフトだと気付かないんだ俺はwあほかバカかw   という感じで凄く大変です。これは・・・ちょっと先が長過ぎるw   ページサイズは1k〜とネット上のではなってるけど・・・うちで今テストで   使ってるサイズ、200バイトなんですけどw先行きがあまりに不安過ぎるw   お、恐ろしいw R2.8.31時点:   SMT?だかのヘッダ、ストリーム情報読み込みのコードちぅ。   ・・・あれ?List型のメンバ、Nothingが設定出来ないよ?newで配列サイズ指定   も出来ないよ???ナニコレ?なんでコンパイル通らないの? ' stream Info ( SI ) friend Structure stSI Dim dwSize as UInteger Dim lstUPages as System.Collections.Generic.List(Of UInteger) End Structure mstRootStream.stStrmTbl( nCnt ).lstUPages = Nothing   うーーーん、何が悪いんだろう…。   VB.NetはもともとGeneric型の対応が少し悪かったりしたのですが   (最新のはシラナイけど)   多分型情報に関してかなりの混乱があるのでしょうね。多分。   もともとはコンパイル時にobject型になんでも突っ込んでも   エラーが出なくなってしまうのを回避するためにgeneric型が考案された   「らしい」のですが、汎用的にどんな型も指定できるようにしちゃおう!   とか、いくつかの設計思想がぶつかって混乱がある、ようですが。 R2.9.1時点:   前日の原因判明w   単にstruct でやってたからwclassでポインタ扱いしてなかったからw   値渡しなのですね。参照私にしてないから…。   System.Collections.Generic.Listで生成した配列にアクセスできなくて   かなりハマリ。   new で数指定しても、Add で追加をきちんとしないとアクセスできないらしい。    mstRootStream.StrmTbls = new System.Collections.Generic.List(Of clsSI)( _ mstRootStream.StreamCnt - 1 )   これやったあとに    Call OpenHeaderAndRootStream_ReadPageWithOffset( _ bytRead, _ 4 + (nCnt+nStAdd) *4 , _ mstRootStream.StrmTbls( nCnt ).dwSize )   これじゃアウト。    mstRootStream.StrmTbls.Add( new clsSI() )   これやらないと配列が駄目らしい。ひえーー、知らんかった・・・。   うへwwwwど素人w R2.9.3時点:   streamの読み出しが多分出来るっぽい。   List型を使って「オレってできる奴!」演出コードにしようと   思ったのに、List型にクラスインスタンスを押し込もうとすると   IEnuableインターフェイスを継承しなきゃいけないけど、   今度はその実装の仕方がサッパリ分からずオオハマリですw   「あれ…このメンバとこれと、GetEnumulator使って…」   「ありゃw自分で配列のメモリ管理しなきゃいけなくなるんじゃんw    List使う意味ねーじゃねーかwどうなってんだ訳分からんw」   「ありゃ、Listなのにindex指定、0から連番だと思ったのに・・・    これキーワード指定なんじゃん!使い方間違えてるじゃねーかw」   「System.arrayのジェネリック版は・・・うほ、どれか分からないw」    駄目な子の典型ですね。しったか振りしてどつぼw    駄目な子の典型例のオレは、仕方なくジェネリック型使わずに    配列を使う事にして、フツーにarray.CreateInstanceで    配列インスタンスを押し込む事に致しました。無能。    そしたらすぐ動きました。あふぉーーーーーー。    (デバッグ表示用のルーチンでindex溢れして     アプリケーションエラー出して、どどーーーーんしたのはナイショ。     デバッグ用ルーチンでミスってどーすんだよオレ・・・     どどーーーーんw)   ・・・が。肝心のデータ、   どのストリームから読むべきかまるで訳わかめw   0番から順に中身を解析?し始めるも…。   もうほとんど英語のHP頼みw自力解析はほぼゼロw   自己ブレークポイントがここまで厳しい道のりとは…。   ソースコード開示されてるけど、何書いてあるのかサッパリだしぃw   すっげー時間かかるな…どういうデータ形式なのかを理解するだけでも   恐ろしい時間がw   うーーん、stream0とか1とか、一体何やってんだろう。訳わかめw   stream3のDBIを見てますけどsubstreamがどどーんと出てきて   うん、結構危ないw   でもネットに資料あるだけマシだねこりゃ。運が良過ぎる。   VisualStudioのバージョンが変わったら全然使えなくなりそうなので、   やはり作る意味があまり無さそうです。うーーーん。   しっかし、バージョン番号を10進数にすると年/月/日になるとは…。   こんなオシャレ、しゃれてる、遊んでるバージョン表示は珍しいw   マイクロソフト系のツールとしちゃ珍しいバージョン表記ですよね。   やっと何とかデバッグ行情報を取得出来そうな感じ…。   Module Sym Stream の中にあるのですが。   [Module Sym Stream] <- stream 3 に頭から入っている、struct ModInfoのメンバからストリーム番号持ってくる    (Module Sym Header)    (Module Info Substream)    (行情報 Substream)    .....   行情報に関しての資料が全然無い。公開ソース読んでも分かんないし…。   ネットのgoogle_breakのソースがあれば解析はひょっとして必要ない?    CV_LineSection, CV_SourceFile, CV_Line x たくさん   これでいいのかなぁ…。   Grobale/Public Symbol streamを読むのは地獄そうな感じ。   まず(size)*1byte (定義ID)*1byte の他に   まず(size)*2byte (定義ID)*2byte の形式があるwその上に山ほどあるw   挙句にLLHM?のホームページだとVC++専用に特化してるのでVB.NETにも   対応したデバッグ情報の形式がどこにも書いてない。(定義ID)*2byte > cvinfo.h を   検索、そこから構造体を特定すれば何とかなるようです。でもすっごい   数多い。探偵じゃないともう無理よこれw   我ながらよくこんな方法見つけたもんですが…(びじゅあるすたじぉちゃん降臨の予感w)   バイナリの中見て、「・・・これ何を表現したいんだろう・・・」と   茫然しまくって、あっちこっち資料読まないと分からない感じ。   読んでも分からないからソースとにらめっこして、ガッカリする感じw   こんなどうでもいい事で時間使っていいのかオレwダメ人間一直線w   なんかすっごい大変だなー、これ〜〜〜。でも挫折せずに   どういう訳か次から次へと新しい「答え」が出て来る辺り、   下手な推理小説を読むよりも「丁度いい難易度で面白い」事は   確かなのかも。中毒性高いな〜。でも積みそうだな〜〜〜〜。 R2.9.4時点:   なんとか行情報取れたくさいです。   [Module Sym Stream]   (Module Sym Header)    [Module Sym section]    [Line Info Section] = CV_DebugSSubsectionHeader_t    (LineInfo) = CV_DebugSLinesFileBlockHeader_t    (LineInfo じっさいの)*n = CV_Line    (LineInfo なにこれ?)*n = CV_Column_t    (DEBUG_S_FILECHKSMS)    (意味不明のデータの羅列)   ここまで分かれば十分かなぁ…。参考までに。   CV_Line * n test data:     00002ab0: 00 00 00 00 e5 02 00 80 01 00 00 00 e6 02 00 80     00002ac0: 0c 00 00 00 e9 02 00 80 12 00 00 00 ee 02 00 80     00002ad0: 18 00 00 00 01 03 00 80 1f 00 00 00 03 03 00 80     00002ae0: 2a 00 00 00 05 03 00 80     MSIL実行バイナリ先頭からのオフセット0x00 = ソースファイル 0x2e5 行目                       0x01 =        0x2e6                       0x0c =        0x2e9                       0x12 =        0x2ee                       0x18 =        0x301                       0x1f =        0x303     見事にソース行と一致。すげー。感動。ちなC11LineInfoはうちの     場合0なのでご注意。   [SModule Sym section] を確実に正確にparseしないと読めないから、   使いそうな奴は実装しないと駄目そうですね。大変だーーー!   どうでもいいけど、pdb なんちゃらサーバーという、リモートから   pdbファイルデータを取る方法があるらしいですね。   こんな便利なものあれば、お客さんとこのバイナリ、リモートデバッグ   できんじゃね?とかふと思いました。たいがいは客先で起きたトラブルは   再現しないものですよね。   アセンブラにOSの中身詳しくないとどーせデバッグすら出来ませんけど…。      分かった部分だけコーディング中w   くっそなげー読みずらいコードにwくっそ長い変数名がゾロゾロw   意味不明誤字脱字間違いだらけのソースコメント、ガベージの山w   だってーー、サブルーチン化し過ぎると何書いてあるか分かんなくなるしー。   だってーー、変数名短くすると何言ってるか全然わかんなくなるしー。      だってさーーー。   1つのファイルに、streamがN本入ってる所までは、納得できますよ?   でもーー、   さらに色んなデータ種類につき1つのsubstreamが入ってて、   その上さらにsubstreamの中に違うモジュールごとにsectionが複数入ってて、   さらにさらにその上そのsectionの中にsubsectionが入ってるらしいんですよー?   こんなの綺麗にコード出来る訳ないじゃんーーーー。      だってさー、.Netライブラリの関数をラップして関数呼ぶと、   何書いてあるか分かんなくなるじゃんー。そりゃ引数とか   ズラズラ長いとすっげー読みずらいけどさー、読んだ時すぐに   分かるコードにしとかないとさーーー。      ・・・という感じで、歴史に残る名ソースとははるかに遠いゴミソースが   また増えるのでした…。   ちなみに大昔は変数プリフィックスに3文字を使っていたのですが、   これは可読性が落ちる。プログラム初心者にはお勧めで、   変数が何の型かすぐ分かる利点がある。      プログラム慣れて来ると、intCnt という表記よりも nCnt という   なんちゃら表現式(正式に名前がある。忘れたけど。)   の方が読みやすくなるんですよねー。   初心者のうちはこの形式、すっごく分かりずらいのですが。   でもこれだと型だけで何型なのかサッパリ分からんけど。   つぅ事で昨今では、こんな感じで名前をつけています。    ・class にはobj/frm。フォームに配置するよく使う奴は     txt とかlblとか。滅多に使わないコントロールはながーい     プリフィックスまたは長いコントロール名そのもの。    ・構造体の定義は頭にstをつける。変数宣言時はm(モジュール)か、     stをつける。    ・クラスモジュール変数を参照する時は必ず Me.をかく。     (そうしないとどこから参照してるかサッパリ分からなくなるw)    ・単純な関数の引数は"value"という変数を使う。    ・基本データ型は s(文字)、i(Integer)、l(long)型等、     頭1文字だけにする。     基本データ型とは呼びずらい、でも基本データ型 ulongなどは     ul/us(ushort)をつける。     single float は何年も使ってない(いるけど)。double float は定番の dbl    ・List、array等、特に多用する.Netクラスに限りlst,ar。     (VB固有の配列操作関数 redim 等は原則使わない。VBのバージョンが      変わると動きが変わるからwありったけ.Netを使うw)    ・enumはenm・・・だったけど最近は大文字のみにしてるかな?     enmXXX って、関数引数にすると醜くなるんですよね。   という感じで、古典表記と初心者表記がゴッチャ。      両方混ぜるから全体がスマートになる、という自己満足の世界w      今回はよく分からない構造体メンバーや、名前が重複しやすそうな   変数が多いのでながーーい変数命名をせざるを得ないw   な・・・長いぞ・・・この変数名…。20文字とかちょっと長くね?   みたいなw      変数のプリフィックスは結構ややこしいですよね。   MSDN なんかだとフツーにプリフィックス省略しまくってるし、MSDN   見まくってると自然と…w   しかしここまで可読性を無視したソースで本当にいいのか俺w   後でデバッグで超苦しむぞオレw危ないぞオレw R2.9.5時点:   シンボル名に漢字が使えるのか調査中。   漢字のローカル変数使ってpdbをダンプするも、symmodule streamが   上手く取れないw全然違うstream番号が取れるw   なんじゃそりゃあああああw   祟りだ!!    R2.9.6時点:   シンボル名に漢字を使ってみる。UTF-8かUnicodeなのは確定   なんだけど、どっちだろう…   "\0"で終わるファイル名、どうやってString型に直せばいいんだw   元のソースファイルの文字体系に依存するんだろうか…      漢字変数を含むpdbファイルを作って、ダンプして解析したけど   読めずwさらに中身が思ったように解析できないw   「手でバイナリ解析したんじゃ間違いがあるんだろう。今まで   作った分のソフトで解析してみよう。」   →全然動かないしw   エラー表示用に new stackTrace やったら、ファイル名や行数が   なぜか表示されないw   ネットで調べてみた所、自動で情報を取得するオプションを指定しないと   いけないだとかwプチハマリw      ・・・UIntegerで値を読み取るべき所に何故かUShortの変数で   読み取る感じになっているwどうしてコンパイルエラーが出ないw   Option Strict をどうやらつけ忘れたようです。   Min にCType を何回も入れる羽目にw訳分からんので min 関数使うの   諦めました。      ぐえーーー、手でバイナリ解読するのもプログラムで読むのも   どっちも上手くいかねぇ・・・文字情報、コード体系、どうやるんだ・・・   これが上手く出来ないとModuleセクションが上手くサイズが確定   しないのですが・・・うはwちょっとはまりすぎじゃねぇのこれw   こんな、文字を読み込むたんびに alloc してたらシステムが   不安定になっちゃうよーーー。一度読み込み済みのバッファから   直接読み込もうとしても今度は\0を含んでその次のデータも system.text.encording   はコンバートかけちゃうしぃぃぃ…   プログラムで丁寧に1文字ずつ変換するしかなさそうな感じ。   UTF-8だと漢字等で使う文字コードはある程度値の範囲が決まっている   「らしい」のですが…。   うーむ。ちょっと動かすだけでこの時間とはw      ちなみにStackTraceでも関数のオフセットとかある程度取れるのですが、   どうやらソースコンパイル時の「コンパイル時」埋め込みらしいです。   いちいちpdb読まないと多分駄目だと思います。たぶん。よく分かっていない。    R2.9.7時点:   pdbファイル内は「UTF-8」で文字情報を扱ってる、らしいです?   UnicodeとUTF-8とでどう違うんだろう???   文字コード体系を無視して"\0"で文字列終端を表現している点があるので、   どうやって読めばいいんだか。   元のソースファイルがEUCだろうがSDISだろうが、構わずUTF-8に   してるのかな???   うーーーん・・・・とりあえずUTF-8で1バイトずつ読み込んで   て感じになる、のかな…。      UTF-16は2/4バイト表記だから、これは的外れ。   .NET自体はUTF-16だけど。pdbファイルの文字表記はASCII表記に   なっているで、漢字を実験的に使ったpdbファイルの中身を見ないと   やっぱり分かりませんねっと。   ・・・こんなのも分からんのかオレw   文字コードは過去に何度も色々挑戦してるのですが、どういう訳か   その都度その都度調べてコードするのが常識になってるようなw   mhttpの時も文字コードはすっごい困った記憶があるのですが。   ・・・まぁその都度その都度調べるしかないんでしょうね。コーディング   するたびに。 R2.9.8時点:   UTF-8というのは。Wikipediaによると、2〜4バイトで文字コードを表現するそうな。   ほんまかいなw   UniCode とUTF-8の違いがイマイチよく分からんけど…。規格書を読まないと   分からんのかも。   "\0" で読み取りを終了するUTF-8 byte 配列パーサーかつstring作成コードを作成中w   めんどくせぇ・・・。けど仕方ない。   今んとこはpdbファイル内の文字列表現は"UTF-8"を大前提にコード中。   危ないw      String( SByte *, Int32,Int32)ですぐに変換出来そうなんだけど、   変換元がByte()なので多分できないw   SByte * > Byte * という「値型配列のキャスト」は.Netじゃ出来ないそうな。   参照型、object型でないと出来ないそうな。   こういう面倒くささはCの方がある意味乱暴で楽でいいですよねw   バグ増えるけどw   この調子じゃいっくらやっても終わる訳がないしw R2.9.9時点:   UTF-8>UTF-16変換かつ\0で読み取りを終了するモジュール作ってみましたが、   漢字が本当に読めるのか全く試していませんw   ASCII読み込む分には動くっぽい。   StringBuilder、コントラスタでサイズを指定しただけはCharsで読めなくて、   Lengthでサイズ指定したら読めるようになった。なんだろこれ?   20,30文字程度ならべっつにString型でどんどん足し算やってもいいですが、   デバッグ用モジュールでガベージコレクタを荒らすというのも具合が悪い。   ModuleInfoSubStreamはPadding4,align4だったようです。うーん、これまた   分かりずらい話だ。   ModuleInfoSbstreamが読めたから、ModuleSymStreamをソフトで読み込む   方法やってみよかな?      上記とは別に、MSILのオフセットが分かったからじゃアセンブラ化した実行   アドレスを求める方法はどうやるんかいな?と調べてみた所w   ICorDebugCodeは〜.libみたいな、C++用staticLibraryでしか供給が無いw   MSDNでSystem空間のページみたら、何故かSystem.Reflectionの記述が無いw   事実上の別モジュールのようです。   System.Reflection.Emit.OpCodes?だか何だか使うとVB等で手作りしたMSILの   配列からモジュールを作成・実行できるようです!これすげーな。   でも物理アドレスやアセンブラ化した奴のアドレスはやっぱり取れる気配なしw   どこ調べればいいんだかサッパリ…。   そもそもMSILで検索かけても、そこから触ってるHPというのはあまり無いようです。   技術情報としてはマニアックだからになるのかな?      漢字の変換コード動くのかなー。デバッグ表示で16進数から文字表示に   変えられたので、それで満足して放置しましょうw(いいのかこれでw   System.Text.Encoding...だと、"\0"も無視して突き抜けてエンコードして   しまうらしいのですw文字列の長さを確定できないw   byte配列から抜き出してbyte配列を作って、encodingする手もあったですが、   「配列作るのはメモリもったいない」理論に基づいてやっぱり気合で手作りw   どっちにしろ2バイト4バイト文字のどこかに"0x00"が入ってる場合、間違って   文字ぶった切ってしまうし。(調べて分かった事ですがUTF8/16では下位エロゲーと?   で00という文字コードは存在し得ないらしいです。複雑だw)   無駄な努力が続きますねぇ・・・。    R2.9.10時点:   SymModule読み込む所で、「ファイルから読み込んだバッファを読む時に   データ足らなくなったら自動的にファイルから追加読み込みしてくれる   モジュールないと大変だよな・・・」(←一度に全部読み込もうという概念がないw   で、色々四苦八苦してシリアライズ化したモジュールを作ってみましたw   なんという無駄な努力…。   最初に上位側でバッファを1KBとか取ると、後はそれをずっと使いまわしw   バッファをとりかく使い回す事でランタイム等に無駄なデータ確保を限界まで   減らそうという無駄な努力が続きますw   でもコード的にぐちゃぐちゃで、しかも動くかどうか不明w   作るの大変。しかも動くかどうかも非常に怪しいwこんな危ないコード入れたら   やっぱ駄目ですね。保守性悪過ぎ。しかもちっともうごかねー。ファイル終端も   検出できねーし終わってんな。      ストリーム番号に対応したページアドレスがとれねぇ〜〜〜。なんでだー。   時間かけた割にさっぱ分からんし。   coff ファイルと MSIL、exe をダンプするツールを作る羽目になりそうです。   だって実行バイナリの中身がよく分からんから、デバッグ情報を幾ら見比べても   よく分かんないし。ダウンロードしようにも・・・。   Linux側なら coff ファイルをダンプ出来るけど、MSIL は無理そうな感じ。   シンボル定義命令の引数の中身を理解するにはダンプツールないと駄目そう?   (まぁ分かんなくてもいいけど)   どーせこんなVB用のクソコード誰も使わんでしょう。ダウンロードできるように   しちゃえw作りかけでバグだらけだしwスパゲティコードだし、   どうせこんなHP誰も見てねぇしw R2.9.13時点:   byte配列を読み込もうとすると止まってしまう・・・なんじゃこりゃあ!   >論理積演算子に "And" ではなく "&" を間違って使ってたから。&は文字列扱いに    強制的にしちゃうんだね。Option Strict On にする勇気は今さらありませんw    どんだけコードが肥大化するか考えると怖くてw   ファイルの読み込み位置がおかしい?なんで前に戻っちゃうの?   〜>バッファの位置の計算間違い・・・StartとSizeを間違えてコードしていたw   どう考えても的外れのページを読んでいるw   〜>Stream番号の振り方を間違えてるらしい。stream4以降はストリーム番号の   番号つけルールが変わるらしく、Page*n と一致しなくなるらしいw   よく分からんけどあわせこんで終了w   どう考えても1ページ2ページずれて違う所を読んでいるw   〜>これまたstream4以降だとなんか特殊な処理がいるのかもって感じ…。      という感じでバグだらけですねwやっとシンボル定義のサイズ・IDが   少し読めるようになってきたーーーー。長い…。まだ中身のメモリ保存の   所すら着手してないのにぃ。   cvinfo.hのシンボル定義の対応する奴は一見して多いように見えますが、   実際にはアドレスセグメント各16/32の4セットを用意しているから、   一見して多く見えるだけのようです。実際には10〜20個ぐらいを   用意すればで足りるみたい?   (VB専用、他のツールで吐いたpdbを読まないなら、という話)      ひでーデバッグ時間かかるなぁ…デバッガなしだとどの変数に中身が何   入ってるかサッパリ分かりませんねーーー。printfデバッグは   やっぱかったるいし時間かかるなぁ・・・。 R2.9.16時点:   やっと何とか、byte配列のシリアル読み込みクラスがなんとか動くようにw   長かった…。あれこれ変数をメンバに追加しても、なんだか動かず訳ワカメで   てきとーに弄りまわしたら動くように。これで本当にいいんだろうかw   (多分駄目な気がするw)      ・・・と、ここで気付いたのが、pdbファイル1つだけでは1つのソース>1つの1pdb   ファイルの情報しか入ってない事。   プロジェクトに複数のソースがあると、そのソース1つに対して1つのpdbファイルが   生成されるらしい、とか。つまりソースが100個あるとpdbも100個出来るらしいとw   ・・・あれ?他のpdbファイルへの参照どうやんのこれwどっかに   情報入ってんのかな・・・w   module定義には、SLOT,GMANPOC,UNAMESPACE,BLOCK,S_ENDぐらいしか入って   ないらすぃです。なんでだろ?中身に対応するコード作って詳細見てみないと   やっぱ分かんないなぁ…。   pdbファイルって複数のファイル・objののデバッグ情報を1つにまとめて   単独のデバッグ情報ファイルにするのかと思ったら、違うんですね。   これかなり意外だ。というか、うちのビルト環境が悪いのかなぁ…。   VCとかだと1つの8MBのpdbが出来るもんだと思ってたから意外だ。   というか、うちのビルト環境の構築が普通のVisualStudioのとかなり   違うのが原因なのかな…。   つまり、ここで作り込むとVisualStudioのとかなり違うpdbファイルが   出来るっつぅ事ですよね。汎用性ゼロじゃんwまぁ仕方ないか…。   (PCにVisualStudio入れろよオレwいつまで入れずに使う気だwみたいなw)      CustumByteSirializerクラスちゃん、ちゃんと動くのかなぁ…。   不安の多いモジュールだwでも結構インターフェイス、エラーチェックの   少なさや変数メモリの使わなさは優秀なのでなかなかお気に入りの完成度   ですよねw(自己満足の世界w)       R2.9.17時点:   SymModuleの中身をprintfしてみる。これ作るだけでも結構めんどい。   BLOCK32 の pParent,pNext は、同じ stream の先頭からのファイルオフセットという事が   判明w pParentは親ブロック/関数らしい。pNext は S_END までのオフセットらしい。   S_MANSLOT ではローカル変数の「詳細情報」を取得出来る、らしい。   構造体メンバをどうするかは後回しとして…。      格納するデータ構造以前に、全体としてどーゆーデータ構造にすりゃいいのか   イマイチ決まらない(まぁだいたいは決まって来た)のでとりあえず各情報の   中身をのぞき見してる感じ。それだけでも結構時間かかるよねこれw   だいたいこんな感じなのかなぁ。   各ファイル1( xxx.pdb )   Module1( というか Module/Class単位?)     関数1       Block         SLot / Block       (S_END で終わる     関数2     関数3.....   Module2   Module3.....   各ファイル2( xxx.pdb )   各ファイル3( xxx.pdb ).......   UNAMESPACE は好き勝手にどこでも入る感じ。      んーー、思ったより構造解析はカンタンだ。分かりやすいなぁ…。   丁度いい難易度w良作と言えるのかもしれない、pdb解析ゲーw   関数名取れた?らしい。Length-Prefixedだったのと、GMANPROCのoff〜name[1]までの   間のメンバは実際の物と違ってて差分がかなりあるらしい。何入ってんだろこれ???   でも関数の引数の型について何もデバッグ情報が入って無いし、offも0x0600 0031とか   やたらでかいし…segも0x13xxとかやたらデカイし…全然さっぱり分からんw   資料(cvinfo.h)と実際の動きが全く違うらしい、という所までは判明。   exe を MSIL ダンプしてみないと分からないですね、こりゃ。 R2.9.19時点:   exeから MSIL を表示するソフト作ってみようとして…。   ECMA-335の規格書にはファイルフォーマット全容が書いてあるようです。うーん。   とりあえずこの通りに"MSIL viewer"を単独で作る事にw   デバッガ関係はあっちこっちで開発やってるようです。   cygwin-gdb, VisualStudioは有名ですけど、それ以外にもかなり   あちこちで作ってるようです。   http://hp.vector.co.jp/authors/VA028184/   んじゃ作る意味ネーナ・・・VB製やらVB専用やら理由をつけても   あんま作る意味ネーナ。   ったく、素直にVisualStudioをインストールすりゃ良いものを、それを   どうしても避けるからwよそのツールを一切DLしないで動かそうとする   からw   コリャさっぱり金になんねーな、x86デバッガなら需要あるなとか思って   たのが甘過ぎるとw      ま、どっちにしろ「うち」の環境ではデバッガ必要臭いですが…。   開発環境を「インストール」すると動作環境が潰れるし…。   開発と動作環境の二つ用意するほど余裕ねーし…。インストールしたら   OS不安定になったりするしw   無駄な努力が続くwいみねぇ!!さっむ〜〜・・・・・・。      どーでもいいけどImportsでよそのクラス・ファイル参照出来るよーに   なるんかな?/addmodule? だかでコンパイルオプション指定せんでも   読めるよーになるんかな???   これは実験しないとちょっと勿体ないかも。   謎が続くw R2.9.22時点:   PE viewer,PE optional Header コーディング中。   CustumBytesSerializerの分岐ソースが生まれるw   CUIコンパイルだとやっぱ参照関係明確にしないと駄目みたい?諦めた。 R2.9.24時点:   Standerd fields の読み込む部分をコードちぅ。   OS Major が5が読める筈なのに4、SybSys Majorが5が読めるはずなのに   4。   うーーむ・・・ヘッダバージョン違ってくるかな…。入力データが   bmp2asm.exeだからかな…。   Magic を2回も読むコードを入れていて、CustumBytesSerializerのバグを   疑って調べ始めた俺は正真正銘のバカなのかも知れないw   (そりゃエラー出るだろ普通に・・・)きゃはっw R2.9.25時点:   MS-DOS header   PE Header    PE optional Header   SectionHeader 1:   SectionHeader 2:   SectionHeader 3:   SectionHeader 4:   (なんちゃらテーブル。Directoryに書いてある奴)   (Section RawData)   と続くようです。PointerToRawData はファイル先頭からのバイト   オフセットアドレスという事のようです。   かなり冗長化しててOS およびHDDのファイルシステム、ページング   システムにファイルフォーマットを合わせているようで、0x200 バイト単位で読み込む   か何かの基本単位でやってるらしい。圧縮したら小さくなるのは   こういう事情があるようです。   Resouce Table、Debug のサイズがゼロにならん。。。これ   なんでだろう…。「0であるべきだ」ってハッキリ書いてあるのにぃぃぃ。      ・・・.textはいいとして、.sdataは初期値つきデータとして…。   .rsrcと.relocって一体何入ってんだろ?サッパリ分からんw   VirtualSizeを読むコードをうっかり2か所でばらばらに読んでて、   ハマリますたwいやぁ、アフォだなぁ。こりゃプログラムなんか   出来るスキルじゃねぇよなw列挙ミス・・・。   あれぇ?セクションの大きさと読もうとしてる所違うぞ??何だよ   pdfとバイナリのsectionheaderのメンバ違ってんのか??   みたいに大真面目に考えちゃったりしてwばかだーーーーw   (算術演算の結果オーバーフローしました。というランタイムエラーがw)      これが分かったオレ偉い!さっすがオレー、えらーーい。    R2.9.29時点:   セクション .text にテーブルの全部が入っている。   (debugとか)   RVAのファイルオフセット=RVA指定値-セクションのvrtualaddress    + .textセクションのファイル先頭からのオフセット      よーし、これでmscoreee.dll とかのdll情報もCLI header の   位置も確定するぞー、よっしゃー。 R2.10.3時点:   CumstumByteSerialier クラスに seek メソッドを追加して、   Import LookupTable をよんで _CorExeMainがpeview.exeで読めた。   ・・・めんどくせーしそろそろ CLI Header 読み込みをコードしてみようかな。   (いい加減飽きて来たw) R6.10.11時点: mscor.dll?ベースでゼロから再構築中。目下、リモートデバッグを念頭にした win32 API ラッパー化修正とターゲット OS 32bit/64it、ターゲット exe バイナリ 32 bit/64bit ごとに動くよう、全面コード修正中。 いつになったらコンパイル通るようになるの? ・・・・長い。いくらやっても終わらないw まぁ下手にインターネットで遊んでるよりはマシですね。