質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

コンパイラ

コンパイラは、プログラミング言語で記述したソースコードを、コンピュータの実行形式であるオブジェクトコードに変換するプログラムです。

Q&A

解決済

2回答

626閲覧

ダイナミックリンカローダーについて

strike1217

総合スコア651

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

コンパイラ

コンパイラは、プログラミング言語で記述したソースコードを、コンピュータの実行形式であるオブジェクトコードに変換するプログラムです。

0グッド

0クリップ

投稿2017/07/18 07:48

編集2017/07/18 08:27

ダイナミックリンカローダについてです。
動的なリンカ
動的なリンカ/ローダ

ELFファイルフォーマットの先頭には _startがあります。.textセクションに入っているやつですね。 ・・・(1)

_start → __libc_start_main() → main() に入ります。

カーネルがプログラムの起動時にダイナミックリンカローダを起動します。
私の環境では以下のようになっていました。

ダイナミックリンカローダ : /lib/x86_64-linux-gnu/ld-2.24.so
共有ライブラリ : /lib/x86_64-linux-gnu/libc.so.6
(間違っていたらご指摘お願いします。)

ELFインタプリタ /lib/x86_64-linux-gnu/ld-2.24.so のエントリアドレスは _startになっていまいます。

このエントリアドレスの_startとは 上記の(1)のことですか?
つまり、ダイナミックリンカローダー → _start → __libc_start_main() → main() ということですかね?
それともこのダイナミックリンカローダの_startとはまた別物ですか??

/lib/x86_64-linux-gnu/ld-2.24.so は直接実行することができます。
普段はカーネルが実行しますが・・・

これとldコマンドとの違いはなんですか?
ld コマンドはアセンブルされた機械語にセクションのマージなどを施すだけでしょうか?
つまり、gcc source.c -o source とやった段階のプリリンカみたいな?
という理解で正しいでしょうか??
(ldと/lib/x86_64-linux-gnu/ld-2.24.soは別物)
リンクについてです。
C/C++のオブジェクトファイルをldコマンドでリンクする方法

名前が紛らわしいので間違っていたらご指摘お願いします。

「追記」
ダイナミックリンカローダーの役割は、共有ライブラリをメモリにロードし実行ファイルの先頭アドレスに移動することですか?
他にも役割があったら教えてください

「追記2」___________________________
このエントリアドレスの_startとは 上記の(1)のことですか?
全くの別物でした。

では、ダイナミックリンカローダーにコンテキストスイッチが行われたあと、どうやってELFファイルの_startに飛んでいるんでしょうか??
%ripレジスタをカウントしていけば自然と_startの中に入るんですか??

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

_start については質問のポイントがわからなくなりましたが、

  • ダイナミンクリンカローダもELFファイルフォーマットです
  • ダイナミンクリンカローダにも、それがロードしようとしている実行可能ファイルにも _start はあります(つまり、メモリ空間上に_startとマークされているアドレスが二箇所あります)

主にこの二点を理解されていないのではないかと思います。

これとldコマンドとの違いはなんですか?

この質問には力が抜けます。。。

  • .o をたくさん集めて実行可能ファイルや共有ライブラリを作る(ファイルを吐き出す)のが ld
  • 実行可能ファイルと共有ライブラリをメモリ空間上にロードし、GOTとかを書き換えて実行できるようにするのがダイナミンクリンカローダ

全然違いますよね。

/lib/x86_64-linux-gnu/ld-2.24.so は直接実行することができます。

これは、トリビア的な話なので、気にしない方がいいと思います。

投稿2017/07/18 09:15

mit0223

総合スコア3401

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2017/07/18 09:44

あ、やはり別物ですね。 名前が似ていたもので・・・・ 「ダイナミンクリンカローダにも、それがロードしようとしている実行可能ファイルにも _start はあります」 ELFファイルフォーマット形式には_startが個別に用意されているんですね!! 実行ファイルのエントリポイントを探し出したので後で載せておきますね。
strike1217

2017/07/18 09:47

ldは共有ライブラリを作成するためだけのものではないですよね。 プリリンクにも使用できるよ!ってことですね!!
mit0223

2017/07/18 09:56

リンクという処理に着目して混乱されているようですが、ld はファイルを吐き出し、これをダイナミンクリンカローダが読み込んでメモリ上に展開すると考えてください。役割が全く異なりますよね。
strike1217

2017/07/18 10:18

gcc source.c -o source とやれば自動的にldが使用されているんですよね。 ダイナミックリンカローダの出番は実行時ということですよね。
guest

0

_lib/x86_64-linux-gnu/ld-2.24.so にある_startには
_dl_start()がありました。

_start:\n\ # Note that _dl_start gets the parameter in %eax.\n\ movl %esp, %eax\n\ call _dl_start\n\ _dl_start_user:\n\ # Save the user entry point address in %edi.\n\ movl %eax, %edi\n\ # Point %ebx at the GOT.\n\ call 0b\n\ addl $_GLOBAL_OFFSET_TABLE_, %ebx\n\ # See if we were run as a command with the executable file\n\ # name as an extra leading argument.\n\ movl _dl_skip_args@GOTOFF(%ebx), %eax\n\ # Pop the original argument count.\n\ popl %edx\n\ # Adjust the stack pointer to skip _dl_skip_args words.\n\ leal (%esp,%eax,4), %esp\n\ # Subtract _dl_skip_args from argc.\n\ subl %eax, %edx\n\ push %edx\n\ # The special initializer gets called with the stack just\n\ # as the application's entry point will see it; it can\n\ # switch stacks if it moves these contents over.\n\ " RTLD_START_SPECIAL_INIT "\n\ # Load the parameters again.\n\ # (eax, edx, ecx, *--esp) = (_dl_loaded, argc, argv, envp)\n\ movl _rtld_local@GOTOFF(%ebx), %eax\n\ leal 8(%esp,%edx,4), %esi\n\ leal 4(%esp), %ecx\n\ movl %esp, %ebp\n\ # Make sure _dl_init is run with 16 byte aligned stack.\n\ andl $-16, %esp\n\ pushl %eax\n\ pushl %eax\n\ pushl %ebp\n\ pushl %esi\n\ # Clear %ebp, so that even constructors have terminated backchain.\n\ xorl %ebp, %ebp\n\ # Call the function to run the initializers.\n\ call _dl_init\n\ # Pass our finalizer function to the user in %edx, as per ELF ABI.\n\ leal _dl_fini@GOTOFF(%ebx), %edx\n\ # Restore %esp _start expects.\n\ movl (%esp), %esp\n\ # Jump to the user's entry point.\n\ jmp *%edi\n\ .previous\n\ ");
・・・ if (bootstrap_map.l_addr || ! bootstrap_map.l_info[VALIDX(DT_GNU_PRELINKED)]) { /* Relocate ourselves so we can do normal function calls and data access using the global offset table. */ ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, 0, 0); } bootstrap_map.l_relocated = 1; /* Please note that we don't allow profiling of this object and therefore need not test whether we have to allocate the array for the relocation results (as done in dl-reloc.c). */ /* Now life is sane; we can call functions and access global data. Set up to use the operating system facilities, and find out from the operating system's program loader where to find the program header table in core. Put the rest of _dl_start into a separate function, that way the compiler cannot put accesses to the GOT before ELF_DYNAMIC_RELOCATE. */ { #ifdef DONT_USE_BOOTSTRAP_MAP ElfW(Addr) entry = _dl_start_final (arg); #else ElfW(Addr) entry = _dl_start_final (arg, &info); #endif #ifndef ELF_MACHINE_START_ADDRESS # define ELF_MACHINE_START_ADDRESS(map, start) (start) #endif return ELF_MACHINE_START_ADDRESS (GL(dl_ns)[LM_ID_BASE]._ns_loaded, entry); }

省略していますが、ELF_DYNAMIC_RELOCATE()によってGOTの設定が行われているようです。

最後にあるreturn の値が
(ELF_MACHINE_START_ADDRESS これ)
main()の方の_startのアドレスに相当しているようですね。
戻り値が%eaxに入るので、それを%ediに転送しています。
その後%ediは一度も書き込まれていないので、最後の行のJmpでmain()の方の_startに飛ぶようです。

main()に来る前に呼ばれる関数の確認 (2/3)

投稿2017/07/18 10:26

strike1217

総合スコア651

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2017/07/18 10:32

_dl_runtime_resolveはカーネルではなくダイナミックリンカローダによってGOTに登録されていました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問