实现64位操作系统的问题解决系列:(一)ubuntu18.04 下高版本gcc实践操作系统时出现的问题之printk.c: undefined reference to `strlen'

ubuntu18.04 下高版本gcc实践操作系统时出现的问题

ub18.04 的gcc 版本本身就高,所以在实践 自制一个64位操作系统 中的实验时,容易出现不少代码在 centos6 能正常编译,到了ub18 上编译不通过,书的作者本人 似乎只是建议读者 采用他自己使用的centos6上实践来避免这个问题,如下截图
在这里插入图片描述

I'm using gcc to compile a printing function. But met the following 2 problems:

Whenever I apply a local array type variable, the linker would report \
and error of "undefined reference to `__stack_chk_fail'"
When I'm using "inline" to define a function, \
it report an error of "undefined reference to `strlen'"
My platform is Ubuntu 18.04, and gcc version is 7.3.0.
  • 我自己 ub18 上实践时的情况如下:
zj@zj-virtual-machine:~/bochs_prj/64os/4-3/kernel$ make
gcc -E  head.S > head.s
as --64 -o head.o head.s
gcc  -mcmodel=large -fno-builtin -m64 -c main.c
gcc  -mcmodel=large -fno-builtin   -m64 -c printk.c
ld -b elf64-x86-64 -z muldefs -o system head.o main.o printk.o -T Kernel.lds 
printk.o: In function `number':
printk.c:(.text+0x4a6): undefined reference to `__stack_chk_fail'
printk.o: In function `vsprintf':
printk.c:(.text+0x866): undefined reference to `strlen'
printk.o: In function `color_printk':
printk.c:(.text+0x13f2): undefined reference to `__stack_chk_fail'
Makefile:20: recipe for target 'system' failed
make: *** [system] Error 1

吐槽
我自己在网上查了不少,反正目前是没有完整解决,有大佬通过 编译链接 让链接器能够正常找到strlen这个符号的话,告诉我一下,不胜感激。

反正,做实验无非是让程序能正常跑起来,所以这里我采用一个折中的办法,来解决上面提到的问题。对于第一个问题的话:

printk.c  开启-fno-stack-protector 能解决 undefined reference to `__stack_chk_fail' 这个问题

具体见下面的 Makefile

all: system
	objcopy -I elf64-x86-64 -S -R ".eh_frame" -R ".comment" -O binary system kernel.bin

system:	head.o main.o printk.o
	ld -b elf64-x86-64 -z muldefs -o system head.o main.o printk.o -T Kernel.lds 

head.o:	head.S
	gcc -E  head.S > head.s
	as --64 -o head.o head.s
	
main.o:	main.c lib.h
	gcc -static  -mcmodel=large -fno-builtin -m64 -c main.c  -fno-stack-protector
	
printk.o: printk.c lib.h
	gcc -static  -mcmodel=large -fno-builtin  -m64 -c printk.c -fno-stack-protector

clean:
	rm -rf *.o *.s~ *.s *.S~ *.c~ *.h~ system  Makefile~ Kernel.lds~ kernel.bin 

关于 strlen 的问题,既然找不到这个符号,本来这个符号的定义是在这个头文件里面的(#include "lib.h"),所以为了偷懒,不要内联优化这些,直接把这个内联的函数给剪切到printk.c这个函数里面,取消内联,直接编译进去,这样就不会出现找不到这个函数的定义了。部分代码见如下:

$cat printk.c

#include <stdarg.h>
#include "printk.h"
#include "lib.h"
#include "linkage.h"

int __strlen(char * String)   //here !!!! 这里我把这个函数名全部统一改成了__strlen
{
	register int __res;
	__asm__	__volatile__	(	"cld	\n\t"
					"repne	\n\t"
					"scasb	\n\t"
					"notl	%0	\n\t"
					"decl	%0	\n\t"
					:"=c"(__res)
					:"D"(String),"a"(0),"0"(0xffffffff)
					:
				);
	return __res;
}
...........

run 一下,效果如图
在这里插入图片描述
后记
如果后面再遇到问题,我可能也要转战 centos6 ,不然解决这些问题 还是挺费时间的。

猜你喜欢

转载自blog.csdn.net/m0_37329910/article/details/89633342
今日推荐