uxf
の編集
https://khfdpl.osask.jp:443/wiki/?uxf
[
トップ
] [
編集
|
差分
|
バックアップ
|
添付
|
リロード
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
-- 雛形とするページ --
2016_10
2016_11
2016_12
BracketName
Essen
Essen0
Essen1
Essen2
Essen3
Essen4
EssenMemo0001
EssenMemo0002
EssenMemo0003
EssenMemo0004
EssenMemo0005
EssenMemo0006
EssenMemo0007
EssenMemo0008
EssenMemo0009
EssenMemo0010
EssenMemo0011
EssenR2
EssenR2_ess03f
EssenR2_ess03h
EssenR2_ess03i
EssenR2_ideas
EssenR2_jit00
EssenR2_jit01
FormattingRules
FrontPage
Help
IP
InterWiki
InterWikiName
InterWikiSandBox
K
KHPC
KHPC_v000doc01
KHPC_v001doc01
KHPC_v002doc01
KHPC_v003doc01
MenuBar
OSC
OSC20181027
OSC20190222
OSC20191123
OSC20230401
OSC20230528
OSC20231021
OSC20240310
OSC20241026
OSC20250221
PHP
PukiWiki
PukiWiki/1.4
PukiWiki/1.4/Manual
PukiWiki/1.4/Manual/Plugin
PukiWiki/1.4/Manual/Plugin/A-D
PukiWiki/1.4/Manual/Plugin/E-G
PukiWiki/1.4/Manual/Plugin/H-K
PukiWiki/1.4/Manual/Plugin/L-N
PukiWiki/1.4/Manual/Plugin/O-R
PukiWiki/1.4/Manual/Plugin/S-U
PukiWiki/1.4/Manual/Plugin/V-Z
RecentDeleted
SandBox
SltVA
VariableArray
WikiEngines
WikiName
YukiWiki
advcal20161205
advcal20161206
advcal20161209
advcal20161210
advcal20161215
eoml0001
eoml0002
essen_ex01_0001
impressions
kcl_malloc
khfdpl_result1
members
memo0001
memo0002
note0001
note0002
note0003
note0004
note0005
note0006
oldworks
oldworks00
oldworks06
oldworks12
oldworks13
osaskjp_index
persistent_C
populars
pr20161105
pr20161105b
scsc
seccamp2017
spam_test
uxf
uxf_01
uxf_02
uxp
* Universal eXecutable Format -(by [[K]], 2016.09.14) ** これは何? -プログラミング言語を作っていると、実行速度が出なくて悩ましいことがある。 -でもプログラムのうち高速化の必要があるところは全体の2割くらいなので、そこだけアセンブラで書けたらいいなと思う。 -こういうときの逃げ道としてC言語が用意しているのはインラインアセンブラだけど、インラインアセンブラをやることにするとアセンブラを解釈できなければいけないので、言語処理系の負担が大きい(naskをライブラリとして呼び出す方法もあるかもしれないけど、それはnaskがないと動かないということになって、情けない)。 --Cはどっちにしてもアセンブラが必要になるので、インラインアセンブラという手法はいい選択だった。 -それで、実行バイナリを扱うわけだけど、COFFやELFはオーバースペック過ぎて「僕がほしいのはこれじゃない」感が強い。こんな複雑なフォーマットを解釈しなければいけないのだとしたら、それだけで処理系も相当に肥大化してしまう。必要十分な機能があればそれでいい。 -第二世代OSASK(efg01)の技術をそのまま使うことも考えたけど、あれはサイズを極端に小さくするために頑張っているので、それもなんかしっくりこない。もっとシンプルでいいんだ。 -ということで、efg01の技術をもっとずっとシンプルにしたようなものを考えた。 ** sh8 -まず、このuxfで使われる可変長整数のエンコードを紹介します(sh8)。このエンコードでセクションサイズやアライン情報などをエンコードします。 0~0x7f: 0xxxxxxx 0~0x3fff: 10xxxxxx xxxxxxxx 0~0x1fffff: 110xxxxx xxxxxxxx xxxxxxxx 0~0xfffffff: 1110xxxx xxxxxxxx xxxxxxxx xxxxxxxx -これより大きな表現も考えられますが、x86の32ビットだけを想定するのなら、これくらいで十分でしょう。 ** フォーマット内容 01 (アライン情報) (.textのサイズ) (.dataのサイズ) (.bssのサイズ) [.textの生データ] [.textのリロケーション情報] [.dataの生データ] [.dataのリロケーション情報] -アライン情報は、4ビットずつで、(.bssのアライン) << 8 | (.dataのアライン) << 4 | (.textのアライン) となっています。この12ビット値を一つの整数として、上記のエンコードでエンコードします。 -アラインは0~15まで指定できるわけですが、「0」の1バイトアライン指定は別の意味があり、この場合はデフォルトのアラインが利用されます。デフォルトのアラインは16バイトです。したがって、どれも16バイトのアラインで十分なら、アライン情報は0を書いておけば十分です。 -各セクションの生データは、サイズ情報が1以上の場合のみ記述されます。リロケーション情報は、生データが存在した場合のみ記述されます。 -リロケーション情報は少し複雑で、次のようになっています。 (リロケーション要素数) (リロケーション間隔の単位) { (次の位置までの間隔) << 2 | セクション番号 } ... --リロケーション要素数が0の場合は、リロケーション位置の単位も記述されませんし、その後の { } も記述されません。 -エントリポイントは.textの先頭に固定されています。 ** ローダプログラム例 void *load_uxf(const unsigned char *p) { if (get_sh8(&p) != 0x01) return NULL; // フォーマット不一致. int i, j, k, l, u, m, siz[3], algn = get_sh8(&p); unsigned char *sct[3]; for (i = 0; i < 3; i++) { siz[i] = get_sh8(&p); sct[i] = NULL; if (siz[i] > 0) sct[i] = malloc_aligned(siz[i], (algn >> (i * 4)) & 0xf); } for (i = 0; i < 2; i++) { if (siz[i] == 0) continue; for (j = 0; j < siz[i]; j++) sct[i][j] = *p++; // 生データのロード. j = get_sh8(&p); if (j == 0) continue; u = get_sh8(&p); l = 0; while (j > 0) { m = get_sh8(&p); l += (m >> 2) * u; int *q = (int *) (sct[i] + l); *q += (int) sct[m & 3]; l += 4; j--; } } for (j = 0; j < siz[2]; j++) sct[2][j] = 0; // bss領域のクリア. // sct[0]の領域に、実行権限を付与する. return sct[0]; } int get_sh8(const unsigned char **pp) { const unsigned char *p = *pp; unsigned char c = *p++, b; int i, j; i = c; for (b = 0x80; (i & b) != 0; b >>= 1) i ^= b; for (b = 0x80; (c & b) != 0; b >>= 1) i = i << 8 | *p++; *pp = p; return i; } void *malloc_aligned(int siz, int algn) { if (algn == 0) algn = 4; algn = 1 << algn; // このsizとalgnでメモリ領域を確保 → p // まあ簡易的には以下の方法で実現できる(freeのことは考えてない). int p = (int) malloc(siz + algn); if ((p & (algn - 1)) != 0) p = (p + (algn - 1)) & ~(algn - 1); return (void *) p; } ** uxfのプログラムはどうやって書くの? -基本的にはC言語で書きます。アセンブラで書いてもいいですが。 -ただ現状ではuxfを出力できるリンカがないので、それを適当に作らないといけません。まあそのうちやります。 ** 拡張仕様 -リロケーション情報でセクション番号に3を指定した場合、それはexternリンクで以下の形式になる、というのはどうだろうか? --{(次の位置までの間隔) << 2 | 3} { 識別子長 << 2 | リンクタイプ } { 識別子 } ... --これでダイナミックリンクも記述できる --リンクタイプ: ---0: 補正なし(リンク位置にある値はもちろん加算する) ---1: 相対アドレス指定に配慮し、上記の値から(書き込み位置のアドレス+4)を引く ---2: publicラベル宣言(リロケーション作業については何もしない) --リンクタイプ=3をプライベートラベルにするか、それともさらなる拡張にするか・・・ --識別子長を0にしたときに拡張動作にするという道もある --識別子はバイト単位なので、長さもバイト数で記述される -リンクタイプ0と1の拡張によって、未解決シンボルを記述できるので、api呼び出しなどを記述できる -リンクタイプ2の拡張によって、publicラベルが宣言できるようになるので、先頭以外をentryにさせることもできるし、uxfをobjファイルの別形式として使うこともできる。 * こめんと欄 -リンカはできました。 -- [[K]] SIZE(10){2016-09-23 (金) 20:00:34} -拡張仕様についてもサポートできました。 -- ''K'' SIZE(10){2016-09-27 (火) 10:43:36} -uxfのリンカはどこでダウンロードできますか? -- 名無しさん SIZE(10){2017-07-17 (月) 11:05:05} -まだどこにもアップロードしていません、すみません。 -- [[K]] SIZE(10){2017-07-31 (月) 11:09:02} #comment
タイムスタンプを変更しない
* Universal eXecutable Format -(by [[K]], 2016.09.14) ** これは何? -プログラミング言語を作っていると、実行速度が出なくて悩ましいことがある。 -でもプログラムのうち高速化の必要があるところは全体の2割くらいなので、そこだけアセンブラで書けたらいいなと思う。 -こういうときの逃げ道としてC言語が用意しているのはインラインアセンブラだけど、インラインアセンブラをやることにするとアセンブラを解釈できなければいけないので、言語処理系の負担が大きい(naskをライブラリとして呼び出す方法もあるかもしれないけど、それはnaskがないと動かないということになって、情けない)。 --Cはどっちにしてもアセンブラが必要になるので、インラインアセンブラという手法はいい選択だった。 -それで、実行バイナリを扱うわけだけど、COFFやELFはオーバースペック過ぎて「僕がほしいのはこれじゃない」感が強い。こんな複雑なフォーマットを解釈しなければいけないのだとしたら、それだけで処理系も相当に肥大化してしまう。必要十分な機能があればそれでいい。 -第二世代OSASK(efg01)の技術をそのまま使うことも考えたけど、あれはサイズを極端に小さくするために頑張っているので、それもなんかしっくりこない。もっとシンプルでいいんだ。 -ということで、efg01の技術をもっとずっとシンプルにしたようなものを考えた。 ** sh8 -まず、このuxfで使われる可変長整数のエンコードを紹介します(sh8)。このエンコードでセクションサイズやアライン情報などをエンコードします。 0~0x7f: 0xxxxxxx 0~0x3fff: 10xxxxxx xxxxxxxx 0~0x1fffff: 110xxxxx xxxxxxxx xxxxxxxx 0~0xfffffff: 1110xxxx xxxxxxxx xxxxxxxx xxxxxxxx -これより大きな表現も考えられますが、x86の32ビットだけを想定するのなら、これくらいで十分でしょう。 ** フォーマット内容 01 (アライン情報) (.textのサイズ) (.dataのサイズ) (.bssのサイズ) [.textの生データ] [.textのリロケーション情報] [.dataの生データ] [.dataのリロケーション情報] -アライン情報は、4ビットずつで、(.bssのアライン) << 8 | (.dataのアライン) << 4 | (.textのアライン) となっています。この12ビット値を一つの整数として、上記のエンコードでエンコードします。 -アラインは0~15まで指定できるわけですが、「0」の1バイトアライン指定は別の意味があり、この場合はデフォルトのアラインが利用されます。デフォルトのアラインは16バイトです。したがって、どれも16バイトのアラインで十分なら、アライン情報は0を書いておけば十分です。 -各セクションの生データは、サイズ情報が1以上の場合のみ記述されます。リロケーション情報は、生データが存在した場合のみ記述されます。 -リロケーション情報は少し複雑で、次のようになっています。 (リロケーション要素数) (リロケーション間隔の単位) { (次の位置までの間隔) << 2 | セクション番号 } ... --リロケーション要素数が0の場合は、リロケーション位置の単位も記述されませんし、その後の { } も記述されません。 -エントリポイントは.textの先頭に固定されています。 ** ローダプログラム例 void *load_uxf(const unsigned char *p) { if (get_sh8(&p) != 0x01) return NULL; // フォーマット不一致. int i, j, k, l, u, m, siz[3], algn = get_sh8(&p); unsigned char *sct[3]; for (i = 0; i < 3; i++) { siz[i] = get_sh8(&p); sct[i] = NULL; if (siz[i] > 0) sct[i] = malloc_aligned(siz[i], (algn >> (i * 4)) & 0xf); } for (i = 0; i < 2; i++) { if (siz[i] == 0) continue; for (j = 0; j < siz[i]; j++) sct[i][j] = *p++; // 生データのロード. j = get_sh8(&p); if (j == 0) continue; u = get_sh8(&p); l = 0; while (j > 0) { m = get_sh8(&p); l += (m >> 2) * u; int *q = (int *) (sct[i] + l); *q += (int) sct[m & 3]; l += 4; j--; } } for (j = 0; j < siz[2]; j++) sct[2][j] = 0; // bss領域のクリア. // sct[0]の領域に、実行権限を付与する. return sct[0]; } int get_sh8(const unsigned char **pp) { const unsigned char *p = *pp; unsigned char c = *p++, b; int i, j; i = c; for (b = 0x80; (i & b) != 0; b >>= 1) i ^= b; for (b = 0x80; (c & b) != 0; b >>= 1) i = i << 8 | *p++; *pp = p; return i; } void *malloc_aligned(int siz, int algn) { if (algn == 0) algn = 4; algn = 1 << algn; // このsizとalgnでメモリ領域を確保 → p // まあ簡易的には以下の方法で実現できる(freeのことは考えてない). int p = (int) malloc(siz + algn); if ((p & (algn - 1)) != 0) p = (p + (algn - 1)) & ~(algn - 1); return (void *) p; } ** uxfのプログラムはどうやって書くの? -基本的にはC言語で書きます。アセンブラで書いてもいいですが。 -ただ現状ではuxfを出力できるリンカがないので、それを適当に作らないといけません。まあそのうちやります。 ** 拡張仕様 -リロケーション情報でセクション番号に3を指定した場合、それはexternリンクで以下の形式になる、というのはどうだろうか? --{(次の位置までの間隔) << 2 | 3} { 識別子長 << 2 | リンクタイプ } { 識別子 } ... --これでダイナミックリンクも記述できる --リンクタイプ: ---0: 補正なし(リンク位置にある値はもちろん加算する) ---1: 相対アドレス指定に配慮し、上記の値から(書き込み位置のアドレス+4)を引く ---2: publicラベル宣言(リロケーション作業については何もしない) --リンクタイプ=3をプライベートラベルにするか、それともさらなる拡張にするか・・・ --識別子長を0にしたときに拡張動作にするという道もある --識別子はバイト単位なので、長さもバイト数で記述される -リンクタイプ0と1の拡張によって、未解決シンボルを記述できるので、api呼び出しなどを記述できる -リンクタイプ2の拡張によって、publicラベルが宣言できるようになるので、先頭以外をentryにさせることもできるし、uxfをobjファイルの別形式として使うこともできる。 * こめんと欄 -リンカはできました。 -- [[K]] SIZE(10){2016-09-23 (金) 20:00:34} -拡張仕様についてもサポートできました。 -- ''K'' SIZE(10){2016-09-27 (火) 10:43:36} -uxfのリンカはどこでダウンロードできますか? -- 名無しさん SIZE(10){2017-07-17 (月) 11:05:05} -まだどこにもアップロードしていません、すみません。 -- [[K]] SIZE(10){2017-07-31 (月) 11:09:02} #comment
テキスト整形のルールを表示する