感谢这篇文章的作者: http://www.cnblogs.com/strugglesometimes/p/4231359.html
编译是个很蛋疼的事情,本想把linux0.12在bochs上跑起来然后就可以各模块的学习,没想各种问题。
问题1:
1 gas -c -o boot/head.o boot/head.s2 make: gas: Command not found
gas已过时,将所有Makfile里gas -> as
具体解决方法
1 | msed gas as |
msed 是个简单的shell 函数,具体定义见下面的传送门。
传送门:
问题2:
1 boot/head.s:43: Error: unsupported instruction `mov' 2 boot/head.s:47: Error: unsupported instruction `mov' 3 boot/head.s:59: Error: unsupported instruction `mov' 4 boot/head.s:61: Error: unsupported instruction `mov' 5 boot/head.s:136: Error: invalid instruction suffix for `push' 6 boot/head.s:137: Error: invalid instruction suffix for `push' 7 boot/head.s:138: Error: invalid instruction suffix for `push' 8 boot/head.s:139: Error: invalid instruction suffix for `push' 9 boot/head.s:140: Error: invalid instruction suffix for `push' 10 boot/head.s:151: Error: invalid instruction suffix for `push' 11 boot/head.s:152: Error: invalid instruction suffix for `push' 12 boot/head.s:153: Error: invalid instruction suffix for `push' 13 boot/head.s:154: Error: operand type mismatch for `push' 14 boot/head.s:155: Error: operand type mismatch for `push' 15 boot/head.s:161: Error: invalid instruction suffix for `push' 16 boot/head.s:163: Error: invalid instruction suffix for `pop' 17 boot/head.s:165: Error: operand type mismatch for `pop' 18 boot/head.s:166: Error: operand type mismatch for `pop' 19 boot/head.s:167: Error: invalid instruction suffix for `pop' 20 boot/head.s:168: Error: invalid instruction suffix for `pop' 21 boot/head.s:169: Error: invalid instruction suffix for `pop' 22 boot/head.s:214: Error: unsupported instruction `mov' 23 boot/head.s:215: Error: unsupported instruction `mov' 24 boot/head.s:217: Error: unsupported instruction `mov'
这是由于在64位机器上编译的原因,需要告诉编译器,我们要编译32位的code,在所有Makefile的AS后面添加 --32,CFLAGS中加-m32
具体解决方法
msed as$ as\ --32 msed -O -O\ -m32
问题3:
boot/head.s: Assembler messages:boot/head.s:231: Error: alignment not a power of 2make: *** [boot/head.o] Error 1
把align n -> align 2^n
具体解决方法
sed -i 's/align 2/align 4/g' boot/head.s sed -i 's/align 3/align 8/g' boot/head.s
问题4:
gcc: error: unrecognized command line option ‘-fcombine-regs’gcc: error: unrecognized command line option ‘-mstring-insns’
把这两个删掉即可,现在GCC已经不支持了
具体解决方法
msed -fcombine-regs \ msed -mstring-insns \
问题5:
额。。。。为了更快的找到Error的地方,我把所有的warning 都关掉了即在CFLAGS 中加-w
具体解决方法
msed -Wall -w
问题6:
In file included from init/main.c:8:0:init/main.c:23:29: error: static declaration of ‘fork’ follows non-static declaration static inline _syscall0(int,fork) ^ include/unistd.h:151:6: note: in definition of macro ‘_syscall0’ type name(void) \ ^ init/main.c:24:29: error: static declaration of ‘pause’ follows non-static declaration static inline _syscall0(int,pause) ^ include/unistd.h:151:6: note: in definition of macro ‘_syscall0’ type name(void) \ ^ include/unistd.h:241:5: note: previous declaration of ‘pause’ was here int pause(void); ^ init/main.c:26:29: error: static declaration of ‘sync’ follows non-static declaration static inline _syscall0(int,sync) ^ include/unistd.h:151:6: note: in definition of macro ‘_syscall0’ type name(void) \ ^ include/unistd.h:252:5: note: previous declaration of ‘sync’ was here int sync(void);
这里是由于include/unistd.h 中声明了一次pause() sync() fork(), 而在main.c 中通过宏又定义了这三个函数,但定义时多了static 限定,与声明不同,所以出错。所以直接把unistd.h中的声明去掉。
问题7:
init/main.c:179:12: error: static declaration of ‘printf’ follows non-static declaration static int printf(const char *fmt, ...)
这个问题困扰了好久,网上的解决方案都是把static去掉,但是这样做,后面在链接的时候会出现另一个错误undefined reference to '_put'. 新的问题是由于GCC会对printf进行优化,把无参的printf优化成put,而linux0.12的libc中又没有实现put才会导致新的问题。那么现在回到这个问题上,猜测应该也是由于GCC本身对printf这个函数名有特别的关照所致,所以把printf稍微改下名,printf -> printw。发现果然就编译通过了。
具体解决方案:
sed -i 's/ printf/ printw/g' init/main.c
问题8:
init/main.c: In function ‘main’:init/main.c:176:3: error: ‘asm’ operand has impossible constraints __asm__("int $0x80"::"a" (__NR_pause):"ax");
类似的问题在后面编译中出现好多,C内嵌汇编的格式__asm__(汇编语句:输入寄存器:输出寄存器:可能被修改的寄存器),最新的GCC规定输入或输出寄存器不能出现在可能被修改的寄存器中,目前看到网上的方法是把所有类似问题的可能被修改的寄存器全部删掉。
具体解决方法
find -type f -exec sed -i 's/:\"\w\{2\}\"\(,\"\w\{2\}\"\)*)/:) /g' {} \;
问题9:
make[1]: gld: Command not found
同gas, 把gld -> ld
具体解决方法
msed gld ld
问题10:
ld -r -o kernel.o sched.o sys_call.o traps.o asm.o fork.o panic.o printk.o vsprintf.o sys.o exit.o signal.o mktime.old: Relocatable linking with relocations from format elf32-i386 (sched.o) to format elf64-x86-64 (kernel.o) is not supported
同问题2,告诉ld以32位链接,在ld命令后面加 -m elf_i386
具体解决方法
msed ld$ ld\ -m\ elf_i386
问题11:
../include/asm/segment.h: Assembler messages:../include/asm/segment.h:27: Error: bad register name `%sil'
去segment.h 的第27行找,没找到sil相关的东西,根据网上的方法,把=r或r 改成=q或q,果然就好了,这里应该是编译器造成的,r表示任意寄存器,在编译的时候就用了sil这个寄存器,可为什么无效还会被用到呢。q表示使用eax,ebx,ecx,edx中任意一个。
具体解决方法
sed -i s'/r"/q"/g' include/asm/segment.h
问题12:
exec.c: In function ‘copy_strings’:exec.c:162:44: error: lvalue required as left operand of assignment !(pag = (char *) page[p/PAGE_SIZE] =
if (!(pag = (char *) page[p/PAGE_SIZE]) && !(pag = (char *) page[p/PAGE_SIZE] = (unsigned long *) get_free_page())) return 0;
以上是原始code,以下是OK的code
if ((!page[p/PAGE_SIZE]) && !(page[p/PAGE_SIZE] = (unsigned long *) get_free_page())) return 0; else pag = (char *) page[p/PAGE_SIZE];
问题13:
In file included from floppy.c:42:0:blk.h:90:6: error: #elif with no expression #elif
这里把第90行的#elif -> #else
问题14:
make[1]: gar: Command not found
老问题了,gar -> ar
msed gar ar
问题15:
malloc.c: In function ‘malloc’:malloc.c:156:46: error: lvalue required as left operand of assignment bdesc->page = bdesc->freeptr = (void *) cp = get_free_page();
和问题12一样
bdesc->page = bdesc->freeptr = (void *) cp = get_free_page();
上面是原始的,下面是OK的,把代码拆分下就好
cp = get_free_page();bdesc->page = bdesc->freeptr = (void *) cp;
========================================================================================
9、ld: warning: cannot find entry symbol _start; defaulting to 0000000008048098
ld -m elf_i386 -s -x -M boot/head.o init/main.o kernel/kernel.o mm/mm.o fs/fs.o kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a kernel/math/math.a lib/lib.a -o tools/system > System.map ld: warning: cannot find entry symbol _start; defaulting to 0000000008048098 这是因为ld在将所有目标文件链接起来时,不知道程序的入口点在哪里。由内核的启动过程知其从head.s中开始执行,因此给head.s的 .text 段添加一句 .globl startup_32,然后给 ./Makefile 中的ld加上选项 -e startup_32 以指定入口点。另外注意,仅指定入口点的标号还不够,后续使用tools/build构建Image仍会出错,因为此时程序入口点的地址仍是0x8048098(见上方出错信息的最后一行),而在tools/build.c中处理system模块时,认定的合法入口点地址为0x0:tools/build.c: 157 if ((id=open(argv[3],O_RDONLY,0))<0) 158 die("Unable to open 'system'"); 159 if (read(id,buf,GCC_HEADER) != GCC_HEADER) 160 die("Unable to read header of 'system'"); 161 if (((long *) buf)[5] != 0) //判断入口点地址是否为0x0 162 die("Non-GCC header of 'system'");
10.
gcc -m32 -Wall -O -fstrength-reduce -fomit-frame-pointer -mtune=i386 -o tools/build tools/build.c In file included from /usr/include/features.h:395:0, from /usr/include/stdio.h:27, from tools/build.c:23: /usr/include/gnu/stubs.h:7:27: fatal error: gnu/stubs-32.h: No such file or directory # include <gnu/stubs-32.h> 很显然这又是一个因64位系统上缺少32位库导致的问题(更多细节见这里),从源里装个32位库即可: sudo aptitude install libc6-dev-i38611.tools/build.c: In function ‘main’: tools/build.c:72:4: warning: implicit declaration of function ‘MAJOR’ [-Wimplicit-function-declaration] major_root = MAJOR(sb.st_rdev); tools/build.c:73:4: warning: implicit declaration of function ‘MINOR’ [-Wimplicit-function-declaration] minor_root = MINOR(sb.st_rdev); /tmp/cctAdnmd.o: In function `main': build.c:(.text+0xc7): undefined reference to `MAJOR' build.c:(.text+0xe1): undefined reference to `MINOR' collect2: error: ld returned 1 exit status build.c中包含的是标准库的头文件 /usr/include/linux/fs.h ,但是这个头文件里并没有实现MAJOR和MINOR宏。解决方法很简单,从include/linux/fs.h中把这两个宏复制到build.c中即可: #define MAJOR(a) (((unsigned)(a))>>8) #define MINOR(a) ((a)&0xff)12.tools/build boot/bootsect boot/setup tools/system /dev/hd6 > Image /dev/hd6: No such file or directory Couldn't stat root device. 这是因为在源代码顶层目录的Makefile中所指定的根设备为/dev/hd6(代表第二个硬盘的第一个分区), 而本机上并不存在这个设备所致。Linus当年之所以指定根设备为/dev/hd6, 是因为他把Linux 0.11安装在了机子的第二块硬盘上。我们这里打算通过在bochs中模拟软盘来启动编译好的系统,故在顶层目录Makefile中设定根设备为软盘:ROOT_DEV=FLOPPY tools/build.c使用Makefile中指定的ROOT_DEV对应的设备号覆盖Image文件中的第509、510字节(即地址508、509处),这两个字节所保存的根设备号将被bootsect.s使用。tools/build.c 115 buf[508] = (char)minor_root 116 buf[509] = (char)major_root 117 i = write(1, buf, 512); //注意标准输出已经被重定向至Image文件 3.总结基本上编译中会遇到的问题就是这些,另推荐这篇博文, 主要介绍的是在32位Ubuntu 11系统下编译并调试运行linux 0.11的过程。编译成功源代码只是第一步,接下来通过调试源代码弄清内核的工作细节才是最艰苦的,不过那将是另一个故事了:-)============================================================================
http://chfj007.blog.163.com/blog/static/173145044201132523034138/
Linux 环境下编译 0.11版本内核 kernel
系统环境:Fedora 13 + gcc-4.4.5
最近在看《linux内核0.11完全注释》一书,由于书中涉及汇编语言的地方众多,本人在大学时汇编语言学得一塌糊涂,所以实在看不下去了,头都大了只好匆匆看了个头尾(前面几章和最后一章)。看来即使有《九阴真经》这样的武功秘籍,内功不够也是修炼不出来神马来的。于是索性下了个0.11版本的kernel下来尝试编译一把。linux-0.11.tar.gz 下载地址:ftp://ftp.kernel.org/pub/linux/kernel/Historic/old-versions/ 下面开始工作:1、 tar xvfz linux-0.11.tar.gz2、 cd linux-0.113、 make make: as86: Command not finded make: ***出错原因:as86 汇编器未安装解决办法: yum install dev86* (请务必保证网络畅通,如果使用Debian Linux系统命令改为 apt-get install dev86*)或 下载dev86-0.16.3-8.i386.rpm安装 下载地址 http://www.oldlinux.org/Linux.old/study/tools/4、 make gas -c -o boot/head.o boot/head.s make: gas: Command not finded make: *** [boot/head.o] Error 127出错原因:gas 汇编器未安装解决办法: yum install binutils* (请确保网络正常)或 下载binutils-2.20.tar.gz安装 下载地址http://ftp.gnu.org/gnu/binutils/ tar xvfz binutils-2.20.tar.gz ./configure make make install 确认 Gnu assembler 已经安装 which as /usr/local/bin/as5、 make gas -c -o boot/head.o boot/head.s make: gas: Command not found make: *** [boot/head.o] Error 127出错原因:gas、gld 的名称已经过时,现在GNU assembler的名称是 as解决办法: 修改主 Makefile 文件 将 AS =gas 修改为 AS =as 将 LD =gld 修改为 LD =ld6、make as -c -o boot/head.o boot/head.s as: unrecognized option '-c' make: *** [boot/head.o] Error 1出错原因:as 语法和1991年的时候有了一些变化解决办法: 修改 Makefile 文件 将 $(AS) -c -o $*.o $< 修改为 $(AS) -o $*.o $<7、make as -o boot/head.o boot/head.s boot/head.s: Assembler messages: boot/head.s:231: Error: alignment not a power of 2 make: *** [boot/head.o] Error 1出错原因:.align 2 是汇编语言指示符,其含义是指存储边界对齐调整; “2”表示把随后的代码或数据的偏移位置调整到地址值最后2比特位为零的位置(2^2),即按4字节对齐内存地址。 不过现在GNU as直接是写出对齐的值而非2的次方值了。 .align 2 应该改为 .align 4 .align 3 应该改为 .align 8解决办法: 修改 boot/head.s 文件 将 .align 2 应该改为 .align 4 .align 3 应该改为 .align 88、make cc1: error: unrecognized command line option "-mstring-insns" cc1: error: unrecognized command line option "-fcombine-regs" make: *** [init/main.o] Error 1解决办法: 修改 Makefile 文件 将 -fcombine-regs -mstring-insns 删除或者注释掉9、make In file include from init/main.c:9:include/unistd.h:207: warning: function return types not compatible due to 'volatile'include/unistd.h:208: warning: function return types not compatible due to 'volatile'init/main.c:24: error: static declaration of 'fork' follows non-static declarationinit/main.c:26: error: static declaration of 'pause' follows non-static declarationinclude/unistd.h:224: note: previous declaration of 'pause' was hereinit/main.c:30: error: static declaration of 'sync' follows non-static declarationinclude/unistd.h:235: note: previous declaration of 'sync' was hereinit/main.c:108: warning: return type of 'main' is not 'int'make: *** [init/main.o] Error 1解决办法: 修改 init/main.c 文件 将 static inline _syscall0(int,fork) 修改为 inline _syscall0(int,fork) static inline _syscall0(int,pause) 修改为 inline _syscall0(int,pause) static inline _syscall1(int,setup,void *,BIOS) 修改为 inline _syscall1(int,setup,void *,BIOS) static inline _syscall0(int,sync) 修改为 inline _syscall0(int,sync)10、make (cd kernel; make)make[1]: Entering directory '***/linux-0.11/kernel'gcc -Wall -O -fstrength-reduce -fomit-frame-pointer -fcombine-regs -finline-functions -mstring-insns -nostdinc -I../include \ -c -o sched.o sched.ccc1: error: unrecognized command line option "-mstring-insns"cc1: error: unrecognized command line option "-fcombine-regs"make[1]: *** [sched.o] Error 1make[1]: Leaving directiory '***/linux-0.11/kernel'make: *** [kernel/kernel.o] Error 2解决办法: 修改 kernel目录下 Makefile 文件 将 -fcombine-regs -mstring-insns 删除或者注释掉11、makegas -c -o system_call.o system_call.smake[1]: gas: Command not foundmake[1]: *** [system_call.o] Error 127make[1]: Leaving directory '***/linux-0.11/kernel'make: *** [kernel/kernel.o] Error 2解决办法: 修改 kernel目录下 Makefile 文件 将 AS =gas 修改为 AS =as 将 LD =gld 修改为 LD =ld 将 $(AS) -c -o $*.o $< 修改为 $(AS) -o $*.o $<12、makefork.c:In function 'copy_process':fork.c:121: warning: suggest parentheses around assignment used as truth valuefork.c:In function 'copy_mem':fork.c:54: error: can't find a register in class 'DREG' while reloading 'asm'fork.c:55: error: can't find a register in class 'DREG' while reloading 'asm'fork.c:46: error: 'asm' operand has impossible constraintsfork.c:47: error: 'asm' operand has impossible constraintsfork.c:54: error: 'asm' operand has impossible constraintsfork.c:55: error: 'asm' operand has impossible constraintsmake[1]: *** [fork.o] Error 1make[1]: Leaving directory '***/linux-0.11/kernel'make: *** [kernel/kernel.o] Error 2在 kernel/fork.c 第 54 行:可以看到这样的调用 set_base(p->ldt[1],new_code_base);在 include/linux/sched.h 第 188 —— 211 行:可以看到 set_base 的实现#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base )#define _set_base(addr,base) \__asm__("movw %%dx,%0\n\t" \ "rorl $16,%%edx\n\t" \ "movb %%dl,%1\n\t" \ "movb %%dh,%2" \ ::"m" (*((addr)+2)), \ "m" (*((addr)+4)), \ "m" (*((addr)+7)), \ "d" (base) \ :"dx")因为这里涉及到汇编的知识,哥卡在这里一直没解决并且郁闷了好久,最后只好看回《linux内核0.11完全注释》一书。赵炯博士在http://www.oldlinux.org/Linux.old/kernel/0.1x/ 这里提供了修改 linux-0.11-060618-gcc4.tar.gz 好的 0.11版本的内核。于是这个时候比较工具 Beyond Compare 就派上用场了。将 #define _set_base(addr,base) \ 修改为 #define _set_base(addr,base) \ __asm__("movw %%dx,%0\n\t" \ __asm__("push %%edx\n\t" \ "rorl $16,%%edx\n\t" \ "movw %%dx,%0\n\t" \ "movb %%dl,%1\n\t" \ "rorl $16,%%edx\n\t" \ "movb %%dh,%2" \ "movb %%dl,%1\n\t" \ ::"m" (*((addr)+2)), \ "movb %%dh,%2\n\t" \ "m" (*((addr)+4)), \ "pop %%edx" \ "m" (*((addr)+7)), \ ::"m" (*((addr)+2)), \ "d" (base) \ "m" (*((addr)+4)), \ :"dx") "m" (*((addr)+7)), \ "d" (base) ) 将 #define switch_to(n) {\ struct {long a,b;} __tmp; \ __asm__("cmpl %%ecx,_current\n\t" \ "je 1f\n\t" \ "movw %%dx,%1\n\t" \ "xchgl %%ecx,_current\n\t" \ "ljmp %0\n\t" \ ------------------------------这里修改为 "ljmp *%0\n\t" \ "cmpl %%ecx,_last_task_used_math\n\t" \ "jne 1f\n\t" \ "clts\n" \ "1:" \ ::"m" (*&__tmp.a),"m" (*&__tmp.b), \ "d" (_TSS(n)),"c" ((long) task[n])); \ } 将 #define _get_base(addr) ({\ 修改为 static inline unsigned long _get_base(char * addr) unsigned long __base; \ { __asm__("movb %3,%%dh\n\t" \ unsigned long __base; movb %2,%%dl\n\t" \ __asm__("movb %3,%%dh\n\t" \ shll $16,%%edx\n\t" \ "movb %2,%%dl\n\t" \ movw %1,%%dx" \ "shll $16,%%edx\n\t" \ "=d" (__base) \ "movw %1,%%dx" \ "m" (*((addr)+2)), \ :"=&d" (__base) \ "m" (*((addr)+4)), \ :"m" (*((addr)+2)), \ "m" (*((addr)+7))); \ "m" (*((addr)+4)), \ __base;}) "m" (*((addr)+7))); return __base; }注意: 由于GNU as汇编器不断进化的原因,需要将 *.s 文件中 类似 .globl _idt,_gdt,_pg_dir,_tmp_floppy_area 修改为 .globl idt,gdt,pg_dir,tmp_floppy_area 不然虽然编译通过,但是连接的时候将出现类似这样的错误 boot/head.o: In function 'setup_idt': (.text+0x87): undefined reference to '_idt' boot/head.o: In function 'idt_descr': (.text+0x54ac): undefined reference to '_idt' kernel/kernel.o: In function 'sched_init': (.text+0x37c): undefined reference to '_idt' --------------------------------------------------------------------------------------------------------------------------------------------------汇编知识(来自互联网)GCC中基本的内联汇编:__asm____volatile__("InstructionList");__asm__("movl $1,%eax\r\t""xor %ebx,%ebx\r\t""int $0x80");带有C/C++表达式的内联汇编:__asm__ __volatile__("InstructionList" :Output :Input :Clobber/Modify);这4个部分都不是必须的,任何一个部分都可以为空,其规则为:1、如果Clobber/Modify 为空,则其前面的冒号(:)必须省略。2、如果Output,Input,Clobber/Modify都为空,Output,Input之前的冒号(:)既可以省略,也可以不省略。3、如果Input,Clobber/Modify为空,但Output不为空,Input前的冒号(:)既可以省略,也可以不省略。4、如果后面的部分不为空,而前面的部分为空,则前面的冒号(:)都必须保留,否则无法说明不为空的部分究竟是第几部分。 每一个Input和Output表达式都必须指定自己的操作约束Operation Constraint,这里将讨论在80386平台上所可能使用的操作约束。当前的输入或输出需要借助一个寄存器时,需要为其指定一个寄存器约束,可以直接指定一个寄存器的名字。常用的寄存器约束的缩写 约束 意义r 表示使用一个通用寄存器,由 GCC 在%eax/%ax/%al,%ebx/%bx/%bl,%ecx/%cx/%cl,%edx/%dx/%dl中选取一个GCC认为合适的。g 表示使用任意一个寄存器,由GCC在所有的可以使用的寄存器中选取一个GCC认为合适的。q 表示使用一个通用寄存器,和约束r的意义相同。a 表示使用%eax/%ax/%alb 表示使用%ebx/%bx/%blc 表示使用%ecx/%cx/%cld 表示使用%edx/%dx/%dlD 表示使用%edi/%diS 表示使用%esi/%sif 表示使用浮点寄存器t 表示使用第一个浮点寄存器u 表示使用第二个浮点寄存器如果一个Input/Output 操作表达式的C/C++表达式表现为一个内存地址,不想借助于任何寄存器,则可以使用内存约束。比如:__asm__("lidt%0":"=m"(__idt_addr));__asm__("lidt%0"::"m"(__idt_addr)); 修饰符 输入/输出 意义= O 表示此Output操作表达式是Write-Only的。+ O 表示此Output操作表达式是Read-Write的。& O 表示此Output操作表达式独占为其指定的寄存器。% I 表示此Input 操作表达式中的C/C++表达式可以和下一 个Input操作表达式中的C/C++表达式互换-------------------------------------------------------------------------------------------------------------------------------------------------------------- 13、make In file included from stat.c:13: ../include/asm/segment.h: Assembler messages: ../include/asm/segment.h:27: Error: bad register name '%sil' make[1]: *** [stat.o] Error 1 make[1]: Leaving directory '***/linux-0.11/fs' make: *** [fs/fs.o] Error 2出错原因: fs 目录下的 Makefile 中编译选项使用了 -O 优化选项导致寄存器错误解决方法: 将fs目录下的Makefile 文件中的 CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer \ 修改为 CFLAGS =-Wall -fstrength-reduce -fomit-frame-pointer \14、make tools/build.c: In function 'main': tools/build.c:75: warning: implicit declaration of function 'MAJOR' tools/build.c:76: warning: implicit declaration of function 'MINOR' tmp/ccsMKTAS.o: In function 'main': build.c:(.text+0xe1): undefined reference to 'MAJOR' build.c:(.text+0xf7): undefined reference to 'MINOR' collect2: ld returned 1 exit status 出错原因:'MAJOR' 和 'MINOR' 未定义解决办法: 我们可以在 include/linux/fs.h 文件中找到 #define MAJOR(a) (((unsigned)(a))>>8) #define MINOR(a) ((a)&0xff) 而在 tools/build.c 中也有包含 #include <linux/fs.h> 那么再看第一层目录中的主 Makefile 文件 tools/build: tools/build.c $(CC) $(CFLAGS) \ -o tools/build tools/build.c 好象确实没有引用头文件 简单的添加 -Iinclude 重新编译后出现一堆报标准C库头文件的错误 再添加 -nostdinc 又报 stderr fprintf 之类的错误 没折,只好将 #define MAJOR(a) (((unsigned)(a))>>8) #define MINOR(a) ((a)&0xff) 添加到 tools/build.c 文件中,然后删除 #include <linux/fs.h>15、make make[1]: Leaving directory '***/linux-0.11/lib' ld -s -x -M boot/head.o init/main.o \ kernel/kernel.o mm/mm.o fs/fs.o \ kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a \ kernel/math/math.a \ lib/lib.a \ -o tools/system > System.map ld: warning: cannot find entry symbol _start; defaulting to 08048a0 gcc -Wall -O -fstrength-reduce -fomit-frame-pointer \ -o tools/build tools/build.c tools/build boot/bootsect boot/setup tools/system /dev/hd6 > Image /dev/hd6: No such file or directory Couldn't stat root device. make: *** [Image] Error 1解决办法: 将第一层主 Makefile 文件中的 tools/system: boot/head.o init/main.o \ $(ARCHIVES) $(DRIVERS) $(MATH) $(LIBS) $(LD) $(LDFLAGS) boot/head.o init/main.o \ $(ARCHIVES) \ $(DRIVERS) \ $(MATH) \ $(LIBS) \ -o tools/system > System.map 修改为 tools/system: boot/head.o init/main.o \ $(ARCHIVES) $(DRIVERS) $(MATH) $(LIBS) $(LD) $(LDFLAGS) boot/head.o init/main.o \ $(ARCHIVES) \ $(DRIVERS) \ $(MATH) \ $(LIBS) \ -o tools/system nm tools/system | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aU] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)'| sort > System.map nm命令将目标文件中的各种符号列出来。 ROOT_DEV=/dev/hd6 修改为 ROOT_DEV=16、make /DISCARD/ *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) OUTPUT(tools/system elf32-i386) nm tools/system | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aU] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)'| sort > System.map nm: tools/system: no symbols gcc -Wall -O -fstrength-reduce -fomit-frame-pointer \ -o tools/build tools/build.c tools/build boot/bootsect boot/setup tools/system > Image Root device is (3, 6) Boot sector 512 bytes. Setup is 312 bytes. Non-Gcc header of 'system' make: *** [Image] Error 1解决办法: 将第一层主 Makefile 文件中的 LDFLAGS =-s -x -M 修改为 LDFLAGS =-m elf_i386 -Ttext 0 -e startup_32Image: boot/bootsect boot/setup tools/system tools/build tools/build boot/bootsect boot/setup tools/system $(ROOT_DEV) > Image sync
Image: boot/bootsect boot/setup tools/system tools/build objcopy -O binary -R .note -R .comment tools/system tools/kernel tools/build boot/bootsect boot/setup tools/kernel $(ROOT_DEV) > Image rm tools/kernel -f sync
===================================================================================================
bochs下安装linux-0.11
首先非常感谢赵炯老师给我们提供了丰富的资源,包括他写的《Linux内核完全注释》和他维护的网站www.oldlinux.org
一、准备工作软件:bochs-20060202.tar.gz软盘映像:http://www.oldlinux.org/Linux.old/images/bootimage-0.11-20040305 http://www.oldlinux.org/Linux.old/images/rootimage-0.11-20040305二、.bochsrc文件(注释已删掉)ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15ata2: enabled=0, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9ata0-master: type=disk, path=minix203.img, cylinders=940, heads=6, spt=17, translation=noneboot: afloppy_bootsig_check: disabled=0log: bochsout.txtpanic: action=askerror: action=reportinfo: action=reportdebug: action=ignoredebugger_log: -parport1: enabled=1, file="parport.out"vga_update_interval: 300000keyboard_serial_delay: 250keyboard_paste_delay: 100000mouse: enabled=1private_colormap: enabled=0ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:00, ethmod=linux, ethdev=eth0keyboard_mapping: enabled=0, map=三、制作软盘映像mshost:/usr/local/bochs # ./bximage======================================================================== bximage Disk Image Creation Tool for Bochs $Id: bximage.c,v 1.31 2005/11/20 20:26:35 vruppert Exp $========================================================================Do you want to create a floppy disk image or a hard disk image?Please type hd or fd. [hd]What kind of image should I create?Please type flat, sparse or growing. [flat]Enter the hard disk size in megabytes, between 1 and 129023[10]mshost:/usr/local/bochs # ./bximage======================================================================== bximage Disk Image Creation Tool for Bochs $Id: bximage.c,v 1.31 2005/11/20 20:26:35 vruppert Exp $========================================================================Do you want to create a floppy disk image or a hard disk image?Please type hd or fd. [hd] fdChoose the size of floppy disk image to create, in megabytes.Please type 0.16, 0.18, 0.32, 0.36, 0.72, 1.2, 1.44, 1.68, 1.72, or 2.88.[1.44]I will create a floppy image with cyl=80 heads=2 sectors per track=18 total sectors=2880 total bytes=1474560What should I name the image?[a.img] a.imgWriting: [] Done.I wrote 1474560 bytes to a.img.The following line should appear in your bochsrc: floppya: image="a.img", status=inserted四、制作启动盘和根文件系统盘首先按照步骤三再作一张b.img,然后运行下列命令:dd if=bootimage-0.11-20040305 of=a.imgdd if=rootimage-0.11-20040305 of=b.img五、启动mshost:/usr/local/bochs # ./bochs启动后会出现Insert root floppy and press ENTER之后cp b.img a.img(注意备份a.img),最后回车,linux-0.11就启动起来了!
========================================================
questions:
1、用bochs调试遇到"Unable to mount root"
把启动盘的Image文件(bootimage)的第509,510字节修改成0x1d, 0x02。这两个字节是根文件系统所在设备号。0x021d表示第2个软盘(b:)设备。
2、为什么在转到B盘后一直显示的是Reset-floppy called
请使用Bochs 2.1.1版本再试试。