问题描述

立志要写一个简单的擦做系统,第一个问题就挂了3天。操作系统中需要使用lds脚本,也就是链接脚本,为什么呢?因为lds中有两个功能我需要,一个时入口函数(这个其实也可以通过gcc -e 入口函数来解决),其二是绕不过去的问题,lds中可以定位代码的终止处并以全局变量的形式传入源代码中。
但在实现这个目标时发现:自己写的lds,cmake要么不认,后来发现ld命令也不对。

过程记录

ld链接器有一个默认的lds脚本,被我抄了过来,加入了一点自己的东西,CMAKE中的代码使用

set(CMAKE_C_LINK_EXECUTABLE 
" ${CMAKE_C_LINK_EXECUTABLE} 
-T /home/wkn/Desktop/untitled/w.ld ")

该cmake脚本的意思就是不使用默认lds脚本,而是使用我的脚本,这里我的lds脚本名字是:w.ld。

我的w.ld代码就只把entry(symbol)处更换了,原来是:entry(_start),我改为了entry(mymain),当然,我的hello world代码中,也没有main函数,只有一个mymain()函数。这个脚本目标就是入口函数变成mymain。

然后愉快的写完剩下的代码,运行一下,出错了,爆出的错是:

/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o:在函数‘_start’中:
(.text+0x20):对‘main’未定义的引用

这段话我也看不懂,搜了搜,无意间撞见了一个博客,发现C语言还有一个_start函数,它才是真正的入口函数,它调用main函数,这样我们觉得main()才是入口函数,解决办法呢,就是改gcc的编译指令,cmake中gcc的编译指令由变量CMAKE_C_FLAGS_DEBUG给出,我是在debug模式下调试的。
现在给CMAKE_C_FLAGS_DEBUG加一个参数,让它不管_start即可

set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -nostartfiles ")

可以试着message一下CMAKE_C_FLAGS_DEBUG的值,就会看见,cmake给他的初始值只有一个-g。如果只改变入口地址,可以不用lds脚本,而是在这个cmake指令为:

set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -e mymain ")

这样,我的脚本可以执行,也不管_start,一切正常了起来,这次解决的问题虽然在cmake中,但其实本质是对GCC和LD知之甚少造成的。

总结

CMAKE_C_FLAGS_DEBUG就是gcc的指令后面的各种参数
CMAKE_C_LINK_EXECUTABLE负责指定ld参数

其他

最终没有使用cmake来管理操作系统,原因或许是我技术太low,或许是cmake本来就不面向底层开发吧,最后的难题还是储在ld上了,cmake我达不到绝对微操执行编译过程,没法实现只用gcc命令就使用ld指令的全部选项,这个我即使看遍了gcc命令选项,也没有找到我想要的ld实现方法。

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐