青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆-80  評論-24  文章-0  trackbacks-0
      開發(fā)WinixJ的第一步工作我打算模仿Linux。
      Linux是先將bootsect、setup、head、system等文件壓縮成一個IMAGE文件,然后再dd進(jìn)軟盤,之后bootsect開始加載過程。我打算采用這種方法,因為這種方法可以省去將軟盤做成某種格式然后用晦澀的匯編在boot中尋找loader、kernel加載。不過不同的地方也很明顯:Linux0.11處理的system文件是a.out格式的二進(jìn)制文件,這種文件格式非常簡單,因此相對容易加載進(jìn)內(nèi)存;但是WinixJ在Linux3.0.0.12下開發(fā),此時的GCC已經(jīng)不支持a.out格式的輸出,因此我只能將WinixJ內(nèi)核編譯為ELF格式的二進(jìn)制文件,而ELF格式的文件相對a.out要復(fù)雜的多,因此我們開發(fā)了proc_kernel.c文件專門處理ELF格式文件,該程序產(chǎn)生kernel.map輸出文件。
先把代碼貼出:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <unistd.h>
  5 #include <sys/stat.h>
  6 
  7 typedef    unsigned int    Elf32_Addr;
  8 typedef    unsigned short    Elf32_Half;
  9 typedef unsigned int    Elf32_Off;
 10 typedef unsigned int    Elf32_Sword;
 11 typedef unsigned int    Elf32_Word;
 12 
 13 #define EI_NIDENT    16
 14 #define MAX_BUF_LEN    1024
 15 
 16 //ELF文件的ELF header結(jié)構(gòu)
 17 typedef struct
 18 {
 19     unsigned char    e_ident[EI_NIDENT]; //ELF魔數(shù)
 20     Elf32_Half        e_type; //文件類型
 21     Elf32_Half        e_machine; //支持的機(jī)器架構(gòu)
 22     Elf32_Word        e_version; //版本號
 23     Elf32_Addr        e_entry; //程序的入口地址,在編譯內(nèi)核的時候可由ld程序手工指定
 24     Elf32_Off        e_phoff; //program header在文件中的偏移量
 25     Elf32_Off        e_shoff; //section header在文件中的偏移量
 26     Elf32_Word        e_flags; //標(biāo)志
 27     Elf32_Half        e_ehsize; //ELF頭的大小
 28     Elf32_Half        e_phentsize; //每個program header entry的大小
 29     Elf32_Half        e_phnum; //program header entry的數(shù)量
 30     Elf32_Half        e_shentsize; //每個section header entry的大小
 31     Elf32_Half        e_shnum; //section header entry的數(shù)量
 32     Elf32_Half        e_shstrndx;
 33 } Elf32_Ehdr;
 34 #define ELFHDR_LEN sizeof(Elf32_Ehdr)
 35 
 36 //ELF文件的program header結(jié)構(gòu)
 37 typedef struct
 38 {
 39     Elf32_Word        p_type; //該頭所指向的program segment的類型
 40     Elf32_Off        p_offset; //該頭所指向的program segment在文件中的偏移
 41     Elf32_Addr        p_vaddr; //該頭所指向的program segment加載進(jìn)內(nèi)存后的虛擬地址
 42     Elf32_Addr        p_paddr; //該頭所指向的program segment加載進(jìn)內(nèi)存后的物理地址
 43     Elf32_Word        p_filesz; //該頭所指向的program segment在文件中的大小
 44     Elf32_Word        p_memsz; //該頭所指向的program segment在內(nèi)存中的大小
 45     Elf32_Word        p_flags;
 46     Elf32_Word        p_align;
 47 }Elf32_Phdr;
 48 #define PHDR_LEN sizeof(Elf32_Phdr)
 49 
 50 //輸出到kernel.map文件中的時候,對每一個program segment,
 51 //都有一個Seghdr開頭,表征該段的信息,包括段的大小,以及段
 52 //的起始虛擬地址
 53 typedef struct
 54 {
 55     int memsz;
 56     int vaddr;
 57 }Seghdr;
 58 #define SEGHDR_LEN sizeof(Seghdr)
 59 
 60 #define FILE_NAME_LEN 50
 61 //緩沖區(qū)
 62 unsigned char buffer[MAX_BUF_LEN];
 63 char infilename[FILE_NAME_LEN];
 64 char outfilename[FILE_NAME_LEN];
 65 FILE *ifp, *ofp;
 66 
 67 static void usage()
 68 {
 69     fprintf(stderr, "Usage: proc_kernel [-r ../boot/boot] [-w ../Image]\n");
 70 }
 71 
 72 void die()
 73 {
 74     fclose(ifp);
 75     fclose(ofp);
 76     exit(1);
 77 }
 78 
 79 static void init()
 80 {
 81     strcpy(infilename, "../kernel/kernel"); //默認(rèn)輸入文件為在頂層目錄的kernel子目錄中的內(nèi)核文件
 82     strcpy(outfilename, "../kernel/kernel.map"); //默認(rèn)輸出到頂層目錄的kernel子目錄中,文件名為kernel.map
 83 }
 84 
 85 static void proc_opt(int argc, char * const *argv)
 86 {
 87     int ch;
 88     opterr = 0//不顯示錯誤信息
 89 
 90     while ((ch = getopt(argc, argv, "r:w:h")) != -1)
 91     {
 92         switch (ch)
 93         {
 94             case 'r'//指定kernel文件名
 95                 strcpy(infilename, optarg);
 96                 break;
 97             case 'w'//指定輸出的系統(tǒng)映像文件名
 98                 strcpy(outfilename, optarg);
 99                 break;
100             case 'h':
101                 usage();
102                 exit(1);
103         }
104     }
105 }
106 
107 static void open_file()
108 {
109     //如果輸入的內(nèi)核文件不存在
110     if (0 != access(infilename, F_OK))
111     {
112         fprintf(stderr, "\"%s\": No such file.\n", infilename);
113         exit(1);
114     }
115 
116     //如果輸出的內(nèi)核映像文件已經(jīng)存在,報warning
117     if (0 == access(outfilename, F_OK))
118     {
119         fprintf(stderr, "Warning: The file \"%s\" exists.\n", outfilename);
120         fprintf(stderr, "But we will go on \n");
121     }
122 
123     ifp = fopen(infilename, "r+");
124     //如果不能打開輸入文件
125     if (NULL == infilename)
126     {
127         fprintf(stderr, "cannot open the file \"%s\".\n", infilename);
128         exit(1);
129     }
130 
131     ofp = fopen(outfilename, "w+");
132     //如果不能創(chuàng)建kernel.map文件
133     if (NULL == ofp)
134     {
135         fprintf(stderr, "cannot create the file \"%s\".\n", outfilename);
136         exit(1);
137     }
138 }
139 
140 int main(int argc, char *const *argv)
141 {
142     int pht_offset, n, i;
143     Elf32_Ehdr elf_header;//保存elf文件頭
144     Elf32_Phdr p_header_buf;
145     Seghdr seg_header_buf;
146     unsigned short loadable_seg_num = 0;
147 
148     init();
149     proc_opt(argc, argv);
150     open_file();
151 
152     //讀出ELF文件頭
153     n = fread((void *)&elf_header, ELFHDR_LEN, 1, ifp);
154 
155     if (n < 1)
156     {
157         fprintf(stderr, "cannot read the \"%s\" file's ELF header!\n", infilename);
158         die();
159     }
160 
161     //輸出文件的文件頭格式為
162     //0  1  2  3  4  5  6  7  8  9  10  11(以字節(jié)為單位)
163     //k  e  r  n  e  l  |入口地址|  |段數(shù)|
164     n = fwrite("kernel"61, ofp);
165 
166     if (n < 1)
167     {
168         fprintf(stderr, "cannot write into \"%s\".\n", outfilename);
169         die();
170     }
171 
172     //entry address
173     n = fwrite((void *)(&(elf_header.e_entry)), 41, ofp);
174 
175     if (n < 1)
176     {
177         fprintf(stderr, "cannot write into \"%s\".\n", outfilename);
178         die();
179     }
180 
181     fprintf(stdout, "entry address: %x\n", elf_header.e_entry);
182     //the number of segments
183     n = fwrite("  "21, ofp);
184 
185     if (n < 1)
186     {
187         fprintf(stderr, "cannot write into \"%s\".\n", outfilename);
188         die();
189     }
190 
191     //判斷輸入文件是否是ELF格式文件
192     //ELF格式的文件頭部的前四字節(jié)是“.ELF”的ascii碼
193     if (((int *)(elf_header.e_ident))[0]!= 0x464c457f)
194     {
195         fprintf(stderr, "\"%s\" is not an ELF file!\n", infilename);
196         die();
197     }
198 
199     //判斷文件是否是可執(zhí)行文件
200     if (elf_header.e_type != 2)
201     {
202         fprintf(stderr, "\"%s\" is not an excutable file!\n", infilename);
203         die();
204     }
205 
206     //該ELF支持的機(jī)器架構(gòu)是否是80386類型
207     if (elf_header.e_machine != 3)
208     {
209         fprintf(stderr, "\"%s\" is not for I386!\n", infilename);
210         die();
211     }
212 
213     //輸出內(nèi)核文件包含的程序段信息
214     fprintf(stdout, "\"%s\"含有的程序段的段數(shù): %d\n", infilename, elf_header.e_phnum);
215 
216     for (i = 0; i < elf_header.e_phnum; ++i)
217     {
218         if (PHDR_LEN != elf_header.e_phentsize)
219         {
220             fprintf(stderr, "program header entry is confused!\n");
221             die();
222         }
223 
224         fseek(ifp, elf_header.e_phoff + i * elf_header.e_phentsize, SEEK_SET);
225         n = fread(&p_header_buf, elf_header.e_phentsize, 1, ifp);
226 
227         if (n < 1)
228         {
229             fprintf(stderr, "cannot read the program header entry!\n");
230             die();
231         }
232 
233         fprintf(stdout, "第%d個段的段頭內(nèi)容:\n", i + 1);
234         fprintf(stdout, "\tp_type:   0x%x\n", p_header_buf.p_type);
235         fprintf(stdout, "\tp_offset: 0x%x\n", p_header_buf.p_offset);
236         fprintf(stdout, "\tp_vaddr:  0x%x\n", p_header_buf.p_vaddr);
237         fprintf(stdout, "\tp_paddr:  0x%x\n", p_header_buf.p_paddr);
238         fprintf(stdout, "\tp_filesz: 0x%x\n", p_header_buf.p_filesz);
239         fprintf(stdout, "\tp_memsz:  0x%x\n", p_header_buf.p_memsz);
240         fprintf(stdout, "\tp_flags:  0x%x\n", p_header_buf.p_flags);
241         fprintf(stdout, "\tp_align:  0x%x\n", p_header_buf.p_align);
242 
243         if (1 != p_header_buf.p_type)//is not PT_LOAD
244         {
245             fprintf(stderr, "this segment is not loadable\n");
246             continue;
247         }
248 
249         loadable_seg_num++;
250         //對每個程序段都在頭部加上描述該程序段的信息頭
251         //包含程序段的長度以及程序段加載到內(nèi)存時的虛擬地址
252         seg_header_buf.memsz = p_header_buf.p_filesz;
253         seg_header_buf.vaddr = p_header_buf.p_vaddr;
254 
255         n = fwrite((void *)&seg_header_buf, SEGHDR_LEN, 1, ofp);
256         if (1 != n)
257         {
258             fprintf(stderr, "cannot write the segment length into \"%s\".\n", outfilename);
259             die();
260         }
261 
262         //將段內(nèi)容寫進(jìn)輸出文件中
263         fseek(ifp, p_header_buf.p_offset, SEEK_SET);
264 
265         while (p_header_buf.p_filesz > MAX_BUF_LEN)
266         {
267             n = fread(buffer, 1, MAX_BUF_LEN, ifp);
268 
269             if (MAX_BUF_LEN != n)
270             {
271                 fprintf(stderr, "cannot read the segment from \"%s\".\n", infilename);
272                 die();
273             }
274 
275             p_header_buf.p_filesz -= MAX_BUF_LEN;
276             n = fwrite(buffer, MAX_BUF_LEN, 1, ofp);
277 
278             if (1 != n)
279             {
280                 fprintf(stderr, "cannot write the segment into \"%s\".\n", outfilename);
281                 die();
282             }
283         }
284 
285         if (p_header_buf.p_filesz > 0)
286         {
287             n = fread(buffer, p_header_buf.p_filesz, 1, ifp);
288 
289             if (1 != n)
290             {
291                 fprintf(stderr, "cannot read the segment from \"%s\".\n", infilename);
292                 die();
293             }
294 
295             n = fwrite(buffer, p_header_buf.p_filesz, 1, ofp);
296 
297             if (1 != n)
298             {
299                 fprintf(stderr, "cannot write the segment into \"%s\".\n", outfilename);
300                 die();
301             }
302         }
303     }
304 
305     //將輸入文件中可加載段的段數(shù)寫進(jìn)輸出文件頭中
306     fseek(ofp, 10, SEEK_SET);
307     n = fwrite((void *)&loadable_seg_num, 21, ofp);
308 
309     if (1 != n)
310     {
311         fprintf(stderr, "cannot write the entry address into the \"kernel.map\" file!\n");
312         die();
313     }
314 
315     fclose(ifp);
316     fclose(ofp);
317     return 0;
318 }

先看看ELF格式文件的組織形式吧:

整個ELF文件中固定的部分只有ELF頭,它表征整個ELF文件的組織形式。其他的包括程序頭和節(jié)頭都不是固定的,甚至可以不包括。程序頭和節(jié)頭分別是從文件執(zhí)行角度和文件鏈接角度來看的。因為我們只關(guān)心如何將ELF加載進(jìn)內(nèi)存,因此我們只關(guān)心程序頭。每個程序頭包括表征一個程序是否可執(zhí)行以及在文件中的位置和加載到內(nèi)存中時的起始虛擬地址等信息。我們需要的就是這個信息。
再看看我們想生成的map文件的組織格式:

可見文件格式還是相當(dāng)簡單的,因為我們的目的就是讓lorder可以非常輕松的將文件加載進(jìn)內(nèi)存指定位置。
紅色區(qū)域為頭部,指定Magic Number:“kernel”,占6字節(jié),之后是內(nèi)核的入口地址,再然后是可加載程序段的段數(shù)。
之后每個可加載程序段都有一個段頭,該段頭指定段的大小和段在內(nèi)存中的起始虛擬地址。
我們的程序核心目的就是將原始的ELF格式內(nèi)核文件轉(zhuǎn)變成我們定義的簡單的map文件,以供loader加載。
posted on 2011-11-20 14:35 myjfm 閱讀(473) 評論(0)  編輯 收藏 引用 所屬分類: 操作系統(tǒng)
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲激情网站免费观看| 亚洲尤物在线视频观看| 一本在线高清不卡dvd| 亚洲国产欧美一区二区三区丁香婷| 国产一区日韩二区欧美三区| 国产伦精品一区二区三区四区免费| 国产精品呻吟| 国产欧美精品一区二区色综合 | 久久久久久久91| 久久国产精品色婷婷| 久久精品国产一区二区电影| 久久精品综合一区| 欧美成人亚洲成人| 最新中文字幕亚洲| 日韩视频中文| 欧美一二区视频| 欧美大片免费看| 国产精品一区二区a| 精品99视频| 99精品欧美一区二区三区综合在线| 亚洲一品av免费观看| 久久久久久久久久久久久女国产乱| 欧美电影资源| 亚洲一区二区三区四区视频| 久久久久国产精品厨房| 国产精品激情电影| 亚洲伦理一区| 亚洲欧美日韩综合一区| 久久综合狠狠| 久久精品国产精品亚洲精品| 免费观看日韩av| 中日韩美女免费视频网站在线观看| 欧美在线视频一区二区三区| 欧美激情麻豆| 国内精品久久久久影院薰衣草| 99国产一区| 免费短视频成人日韩| 亚洲一区三区在线观看| 欧美成在线视频| 激情综合视频| 欧美一区二区三区视频免费播放| 欧美激情一区二区三区四区| 午夜日韩在线观看| 欧美日韩视频一区二区三区| 欲香欲色天天天综合和网| 午夜日韩av| 日韩午夜电影| 欧美11—12娇小xxxx| 国内外成人在线| 欧美亚洲在线| 亚洲特级毛片| 国产精品va在线| 亚洲视频在线播放| 亚洲欧洲在线播放| 男女av一区三区二区色多| 一区二区亚洲欧洲国产日韩| 欧美在线影院| 亚洲综合色婷婷| 亚洲小说区图片区| 欧美日韩亚洲高清| 最新精品在线| 亚洲电影中文字幕| 美女精品视频一区| 亚洲国产高清高潮精品美女| 久久嫩草精品久久久久| 欧美一区二区播放| 国产一区av在线| 久久精品30| 欧美一区二区三区播放老司机 | 亚洲午夜视频| 一区二区欧美激情| 国产精品久久久久久久久免费樱桃| 一区二区国产精品| 亚洲精品在线视频| 国产精品家教| 欧美有码在线观看视频| 亚洲愉拍自拍另类高清精品| 国产精品网站在线| 久久成人亚洲| 久久人人97超碰精品888| 亚洲电影有码| 亚洲欧洲日本国产| 亚洲一区精品电影| 亚洲主播在线观看| 国产一区二区三区久久久| 久久精品国产久精国产一老狼| 久久xxxx| 亚洲美女一区| 亚洲网站视频福利| 激情久久五月| 亚洲精品一线二线三线无人区| 国产精品vvv| 亚洲激情视频| 亚洲图片激情小说| 狠狠色综合网| 日韩西西人体444www| 国产伦精品一区二区三区免费| 久久人人爽人人| 欧美日韩成人一区二区| 久久久www| 欧美日韩亚洲一区二区三区在线观看| 亚洲欧美日本另类| 美国十次成人| 欧美专区福利在线| 欧美激情视频网站| 久久免费高清| 欧美午夜精品久久久久久久| 噜噜噜躁狠狠躁狠狠精品视频| 欧美精品粉嫩高潮一区二区| 久久久精品日韩| 欧美日韩精品国产| 男人天堂欧美日韩| 国产精品丝袜白浆摸在线| 欧美国产高潮xxxx1819| 国产免费一区二区三区香蕉精| 亚洲国产欧美日韩| 激情欧美国产欧美| 亚洲一区二区成人在线观看| 亚洲欧洲综合另类| 久久精品女人天堂| 欧美一级专区免费大片| 欧美日韩国产欧| 亚洲国产精品嫩草影院| 狠狠色狠狠色综合| 欧美一区二区三区另类| 性感少妇一区| 国产免费亚洲高清| 欧美一级久久| 久久不射中文字幕| 国产日韩欧美a| 亚洲欧美久久| 久久精品视频一| 精品av久久久久电影| 久久久久国色av免费看影院| 久久亚洲色图| 亚洲片国产一区一级在线观看| 麻豆亚洲精品| 亚洲精品一区在线| 亚洲欧美国产高清| 国产模特精品视频久久久久| 性做久久久久久| 久久一区二区精品| 亚洲二区在线| 欧美精品在线一区二区三区| 91久久久久久| 亚洲欧美一区二区原创| 国产精品手机在线| 久久精品91| 亚洲国产精品一区二区尤物区| 国产精品国产三级国产普通话蜜臀| 国产丝袜一区二区| 亚洲欧美另类中文字幕| 亚洲午夜av| 欧美精品在线免费观看| 99精品视频网| 中文精品99久久国产香蕉| 女人天堂亚洲aⅴ在线观看| 亚洲国产欧美日韩另类综合| 亚洲激情第一页| 欧美日本视频在线| 亚洲精品国精品久久99热| 一本色道久久综合亚洲91| 欧美激情影院| 91久久精品www人人做人人爽| 亚洲无毛电影| 国产精品久久久久久亚洲调教| 日韩视频免费| 亚洲国产91| 欧美精品久久一区| 亚洲精品一区二区网址| 在线一区二区三区四区五区| 国产性天天综合网| 久久久久99| 亚洲欧洲一区| 久久成人资源| 激情婷婷亚洲| 欧美大片18| 在线综合+亚洲+欧美中文字幕| 久久国产高清| 亚洲第一色中文字幕| 欧美精品久久久久久久| 亚洲香蕉视频| 亚洲激情综合| 欧美在线不卡| 亚洲激情欧美| 伊人久久大香线蕉av超碰演员| 欧美成人国产| 亚洲中字黄色| 亚洲福利国产精品| 久久一区中文字幕| 亚洲视频在线观看免费| 国模吧视频一区| 亚洲一区二区视频在线| 最近中文字幕日韩精品| 欧美一区二区精品| 亚洲人成网站在线播| 欧美日韩国产综合视频在线观看| 亚洲欧美日韩精品一区二区| 亚洲大胆人体视频| 午夜精品一区二区三区在线|