GeekOS:Project1. Loading Executable Files
轉自 http://www.cnblogs.com/wuchang/archive/2009/06/14/geekos-project1.html一、項目設計目的
熟悉ELF文件格式,瞭解GeekOS系統如何將ELF格式的可執行程序裝入到內存,建立內核進程並運行的實現技術。
二、項目設計要求
1、修改/geekos/elf.c文件:在函數Parse_ELF_Executable(
)中添加代碼,分析ELF格式的可執行文件(包括分析得出ELF文件頭、程序頭,獲取可執行文件長度,代碼段、數據段等信息),並填充
Exe_Format數據結構中的域值。
2、在Linux環境下編譯系統得到GeekOS鏡像文件。
3、編寫一個相應的bochs配置文件。
4、在bochs中運行GeekOS系統顯示結果。
在此項目中,GeekOS需要從磁盤加載一個可執行文件到內存中,並且在內核線程中執行此程序。我們需要做的就是完成/geekos/elf.c中Parse_ELF_Executable函數,把EXE文件的內容填充到指定的Exe_format格式的區域。
/geekos/elf.c中Parse_ELF_Executable函數的定義如下:
int Parse_ELF_Executable(char *exeFileData, ulong_t exeFileLength, struct Exe_Format *exeFormat) |
exeFileData爲ELF(Executable and Linking Format)格式的可執行文件的內容,exeFileLength爲文件的長度,函數就是需要把exeFileData中的數據填充到exeFormat中。
先來分析一下ELF文件內容佈局:
文件最開始是ELF文件頭結構,跟着是ProgramesHeader表,接下來是各個區段,最後是可選的區段頭表。詳細的可以參看ELF Specification
。
在elf.h中可以找到 ELF Header和programHeader的定義:
typedef struct {
unsigned char ident[16];
unsigned short type;
unsigned short machine;
unsigned int version;
unsigned int entry;
unsigned int phoff;
unsigned int sphoff;
unsigned int flags;
unsigned short ehsize;
unsigned short phentsize;
unsigned short phnum;
unsigned short shentsize;
unsigned short shnum;
unsigned short shstrndx;
} ELFHeader;
ELFHEader各字段的含義參看這裏ELF Header 。
typedef struct {
unsigned int type;
unsigned int offset;
unsigned int vaddr;
unsigned int paddr;
unsigned int fileSize;
unsigned int memSize;
unsigned int flags;
unsigned int alignment;
} programHeader;
Exe_Format結構的定義如下:
struct Exe_Format {
struct Exe_Segment segmentList[EXE_MAX_SEGMENTS]; /* Definition of segments */
int numSegments; /* Number of segments contained in the executable */
ulong_t entryAddr; /* Code entry point address */
};
struct Exe_Segment {
ulong_t offsetInFile; /* Offset of segment in executable file */
ulong_t lengthInFile; /* Length of segment data in executable file */
ulong_t startAddress; /* Start address of segment in user memory */
ulong_t sizeInMemory; /* Size of segment in memory */
int protFlags; /* VM protection flags; combination of VM_READ,VM_WRITE,VM_EXEC */
};
明白了這幾個結構後,程序就很容易了:
int Parse_ELF_Executable(char *exeFileData, ulong_t exeFileLength,
struct Exe_Format *exeFormat)
{
int i;
elfHeader *hdr =(elfHeader*) exeFileData;
programHeader *phdr=(programHeader *)(exeFileData + hdr->phoff);;
struct Exe_Segment * segment= exeFormat->segmentList ;
for( i=0; i< hdr->phnum; i++)
{
segment->offsetInFile = phdr->offset;
segment->lengthInFile = phdr->fileSize;
segment->startAddress = phdr->vaddr;
segment->sizeInMemory = phdr->memSize;
phdr++;
segment++;
}
exeFormat->numSegments = hdr->phnum;
exeFormat->entryAddr = hdr->entry;
return 0;
}
此項目中執行的是 src/user/a.c編譯後的a.exe程序,如果想修改顯示信息的可以打開此文件修改。
此項目執行的程序放在disk.img磁盤映像中,和project0稍有不同,所以要修改下.bochsrc文件,參考配置如下:
config_interface: textconfig
romimage: file=/usr/share/bochs/BIOS-bochs-latest
megs: 8
vgaromimage: file=/usr/share/vgabios/vgabios.bin
floppya: 1_44=./fd.img, status=inserted
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata1: enabled=0, ioaddr1=0x170, ioaddr2=0x370, irq=15
#ata2: enabled=0, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11
#ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9
ata0-master: type=disk, path="diskc.img", mode=flat, cylinders=40, heads=8, spt=64
#ata0-slave: type=cdrom, path="/dev/cdrom", status=inserted
boot: a
ips: 1000000
log:./bochs.out
vga_update_interval: 300000
keyboard_serial_delay: 250
keyboard_paste_delay: 100000
private_colormap: enabled=0