リンカとはosに依存するツールだと書いてあったのですが、いまいちリンカが何なのかわかりません。
リンカがソフトとも書いてありましたが、C言語をコンパイルしてアセンブリプログラムをアセンブルする過程でリンカが働いているのでしょうか?
リンカと調べるとリンカスクリプトと出てきてリンカについての情報が曖昧です。
どうかリンカが何なのか教えて頂けないでしょうか?
アセンブリ言語とは直接でないにしても関係のあるような記事はいくつかありました。
アセンブリプログラムのアセンブル(アセンブリ用のコンパイラ)がリンカなのでしょうか?
編集
図書館で調べたり、書店で立ち読みしたり、サイトで調べた結果。
Linuxで複数のアセンブリプログラムを一つにするのかに、リンカが必要だそうですが、リンカを使わないで、複数のアセンブリプログラムを一つにまとめて見ます。これに関してはリンカ自体を手作業でやるようなものであり、何ヶ月、何年かかるかわかりませんが。好奇心が満たせるなら行いたいです。
また、一つにしたアセンブリプログラムをメモリに入れる際のメモリの指定も自分でやってみます。
リンカの行なっていることを手作業でやることで、知識が深まると思います。
また、アセンブリプログラムを機械語に変換するのに、リンカが関係ないこともわかりました。
なぜなら、複数のアセンブリプログラムを一つにするのがリンカ
の役割で、その一つにしたアセンブリプログラムをメモリに収納するまでが、リンカの仕事で、あとはアセンブルが単純にアセンブリ命令に対応した機械語を出力するだけですので。
確認として以上の認識であっていますか?間違っていたら怖いのでお願いいたします。
まぁ、以上の話からアセンブリプログラムを機械語に変化するアセンブラにはリンカが必要ないと書いてありました。また、リンカはあくまて複数のアセンブリプログラムを一つにするためにアセンブリプログラムのアドレスを基に複数のアセンブリプログラムを一つにするとも書いてありました。念のため確認します。
編集2
度々、すいません、
オブジェクトファイルにcpuに繋がる外部装置や、複数のアセンブリプログラムを一つにする為のアドレスやメモリ状況がわかるでしょうか?ならば、
オブジェクトファイルをアセンブリやニーモニックに変換するソフトを使えば、複数のアセンブリプログラムを一つにする方法や情報が書いてあるのでしょうか?
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答8件
0
リンカというのは、複数のオブジェクトファイルをまとめて1つの実行形式のファイルを作る作業ですね。
コンパイル → アセンブル → リンク → 実行可能!
という流れですね。
具体的に、リンカは何をやっているかというと・・・
・セクションのマージ
・再配置
・シンボル解決
という3つが基本ですね。
例えば、readelf -S [オブジェクトファイル]で調べるとセクションの一覧が取得できます。
[14] .text PROGBITS 00000000004005b0 000005b0 00000000000001d2 0000000000000000 AX 0 0 16 [15] .fini PROGBITS 0000000000400784 00000784 0000000000000009 0000000000000000 AX 0 0 4 [16] .rodata PROGBITS 0000000000400790 00000790 0000000000000015 0000000000000000 A 0 0 4 [17] .eh_frame_hdr PROGBITS 00000000004007a8 000007a8 0000000000000044 0000000000000000 A 0 0 4
複数のオブジェクトファイルからこの各セクションを取得し、1つにまとめます。
この後に、シンボル解決を行います。
これは、変数名や関数名というシンボルにアドレスを割り当てます。
nmコマンドを使うとシンボルを表示できます。
リンカの一番の仕事は「ロードするメモリアドレスの決定」であると考えています。
複数のセクションはセグメントという領域に割り当てられます。
これもリンカの仕事です。
readelf --segments [バイナリファイル] とやると確認できます。
02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .plt.got 03 .bss 04 .text .fini .rodata .eh_frame_hdr .eh_frame 05 .init_array .fini_array .dynamic .got .got.plt .data 06 .dynamic 07 .note.ABI-tag .note.gnu.build-id
ローダはこのセグメント情報を元にメモリにロードします。
セグメントを作れば、実行することができます。
逆にセクメンとを持たないオブジェクトファイルは実行できません。
OSはシステムコールが発行されるとload_elf_binary()を使ってELF形式のバイナリファイルをメモリにロードするわけです。
(ちなみにLinux Kernel もELFなので、コンパイルする際にはリンカが必要です。)
このロードするアドレスは「リンカスクリプト」というファイルに記述されています。
ld --verbose とやると見ることができます。
SECTIONS { /* Read-only sections, merged into text segment: */ PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS; .interp : { *(.interp) } .note.gnu.build-id : { *(.note.gnu.build-id) } .hash : { *(.hash) } .gnu.hash : { *(.gnu.hash) } .dynsym : { *(.dynsym) } .dynstr : { *(.dynstr) } .gnu.version : { *(.gnu.version) } .gnu.version_d : { *(.gnu.version_d) } .gnu.version_r : { *(.gnu.version_r) } .rela.dyn : { *(.rela.init)
リンカはこのスクリプト情報を元に、マージするセクション、ロード先のアドレスを決定します。
他にもリンカには静的リンク、動的リンクがあり、動的にリンクは実行の際にダイナミックリンカというプログラムが起動し、printfなのどのシンボル解決を行います。
通常、gcc test.c -o test とコンパイルすると動的リンクになります。
静的にリンクしたい時は、-static オプションを付けると可能です。
投稿2018/03/24 06:47
編集2018/03/24 07:47総合スコア651
0
リンカというのは実行ファイル(あるいはライブラリ)を作る、最後の段階の作業を行うものです。
- コンパイラにより高級言語のソースコードからオブジェクトファイルを作る
(場合によってはいったんアセンブリ言語にするものもある)
2. アセンブリ言語の場合はアセンブラがオブジェクトファイルを作る
3. オブジェクトファイルをまとめ、ライブラリの依存関係を解消した状態で、最終結果の実行ファイルを作る(ライブラリによっては実行時に動的リンクをする設定になる場合もある)
リンカは最終的な実行ファイルを作成しているので、その時点で OS に依存します。オブジェクトファイルの段階では、CPU アーキテクチャには依存しますが、OS にはまだ依存しきっていません。とはいっても必要とするライブラリが OS 依存しますから、まず依存を解消することはできないのですけれども。
リンカがやることを手作業でやることに全く意味はありません。独自のコンパイラを作る場合でさえ、リンカまでは自作することはないのです。それこそ GCC のメンテナでも無い限り、リンカの挙動について考える必要なんて無いでしょう。
もっとも、最近の高級言語だと、Java や .NET のように、コンパイラはバイトコードと呼ばれる仮想マシンコードを作成し、実行は実行環境にある仮想マシンエミュレータがバイトコードを読み取りつつ動作するものもあります(こういう方法自体はそれこそ 8bit パソコンの時代にもありました)
投稿2018/03/15 13:40
総合スコア13703
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/16 16:11
2018/03/19 23:08
0
例えば、C言語から標準ライブラリのprintfで文字列を表示するプログラムがあったとします。このプログラムをコンパイルすると、その機械語は作成できますが、この中にprintfを実行するための機械語はありません。
リンカとは、標準ライブラリや別のソースプログラムから作成された機械語をくっつけて一つの実行できる機械語(実行形式)にするものです。実行形式は、それぞれのOSによってメモリに配置する方法がことなります。例えば、MacもWindowsも同じicoreチップで動作しますが、実行プログラムは動作しません。
ランカーの仕事は、先程の例では、mainプログラムの中のprintfを呼び出す機械語部分のアドレスを、標準ライブラリからくっつけたprintfモジュールがどのアドレスに配置されるのか算出したアドレス値に書き換えます。
今では、リンクの作業は、ダイナミックリンク(動的リンク)に取って代わり、プログラム実行時に自動的に行われるようになっています
投稿2018/03/13 23:23
総合スコア157
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/14 10:47
2018/03/14 10:55
2018/03/14 13:26
2018/03/15 14:22
2018/03/15 15:19
2018/03/15 15:20
2018/03/16 02:20
2018/03/19 23:06
2018/03/19 23:09
0
”リンカ”でググったらトップにそのものの説明が出てきたのですが、本当に調べました?
リンカとは、リンケージエディタのことで、機械語のプログラムの断片を結合し、実行可能なプログラムにするプログラムのことである。 例えば、C言語の場合、ソースファイルをコンパイルするオブジェクトファイルが生成され、それに他のオブジェクトファイルやライブラリを結合し、1つのプログラムにする。
https://it-words.jp/w/E383AAE383B3E382AB.html
リンカスクリプトはリンカに食わせるスクリプトで、プログラマがプログラムやデータの配置アドレスを指定したい場合に使います。
用途としては主に組み込み分野で、リアルタイムOSやベアメタルのプログラムを作った時に、プログラムを配置するROMやメモリのアドレスを指定したりします。
投稿2018/03/13 15:09
編集2018/03/13 15:11総合スコア1449
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/13 15:57
2018/03/13 17:26
0
リンカは分割コンパイルと密接に関係する機能を提供しています。
分割してコンパイルしたオブジェクトをひとつにまとめるのがリンカです。
コンパイラ(やアセンブラ)では人間が書いたソースコードにある名前を内部名と外部名とに分けてオブジェクトを作成します。
外部名になるのは、共用変数や、外部に公開するサブルーチン、外部にあると指定したサブルーチンや変数などです。
ローカル変数や内部サブルーチンは外部名にはなりません。
外部名にならなかった名前はオブジェクトには現れません。
リンカ(linker)は複数のオブジェクトを読んで、それらの外部名を結びつけます。リンクづけするからリンカと呼ばれます。
(linkage editorと呼ばれるOS環境もあります)
手でソースをひとつにすることでリンカのなすべき処理の大半をコンパイラにさせることができます。しかし手でソースをひとつにする際、上記で述べた内部名は元のソースが別だったら同じ名前を使ってはいけません。同じ名前を使ったままひとつのソースしてコンパイルすると、同じものとしてコンパイルされ、その結果、プログラムの動作が違ってくるからです。
別々にコンパイルした場合、内部名は見えなくなっているので、リンカで同じものとしての処理されることはありません。
(逆に言うと同じものとしてリンカに処理してもらいたいものは外部名となるように指定します)
投稿2019/04/28 14:37
総合スコア1240
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
複数の中間生成物(hello.o)から実行ファイル(hello.exe)を作成する。
hello.o はユーザが作ったコードを意味している感じますが、リンカは、システムに存在するライブラリも連結します。printf("hello")ならprintfはどこかで定義されていて、ウインドウを作ってその中に色付きの文字を表示するならそのウィンドウを準備したり、#112233みたいな色をハードの教えるために部分が必要になります。
printfを間違えてprintgとしてもアセンブラは文句を言いませんが、リンカでprintgが見つからないというエラーになります。asmさんのコメントにあるように部分的にロード時まで解決を遅らせることもできます。
dllの場合は、すでに読み込まれているdllを利用できる場合、実行途中でリンクする場合などもっと複雑な方法が取れます。Linuxの場合、実行途中でシステムのライブラリをデバッグ・ハッキングのために自作のものに切り替えたり、それを阻止するような対策を打つことがあります。
投稿2018/03/24 05:21
総合スコア580
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
なぜなら、複数のアセンブリプログラムを一つにするのがリンカ
の役割で、その一つにしたアセンブリプログラムをメモリに収納するまでが、リンカの仕事で、あとはアセンブルが単純にアセンブリ命令に対応した機械語を出力するだけですので。
間違った認識です。
- アセンブラ(
as
)
アセンブリソース(hello.s)から不完全な機械語を含む中間生成物(hello.o)を作成する。
- リンカ(
ld
)
中間生成物(hello.o)から実行ファイル(hello.exe)を作成する。
- ローダー(ツールというかOSもしくはBIOS)
実行ファイル(hello.exe)を実行するよう命令されたOSが(多くの場合、仮想の)メモリ上に
実行ファイルやライブラリ(.dll)等を読み込み。実行ファイルに指定されたアドレスをエントリーポイントとして呼び出します。
アセンブリ言語は規格化された言語とは違いますので、アセンブラ毎に処理や生成物等が違う可能性がありますが
少なくともGNUアセンブラではこんな感じです。
投稿2018/03/16 23:31
編集2018/03/16 23:33総合スコア15149
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
リンカが行うリンクは、コンパイルやアセンブルの後処理で、実行プログラムを作ることです。
とりあえず、https://ja.wikipedia.org/wiki/%E3%83%AA%E3%83%B3%E3%82%B1%E3%83%BC%E3%82%B8%E3%82%A8%E3%83%87%E3%82%A3%E3%82%BF を読んで不明点を書いてください。
リンカスクリプトとは、リンカにリンクの仕方を指示する場合に、それが複雑な場合の指示の記述のことです。
投稿2018/03/13 14:46
総合スコア85960
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/24 06:56
2018/03/24 07:11
2018/03/24 07:19
2018/03/24 07:26
2018/03/24 07:30
2018/03/24 08:10
2018/03/24 08:15
2018/03/24 08:59
2018/03/24 10:05
2018/03/24 10:55
2018/03/24 11:01