Linux ELFフォーマットファイル解析のrelocationとentryエントリポイント、gasアセンブリ言語の視点に基づく


問題の導入:
Linuxのelfファイルは最初から理解するのは確かに難しく、「linkers and loaders」を読む人もいるかもしれません.この本は確かにいいですが、多くの詳細を詳しく説明していません.特にアセンブリ言語の視点からです.私はこの本をたくさん読んでからまだ分からないので、IBM 360コンピュータのアセンブリ設計ドキュメントを読みました.二次スキャンアセンブリの設計原理とrelocation概念を詳しく説明しました.しかし、これらは依然として私の疑問を解決することができません.私を悩ませているのは選択肢です.つまりld-ttext=orgです.このorgオフセットがプログラムにどのような影響を及ぼすか分かりません.最初はelfのファイルヘッダ情報を変更しただけだと思っていましたが、私は間違っていました.これは複雑なメカニズムに関連しています.そこで私は何度も実験を経て、ついに今の個人的な見解を得ました.個人的な見解とは、いくつかの細部で私の理解がまだ正確ではないかもしれないので、読者の皆さんに指摘してほしいと思っています.ここで謝ります.もし私の文章が皆さんに役に立つなら、私はとても光栄です.
まず簡単なアセンブリを見てみましょう
.section .data
a:
	.int 2222
.section .text
.globl _start
_start:
mov a,%eax
mov $1,%eax
mov $250,%ebx
int $0x80

このプログラムは簡単です.もちろん、AT&T文法で書かれています.プログラムは簡単に2222をeaxに格納、終了し、終了コード250に戻る.
それをまとめましょう.
as -o testelf.o testelf.s

次はリンクを開始します.コードを後ではっきり見るためにldの多くのオプションを使用します.-xと-sは不要な記号情報を削除するために使用されます.私たちのこのブログの重点は関数のエントリポイントと再配置です.
はい、コマンドを実行します.
ld -o testelf testelf.o -s -x

次は
readelf testelf -a

elf実行可能ファイルの詳細を見てください.【簡潔にするために、必要な出力部分をスクリーンショットせずに直接コピーします】
Entry point address:               0x8048074
Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x08048000 0x08048000 0x00085 0x00085 R E 0x1000
  LOAD           0x000088 0x08049088 0x08049088 0x00004 0x00004 RW  0x1000
 Section to Segment mapping:
  Segment Sections...
   00     .text 
   01     .data
説明して、私は翻訳しないで、更に正確です
Offset:This member gives the offset from the beginning of the file at which the first byte of the segment resides.
VirtAddr:This member gives the virtual address at which the first byte of the segment resides in memory.
PhysAddr:On systems for which physical addressing is relevant, this member is reserved for the segment’s physical address. Because System V ignores physical addressing for application
programs, this member has unspecified contents for executable files and shared objects.
FileSiz:This member gives the number of bytes in the file image of the segment; it may be zero.
MemSiz:This member gives the number of bytes in the memory image of the segment; it may be zero.
「もっと詳しく書くのが面倒だと気づいた.16進コードで書けない..自分でメモしておいたほうがいい.ごめんなさい」
つまり、私は-ttextを使用してVirtAddrの値に影響を与えることができます.-ttext 0 x 22、VirtAddrは0 x 22になります(完全に対等ではありません.後述します).しかし、entryは0 x 24です.位置合わせの要因があるからです.
-ttext 0の場合、ページ揃え、すなわちelfファイルが4 kのページ揃えであり、1ページ目の4 kバイト以内で、先頭がファイルヘッダとプログラムヘッダであり、残りは0であり、0ページ目と1ページ目の間の隙間を埋めるためであることがわかります.ld textセグメントをファイル内の0ページ目に0 x 22シフトすると、ファイルヘッダが上書きされるので、textを1ページ目にします.そのため、隙間が発生します.textの1ページ目のオフセットは0 x 22です.
Entry point address:               0x24
Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x001022 0x00000022 0x00000022 0x00013 0x00013 R E 0x1000
  LOAD           0x001038 0x00001038 0x00001038 0x00004 0x00004 RW  0x1000
ほら、これが変化です.もともとtextとファイルヘッダを一緒にロードしていたので、オフセット0から始まり、今はtextをロードするだけなので、1ページ目のオフセット0 x 22から始まります.もちろん整列のため、本物のコードは2バイト後退したので、エントリは0 x 24である.コード0 x 01022--0 x 010344をメモリ0 x 0000022の位置にロードし、コードエントリはちょうど0 x 0000024である.
-ttext 0 x 128であれば、textが0ページ目に置かれてもファイルヘッダを上書きしないので、ldはtextを0ページ目に置き、ファイルヘッダとの間の隙間数百バイトを0で補完する.プログラムヘッダの内容が調整されます.
Entry point address:               0x128
Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x00000000 0x00000000 0x00139 0x00139 R E 0x1000
  LOAD           0x00013c 0x0000113c 0x0000113c 0x00004 0x00004 RW  0x1000
今回はオフセット0からtextをロードし、ファイルヘッダとともにロードします.0 x 00000000にロードされ、entryは0 x 128がコードの先頭にアクセスします.
-nでldのページングを禁止すると、-ttext 0はldにtextを0ページ目の先頭に強制し、ファイルヘッダを上書きしないようにldはtextをファイルヘッダの後ろに強制します.しかし、dataは依然として1ページ目で、textの後ろに付いていません.なぜなら、-ttext 0は-Tdata 0を使用しない限り、dataに影響しません.
基本的には、ldはパラメータによって調整されるため、elfの多くの情報に影響します.私はただメモを残して、書き終わっただけで、私も気絶しました.皆さんさようなら...