SlideShare a Scribd company logo
1 of 52
Download to read offline
スタート低レイヤー #2
ELFの動的リンク
七誌
お断わり
• ELFの仕様書を参考に実験したことを基にした書き下
ろしです。要約ではありません。
• 独断と偏見で書いています。
• コマンドや簡単なプログラムでELFをいじりながら、動
的リンクの仕組みを追います。
• NetBSDのソースは読みません。
• 折に触れてNetBSDには言及します。
• Pythonで書いたサンプル実装を使います。
• https://bitbucket.org/7shi/elf-dyn
• 使用するコンパイラはi386-elf-gccです。
• binutilsとgccを --target=i386-elf でビルド
七誌について
自己紹介
• 池袋バイナリ勉強会を主催(後述)
• 歴史的発展に興味があり、UNIX V1からNetBSDへの
系譜を追い掛けようとしている
• V1 → V6 → V7 → 32V → 4BSD → 386BSD → NetBSD
• NetBSDをOS学習の定番にしたいですね!
• 落ち着いたらMulticsに進みたい
• 手始めのV6で格闘中
• せっかくなので調べたことを教材にまとめたい
• PDP-11や8進数が障害になっていると感じたため、8086移
植を計画中(後述)
池袋バイナリ勉強会
• 本来の趣旨は、OSを作れるコンパイラを作ること
• 趣味の陶芸教室(ろくろ?)みたいな感覚で、実用的な知
識を提供しようとはあまり思っていない
• 色々な勉強会を試したものの淘汰された
• 淘汰=継続的に人が集まらない
• 現時点で続いているのは5つ
• 池袋バイナリ勉強会
• BSDカーネルの設計と実装 読書会
• はじめてのOSコードリーディング 読書会
• F#談話室
• 初級ラテン語リーディング
• その他、他の方の勉強会も開いたりします
V6移植ハッカソン
• OS学習用教材作成の
一環
• 夏休み中に開催
• 全部は無理だと思う
• アセンブラとコンパイラ
の8086化までできれば
良いな
1. ELFファイルの概要
ELFファイルとは
• 実行可能バイナリのファイル形式
• 歴史的発展: a.out → COFF → ELF
• NetBSDのネイティブサポートはCOFFを経由せずに
a.out → ELF
• WindowsのPEはCOFFを拡張したもの
• Mac OS XではMach-Oという形式
• 読んだことがないので、詳しく知りません
• NetBSDではCOFFもPEもMach-Oもバイナリエミュレー
ションとして読み込むことはできる
• 参照するライブラリが揃わないと実行できないけど
a.outファイルの構造
• UNIX V6のものを示す
• a.outファイルは独自拡張された
亜種が多い
• セクションは.textと.data固定
• .bssはすべてゼロのため、ヘッダ
にサイズだけ定義されている
• 後ろに再配置情報やシンボル
情報が付けられるが、実行に
は必須ではないため省略
• stripコマンドによってそれらを
削った状態が右図
a.outヘッダ
.text
.data
COFFファイルの構造
• セクションヘッダにより、セクショ
ンが自由に定義できる
• 機能拡張は独自のセクションを
定義する形で行える
• PEファイルでの拡張点
• DOSスタブやオプショナルヘッダ
などCOFFにない要素がある
• オンデマンドページングでシーク
しやすいように、セクションごとの
アラインメントが強制
COFFヘッダ
セクションヘッダ
セクション
セクション
セクション
セクション
ELFファイルの構造
• セクションとセグメントという
二重構造(後述)
• セクションは用途別に細かく
別れている
• 実行時にはそこまで細かい
分類は必要ないので、メモリ
属性に基づいてセクションを
まとめたものがセグメント
• セクションヘッダは取り外しの
便のため後ろに配置
ELFヘッダ
プログラムヘッダ
(セグメント管理)
セクション
セクション
セクション
セクション
セクションヘッダ
セクションとセグメント (1)
• セグメントという用語は色々な用法があるため混乱を
招きやすい
• x86のセグメントはCPUの機能を指しているため、ELFのセ
グメントと同じ概念ではない
• 前者(x86の機能)で後者(ELFのセグメント)を実装できる
ため、まったく別物というわけではない
• しかし現在そのような実装は主流ではない
• 64bitではセグメント自体が廃止された
• セグメントのことはあまり深く考えないで、セクション
中心に見ていけば良いと思う
• ここから先はその方針で進める
セクションとセグメント (2)
• UNIX V6にもセグメントの概念は
存在した
• メモリを用途別にMMUで分割し
た単位がセグメント
1. .text
2. .data + .bss + ヒープ + スタック
• ヒープとスタックの間の空きは割り
当てないで物理メモリを節約
• これが発展して抽象化されたの
がELFのセグメント
• と考えれば良いのではないか
メモリ配置
.text
.data
.bss
ヒープ
(空き)
スタック
2. セクション
静的リンク
• まずは静的リンクから
$ i386-elf-gcc –nostdlib -s ret.s
$ i386-elf-readelf -S a.out
There are 3 section headers, ...
Section Headers:
[Nr] Name ...
[ 0] ...
[ 1] .text ...
[ 2] .shstrtab ...
ret.s
.globl _start
_start:
ret
ELFヘッダ
プログラムヘッダ
.text
.shstrtab
セクションヘッダ
セクションの説明
• 実質的には.textが1つ
ret.s
.globl _start
_start:
ret
ELFヘッダ
プログラムヘッダ
.text
.shstrtab
セクションヘッダ
セクション名 役割
.text
機械語コードが
格納されている
.shstrtab
セクション名の文
字列が格納され
ている
共有ライブラリの作成
• 動的リンク対象として準備
• 今回は呼び出し側を追うため、共
有ライブラリ側は追わない
• セクションとか凄いことになっている
$ i386-elf-gcc -c test.s
$ i386-elf-ld -shared -s -o libtest.so test.o
$ file libtest.so
libtest.so: ELF 32-bit LSB shared object, Intel
80386, version 1 (SYSV), dynamically linked,
stripped
test.s
.globl test
test:
ret
動的リンク
• 共有ライブラリの中のコードは
PLT(Procedure Linkage Table)経
由で呼び出す(後述)
• いきなりセクションが爆発!
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
start.s
.globl _start
_start:
call test@PLT
$ i386-elf-gcc -nostdlib -s
start.s libtest.so
セクション概要
セクション 説明
.interp 動的リンクを処理するインタプリタ
.hash シンボル名のハッシュテーブル
.dynsym シンボルテーブル
.dynstr シンボル名の文字列テーブル
.rel.plt
動的リンクのために書き替えが必要なアド
レスのリスト
.plt
動的リンクされた関数などを.got.pltからア
ドレスを取得して呼び出すコード
.text
C言語などで書いたプログラムをコンパイ
ルしたコード
.dynamic 動的リンクに必要な情報を集めたテーブル
.got.plt
動的リンクされた関数などのアドレステー
ブル
.shstrtab セクション名の文字列テーブル
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
ELFヘッダ
• 32bit/64bit、エンディアン、CPU
• 後続のヘッダへのポインタ
$ i386-elf-readelf -h a.out
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x80481b4
Start of program headers: 52 (bytes into file)
Start of section headers: 672 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 5
Size of section headers: 40 (bytes)
Number of section headers: 11
Section header string table index: 10
プログラムヘッダ
• ローダのための情報
• セグメント、動的リンク関係
$ i386-elf-readelf -l a.out
Elf file type is EXEC (Executable file)
Entry point 0x80481b4
There are 5 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x000a0 0x000a0 R E 0x4
INTERP 0x0000d4 0x080480d4 0x080480d4 0x00013 0x00013 R 0x1
[Requesting program interpreter: /usr/lib/libc.so.1]
LOAD 0x000000 0x08048000 0x08048000 0x001b9 0x001b9 R E 0x1000
LOAD 0x0001bc 0x080491bc 0x080491bc 0x00098 0x00098 RW 0x1000
DYNAMIC 0x0001bc 0x080491bc 0x080491bc 0x00088 0x00088 RW 0x4
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .hash .dynsym .dynstr .rel.plt .plt .text
03 .dynamic .got.plt
04 .dynamic
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
.interp
• 文字列が格納されている
• 動的リンクを行う外部プログラム
• インタプリタと呼ばれる
• NetBSDではld.elf_so
• シーケンス
1. execveシステムコール
2. カーネルのローダが指定された
ELFファイルを読み込み
3. インタプリタが動的リンクを処理
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
$ i386-elf-readelf -p .interp a.out
String dump of section '.interp':
[ 0] /usr/lib/libc.so.1
.hash
• シンボル名の検索を高速化するため
のハッシュテーブル
• 共有ライブラリ内で未定義のシンボル
があれば実行ファイルから検索してリ
ンクされるため、実行ファイル側にも
持っておく必要がある
• 以前のNetBSDではlibcにenvironと
__prognameが未定義で、実行ファイル
側に定義させていた
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
$ i386-elf-readelf -x .hash a.out
Hex dump of section '.hash':
0x080480e8 03000000 05000000 03000000 04000000 ................
0x080480f8 02000000 00000000 00000000 00000000 ................
0x08048108 00000000 01000000 ........
.dynsym
• シンボルのテーブル
• .hashで名前がハッシュ化
• 共有ライブラリの関数への参照
• Valueがゼロ、NdxがUND
• 自身が持つシンボル
• Valueにアドレス入っている
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
$ i386-elf-readelf -s a.out
Symbol table '.dynsym' contains 5 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 NOTYPE GLOBAL DEFAULT UND test
2: 08049254 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
3: 08049254 0 NOTYPE GLOBAL DEFAULT ABS _edata
4: 08049254 0 NOTYPE GLOBAL DEFAULT ABS _end
.dynstr
• 文字列が格納されている
• シンボル名
• .dynsymから参照
• 共有ライブラリのファイル名
• .dynamicから参照
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
$ i386-elf-readelf -p .dynstr a.out
String dump of section '.dynstr':
[ 1] libtest.so
[ c] test
[ 11] _edata
[ 18] __bss_start
[ 24] _end
.rel.plt
• 動的リンクのために書き替えが
必要なアドレスのリスト
• アドレスとシンボルのペア
• インタプリタによって共有ライブラ
リ内のアドレスが書き込まれる
• 動的リンクの根幹メカニズム
• 下の例では08049250にtestのアド
レスを書き込むことで動的リンクが
実現される
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
$ i386-elf-readelf -r a.out
Relocation section '.rel.plt' at offset 0x18c contains 1 entries:
Offset Info Type Sym.Value Sym. Name
08049250 00000107 R_386_JUMP_SLOT 00000000 test
.plt
• リンカが自動生成する定型コード
• 動的リンクされた関数を.got.pltから
アドレスを取得して飛ぶラッパー
• それ以外のコードは遅延リンク(後述)
• サンプルコードのtest@PLTがこれ
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
$ i386-elf-objdump -d -M intel -j .plt a.out
Disassembly of section .plt:
08048194 <test@plt-0x10>:
8048194: ff 35 48 92 04 08 push DWORD PTR ds:0x8049248
804819a: ff 25 4c 92 04 08 jmp DWORD PTR ds:0x804924c
80481a0: 00 00 add BYTE PTR [eax],al
080481a4 <test@plt>:
80481a4: ff 25 50 92 04 08 jmp DWORD PTR ds:0x8049250
80481aa: 68 00 00 00 00 push 0x0
80481af: e9 e0 ff ff ff jmp 8048194 <test@plt-0x10>
start.s
.globl _start
_start:
call test@PLT
.text
• 機械語コードが格納されている
• いわゆるバイナリはここがメイン
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
$ i386-elf-objdump -d -M intel -j .text a.out
Disassembly of section .text:
080481b4 <.text>:
80481b4: e8 eb ff ff ff call 80481a4 <test@plt>
start.s
.globl _start
_start:
call test@PLT
.dynamic (1)
• 動的リンクに必要な情報を集め
たテーブル
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
$ i386-elf-readelf -d a.out
Dynamic section at offset 0x1bc contains 12 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libtest.so]
0x00000004 (HASH) 0x80480e8
0x00000005 (STRTAB) 0x8048160
0x00000006 (SYMTAB) 0x8048110
0x0000000a (STRSZ) 41 (bytes)
0x0000000b (SYMENT) 6 (bytes)
0x00000015 (DEBUG) 0x0
0x00000003 (PLTGOT) 0x8049244
0x00000002 (PLTRELSZ) 8 (bytes)
0x00000014 (PLTREL) REL
0x00000017 (JMPREL) 0x804818c
0x00000000 (NULL) 0x0
.dynamic (2) ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
セクション Type 説明
.hash HASH セクションのアドレス
.dynsym
SYMTAB セクションのアドレス
SYMENT
セクションに含まれるシンボル
情報の1エントリのサイズ
.dynstr STRTAB セクションのアドレス
STRSZ セクションのサイズ
.rel.plt
JMPREL セクションのアドレス
PLTRELSZ セクションのサイズ
PLTREL
セクション内に含まれる再配
置情報の種類 (REL/RELA)
.got.plt PLTGOT セクションのアドレス
08048194 <test@plt-0x10>:
8048194: ff 35 48 92 04 08 push DWORD PTR ds:0x8049248
804819a: ff 25 4c 92 04 08 jmp DWORD PTR ds:0x804924c
80481a0: 00 00 add BYTE PTR [eax],al
080481a4 <test@plt>:
80481a4: ff 25 50 92 04 08 jmp DWORD PTR ds:0x8049250
80481aa: 68 00 00 00 00 push 0x0
80481af: e9 e0 ff ff ff jmp 8048194 <test@plt-0x10>
.got.plt
• 動的リンクされた関数などのアド
レステーブル
• ここをインタプリタが書き替える
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
$ i386-elf-readelf -x .got.plt a.out
Hex dump of section '.got.plt':
0x08049244 bc910408 00000000 00000000 aa810408
.dynamic 遅延リンク関係 書替対象
.pltが参照しているのはココ!
.shstrtab
• セクション名の文字列が格納さ
れている
• 名前を任意長で取るため
• COFF/PEではセクションヘッダに名
前が固定長8文字で格納
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
$ i386-elf-readelf -p .shstrtab a.out
String dump of section '.shstrtab':
[ 1] .shstrtab
[ b] .interp
[ 13] .hash
[ 19] .dynsym
[ 21] .dynstr
[ 29] .rel.plt
[ 32] .text
[ 38] .dynamic
[ 41] .got.plt
文字列の途中から
参照することで兼ね
ている
(NULL終端による)
セクションヘッダ
• セクションの情報
• 位置やセクション数はELFヘッダ
で定義されている
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
$ i386-elf-readelf -S a.out
There are 11 section headers, starting at offset 0x2a0:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 080480d4 0000d4 000013 00 A 0 0 1
[ 2] .hash HASH 080480e8 0000e8 000028 04 A 3 0 4
[ 3] .dynsym DYNSYM 08048110 000110 000050 10 A 4 1 4
[ 4] .dynstr STRTAB 08048160 000160 000029 00 A 0 0 1
[ 5] .rel.plt REL 0804818c 00018c 000008 08 A 3 6 4
[ 6] .plt PROGBITS 08048194 000194 000020 04 AX 0 0 4
[ 7] .text PROGBITS 080481b4 0001b4 000005 00 AX 0 0 4
[ 8] .dynamic DYNAMIC 080491bc 0001bc 000088 08 WA 4 0 4
[ 9] .got.plt PROGBITS 08049244 000244 000010 04 WA 0 0 4
[10] .shstrtab STRTAB 00000000 000254 00004a 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
ローダとセクション
• ローダはセクションヘッダを見ないということ
にはなっているけど、NetBSDではLinuxバイ
ナリかどうかの判定で見ている
• NetBSD 5.1でバイナリをいじっていたとき、
縮めるためセクションヘッダと.shstrtabを削
除したのにELFヘッダの修正を忘れて不正な
参照が残りカーネルパニックになったことが
ある(NetBSD 6で修正済み)
• その問題を追った時に作ったパッチ
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
--- sys/compat/linux/common/linux_exec_elf32.c.orig
+++ sys/compat/linux/common/linux_exec_elf32.c
@@ -111,7 +111,7 @@
* Now let's find the string table. If it does not exists, give up.
*/
strndx = (int)(eh->e_shstrndx);
- if (strndx == SHN_UNDEF) {
+ if (strndx == SHN_UNDEF || strndx >= eh->e_shnum) {
error = ENOEXEC;
goto out;
}
PEとの比較
• PEでは.dynsymと.dynstrと.got.plt
が1つになった.idataというセク
ションで動的リンクが処理される
• カーネルが直接処理して、インタプ
リタのようなものはない
• アドレスが書き込まれる箇所
(.got.plt相当)はサンクと呼ぶ
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
PEヘッダ
セクションヘッダ
.idata
.text
3. 動的リンク
Pythonで動的リンク
• ここからはPythonで簡単なローダ
を作って処理を追ってみます
• 完全なインタプリタを実装するわ
けではありません
• 実行ファイルに対するリンク処理の
みを行います
• 共有ライブラリを読み込む処理は実
装しません
• WindowsでELFを読み込むという
一種のネタです
• Pythonを選んだのはF#を見せても
読めないと言われそうだからです
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
ファイルの読み込み
• 指定されたファイルを読み込む
• 省略した場合は a.out
• 単純化のため逐次読み込みしな
いで、全体を一度に読み込む
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
from sys import argv
aout = "a.out" if len(argv) < 2 else argv[1]
with open(aout, "rb") as f:
elf = f.read()
ELFヘッダ (1)
• ELFファイルかどうかをチェック
• ファイルサイズ
• ファイル全体がヘッダより小さいという
ことはあり得ない
• ゴルフと言ってヘッダの中にセクション
を入れる遊びはあるけど・・・
• シグネチャ
• アーキテクチャのチェック
• 32bit
• リトルエンディアン
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
assert len(elf) >= 52, "not found: ELF32 header"
assert elf[0:4] == "¥x7fELF", "not found: ELF signature"
assert ord(elf[4]) == 1, "not 32bit"
assert ord(elf[5]) == 1, "not little endian"
ELFヘッダ (2)
• ヘッダ本体の読み込み
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
(e_type,
e_machine,
e_version,
e_entry,
e_phoff,
e_shoff,
e_flags,
e_ehsize,
e_phentsize,
e_phnum,
e_shentsize,
e_shnum,
e_shstrndx) = unpack(
"<HHLLLLLHHHHHH", elf[16:52])
ELFヘッダ (3)
• 位置独立コードで、i386を対象と
しているかをチェック
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
assert e_type == 3, "not PIE"
assert e_machine == 3, "not i386"
• 今回のローダはWindows用
• アドレスを指定しても既に使用さ
れていれば確保できないため、ど
こに読み込んでも良いように位置
独立を要求
• セクションのサンプルで使ったバ
イナリはPIEではないため対象外
プログラムヘッダ (1)
• プログラムヘッダは複数ある
• 1つずつインスタンスとして読み込
むためのクラスを定義
class Elf32_Phdr:
def __init__(self, data, pos):
(self.p_type,
self.p_offset,
self.p_vaddr,
self.p_paddr,
self.p_filesz,
self.p_memsz,
self.p_flags,
self.p_align) = unpack(
"<LLLLLLLL", data[pos : pos + 32])
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
プログラムヘッダ (2)
• ELFヘッダの情報を基に、プログラ
ムヘッダを読み込む
phs = [Elf32_Phdr(elf, e_phoff + i * e_phentsize)
for i in range(e_phnum)]
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
• 内包表記でリストを作成
項目 説明
e_phoff プログラムヘッダのファイル中の位置
e_phentsize プログラムヘッダ1個のサイズ
e_phnum プログラムヘッダの個数
セグメントのロード
• メモリサイズの算出
memlen = max([ph.p_vaddr + ph.p_memsz for ph in phs])
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
• 実行可能ページを確保
mem = VirtualAlloc(0, memlen,
MEM_COMMIT, PAGE_EXECUTE_READWRITE)
• プログラムヘッダを見てロード
pelf = cast(elf, c_void_p).value
for ph in phs:
addr = mem + ph.p_vaddr
if ph.p_type == 1: # PT_LOAD
o, sz = ph.p_offset, ph.p_memsz
memmove(addr, pelf + o, sz)
print "LOAD: %08x-%08x => %08x-%08x" % (
o, o + sz - 1, addr, addr + sz - 1)
.dynamic
• プログラムヘッダに.dynamicが指
定されていれば読み込む
• 最低限必要なものだけ
• type = 0 は終端
elif ph.p_type == 2: # PT_DYNAMIC
while True:
type = read32(addr)
val = read32(addr + 4)
if type == 0: break
elif type == 5: strtab = mem + val
elif type == 6: symtab = mem + val
elif type == 11: syment = val
elif type == 23: jmprel = mem + val
elif type == 2: pltrelsz = val
addr += 8
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
.rel.plt
• アドレスとシンボルを読み込み
• .dynsymと.dynstrをたどることで、
シンボルを解釈
if jmprel != None:
print
print ".rel.plt(DT_JMPREL):"
for reladdr in range(jmprel, jmprel + pltrelsz, 8):
offset = read32(reladdr)
info = read32(reladdr + 4)
stroff = read32(symtab + (info >> 8) * syment)
name = string_at(strtab + stroff)
print "[%08x]offset: %08x, info: %08x; %s" % (
reladdr, offset, info, name)
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
リンク
• シンボル名に合致する関数を探し
てアドレスを書き込む
• 単純化のため共有ライブラリは読
み込まないでPythonで定義した関
数へのサンクを書き込んでいる
assert libc.has_key(name), "undefined reference: " + name
addr = mem + offset
faddr = cast(libc[name], c_void_p).value
print "linking: %s -> [%08x]%08x" % (name, addr, faddr)
write32(addr, faddr)
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
Hex dump of section '.got.plt':
0x08049244 bc910408 00000000 00000000 aa810408
書替対象
080481a4 <test@plt>:
80481a4: ff 25 50 92 04 08 jmp DWORD PTR ds:0x8049250
参
照
動的リンク完了
• .got.pltを書き替えて完成
• .pltのコードが.got.pltを参照してリン
ク先に飛べる
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
Hex dump of section '.got.plt':
0x08049244 bc910408 00000000 00000000 aa810408
080481a4 <test@plt>:
80481a4: ff 25 50 92 04 08 jmp DWORD PTR ds:0x8049250
参
照
080481b4 <.text>:
80481b4: e8 eb ff ff ff call 80481a4 <test@plt>
• ここでは起動時にアドレス解決を
行ったが、最初に呼び出すまで遅
延させる仕組みが入っている
4. 遅延リンク
遅延リンク
1. 最初に呼び出されたときにインタ
プリタで受け取る
2. .got.pltを書き替えて対象に飛ぶ
3. 次回からはそのまま飛べる
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
08048194 <test@plt-0x10>:
8048194: ff 35 48 92 04 08 push DWORD PTR ds:0x8049248
804819a: ff 25 4c 92 04 08 jmp DWORD PTR ds:0x804924c
80481a0: 00 00 add BYTE PTR [eax],al
080481a4 <test@plt>:
80481a4: ff 25 50 92 04 08 jmp DWORD PTR ds:0x8049250
80481aa: 68 00 00 00 00 push 0x0
80481af: e9 e0 ff ff ff jmp 8048194 <test@plt-0x10>
Hex dump of section '.got.plt':
0x08049244 bc910408 00000000 00000000 aa810408
8049248 8049250804924c
jmp [0x08049250] → jmp 0x080481aa
.plt.text .text
インタプリタ
3
1 2
実行ファイル 共有ライブラリ
Pythonで遅延リンク
• Python内のインタプリタを呼ぶた
めのサンクを.got.pltに登録
def interp(id, offset):
print "delayed link: id=%08x, offset=%08x" % (id, offset)
return link(jmprel + offset)
thunk_interp = CFUNCTYPE(c_void_p, c_void_p, c_uint32)(interp)
call_interp = JIT([
0xff, 0x14, 0x24, # call [esp]
0x83, 0xc4, 8, # add esp, 8
0x85, 0xc0, # test eax, eax
0x74, 2, # jz 0f
0xff, 0xe0, # jmp eax
0xc3 ]) # 0: ret
if pltgot != None:
writeptr(pltgot + 4, thunk_interp)
writeptr(pltgot + 8, call_interp)
ELFヘッダ
プログラムヘッダ
.interp
.hash
.dynsym
.dynstr
.rel.plt
.plt
.text
.dynamic
.got.plt
.shstrtab
セクションヘッダ
Hex dump of section '.got.plt':
0x08049244 bc910408 00000000 00000000 aa810408
08048194: push thunk_interp
0804819a: jmp call_interp
test@plt:
080481a4: jmp [0x08049250]
080481aa: push 0x0
080481af: jmp 0x08048194
ご清聴ありがとうございました

More Related Content

What's hot

ARM Trusted FirmwareのBL31を単体で使う!
ARM Trusted FirmwareのBL31を単体で使う!ARM Trusted FirmwareのBL31を単体で使う!
ARM Trusted FirmwareのBL31を単体で使う!Mr. Vengineer
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexprGenya Murakami
 
FPGA+SoC+Linux実践勉強会資料
FPGA+SoC+Linux実践勉強会資料FPGA+SoC+Linux実践勉強会資料
FPGA+SoC+Linux実践勉強会資料一路 川染
 
x86とコンテキストスイッチ
x86とコンテキストスイッチx86とコンテキストスイッチ
x86とコンテキストスイッチMasami Ichikawa
 
Constexpr 中3女子テクニック
Constexpr 中3女子テクニックConstexpr 中3女子テクニック
Constexpr 中3女子テクニックGenya Murakami
 
TCAMのしくみ
TCAMのしくみTCAMのしくみ
TCAMのしくみogatay
 
SAT/SMTソルバの仕組み
SAT/SMTソルバの仕組みSAT/SMTソルバの仕組み
SAT/SMTソルバの仕組みMasahiro Sakai
 
Wiresharkの解析プラグインを作る ssmjp 201409
Wiresharkの解析プラグインを作る ssmjp 201409Wiresharkの解析プラグインを作る ssmjp 201409
Wiresharkの解析プラグインを作る ssmjp 201409稔 小林
 
Wireshark だけに頼らない! パケット解析ツールの紹介
Wireshark だけに頼らない! パケット解析ツールの紹介Wireshark だけに頼らない! パケット解析ツールの紹介
Wireshark だけに頼らない! パケット解析ツールの紹介morihisa
 
Zynq mp勉強会資料
Zynq mp勉強会資料Zynq mp勉強会資料
Zynq mp勉強会資料一路 川染
 
Unicode文字列処理
Unicode文字列処理Unicode文字列処理
Unicode文字列処理信之 岩永
 
0章 Linuxカーネルを読む前に最低限知っておくべきこと
0章 Linuxカーネルを読む前に最低限知っておくべきこと0章 Linuxカーネルを読む前に最低限知っておくべきこと
0章 Linuxカーネルを読む前に最低限知っておくべきことmao999
 
.NET Core 3.0時代のメモリ管理
.NET Core 3.0時代のメモリ管理.NET Core 3.0時代のメモリ管理
.NET Core 3.0時代のメモリ管理KageShiron
 
高位合成ツールVivado hlsのopen cv対応
高位合成ツールVivado hlsのopen cv対応高位合成ツールVivado hlsのopen cv対応
高位合成ツールVivado hlsのopen cv対応marsee101
 
すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!Genya Murakami
 
はりぼて OS で ELF なアプリを起動してみた
はりぼて OS で ELF なアプリを起動してみたはりぼて OS で ELF なアプリを起動してみた
はりぼて OS で ELF なアプリを起動してみたuchan_nos
 
TensorFlow Lite Delegateとは?
TensorFlow Lite Delegateとは?TensorFlow Lite Delegateとは?
TensorFlow Lite Delegateとは?Mr. Vengineer
 
何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門masayoshi takahashi
 

What's hot (20)

ARM Trusted FirmwareのBL31を単体で使う!
ARM Trusted FirmwareのBL31を単体で使う!ARM Trusted FirmwareのBL31を単体で使う!
ARM Trusted FirmwareのBL31を単体で使う!
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexpr
 
FPGA+SoC+Linux実践勉強会資料
FPGA+SoC+Linux実践勉強会資料FPGA+SoC+Linux実践勉強会資料
FPGA+SoC+Linux実践勉強会資料
 
x86とコンテキストスイッチ
x86とコンテキストスイッチx86とコンテキストスイッチ
x86とコンテキストスイッチ
 
Constexpr 中3女子テクニック
Constexpr 中3女子テクニックConstexpr 中3女子テクニック
Constexpr 中3女子テクニック
 
Raspberry Piで始める自宅サーバー超入門
Raspberry Piで始める自宅サーバー超入門Raspberry Piで始める自宅サーバー超入門
Raspberry Piで始める自宅サーバー超入門
 
TCAMのしくみ
TCAMのしくみTCAMのしくみ
TCAMのしくみ
 
SAT/SMTソルバの仕組み
SAT/SMTソルバの仕組みSAT/SMTソルバの仕組み
SAT/SMTソルバの仕組み
 
Wiresharkの解析プラグインを作る ssmjp 201409
Wiresharkの解析プラグインを作る ssmjp 201409Wiresharkの解析プラグインを作る ssmjp 201409
Wiresharkの解析プラグインを作る ssmjp 201409
 
Wireshark だけに頼らない! パケット解析ツールの紹介
Wireshark だけに頼らない! パケット解析ツールの紹介Wireshark だけに頼らない! パケット解析ツールの紹介
Wireshark だけに頼らない! パケット解析ツールの紹介
 
Zynq mp勉強会資料
Zynq mp勉強会資料Zynq mp勉強会資料
Zynq mp勉強会資料
 
Unicode文字列処理
Unicode文字列処理Unicode文字列処理
Unicode文字列処理
 
0章 Linuxカーネルを読む前に最低限知っておくべきこと
0章 Linuxカーネルを読む前に最低限知っておくべきこと0章 Linuxカーネルを読む前に最低限知っておくべきこと
0章 Linuxカーネルを読む前に最低限知っておくべきこと
 
.NET Core 3.0時代のメモリ管理
.NET Core 3.0時代のメモリ管理.NET Core 3.0時代のメモリ管理
.NET Core 3.0時代のメモリ管理
 
高位合成ツールVivado hlsのopen cv対応
高位合成ツールVivado hlsのopen cv対応高位合成ツールVivado hlsのopen cv対応
高位合成ツールVivado hlsのopen cv対応
 
すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!
 
はりぼて OS で ELF なアプリを起動してみた
はりぼて OS で ELF なアプリを起動してみたはりぼて OS で ELF なアプリを起動してみた
はりぼて OS で ELF なアプリを起動してみた
 
TensorFlow Lite Delegateとは?
TensorFlow Lite Delegateとは?TensorFlow Lite Delegateとは?
TensorFlow Lite Delegateとは?
 
何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門
 
Marp Tutorial
Marp TutorialMarp Tutorial
Marp Tutorial
 

Similar to ELFの動的リンク

【学習メモ#5th】12ステップで作る組込みOS自作入門
【学習メモ#5th】12ステップで作る組込みOS自作入門【学習メモ#5th】12ステップで作る組込みOS自作入門
【学習メモ#5th】12ステップで作る組込みOS自作入門sandai
 
Hello world make
Hello world makeHello world make
Hello world makemitsu1119
 
C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1信之 岩永
 
Windowsのパケットモニタ作成
Windowsのパケットモニタ作成Windowsのパケットモニタ作成
Windowsのパケットモニタ作成Shinichi Hirauchi
 
Exploring the x64
Exploring the x64Exploring the x64
Exploring the x64FFRI, Inc.
 
プログラミング .NET Framework 第4版
プログラミング .NET Framework 第4版プログラミング .NET Framework 第4版
プログラミング .NET Framework 第4版信之 岩永
 
スタート低レイヤー #0
スタート低レイヤー #0スタート低レイヤー #0
スタート低レイヤー #0Kiwamu Okabe
 
Trema day 1
Trema day 1Trema day 1
Trema day 1ykuga
 
ELK ではじめる自宅ネットワーク監視
ELK ではじめる自宅ネットワーク監視ELK ではじめる自宅ネットワーク監視
ELK ではじめる自宅ネットワーク監視npsg
 
Open vSwitchソースコードの全体像
Open vSwitchソースコードの全体像 Open vSwitchソースコードの全体像
Open vSwitchソースコードの全体像 Sho Shimizu
 
ElixirをIoTボードで動かしてみた ~ラズパイ・big.LITTLE・Zynq編~
ElixirをIoTボードで動かしてみた ~ラズパイ・big.LITTLE・Zynq編~ElixirをIoTボードで動かしてみた ~ラズパイ・big.LITTLE・Zynq編~
ElixirをIoTボードで動かしてみた ~ラズパイ・big.LITTLE・Zynq編~Hideki Takase
 
第3回ローレイヤー勉強会 : FPGAでコンピュータを作ってみた
第3回ローレイヤー勉強会 : FPGAでコンピュータを作ってみた第3回ローレイヤー勉強会 : FPGAでコンピュータを作ってみた
第3回ローレイヤー勉強会 : FPGAでコンピュータを作ってみたIto Takahiro
 
CLRの基礎 - プログラミング .NET Framework 第3版 読書会
CLRの基礎 - プログラミング .NET Framework 第3版 読書会CLRの基礎 - プログラミング .NET Framework 第3版 読書会
CLRの基礎 - プログラミング .NET Framework 第3版 読書会Yoshihisa Ozaki
 
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)inaz2
 
Cookpad Summer Intern 2015 - Programming Paradigm
Cookpad Summer Intern 2015 - Programming ParadigmCookpad Summer Intern 2015 - Programming Paradigm
Cookpad Summer Intern 2015 - Programming ParadigmMinero Aoki
 
関数型言語ElixirのIoTシステムへの導入に向けた基礎評価
関数型言語ElixirのIoTシステムへの導入に向けた基礎評価関数型言語ElixirのIoTシステムへの導入に向けた基礎評価
関数型言語ElixirのIoTシステムへの導入に向けた基礎評価Hideki Takase
 
LLVM overview 20110122
LLVM overview 20110122LLVM overview 20110122
LLVM overview 20110122nothingcosmos
 
4章 Linuxカーネル - 割り込み・例外 4
 4章 Linuxカーネル - 割り込み・例外 4 4章 Linuxカーネル - 割り込み・例外 4
4章 Linuxカーネル - 割り込み・例外 4mao999
 
4章 Linuxカーネル - 割り込み・例外 2
4章 Linuxカーネル - 割り込み・例外 24章 Linuxカーネル - 割り込み・例外 2
4章 Linuxカーネル - 割り込み・例外 2mao999
 
Ns2240series users manual_07
Ns2240series users manual_07Ns2240series users manual_07
Ns2240series users manual_07squat12
 

Similar to ELFの動的リンク (20)

【学習メモ#5th】12ステップで作る組込みOS自作入門
【学習メモ#5th】12ステップで作る組込みOS自作入門【学習メモ#5th】12ステップで作る組込みOS自作入門
【学習メモ#5th】12ステップで作る組込みOS自作入門
 
Hello world make
Hello world makeHello world make
Hello world make
 
C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1
 
Windowsのパケットモニタ作成
Windowsのパケットモニタ作成Windowsのパケットモニタ作成
Windowsのパケットモニタ作成
 
Exploring the x64
Exploring the x64Exploring the x64
Exploring the x64
 
プログラミング .NET Framework 第4版
プログラミング .NET Framework 第4版プログラミング .NET Framework 第4版
プログラミング .NET Framework 第4版
 
スタート低レイヤー #0
スタート低レイヤー #0スタート低レイヤー #0
スタート低レイヤー #0
 
Trema day 1
Trema day 1Trema day 1
Trema day 1
 
ELK ではじめる自宅ネットワーク監視
ELK ではじめる自宅ネットワーク監視ELK ではじめる自宅ネットワーク監視
ELK ではじめる自宅ネットワーク監視
 
Open vSwitchソースコードの全体像
Open vSwitchソースコードの全体像 Open vSwitchソースコードの全体像
Open vSwitchソースコードの全体像
 
ElixirをIoTボードで動かしてみた ~ラズパイ・big.LITTLE・Zynq編~
ElixirをIoTボードで動かしてみた ~ラズパイ・big.LITTLE・Zynq編~ElixirをIoTボードで動かしてみた ~ラズパイ・big.LITTLE・Zynq編~
ElixirをIoTボードで動かしてみた ~ラズパイ・big.LITTLE・Zynq編~
 
第3回ローレイヤー勉強会 : FPGAでコンピュータを作ってみた
第3回ローレイヤー勉強会 : FPGAでコンピュータを作ってみた第3回ローレイヤー勉強会 : FPGAでコンピュータを作ってみた
第3回ローレイヤー勉強会 : FPGAでコンピュータを作ってみた
 
CLRの基礎 - プログラミング .NET Framework 第3版 読書会
CLRの基礎 - プログラミング .NET Framework 第3版 読書会CLRの基礎 - プログラミング .NET Framework 第3版 読書会
CLRの基礎 - プログラミング .NET Framework 第3版 読書会
 
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
 
Cookpad Summer Intern 2015 - Programming Paradigm
Cookpad Summer Intern 2015 - Programming ParadigmCookpad Summer Intern 2015 - Programming Paradigm
Cookpad Summer Intern 2015 - Programming Paradigm
 
関数型言語ElixirのIoTシステムへの導入に向けた基礎評価
関数型言語ElixirのIoTシステムへの導入に向けた基礎評価関数型言語ElixirのIoTシステムへの導入に向けた基礎評価
関数型言語ElixirのIoTシステムへの導入に向けた基礎評価
 
LLVM overview 20110122
LLVM overview 20110122LLVM overview 20110122
LLVM overview 20110122
 
4章 Linuxカーネル - 割り込み・例外 4
 4章 Linuxカーネル - 割り込み・例外 4 4章 Linuxカーネル - 割り込み・例外 4
4章 Linuxカーネル - 割り込み・例外 4
 
4章 Linuxカーネル - 割り込み・例外 2
4章 Linuxカーネル - 割り込み・例外 24章 Linuxカーネル - 割り込み・例外 2
4章 Linuxカーネル - 割り込み・例外 2
 
Ns2240series users manual_07
Ns2240series users manual_07Ns2240series users manual_07
Ns2240series users manual_07
 

More from 7shi

F#とトランスレータ
F#とトランスレータF#とトランスレータ
F#とトランスレータ7shi
 
F#談話室(3) LT
F#談話室(3) LTF#談話室(3) LT
F#談話室(3) LT7shi
 
マーク&スイープ勉強会
マーク&スイープ勉強会マーク&スイープ勉強会
マーク&スイープ勉強会7shi
 
Cコンパイラの改造(未)
Cコンパイラの改造(未)Cコンパイラの改造(未)
Cコンパイラの改造(未)7shi
 
V6でJIT・部分適用・継続
V6でJIT・部分適用・継続V6でJIT・部分適用・継続
V6でJIT・部分適用・継続7shi
 
ZIP勉強会
ZIP勉強会ZIP勉強会
ZIP勉強会7shi
 
V6 Interpreter (Nagoya Geek Bar 2011-05-02)
V6 Interpreter (Nagoya Geek Bar 2011-05-02)V6 Interpreter (Nagoya Geek Bar 2011-05-02)
V6 Interpreter (Nagoya Geek Bar 2011-05-02)7shi
 
Deflate
DeflateDeflate
Deflate7shi
 
CRC-32
CRC-32CRC-32
CRC-327shi
 
無料環境でWindows Mobileアプリ開発
無料環境でWindows Mobileアプリ開発無料環境でWindows Mobileアプリ開発
無料環境でWindows Mobileアプリ開発7shi
 
LLPML
LLPMLLLPML
LLPML7shi
 

More from 7shi (11)

F#とトランスレータ
F#とトランスレータF#とトランスレータ
F#とトランスレータ
 
F#談話室(3) LT
F#談話室(3) LTF#談話室(3) LT
F#談話室(3) LT
 
マーク&スイープ勉強会
マーク&スイープ勉強会マーク&スイープ勉強会
マーク&スイープ勉強会
 
Cコンパイラの改造(未)
Cコンパイラの改造(未)Cコンパイラの改造(未)
Cコンパイラの改造(未)
 
V6でJIT・部分適用・継続
V6でJIT・部分適用・継続V6でJIT・部分適用・継続
V6でJIT・部分適用・継続
 
ZIP勉強会
ZIP勉強会ZIP勉強会
ZIP勉強会
 
V6 Interpreter (Nagoya Geek Bar 2011-05-02)
V6 Interpreter (Nagoya Geek Bar 2011-05-02)V6 Interpreter (Nagoya Geek Bar 2011-05-02)
V6 Interpreter (Nagoya Geek Bar 2011-05-02)
 
Deflate
DeflateDeflate
Deflate
 
CRC-32
CRC-32CRC-32
CRC-32
 
無料環境でWindows Mobileアプリ開発
無料環境でWindows Mobileアプリ開発無料環境でWindows Mobileアプリ開発
無料環境でWindows Mobileアプリ開発
 
LLPML
LLPMLLLPML
LLPML
 

Recently uploaded

持続可能なDrupal Meetupのコツ - Drupal Meetup Tokyoの知見
持続可能なDrupal Meetupのコツ - Drupal Meetup Tokyoの知見持続可能なDrupal Meetupのコツ - Drupal Meetup Tokyoの知見
持続可能なDrupal Meetupのコツ - Drupal Meetup Tokyoの知見Shumpei Kishi
 
20240326_IoTLT_vol109_kitazaki_v1___.pdf
20240326_IoTLT_vol109_kitazaki_v1___.pdf20240326_IoTLT_vol109_kitazaki_v1___.pdf
20240326_IoTLT_vol109_kitazaki_v1___.pdfAyachika Kitazaki
 
TaketoFujikawa_台本中の動作表現に基づくアニメーション原画システムの提案_SIGEC71.pdf
TaketoFujikawa_台本中の動作表現に基づくアニメーション原画システムの提案_SIGEC71.pdfTaketoFujikawa_台本中の動作表現に基づくアニメーション原画システムの提案_SIGEC71.pdf
TaketoFujikawa_台本中の動作表現に基づくアニメーション原画システムの提案_SIGEC71.pdfMatsushita Laboratory
 
IFIP IP3での資格制度を対象とする国際認定(IPSJ86全国大会シンポジウム)
IFIP IP3での資格制度を対象とする国際認定(IPSJ86全国大会シンポジウム)IFIP IP3での資格制度を対象とする国際認定(IPSJ86全国大会シンポジウム)
IFIP IP3での資格制度を対象とする国際認定(IPSJ86全国大会シンポジウム)ssuser539845
 
2024 01 Virtual_Counselor
2024 01 Virtual_Counselor 2024 01 Virtual_Counselor
2024 01 Virtual_Counselor arts yokohama
 
「今からでも間に合う」GPTsによる 活用LT会 - 人とAIが協調するHumani-in-the-Loopへ
「今からでも間に合う」GPTsによる 活用LT会 - 人とAIが協調するHumani-in-the-Loopへ「今からでも間に合う」GPTsによる 活用LT会 - 人とAIが協調するHumani-in-the-Loopへ
「今からでも間に合う」GPTsによる 活用LT会 - 人とAIが協調するHumani-in-the-LoopへTetsuya Nihonmatsu
 
情報処理学会86回全国大会_Generic OAMをDeep Learning技術によって実現するための課題と解決方法
情報処理学会86回全国大会_Generic OAMをDeep Learning技術によって実現するための課題と解決方法情報処理学会86回全国大会_Generic OAMをDeep Learning技術によって実現するための課題と解決方法
情報処理学会86回全国大会_Generic OAMをDeep Learning技術によって実現するための課題と解決方法ssuser370dd7
 
2024 02 Nihon-Tanken ~Towards a More Inclusive Japan~
2024 02 Nihon-Tanken ~Towards a More Inclusive Japan~2024 02 Nihon-Tanken ~Towards a More Inclusive Japan~
2024 02 Nihon-Tanken ~Towards a More Inclusive Japan~arts yokohama
 

Recently uploaded (11)

持続可能なDrupal Meetupのコツ - Drupal Meetup Tokyoの知見
持続可能なDrupal Meetupのコツ - Drupal Meetup Tokyoの知見持続可能なDrupal Meetupのコツ - Drupal Meetup Tokyoの知見
持続可能なDrupal Meetupのコツ - Drupal Meetup Tokyoの知見
 
20240326_IoTLT_vol109_kitazaki_v1___.pdf
20240326_IoTLT_vol109_kitazaki_v1___.pdf20240326_IoTLT_vol109_kitazaki_v1___.pdf
20240326_IoTLT_vol109_kitazaki_v1___.pdf
 
TaketoFujikawa_台本中の動作表現に基づくアニメーション原画システムの提案_SIGEC71.pdf
TaketoFujikawa_台本中の動作表現に基づくアニメーション原画システムの提案_SIGEC71.pdfTaketoFujikawa_台本中の動作表現に基づくアニメーション原画システムの提案_SIGEC71.pdf
TaketoFujikawa_台本中の動作表現に基づくアニメーション原画システムの提案_SIGEC71.pdf
 
IFIP IP3での資格制度を対象とする国際認定(IPSJ86全国大会シンポジウム)
IFIP IP3での資格制度を対象とする国際認定(IPSJ86全国大会シンポジウム)IFIP IP3での資格制度を対象とする国際認定(IPSJ86全国大会シンポジウム)
IFIP IP3での資格制度を対象とする国際認定(IPSJ86全国大会シンポジウム)
 
What is the world where you can make your own semiconductors?
What is the world where you can make your own semiconductors?What is the world where you can make your own semiconductors?
What is the world where you can make your own semiconductors?
 
2024 01 Virtual_Counselor
2024 01 Virtual_Counselor 2024 01 Virtual_Counselor
2024 01 Virtual_Counselor
 
「今からでも間に合う」GPTsによる 活用LT会 - 人とAIが協調するHumani-in-the-Loopへ
「今からでも間に合う」GPTsによる 活用LT会 - 人とAIが協調するHumani-in-the-Loopへ「今からでも間に合う」GPTsによる 活用LT会 - 人とAIが協調するHumani-in-the-Loopへ
「今からでも間に合う」GPTsによる 活用LT会 - 人とAIが協調するHumani-in-the-Loopへ
 
2024 04 minnanoito
2024 04 minnanoito2024 04 minnanoito
2024 04 minnanoito
 
2024 03 CTEA
2024 03 CTEA2024 03 CTEA
2024 03 CTEA
 
情報処理学会86回全国大会_Generic OAMをDeep Learning技術によって実現するための課題と解決方法
情報処理学会86回全国大会_Generic OAMをDeep Learning技術によって実現するための課題と解決方法情報処理学会86回全国大会_Generic OAMをDeep Learning技術によって実現するための課題と解決方法
情報処理学会86回全国大会_Generic OAMをDeep Learning技術によって実現するための課題と解決方法
 
2024 02 Nihon-Tanken ~Towards a More Inclusive Japan~
2024 02 Nihon-Tanken ~Towards a More Inclusive Japan~2024 02 Nihon-Tanken ~Towards a More Inclusive Japan~
2024 02 Nihon-Tanken ~Towards a More Inclusive Japan~
 

ELFの動的リンク