-
genuine98/PE - reiria
2024/05/01 (Wed) 22:47:06
■これは
genuine98 の PE 版です。
lep 用 PE 形式の<?del> flat 専用<?/del>実行ファイルとなっています。
<?del>lep にオプション -f を指定し、<?/del>
|A:\>lep <?del>-f<?/del> genuinep
というように実行します。
DLL は不要です。
lep 以外で実行した場合、何もせず終了します。
■オプション
pesc 「32 BIT PE MODEL FLAT」を表示する (default)
beep ビープを鳴らす (default)
頭に !を付加するか、not を書くと逆の意味なります。
(例 !pesc) (例 not pesc)
Re: genuine98/PE - reiria
2024/05/01 (Wed) 23:07:40
makefile.d は DLL 使用版 (kernel32.dll x32.dll) が生成されます。
lep のサンプル同様にディレクトリを作り、そこで make -f makefile.d します。
Re: genuine98/PE - reiria
2024/05/02 (Thu) 09:08:55
当方の Borland 環境ではセクションの VirtualSize が通常 1000h 単位(= SectionAlignment = tlink32 -Ao:値)
に切り上げられてしまうので、PE のロードイメージを小さくすべく、
セクションを VirtualSize と SizeOfRawData の小さいほうで配置(それに合わせてあちこち補正)したところ、
そこそこ普通に実行出来そうなのですが、困りものはデータセクションの未初期化データで、
未初期化データ量が不明なためデータセクションは VirtualSize より小さくするわけにいきません。
(MS のものは VirtualSize は切り上げられてないっぽい?)
で、セクションの Characteristics bit7=1 で未初期化データを表すぽいですが、
当方の環境では bit7=1 なセクションなんぞ生成されず、初期化済み/未初期化は一つのセクションにまとめられ、
それが更に 1000h 単位に切り上げられ、データセクションの実際の使用量は不明ぽい。
このへんの仕事をやってるのってリンカなのかよくわかりませんが、
今時の賢いリンカ(?)だと、初期化済み/未初期化を分離したセクションを生成出来たりするんですかヌ(^^;
要するに .data (_DATA) と .data? (_BSS) を別のセクションにする感じで。
いや、そもそもセクションの Characteristics bit7=1 ってそういう用途のものじゃないかもですが・・・ (^^;;;
Re: genuine98/PE - KAZ.K
2024/05/02 (Thu) 14:01:51
うん? いやまあリンカによってはリンカ側で後から変更する余地がある場合もあるけれど、原則としては segment group が section にそのまま対応しているはずでは? そしてそうである以上 flat model なのに data group が複数に分離している状態って Win32 PE ではあんまり想定されていないような気が。
そもそもMS自身のWin32開発環境って、後に自前のNT系に乗せられるようになるまでは普通にXENIXなんですよね。コンパイラ自体やランタイムの実装も DOS や OS/2 1.x 方面用のとはここで一度断絶している。だから PE がUnix方面の COFF のなれの果てでしかないのも必然だし、なればこそMSランタイムのセクション名は伝統的なUnix流の .text .data になっているわけで。一方(現存する)WATCOMランタイムは原型がDOSの時代にあって、それをそのまま継承してプラットフォームの増築を繰り返したものなので、Win32 PE を出力してもDOS時代の命名のままAUTOとDGROUP。
Re: genuine98/PE - reiria
2024/05/03 (Fri) 01:33:11
言われてるみると確かに dgroup がそのまま一つのセクションになってる感じですな。
となると、_DATA と _BSS が合体してるなら Characteristics bit7=1 でもよさそうに思えるものの、
もしかすると、_BSS はゼロクリアしとけば初期化済みたいな扱いとか・・・ (^^;
って、そもそも Characteristics bit7 (だけじゃないけれど) ってのはファイル内のデータのことだとすれば、
通常、_BSS のデータはファイル内に無いのだから bit7=0 で当然なのかも(^^;;;;;;
このへん未だによくわかってませんヌ(^^;;;
Re: genuine98/PE - reiria
2024/05/13 (Mon) 01:05:23
この genuine98/PE は LEMM API AX=DEBFh の新型のテストにもなっていまして、
|A:\>lep -fx genuinep debug
というように debug を指定して実行して、intr_xnt_count > 0 なら新型が使われています。
|A:\>lep -fx genuinep debug !xnt
というように !xnt を指定すると旧型が使われ、intr_x_count > 0 になります。
あと、カラフルな文字列はただの表示テスト用の文字列で、実行したマシンとは無関係です(^^;
Re: genuine98/PE - KAZ.K
2024/05/13 (Mon) 08:44:07
lep 側に -f を要求する機構は独自拡張だろうと何だろうとなにがしかで PE 自体に埋め込むべきじゃないですかねぇ。なんかフラグ定義するなり .note セクション的なのするなり。ってもリンカから直接生成できる範囲内にしておかないと面倒ですが。
いやまあ lep 自体がまだわりと実験的というか風呂敷の広がりすぎたサンプル的というか、実用性なんか考慮する段階じゃなさげなのはわかるんだけど。-f 前提で書いたコードは非 -f では動きようがないし、非 -f で動くコードを -f で動かすのは危険が危ないだけで意味がない・・・よね?
現状 Win32 console なり NTnative なりとの互換性確保に進む方向でもないですよねぇ。単に PE のガワを借りているだけで。
> 新型
わりと何の話だか感がすごいのでひとまずドキュメントなぞを・・・と、思いきや、なんか 2000/10/16 付のしか見あたらないんですが。さすがにこれは行間が広すぎやしませんか()
Re: genuine98/PE - reiria
2024/05/13 (Mon) 11:28:39
> 非 -f で動くコードを -f で動かすのは危険が危ないだけで意味がない・・・よね?
そんな感じですねえ、-f のポインタや esp は非 -f に比べてリニアアドレス全域を誤爆する可能性高いですので。
実行バイナリにフラグ埋め込む案は一応 todo リストに入っておりまして、
stub か startup のエントリポイントの "LEPXMD" の後に入れようかと思ってはみたものの、
いちいち stub や startup を直接書き換えるのも何だかなあ・・・ って微妙な気分になって絶賛放置中ですヌ(^^;
> 現状 Win32 console なり NTnative なりとの互換性確保に進む方向でもないですよねぇ
そのうち誰かが JEMM 方面を 98 に移植しそうな予感ががが(^^;;;
>> 新型
従来の LEMM API AX=DE8Eh,8Fh でセグメントを設定/取得する方法は、
AX=DE8Eh,8Fh とその対象のソフトウェア割り込みの間のハードウェア割り込み内でソフトウェア割り込みが入ると、
AX=DE8Eh,8Fh のセグメント情報が更新されてしまうという潜在的危険性がありまして(^^;;;;;;
で、そのへんの安全を考慮すると AX=DE8Eh,8Fh とその対象のソフトウェア割り込みの間を cli にする必要があり、
例えば、lep の xdpmi.c _dpmi2x() なんかでも面倒くさい書き方になってしまい、(Jack 等も同様)
この長年の悪癖というか面倒な書き方から卒業したくて、今更ながら新型とかいって何とかしましたヌ(;_;)
> 2000/10/16 付
罫線とか使ってかっこよく文章整形しようとして泥沼化して放置中でして・・・ もう html でいいかなみたいな(^^;
Re: genuine98/PE - KAZ.K
2024/05/14 (Tue) 09:07:19
> 誰かが JEMM 方面
原理的には JEMM 自体を移植せんでも HX だけ持ってこればって話ですよね。そこは WDOSX/DWPL ベースにしても同じですが。原則として言うなら DPMI/Extender 層と PE link/loader 層と互換レイヤはそれぞれ別々から持ってきてもかまわないはず・・・、いやまあ現実には DPMI の重箱の隅で引っかかったり、勝手に決め打ち手抜きされてたり、謎の増設裏口に依存していたりで大抵ぐちゃーするわけですが(--;
追) あーでもloader側でlinkerを持っている場合、KERNEL32.DLLから呼べないとLoadLibrary*に困るので、まじめに作るとここだけは循環依存?になりますか。本来なら NTOSKRNL(loader)→NTDLL.DLL(linker)→(←KERNEL32.DLL←app.exe) みたいな流れの部分。ぬがーMSお得意の名前と実際の中身が一致しない病がガガガ(^^;;;
IMAGE_SCN_CNT_UNINITIALIZED_DATA - KAZ.K URL
2024/05/29 (Wed) 17:18:09
一応もちゃもちゃ考えてはいた、の、だけど・・・
根本的な話、IMAGE_SCN_CNT_UNINITIALIZED_DATA って実はそもそもPEに出現するべきものでは無いのでは? もしかしたら .obj 段階では .bss がそうなっているのかもだけど、少なくとも Win32 あるいは WinNT 的なローダーがそれで何かをどうこうする気は最初からなにも無いような気がする。
ナナメ読みした感じ、昔 wine でも古来のUnix流に「イメージファイル上にデータがあっても読まずに無視して zero map する」的な事をしていたら、そのせいでかえって動かないバイナリが発見されたので処理を撤去した、みたいな感じっぽい? ・・・読み間違えてなければ? 実際今 grep かけると tests とか以外でヒットするのは dlls/krnl386.exe16/vxd.c だけで、これは Win32s VxD サービスの実装らしいけどさすがにそれは今時の普段には関係ないのでは・・・?
追) うん、やっぱり何度読み直しても VirtualSize だけが唯一に権威的なので、その値が多少アレだからって他でどうこうできる余地は無いものと。いやまあこんなふわっとお気持ちの表明を並べただけのものがspecなどとは片腹痛いにも程があるわけで、いったいどこからが絶対でどのへんが推奨でどこまでが許容でなにが禁止なのかこれではさっぱりなにもわかりませんナ。とはいえ元になったUnix方面のCOFF自体、実際には「そのOSで読めるもの全部」的なローカルルールの継ぎ接ぎで一貫性なんてありゃしないので、その意味では伝統に正しく従っているような気がしないでもない・・・。
追2) そういえばUEFI方面はどうだろうかと思い付いた。ちょちょっと探してみたら tianocore/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoff.c あたりのようだ・・・結論: そもそもsection->Characteristics を見ていない(^^;;;;;
書記するしかないの化 - reiria
2024/05/30 (Thu) 09:30:49
手持ちの環境では IMAGE_SCN_CNT_UNINITIALIZED_DATA = 1 のセクションを生成出来そうもないぽいので、
手作業で PE ファイルを IMAGE_SCN_CNT_UNINITIALIZED_DATA = 1 に書き換えて、
Windows 95,10 で実行してみたところ、警告とか表示されることもなく普通に実行出来ました(^^;
データセクションだけでなくコードセクションを未初期化にしたり、
OPTIONAL HEADER の SizeOfUninitializedData を 0 以外の滅茶苦茶な値にしても何事もなく実行出来るようで、
どうやら PE ヘッダの未初期化データの情報なんて全く眼中にない予感ヌ(^^;;;
まあそうだろうなぁと - KAZ.K
2024/05/30 (Thu) 09:54:33
wineでの話の経緯からそんなことじゃないかなぁとは。specが実際にはspecじゃなくてせいぜいで願望、下手すると妄想の域なので、まあ書いてあることを当てにした方が馬鹿を見るという(--;;; .objとしてのCOFFの話とごっちゃにしているのも事態を悪化させている感。
edk2の方はある意味当然だったかも。それこそ lep -f 的な 4G flat なので、CODEもREADもWRITEもしったこっちゃなかった。
flatといえば UEFI はまじめ(?)に 4G flat だけど、EFI化する前の世代の PCI Firmware specification は8086的なBIOSへの継ぎ接ぎなので、いわゆる unreal mode が明文化されて書いてあるんだとか。うん、intelがSDMとかで口を酸っぱくして「それはしちゃいけません」って書いているアレですよ。PCISIGなんて中の人は実質intelなのにいったいどんな顔して書いたのかちょっと見てみたい気はするんだけど、残念ながらspec自体がしこたま高い売り物なので現物を目にする機会は無さそうですん・・・。
追) 元になった POST Memory Manager specification (著:Phoenix+intel) 見たら「その頃にはBIOS側で big real mode にしておくので勝手に使ってね」という感じのようだ? なるほど存在自体は明文化されているけど実際の中身への言及は無い・・・。
SizeOfUninitializedData - KAZ.K
2024/05/30 (Thu) 22:44:16
うん??? よくよく見たらいつの間にか定義自体が first such section から sum of all such sections に変わってる(^^;;; なんだぁこれぇ(^^;;;;;
Versionと名の付くfieldはそこら中にあるけれど、どれ一つとしてPE/COFF自体の仕様versionに紐付いているわけじゃないので、文脈なしに外見からどっちの意味か判別することは確実に不可能(全否定の意味で)ですよ。まるっきり地獄じゃねえか(^^;;;;;;;;;;
元々該当しそうなsectionが一つしかなければ大丈夫だろ・・・と、言いたいところだけど、だめだよねこれ。そもそも複数のsectionが対象になり得ると言っているんだからsection名が .bss のもの一つという意味ではなくて性質が .bss っぽいもの全部の意味であるはずで、では .bss が内包された data group は入るのか入らないのかどっちだよ。どっちともとれる。意味が定かでない時点で存在意義が行方不明・・・。
わりと ひどい。
追) 時系列は NT3.1/Win32s → spec4.0 (first) → spec4.1 (sum of all) → NT3.5。だいぶ初期ではある、ものの、存在ごと無視して許されるほど初期でも無いですなー。なおUEFIは spec6.0 を固定で参照しているので理論上それ以降の変更は取り入れてはいけないことになるけど、まあ実質どのみち関係なさそうではある。
序文に This specification [...] is not guaranteed to be a complete specification in all respects. とか堂々と書いてある心遣いが身に沁みますなー・・・とでも言うと思ったか! アホー! アホーー!!
緑茶もいける化 - reiria
2024/05/31 (Fri) 10:15:41
SizeOfCode や SizeOfInitializedData も滅茶苦茶な値で何事もなく実行出来るぽいんですよねえ(^^;
Windows 10 でこうなんだし、今までずっとそういう方針で来てるのかもヌ。
あと、https://www.glamenv-septzen.net/view/664 の SizeOfUninitializedData に、
リンカがデータセクションに未初期化データを含めることが出来た場合は 0 って書かれてて、
0 じゃない場合 (その場合は IMAGE_SCN_CNT_UNINITIALIZED_DATA = 1 かも?) も有り得るような書き方だけど、
該当リンカのマニュアルか何かでそのへん言及されてるんですかねえ。
OOTA - KAZ.K
2024/05/31 (Fri) 12:00:17
まるっと訳したとかじゃなくて色々まとめて作文した感があるけど、そこで何を根拠にしたのかはまるっきり謎ですな。少なくともMSが出荷している winnt.h にそんな気の利いたコメントは書いてないですし、mingw/wine 方面のも同様。
そもそもCOFFの Optional Header の冒頭28バイトって本来はa.outそのものなんですよ。なので本来の意味ではなんとなく帳尻あわせで要約っぽい値をでっち上げてそれらしい感を装っても意味が無くて当たり前で、まず前提条件としてsection配置自体がa.out互換になっていなければ話は最初から破綻している。代わりになんぞ明確な定義を新たに与える余地はあったのかもしれないけれど現実問題されてない。むしろ機会は幾度もあった筈なのに何で誰も明示的にdeprecatedを宣言しなかったのか、コレガワカラナイ・・・
追) 本来はa.outそのもの
ここで言っているのはSVR1以前のAT&T UNIXに由来する古典的形態の方のa.out。BSD方面とかに見られるshlib対応の魔改造版a.outは実質別物。
Re: genuine98/PE - reiria
2025/06/28 (Sat) 15:59:44
-f を指定しなくても実行出来るようにしました。