ucore--可讀ELF格式文件的baby bootloader--proj2-第三部分

    // read the 1st page off disk,讀取內核elf文件的頭部出來,這個地方只是讀取了4KB
    readseg((uintptr_t)ELFHDR, SECTSIZE * 8, 0);

我們查看一下製作內核的時候的文件是多大

dd if=bin/kernel of=bin/ucore.img seek=1 conv=notrunc

真實的文件大小差不多在29K左右

sgy@ubuntu:~/workspace/ucore_step_by_myself$ ls bin/kernel -lh
-rwxrwxr-x 1 sgy sgy 29K Apr 17 15:00 bin/kernel

所以真正讀取的數據是在下面的這幾行代碼。

    struct proghdr *ph, *eph;

    // load each program segment (ignores ph flags)
    ph = (struct proghdr *)((uintptr_t)ELFHDR + ELFHDR->e_phoff);
    eph = ph + ELFHDR->e_phnum;
    for (; ph < eph; ph ++) {
        readseg(ph->p_va & 0xFFFFFF, ph->p_memsz, ph->p_offset);
    }

    // call the entry point from the ELF header
    // note: does not return
    ((void (*)(void))(ELFHDR->e_entry & 0xFFFFFF))();

這幾行代碼什麼意思,需要講一下elf文件的格式。

程序員的自我修養—鏈接、裝載與庫.pdf-P94
ELF文件格式詳解.pdf

elf文件的最開始是文件頭。
在這裏插入圖片描述
elf文件中很重要的一個概念是段表,section header table
在這裏插入圖片描述
那麼怎麼來查看elf文件的頭部呢?
readelf -h bin/kernel

sgy@ubuntu:~/workspace/ucore_step_by_myself$ readelf -h bin/kernel
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x100000
  Start of program headers:          52 (bytes into file)
  Start of section headers:          26828 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         3
  Size of section headers:           40 (bytes)
  Number of section headers:         16
  Section header string table index: 13
sgy@ubuntu:~/workspace/ucore_step_by_myself$

對照elf文件頭結構體的代碼實現一起看會清晰一點

/* file header */
struct elfhdr {
    uint32_t e_magic;     // must equal ELF_MAGIC
    uint8_t e_elf[12];
    uint16_t e_type;      // 1=relocatable, 2=executable, 3=shared object, 4=core image
    uint16_t e_machine;   // 3=x86, 4=68K, etc.
    uint32_t e_version;   // file version, always 1
    uint32_t e_entry;     // entry point if executable
    uint32_t e_phoff;     // file position of program header or 0
    uint32_t e_shoff;     // file position of section header or 0
    uint32_t e_flags;     // architecture-specific flags, usually 0
    uint16_t e_ehsize;    // size of this elf header
    uint16_t e_phentsize; // size of an entry in program header
    uint16_t e_phnum;     // number of entries in program header or 0
    uint16_t e_shentsize; // size of an entry in section header
    uint16_t e_shnum;     // number of entries in section header or 0
    uint16_t e_shstrndx;  // section number that contains section name strings
};

其中我感覺比較重要的幾個變量
e_entry
程序的入口地址,操作系統在加載完elf可執行程序之後從這個地址開始執行指令。對應下面這個值

Entry point address:               0x100000

e_shoff
就是前面說的很重要的結構,段表。

Start of section headers:          26828 (bytes into file)---0x68cc
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章