Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
リンカを作ってみた
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
hotaru
April 17, 2026
200
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
リンカを作ってみた
hotaru
April 17, 2026
More Decks by hotaru
See All by hotaru
Raspberry Pi 5の起動プロセスについて
hotaru_jp
1
1.2k
デバッグ支援ハイパーバイザとRaspberry pi 5でのAMP
hotaru_jp
0
100
Featured
See All Featured
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.5k
Building Flexible Design Systems
yeseniaperezcruz
330
40k
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
330
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
570
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
360
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
590
So, you think you're a good person
axbom
PRO
2
2.1k
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
65
55k
The Spectacular Lies of Maps
axbom
PRO
1
810
Building an army of robots
kneath
306
46k
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
0
150
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.3k
Transcript
リンカを 2 週間で作ってみた 2026/4/17 コンパイラのコンパの部分 第2回 LT ほたるいか 1 1
ほたるいか 詳細なプロフィール 東京科学大学 学士3年 サイボウズ・ラボユース ‘25 SecHack365 '25 坂井ゼミ セキュリティキャンプ
2024 全国大会 ハイパーバイザゼミ 2 ハイパーバイザやCコンパイラを作成しています
モチベーション 3 去年の2月ぐらいからコンパイラを作っているが、IR対応/multi arch 対応したら 2万行以上になってセルフホストせずに放置してる、、、 + 最近実行バイナリをそのまま吐くコンパイラ?を作ったが案外簡単 ↓ リンカをつくれるのでは?
つくってみた
今回の目標 (簡単な)リンカを作ってみよう 4
できたもの 5 入力されたobject fileをまとめて静的リンクをするリンカ newlibによる標準ライブラリもリンクできるようにしている ここでデモ GitHub
リンカの仕組み (簡単な)リンカの仕組み 6
リンカの仕組み 7 elfリンカの役割は、複数のオブジェクトファイルを統合して実行可能な ファイルにすること。 Cコード アセンブリ オブジェクト ファイル 実行可能 elf
コンパイラ アセンブラ リンカ
オブジェクトファイルの中身 8 オブジェクトファイルとは、linkableな方のelf fileである。 elf は executable and linkable formatの略であり、実行可能fileとリンク可能fileの
2つの形態がある。 executable elf そのままローダに通して、‘./a.out’等で実行可能なelf linkable elf (オブジェクトファイル) Cコードやアセンブリと1対1で対応する型式 Cコードやアセンブリでexternとして外部定義するシンボル(関数/変数)は アドレスを決められずに残ったまま
オブジェクトファイルをlinkする方法 9 基本はすごい簡単な2 step 1.すべてのオブジェクトファイルを読んで、シンボルをすべてリストアップ 2.そのシンボルを使って未解決なまま残っている外部定義シンボルを解決する これさえやれば標準ライブラリを使わないプログラムは動く
外部シンボルの解決方法 10 ※静的リンクの場合 object file object/archive file を読む object fileのセクションのうち
必要なものをまとめる シンボルをまとめて 未解決シンボルを解決 .textセクション等に relocationを適用 executable elfを 出力する executable elf
object/archive fileを読む 11 標準ライブラリへの対応には、object fileだけでなく、archive fileも読めなければなら ない。 archive fileはUnixのar型式で、object fileをまとめたもの。
このarchive file内部にobject fileが複数並んでいるので、それを必要に応じて入れる。 archive fileにはどのobject fileになんのシンボルが定義されているか/未定義のまま残さ れているかが書かれている。 このmain.cをコンパイルしたmain.oには printfが未定義 ↓ 標準ライブラリのarchive fileからprintf が定義されているobject fileを探して一緒にリンク
object fileのセクションのうち 必要なものをまとめる 12 object fileには色々なセクションがある .textセクション: プログラムが入る .dataセクション: グローバル変数が入る
.rodataセクション: read onlyなグローバル変数が入る .bssセクション: 0埋めのグローバル変数が入る .noteセクション: gccのメモ書き等で使われたりする .debugセクション: DWARFが入ってたりする ※より正確にはSHF_ALLOCであるもののみ持って、SHT_NOBITSなら.bss、SHF_EXECINSTRなら.text、 SHF_WRITEなら.data、それ以外を.rodataに入れている 今回は最低限の.text .data .rodata .bss以外すべて捨てる! デバッグ用等で実際にはメモリに乗らないものも多いので、 、 、
シンボルをまとめて 未解決シンボルを解決 13 シンボルとは、関数やグローバル変数のことである。 別の関数で定義されているシンボルはobject fileの時点では読めないため、 Undefinedなシンボルとして扱われる。 ここでは、definedなシンボルをまず集めて、Undefinedなシンボルを解決しようとしている Undefinedなシンボルが解決できなかったらarchive fileを見て、それにもなければエラー
__attribute__((weak))等のweak symbolもここで衝突したら無視するなどの処理を入れる
.textセクション等にrelocationを適用 14 .textセクションでは機械語が実際に書かれている その際に、関数呼び出し等があるが、object fileの時点で未解決なシンボルに相当する 機械語部分は0埋め(RELA)または情報が置かれている(REL) ここに実際のシンボルのアドレスを入れる シンボルが関数の場合 関数アドレスを入れる シンボルが変数の場合
変数のアドレスを入れる 絶対アドレスによる呼び出し、PC相対呼び出し等によって入れるべき値が違うため、 object fileのrelocation情報の書かれたセクションからどういう計算をすればいいかを知る .e.g.: R_X86_64_PC32であれば相対32bitなので、 symbol_addr + addend /* offsetのようなもの */ - place_addr で計算される ※今回はRELA対応のみ
executable elfを出力する 15 最後、executableなelfとして出力する elfには最初に実行されるべきentry pointを必要とするが、これは_startシンボルのアドレス とする また、.text .data .rodata
.bssはそれぞれpage size alignされている必要がある これをしてなかったせいで、.dataと.rodataが一緒のページに配置されてセグフォした
TODO 16 Thread Local Storageへの対応 グローバル変数はプロセスごとにわかれているのみであり、同じプロセス のスレッドは変数を共有してしまう ライブラリではerrno等、スレッドごとに記憶領域を別にしたいものは Thread Local
Storage(TLS)に入れられている。 CではTLSは通常の変数へのアクセスのように扱われるが、linuxではTLSへ のアクセスはFS セグメントからの相対アドレスで扱われる このため、executable elfでも.dataセクション等とは別の扱いが必要であ り、.tdataセクション等にまとめる必要がある。
TODO 17 glibcへの対応を行う そもそも今回はnewlibへの対応しかしなかった newlibとした利点は、TLS無しにできたり、よくわからないセクションを吐 かないため .text/.data/.rodata/.bssに帰着できないセクションを吐かれるとリンク不能/ セグフォする 外部リンクへの対応 どうやればいいかあまりわかってないから調べるところから
pltやgotなどセクションが更に増えてややこしそう
おまけ 18 weak undefined symbolの話 __attribute__((weak))で定義されていて、かつundefinedな場合 つまり、‘__attribute__((weak)) extern foo’等のとき、 未定義シンボルが解決されなかった場合には、そのシンボルはNULLとなる
このため、 if (foo) foo(); のようにする必要がある。