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

隨筆-80  評(píng)論-24  文章-0  trackbacks-0
      開發(fā)WinixJ的第一步工作我打算模仿Linux。
      Linux是先將bootsect、setup、head、system等文件壓縮成一個(gè)IMAGE文件,然后再dd進(jìn)軟盤,之后bootsect開始加載過程。我打算采用這種方法,因?yàn)檫@種方法可以省去將軟盤做成某種格式然后用晦澀的匯編在boot中尋找loader、kernel加載。不過不同的地方也很明顯:Linux0.11處理的system文件是a.out格式的二進(jìn)制文件,這種文件格式非常簡(jiǎn)單,因此相對(duì)容易加載進(jìn)內(nèi)存;但是WinixJ在Linux3.0.0.12下開發(fā),此時(shí)的GCC已經(jīng)不支持a.out格式的輸出,因此我只能將WinixJ內(nèi)核編譯為ELF格式的二進(jìn)制文件,而ELF格式的文件相對(duì)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; //版本號(hào)
 23     Elf32_Addr        e_entry; //程序的入口地址,在編譯內(nèi)核的時(shí)候可由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; //每個(gè)program header entry的大小
 29     Elf32_Half        e_phnum; //program header entry的數(shù)量
 30     Elf32_Half        e_shentsize; //每個(gè)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文件中的時(shí)候,對(duì)每一個(gè)program segment,
 51 //都有一個(gè)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//不顯示錯(cuò)誤信息
 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)存在,報(bào)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個(gè)段的段頭內(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         //對(duì)每個(gè)程序段都在頭部加上描述該程序段的信息頭
251         //包含程序段的長(zhǎng)度以及程序段加載到內(nèi)存時(shí)的虛擬地址
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格式文件的組織形式吧:

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

可見文件格式還是相當(dāng)簡(jiǎn)單的,因?yàn)槲覀兊哪康木褪亲宭order可以非常輕松的將文件加載進(jìn)內(nèi)存指定位置。
紅色區(qū)域?yàn)轭^部,指定Magic Number:“kernel”,占6字節(jié),之后是內(nèi)核的入口地址,再然后是可加載程序段的段數(shù)。
之后每個(gè)可加載程序段都有一個(gè)段頭,該段頭指定段的大小和段在內(nèi)存中的起始虛擬地址。
我們的程序核心目的就是將原始的ELF格式內(nèi)核文件轉(zhuǎn)變成我們定義的簡(jiǎn)單的map文件,以供loader加載。
posted on 2011-11-20 14:35 myjfm 閱讀(473) 評(píng)論(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>
            国产情侣一区| aⅴ色国产欧美| 亚洲视频久久| 亚洲精选在线| 一本一本久久a久久精品牛牛影视| 亚洲国产日韩欧美在线图片| 亚洲欧洲日产国码二区| 亚洲人在线视频| 一区二区高清视频| 午夜精品短视频| 久久伊人亚洲| 亚洲国产欧美一区二区三区久久| 欧美国产亚洲另类动漫| 99国产精品久久久久久久成人热| 一区二区欧美在线| 久久成人av少妇免费| 另类尿喷潮videofree| 欧美日韩国产综合在线| 国产精品一香蕉国产线看观看 | 亚洲一区在线观看视频 | 欧美在线免费观看视频| 免费日韩av| 在线中文字幕一区| 久久三级福利| 国产精品久久久久aaaa九色| 激情成人中文字幕| 亚洲在线播放| 欧美.www| 在线综合亚洲| 美腿丝袜亚洲色图| 国产精品视频99| 亚洲日本电影在线| 久久精品夜色噜噜亚洲aⅴ| 亚洲精品日韩综合观看成人91| 午夜一区在线| 欧美性jizz18性欧美| 亚洲国产美国国产综合一区二区| 午夜在线a亚洲v天堂网2018| 亚洲茄子视频| 老司机久久99久久精品播放免费| 国产精品视频精品| 中文日韩欧美| 亚洲欧洲精品天堂一级| 久久久精品999| 国产一区二区三区精品久久久| 亚洲伊人网站| 亚洲免费不卡| 欧美精品一区在线发布| 亚洲级视频在线观看免费1级| 久久久久国产精品一区| 亚洲免费在线| 国产精品久久久久久久久久免费 | 亚洲第一精品电影| 久久国产精品第一页| 国产美女扒开尿口久久久| 亚洲视频国产视频| 亚洲人线精品午夜| 欧美高清视频一区二区| 亚洲第一在线视频| 欧美激情一二三区| 免费不卡在线视频| 亚洲欧洲午夜| 亚洲经典三级| 欧美精品一区二区久久婷婷| 亚洲黄色影院| 亚洲国产岛国毛片在线| 欧美福利一区| 99伊人成综合| 99天天综合性| 国产女人aaa级久久久级| 欧美一区二区三区男人的天堂 | 亚洲午夜成aⅴ人片| 国产精品videosex极品| 欧美在线在线| 久久久久久色| 亚洲电影观看| 亚洲黄色大片| 欧美日韩国产片| 亚洲欧美日韩精品在线| 欧美激情无毛| 亚洲美女黄网| 亚洲精品影院在线观看| 国产精品a级| 校园春色国产精品| 久久久久久久久综合| 亚洲精品综合在线| 亚洲网站视频福利| 精品电影一区| 亚洲国内高清视频| 国产精品日韩一区二区| 久久综合激情| 欧美日韩在线高清| 久久不射电影网| 免费看精品久久片| 亚洲欧美在线免费| 久久久久久网址| 亚洲欧美日韩国产另类专区| 欧美在线视频免费| 日韩一级在线| 久久精品成人欧美大片古装| 一本不卡影院| 欧美在线视频导航| 亚洲淫片在线视频| 欧美jizz19hd性欧美| 欧美中文在线免费| 欧美日韩国产精品一区| 欧美ed2k| 国产精品视频内| 美女网站在线免费欧美精品| 国产精品久久久久久久7电影| 欧美v日韩v国产v| 国产精品你懂的| 亚洲激情在线观看| 在线观看欧美亚洲| 先锋a资源在线看亚洲| 亚洲一区二区三区午夜| 蜜臀av在线播放一区二区三区| 久久精品99国产精品酒店日本| 欧美日韩国产在线播放| 欧美成人69av| 狠狠色狠狠色综合人人| 亚洲欧美日韩国产| 亚洲婷婷综合久久一本伊一区| 欧美国产精品人人做人人爱| 欧美v日韩v国产v| 黄色一区二区三区| 欧美一区二区三区免费视频| 欧美一区2区三区4区公司二百| 国产精品成人va在线观看| 欧美成人免费在线| 又紧又大又爽精品一区二区| 久久久999| 老司机免费视频一区二区| 韩国精品一区二区三区| 久久国产精品黑丝| 久久天天躁夜夜躁狠狠躁2022 | 亚洲一区国产精品| 在线视频一区观看| 欧美视频二区| 日韩一区二区精品在线观看| 宅男噜噜噜66国产日韩在线观看| 欧美激情在线狂野欧美精品| 欧美黄色一区| 一区二区三区日韩精品视频| 中国成人亚色综合网站| 欧美人妖另类| 99国产一区| 亚洲在线观看视频网站| 国产精品夫妻自拍| 亚洲欧美视频在线观看| 久久久亚洲高清| 亚洲电影专区| 欧美精品在线播放| 亚洲视频第一页| 久久www成人_看片免费不卡| 黄色国产精品| 欧美国产亚洲视频| 洋洋av久久久久久久一区| 亚洲欧美一区二区三区极速播放 | 国产精品视频一区二区三区| 亚洲欧美一区二区视频| 美女视频黄免费的久久| 99精品国产在热久久婷婷| 国产精品久久久久久av下载红粉| 校园激情久久| 欧美国产免费| 亚洲视频一区在线| 国产麻豆9l精品三级站| 久久中文欧美| 99日韩精品| 另类激情亚洲| 国产精品99久久不卡二区 | 一区二区三区产品免费精品久久75| 欧美日韩视频一区二区三区| 午夜精品一区二区在线观看 | 亚洲福利在线观看| 亚洲一区在线免费观看| 怡红院精品视频| 国产精品国产自产拍高清av王其| 久久精品国产综合精品| 亚洲免费高清| 牛牛影视久久网| 亚洲免费视频在线观看| 1024成人| 国产精品自拍在线| 欧美区一区二区三区| 久久aⅴ国产欧美74aaa| 99视频精品在线| 亚洲国产精品成人综合| 欧美专区在线观看| 亚洲综合首页| 91久久在线| 国内偷自视频区视频综合| 欧美视频在线一区二区三区| 久久综合久色欧美综合狠狠| 午夜精品久久久久久久久久久久| 亚洲日本久久| 欧美激情视频给我| 免费永久网站黄欧美| 亚洲国产成人久久综合|