操作系统之旅(006)—— 编译内核映像

前面已经成功编译并运行引导程序,现在进行内核部分的编译修改。

首先针对Makefile进行修改,现我们定下内核映像文件在build目录下生成,名为system.bin,则对all规则修改:

all : build/bootsect.bin build/setup.bin build/system.bin
    dd if=build/bootsect.bin of=bootimage-fd.img bs=512 count=1 conv=notrunc
    dd if=build/setup.bin of=bootimage-fd.img bs=512 seek=1 count=4 conv=notrunc
    dd if=build/system.bin of=bootimage-fd.img bs=512 seek=5 conv=notrunc


增加的依赖项build/system.bin对应原Makefile下的tools/system,对该规则修改:

build/system.bin :   boot/head.o init/main.o $( ARCHIVES ) $( DRIVERS ) $( MATH ) $( LIBS )
     $( LD ) $( LDFLAGS ) boot/head.o init/main.o $( ARCHIVES ) $( DRIVERS ) $( MATH ) $( LIBS ) -o build/system.bin > System.map



修改完成后,尝试执行make all,提示如下:

nasm boot/bootsect.s -o build/bootsect.bin
nasm boot/setup.s -o build/setup.bin
gas -c -o boot/head.o boot/head.s
make: gas: Command not found
Makefile:31: recipe for target 'boot/head.o' failed
make: *** [boot/head.o] Error 127

gas现对应as,gld对应ld,修改AS和LD:

AS   =as
LD   =gd


重新执行make all,提示如下:

as -c -o boot/head.o boot/head.s

boot/head.s: Assembler messages:
boot/head.s:43: Error: unsupported instruction `mov'
boot/head.s:47: Error: unsupported instruction `mov'
boot/head.s:59: Error: unsupported instruction `mov'
boot/head.s:61: Error: unsupported instruction `mov'
boot/head.s:136: Error: invalid instruction suffix for `push'
boot/head.s:137: Error: invalid instruction suffix for `push'
boot/head.s:138: Error: invalid instruction suffix for `push'
boot/head.s:139: Error: invalid instruction suffix for `push'
boot/head.s:140: Error: invalid instruction suffix for `push'
boot/head.s:151: Error: invalid instruction suffix for `push'
boot/head.s:152: Error: invalid instruction suffix for `push'
boot/head.s:153: Error: invalid instruction suffix for `push'
boot/head.s:154: Error: operand type mismatch for `push'
boot/head.s:155: Error: operand type mismatch for `push'
boot/head.s:161: Error: invalid instruction suffix for `push'
boot/head.s:163: Error: invalid instruction suffix for `pop'
boot/head.s:165: Error: operand type mismatch for `pop'
boot/head.s:166: Error: operand type mismatch for `pop'
boot/head.s:167: Error: invalid instruction suffix for `pop'
boot/head.s:168: Error: invalid instruction suffix for `pop'
boot/head.s:169: Error: invalid instruction suffix for `pop'
boot/head.s:214: Error: unsupported instruction `mov'
boot/head.s:215: Error: unsupported instruction `mov'
boot/head.s:217: Error: unsupported instruction `mov'
boot/head.s:231: Error: alignment not a power of 2
Makefile:31: recipe for target 'boot/head.o' failed
make: *** [boot/head.o] Error 1

上述实际只是两个错误:

1、Ubuntu为64位,需要指定生成32位指令,修改Makefile。

.s.o :
     $( AS ) --32 -o $* .o $<

2、现代as汇编器对.align伪指令使用方法改变,现在需要直接填写要对齐的字节数,数字必须为2的幂,其他会提示编译错误。

本错误修改boot/head.s文件,如.align 2 => .align 4, .align 3 => .align 8。

同时将本修改展开到其他.s文件。


再次执行make all,提示如下:

gcc  -Wall -O -fstrength-reduce -fomit-frame-pointer -fcombine-regs -mstring-insns \
-nostdinc -Iinclude -c -o init/main.o init/main.c
gcc: error: unrecognized command line option ‘-fcombine-regs’; did you mean ‘-Wcompare-reals’?
gcc: error: unrecognized command line option ‘-mstring-insns’; did you mean ‘-fstrict-enums’?
Makefile:33: recipe for target 'init/main.o' failed
make: *** [init/main.o] Error 1


上述错误中两个gcc参数为linus自定义的参数,gcc中不包含,删除后重新编译:

gcc  -Wall -O -fstrength-reduce -fomit-frame-pointer \
-nostdinc -Iinclude -c -o init/main.o init/main.c
In file included from init/main.c:9:0:
include/time.h:39:8: warning: conflicting types for built-in function ‘strftime’ [-Wbuiltin-de
claration-mismatch]
 size_t strftime(char * s, size_t smax, const char * fmt, const struct tm * tp);
        ^~~~~~~~
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:134:6: note: in definition of macro ‘_syscall0’
 type name(void) \
      ^~~~
include/unistd.h:210:5: note: previous declaration of ‘fork’ was here
 int fork(void);
     ^~~~
init/main.c:24:29: error: static declaration of ‘pause’ follows non-static declaration
 static inline _syscall0(int,pause)
                             ^
include/unistd.h:134:6: note: in definition of macro ‘_syscall0’
 type name(void) \
      ^~~~
include/unistd.h:224: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:134:6: note: in definition of macro ‘_syscall0’
 type name(void) \
      ^~~~
include/unistd.h:235:5: note: previous declaration of ‘sync’ was here
 int sync(void);
     ^~~~
init/main.c:104:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
 void main(void)  /* This really IS void, no error here. */
      ^~~~
Makefile:32: recipe for target 'init/main.o' failed
make: *** [init/main.o] Error 1


上述错误由于函数声明和函数定义不一致导致,为了编译通过,暂时将include/unistd.h中的fork、sync和pause的函数声明注释掉,重新编译:
gcc  -Wall -O -fstrength-reduce -fomit-frame-pointer \
-nostdinc -Iinclude -c -o init/main.o init/main.c
In file included from init/main.c:9:0:
include/time.h:39:8: warning: conflicting types for built-in function ‘strftime’ [-Wbuiltin-declaration-mismatch]
 size_t strftime(char * s, size_t smax, const char * fmt, const struct tm * tp);
        ^~~~~~~~
init/main.c:104:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
 void main(void)  /* This really IS void, no error here. */
      ^~~~
init/main.c: Assembler messages:
init/main.c:138: Error: invalid instruction suffix for `push'
init/main.c:139: Error: invalid instruction suffix for `push'
init/main.c:140: Error: invalid instruction suffix for `pushf'
init/main.c:141: Error: invalid instruction suffix for `push'
init/main.c:142: Error: invalid instruction suffix for `push'
Makefile:32: recipe for target 'init/main.o' failed
make: *** [init/main.o] Error 1


修改Makefile,为gcc和ld指定32位编译参数:

LDFLAGS  =-m elf_i386 -s -x -M
CC   =gcc $( RAMDISK )
CFLAGS   =-m32 -Wall -O -fstrength-reduce -fomit-frame-pointer

然后将Makefile中的所有修改展开到子目录中的Makefile,重新编译:

../include/string.h: In function ‘strcpy’:
../include/string.h:29:1: error: ‘asm’ operand has impossible constraints
 __asm__("cld\n"


上述错误由于现代编译器对扩展内联汇编的规则有所改变导致,已经在输入输出中出现的寄存器不需要再在修改过的寄存器列表中写出,如:

    :: "S" (src), "D" (dest): "si" , "di" , "ax" );

改为

    :: "S" (src), "D" (dest):ax ");



将上述修改展开到所有扩展内联汇编中,重新编译:

出现很多如下重定义错误,

traps.o: In function `get_fs_byte':
traps.c:(.text+0x4b7): multiple definition of `get_fs_byte'
sched.o:sched.c:(.text+0x10f): first defined here

问题出现在extern inline声明在现代编译器中含义有所改变,很多声明为extern inline的方法实现定义在.h文件中,导致每个包含这些.h的文件都有一份函数的定义,这里暂时简单更改为static inline。

重新编译,又出现如下错误:

file_dev.c: In function ‘file_read’:
file_dev.c:46:1: error: unsupported size for integer register
 }


上述错误需要关闭编译优化来解决,即去掉gcc编译参数中的-O,采用默认值(-O0),同时修改-Wall为-W -Wall,重新编译:

exec.c:139:44: error: lvalue required as left operand of assignment

                 if ( ! (pag = ( char * ) page[p / PAGE_SIZE]) &&
                    ! (pag = ( char * ) page[p / PAGE_SIZE] =
                      ( unsigned long * ) get_free_page ()))
                     return 0 ;
(char *) page[p/PAGE_SIZE]表达式为右值,右值不能出现在等号左边,修改如下:

                 if (
                     ! (page[p / PAGE_SIZE])
                 &&    ! (page[p / PAGE_SIZE] = ( unsigned long * ) get_free_page ())
                    )
                     return 0 ;
                 else
                    pag = ( char * )page[p / PAGE_SIZE];



重新编译,新错误如下:

keyboard.S:47: Error: `%al' not allowed with `xorl'

 xorl %al,%al 改为 xorb %al,%al


重新编译,新错误如下:

malloc.c:156:46: error: lvalue required as left operand of assignment

        bdesc-> page = bdesc-> freeptr = ( void * ) cp = get_free_page ();

修改为

        cp = get_free_page ();
        bdesc-> page = bdesc-> freeptr = ( void * )cp;


重新编译,新错误为链接错误:

boot/head.o: In function `startup_32':
(.text+0x10): undefined reference to `_stack_start'
(.text+0x2e): undefined reference to `_stack_start'
boot/head.o: In function `after_page_tables':
(.text+0x540c): undefined reference to `_main'

。。。

。。。

错误原因为是过去的gcc编译器会把符号前加下划线,现代gcc去除这一规则,此处将.s中引用.c中的及.s提供给.c使用的所有符号前的下划线去掉。


重新编译,新错误为:

undefined reference to `__stack_chk_fail_local'

修改方式为修改Makefile,为gcc编译标志加上-fno-stack-protector。

fs/fs.o: In function `check_disk_change':
(.text+0x1e11): undefined reference to `invalidate_buffers'
kernel/blk_drv/blk_drv.a(floppy.o): In function `seek_interrupt':
floppy.c:(.text+0x69c): undefined reference to `setup_rw_floppy'

这两处错误去掉函数定义出的inline标志即可。


再次编译,无提示错误,build目录下生成3个.bin文件,表明编译成功。

你可能感兴趣的:(操作系统之旅(006)—— 编译内核映像)