.elf 形式の内部確認

.elf 形式の内部確認

エルフヘッダー、プログラムヘッダー、セクション、セグメントなど、これらすべてを伝えるELF形式の仕様を読んでいます。これらのすべては、さまざまなフィールドと値を持つ構造として参照されます。

もしそうなら、問題はこれがどこに行くのかということです。私の言葉は、readelfutilの出力の代わりに構造で処理できますか?

これらすべてを含む中間ファイルはありますか?エルフ魔法存在し、ソースコードにマージされましたか?それともコンパイラの内部構造であり、その構造は人間だけのための仕様書に言及されているのでしょうか? )

私にとって、これは「鶏と卵の問題」(コンパイルされたコードについて話すためにコードを使用する)のようです。

ベストアンサー1

これらの構造はELFファイルに存在します。

ELFヘッダーを見てみましょう。

#define EI_NIDENT (16)

typedef struct
{
  unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */
  Elf32_Half    e_type;                 /* Object file type */
  Elf32_Half    e_machine;              /* Architecture */
  Elf32_Word    e_version;              /* Object file version */
  Elf32_Addr    e_entry;                /* Entry point virtual address */
  Elf32_Off     e_phoff;                /* Program header table file offset */
  Elf32_Off     e_shoff;                /* Section header table file offset */
  Elf32_Word    e_flags;                /* Processor-specific flags */
  Elf32_Half    e_ehsize;               /* ELF header size in bytes */
  Elf32_Half    e_phentsize;            /* Program header table entry size */
  Elf32_Half    e_phnum;                /* Program header table entry count */
  Elf32_Half    e_shentsize;            /* Section header table entry size */
  Elf32_Half    e_shnum;                /* Section header table entry count */
  Elf32_Half    e_shstrndx;             /* Section header string table index */
} Elf32_Ehdr;

typedef struct
{
  unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */
  Elf64_Half    e_type;                 /* Object file type */
  Elf64_Half    e_machine;              /* Architecture */
  Elf64_Word    e_version;              /* Object file version */
  Elf64_Addr    e_entry;                /* Entry point virtual address */
  Elf64_Off     e_phoff;                /* Program header table file offset */
  Elf64_Off     e_shoff;                /* Section header table file offset */
  Elf64_Word    e_flags;                /* Processor-specific flags */
  Elf64_Half    e_ehsize;               /* ELF header size in bytes */
  Elf64_Half    e_phentsize;            /* Program header table entry size */
  Elf64_Half    e_phnum;                /* Program header table entry count */
  Elf64_Half    e_shentsize;            /* Section header table entry size */
  Elf64_Half    e_shnum;                /* Section header table entry count */
  Elf64_Half    e_shstrndx;             /* Section header string table index */
} Elf64_Ehdr;

ELFヘッダーは次の場所にあります。すべてELFファイル。

これが実際に意味するのは、ELFファイルの最初の16バイトがe_identELFヘッダーのフィールドであることです。

  • 最初のバイトは0x7fです。

  • 2番目は'E';

  • 3番目は'L';

  • 4番目'F'

  • 5番目はクラスです。

  • 6番目はデータエンコーディングです。

  • 7番目はファイルバージョンです。

  • 8番目はオペレーティングシステムABIです。

  • など。

このフィールドe_identの後の2バイトはですe_type

それがあなたなら、最初に近いものを見るhead /bin/bashことができます。ELF

これでELFファイルの先頭の16進ダンプが得られます。

$ xxd /bin/bash | xxdヘッダー|
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF..............
00000010: 0200 3e00 0100 0000 7005 4200 0000 0000 ..>.....pB....
00000020: 4000 0000 0000 0000 c0cd 0f00 0000 0000 @...........
00000030:0000 0000 4000 3800 0900 4000 1d00 1c00  [Eメール保護]...@.....
00000040: 0600 0000 0500 0000 4000 0000 0000 0000 .......@.......
00000050: 4000 4000 0000 0000 4000 4000 0000 0000 @.@.....@.@.....
00000060: f801 0000 0000 0000 f801 0000 0000 0000 ........
00000070: 0800 0000 0000 0000 0300 0000 0400 0000 ............
00000080: 3802 0000 0000 0000 3802 4000 0000 0000 8.......8.@.....
00000090: 3802 4000 0000 0000 1c00 0000 0000 0000 8.@........................

この16進ダンプの最初の行は最初の16バイト(e_ident)です。

  • 最初のバイトは実際に0x7f;

  • それから"ELF";

  • それには(ELF64)0x02クラスがあります。ELFCLASS64

  • 0x01その後、エンコードが続きますELFDATA2LSB

  • など。

2行目の最初の2バイトはですe_type。 LSBでエンコードされるので、ELFDATA2LSB値は実際には実行可能ファイルであることを0x0002意味します。ET_EXEC

次の2バイトはアーキテクチャ(e_machine)です。これは実行可能ファイルだ0x003eからです。EM_X86_64x86_64

ELFヘッダー内のすべてのフィールドを手動でデコードできる必要があり、指定された値と同じ値を見つける必要がありますreadelf。これにより、ファイル内ElfXX_Shdrまたは他のELF構造を見つけ、その定義ElfXX_Phdrに従ってデコードできます(与えられた情報と同じ情報を見つける必要がありますreadelf)。

おすすめ記事