linux0.12 链接过程
终于编译OK了。。可链接就是一大堆错误
问题1:
boot/head.o: In function `startup_32': (.text+0x10): undefined reference to `_stack_start' boot/head.o: In function `startup_32': (.text+0x2e): undefined reference to `_stack_start' boot/head.o: In function `after_page_tables': (.text+0x540c): undefined reference to `_main' boot/head.o: In function `ignore_int': (.text+0x5440): undefined reference to `_printk'
一堆的undefined reference to xxxxx,stack_start 定义在kernel/sched.c中,main 定义在init/main.c中,实际上这些符号是存在的,可为什么链接的时候找不到呢。最终找到原因,是由于现在GCC在编译C时不会在函数前加"_"了,即以前GCC编译一个C函数,例如:fun() 编译后会变成_fun(), 而现在还是fun(),所以就导致了符号找不到,这个叫name magling,有兴趣的可以自行google下。
解决的思路有两种:
1. 网上的是把把有引用C符号的.s 和 .S中的变量前的"_"全部删掉,这个用正则不太好弄,得一个个删。
2. 在查name magling的时候,有幸让我看到了-fleading-underscore这个option, 可以让让GCC在编译的时候强制加上"_",这种只需要在CFLAGS中加-fleading-underscore即可,第二种方法更省事。
方案2具体解决方法
msed -O -O\ -fleading-underscore
请记得在改完后,make clean,后再make。
问题2:
main.c:(.text+0x6c): undefined reference to `_printf' main.c:(.text+0x87): undefined reference to `_printf' main.c:(.text+0x142): undefined reference to `_puts' main.c:(.text+0x1e9): undefined reference to `_printf'
额,之前编译的时候似乎正则没全部匹配到,只好手动改下了,把init/main.c 里的printf 全改成 printw
问题3:
vsprintf.c:(.text+0x18cb): undefined reference to `___stack_chk_fail' fs/fs.o: In function `_do_execve': (.text+0x3554): undefined reference to `___stack_chk_fail' kernel/chr_drv/chr_drv.a(tty_ioctl.o): In function `_tty_ioctl': tty_ioctl.c:(.text+0x51d): undefined reference to `___stack_chk_fail'
直接google到的答案,这是由于ubuntu的GCC默认是加-fstack-protector的,这里在CFLAGS中去掉这个option,加入-fno-stack-protector,至于这个option到底有什么作用,请有兴趣的自行google
msed -O -O\ -fno-stack-protector
问题4:
build.c:(.text+0x1c): undefined reference to `_stderr' build.c:(.text+0x24): undefined reference to `___fprintf_chk' /tmp/cctqTbXN.o: In function `_main': build.c:(.text+0x7d): undefined reference to `_strcmp' build.c:(.text+0x99): undefined reference to `___xstat' build.c:(.text+0xab): undefined reference to `_perror'
这个问题是由问题1的解决方案引入的,build.c链接时用的是glibc,而glibc在是没-fleading-underscore这个option的,所以在编译build.c时我们 把这个option去掉。。。,目前没找到什么好方法,我只好手动把CFLAGS展开,然后去掉-fleading-underscore了
修改linux0.12根目录下的Makefile第50行
tools/build: tools/build.c $(CC) $(CFLAGS) \ -o tools/build tools/build.c
上面是原来的,下面是展开后的
tools/build: tools/build.c $(CC) -w -O -fno-stack-protecto -m32 -fstrength-reduce -fomit-frame-pointer \ -o tools/build tools/build.c
问题5:
build.c:(.text+0xcb): undefined reference to `MAJOR' build.c:(.text+0xe3): undefined reference to `MINOR' build.c:(.text+0x16c): undefined reference to `MAJOR' build.c:(.text+0x184): undefined reference to `MINOR'
缺少两个宏定义,将以下两个定义加入到build.c中即可
#define MAJOR(x) (((unsigned)(x))>>8) #define MINOR(x) ((x)&0xff)
问题6:
/dev/hd6: No such file or directory Couldn't stat root device.
这个是在linux0.12根目录下的Makefile中定义的
ROOT_DEV=/dev/hd6 SWAP_DEV=/dev/hd2
但我们没这东西,阅读build.c 代码,了解到这里可以写成FLOPPY代替/dev/hd6
) { ], "FLOPPY")) { ], &sb)) { perror(argv[]); die("Couldn't stat root device."); } major_root = MAJOR(sb.st_rdev); minor_root = MINOR(sb.st_rdev); } else { major_root = ; minor_root = ; } } else { major_root = DEFAULT_MAJOR_ROOT; minor_root = DEFAULT_MINOR_ROOT; }
问题6:
/dev/hd2: No such file or directory Couldn't stat root device.
与上个问题类似,相同的地方,阅读build.c,可以用NONE代替/dev/hd2
) { ], "NONE")) { ], &sb)) { perror(argv[]); die("Couldn't stat root device."); } major_swap = MAJOR(sb.st_rdev); minor_swap = MINOR(sb.st_rdev); } else { major_swap = ; minor_swap = ; } } else { major_swap = DEFAULT_MAJOR_SWAP; minor_swap = DEFAULT_MINOR_SWAP; }
问题7:
Non-GCC header of 'system'
我们先看代码
],O_RDONLY,))<) die("Unable to open 'system'"); if (read(id,buf,GCC_HEADER) != GCC_HEADER) die("Unable to read header of 'system'"); ] != ) die("Non-GCC header of 'system'"); ; (c=read(id,buf, ; i+=c ) ,buf,c)!=c) die("Write call failed");
大致分4步,1. 打开第4个参数的文件,即system,2. 读system的头1024个字节;3. 判断程序入口地址是不是0x0;4. 读取剩下的部分写入Image中。错在第三步。我们用readelf -h system来看下
~/workspace/blog/linux-0.12/tools$ readelf -h system ELF Header: Magic: 7f 4c Class: ELF32 Data: 's complement, little endian Version: (current) OS/ABI: UNIX - System V ABI Version: Type: EXEC (Executable file) Machine: Intel Version: 0x1 Entry point address: 0x80480a0 Start of program headers: (bytes into file) Start of section headers: (bytes into file) Flags: 0x0 Size of (bytes) Size of program headers: (bytes) Number of program headers: Size of section headers: (bytes) Number of section headers: Section header
这里可以看到程序的入口是0x80480a0,不是0x0,所以要告诉链接器,把text段放到0x0上,在linux0.12根目录下面的Makefile,修改ld命令,在其后面加上-Ttext 0x0 -e startup_32, 同时在head.s 的.global中加入startup_32以便外部访问。除此而外,GCC头的第24个字节是version,第26个字节开始才是程序入口。。。额,索性直接把判断GCC头那段给干掉。。。
然后链接也OK了,生成了Image 进入调试阶段。。
linux0.12 链接过程的更多相关文章
- linux0.12 编译过程
感谢这篇文章的作者: http://www.cnblogs.com/strugglesometimes/p/4231359.html 编译是个很蛋疼的事情,本想把linux0.12在bochs上 ...
- linux0.12 学习总序(不断更新状态中)
最近有空闲时间,想静下心来学点东西.一直对kernel有兴趣,又苦于无从下手,就拿linux0.12练手.尝试了解并熟悉kernel各模块工作原理. 接下来的博客主要用来记录自己所遇到的问题和解决的方 ...
- 第一次作业:基于Linux-0.12的进程分析
这次作业主要基于Linux-0.12的源代码,分析Linux是如何组织进程,进程的状态之间是如何转换,以及进程是如何调度的. 一. 进程的概念: 1.进程就是:程序在数据集合上的一次运行过程,是系统进 ...
- GCC编译链接过程
编译链接过程 代码 #cat main.c #include <stdio.h> int add(int x, int y); int sub(int x, int y); int mul ...
- 鸿蒙内核源码分析(静态链接篇) | 完整小项目看透静态链接过程 | 百篇博客分析OpenHarmony源码 | v54.01
百篇博客系列篇.本篇为: v54.xx 鸿蒙内核源码分析(静态链接篇) | 完整小项目看透静态链接过程 | 51.c.h.o 下图是一个可执行文件编译,链接的过程. 本篇将通过一个完整的小工程来阐述E ...
- 【图片+代码】:GCC 链接过程中的【重定位】过程分析
作 者:道哥,10+年嵌入式开发老兵,专注于:C/C++.嵌入式.Linux. 关注下方公众号,回复[书籍],获取 Linux.嵌入式领域经典书籍:回复[PDF],获取所有原创文章( PDF 格式). ...
- [转]C++编译链接过程详解
C语言的编译链接过程要把我们编写的一个c程序(源代码)转换成可以在硬件上运行的程序(可执行代码),需要进行编译和链接.编译就是把文本形式源代码翻译为机器语言形式的目标文件的过程.链接是把目标文件.操作 ...
- mysql学习(2)-Navicat Premium 12 链接MySQL8.0.11数据库报2059错误
Navicat Premium 12 链接MySQL8.0.11数据库报2059错误 1,问题现象 安装完MySQL8.0.11和Navicat Premium12后,我们会用Navicat去测试连接 ...
- C-从源文件到可执行文件的详细编译链接过程
一直用windows一键搞定, 没有去了解详细的编译链接过程, 今天看了一篇文章, 顺便实验和记录在Linux下逐步生成的步骤. 预处理: 执行#include, #define, #if, #ifd ...
随机推荐
- Brunch:快捷的HTML5构建工具
Brunch,一个超快的HTML5构建工具.它可以(官方介绍): 编译你的脚本,模板,样式,链接它们, 将脚本和模板封装进common.js/AMD模块里,链接脚本和样式, 为链接文件生成源地图,复制 ...
- android实现界面左右滑动(GridView动态设置item,支持每个item按某个属性排序来显示在不同的界面)
效果图 : 分别是第一页.第二页.第三页,随手截的图,不整齐,勿见怪.开始走了弯路,废了不少时间. 思路如下: 1.用ViewPager实现左右分页滑动 ...
- 批量升级BMC固件asu64、ipmitool
需求:通过服务器远程管理IP批量升级IMM.UEFI固件 工具:asu64.ipmitool.iflash64.cdc_interface.sh 下载:http://pan.baidu.com/s/1 ...
- php 时间转换
在数据库读出的数据,都是字符类型的,所以需要转换: 时间的转换:用date ()函数来实现时间格式; date() 函数默认时间是1970/01/01/ 00:00:00; 要想得到想要的时间就还得用 ...
- OD: DEP - Ret2Libc via VirtualProtect() & VirtualAlloc()
一,通过 VirutalProtect() 修改内存属性绕过 DEP DEP 的四种工作模式中,OptOut 和 AlwaysOn 下所有进程默认都开启 DEP 保护,这里如果一个程序自身需要从堆栈中 ...
- div中实现居中
今天纠结了大半天的居中,把学到的先记录下来,还没完全弄清楚,发现网上原创的技术贴并不算多,大多都是相互转载.(ps.先安利一个大神的帖集,昨天才发现的,内容丰富,语言,呃...很幽默,一般都是图文并茂 ...
- php捕获异常的处理
try { $result = *} catch (Exception $e) { $result = $e; } 如果try里面报异常,$result = ...
- 2.Android Studio系列教程2——基本设置与运行
原文链接:http://stormzhang.com/devtools/2014/11/28/android-studio-tutorial2/ 一.项目结构 二.Android Studio ...
- java学习——集合框架(Collection,List,Set)
集合类的由来: 对象用于封装特有数据,对象多了需要存储,如果对象的个数不确定,就使用集合容器进行存储. 集合特点:1,用于存储对象的容器.2,集合的长度是可变的.3,集合中不可以存储基本数据类型值. ...
- osg for android (一) 简单几何物体的加载与显示
1. 首先需要一个OSG for android的环境. (1).NDK 现在Eclipse 对NDK已经相当友好了,已经不需要另外cygwin的参与,具体可以参考 Android NDK开发篇(一) ...