FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

RustでELFファイルを開く方法を調査する (3. Section Headerを読み取る)

Program Headerを読み取ることができるようになったので、次はSection Headerを読み取ることにする。Section Headerに関する情報は、ELFファイルの先頭から、ELFヘッダテーブルにおけるSHOFFバイトの位置から開始している。また、各セクションの大きさは、SHENTSIZE分なので、SHNUM分だけセクションを読んでいけばよい。

        for sh_idx in 0..loader.get_e_shnum() {
            let shdr: SectionHeader = loader.get_section_header(sh_idx.into());
            shdr.dump();
            loader.dump_section(shdr.sh_offset, shdr.sh_size);
        }

get_section_header()では、SHOFFからSHENTSIZEバイトずつデータを読み込んで情報を表示してく。Section Headerの構成は以下のようになっているので、そのまま値を書きだしていく仕組みだ。

typedef struct
{
  Elf64_Word    sh_name;        /* Section name (string tbl index) */
  Elf64_Word    sh_type;        /* Section type */
  Elf64_Xword   sh_flags;       /* Section flags */
  Elf64_Addr    sh_addr;        /* Section virtual addr at execution */
  Elf64_Off sh_offset;      /* Section file offset */
  Elf64_Xword   sh_size;        /* Section size in bytes */
  Elf64_Word    sh_link;        /* Link to another section */
  Elf64_Word    sh_info;        /* Additional section information */
  Elf64_Xword   sh_addralign;       /* Section alignment */
  Elf64_Xword   sh_entsize;     /* Entry size if section holds table */
} Elf64_Shdr;
    fn get_section_header(&self, idx: u32) -> SectionHeader {
        let mut sh_off   = self.get_e_shoff();
        let sh_entsize  = self.get_e_shentsize() as u32;

        sh_off += sh_entsize*idx;

        let sh_name      = self.get_4byte_elf(sh_off as usize); sh_off += 4;
        let sh_type      = self.get_4byte_elf(sh_off as usize); sh_off += 4;
        let sh_flags     = self.get_8byte_elf(sh_off as usize); sh_off += 8;
        let sh_addr      = self.get_8byte_elf(sh_off as usize); sh_off += 8;
        let sh_offset    = self.get_8byte_elf(sh_off as usize); sh_off += 8;
        let sh_size      = self.get_8byte_elf(sh_off as usize); sh_off += 8;
        let sh_link      = self.get_4byte_elf(sh_off as usize); sh_off += 4;
        let sh_info      = self.get_4byte_elf(sh_off as usize); sh_off += 4;
        let sh_addralign = self.get_8byte_elf(sh_off as usize); sh_off += 8;
        let sh_entsize   = self.get_8byte_elf(sh_off as usize); // sh_off += 8;

        SectionHeader::new (sh_name, sh_type, sh_flags, sh_addr, sh_offset,
                            sh_size, sh_link, sh_info, sh_addralign, sh_entsize.into())
    }

このようにして最終的に結果をダンプしていく。以下のようになった。

...
== Section Dump ==
  Name      : 1b
  Type      : 1
  Flags     : 6
  Addr      : 80000000
  Offset    : 1000
  Size      : 144
  Link      : 0
  Info      : 0
  AddrAlign : 40
  EntSize   : 0
04c0006f 34202f73 00800f93 03ff0a63
00900f93 03ff0663 00b00f93 03ff0263
80000f17 fe0f0f13 000f0463 000f0067
34202f73 000f5463 0040006f 5391e193
00001f17 fc3f2023 ff9ff06f f1402573
00051063 00000297 01028293 30529073
18005073 00000297 01c28293 30529073
...
72757461 65620065 5f6e6967 6e676973
72757461 735f0065 74726174 6e655f00
72660064 6f686d6f 00007473
== Section Dump ==
  Name      : 11
  Type      : 3
  Flags     : 0
  Addr      : 0
  Offset    : 223b
  Size      : 2e
  Link      : 0
  Info      : 0
  AddrAlign : 1
  EntSize   : 0
79732e00 6261746d 74732e00 62617472
68732e00 74727473 2e006261 74786574
696e692e 742e0074 736f686f 00000074