> 文章列表 > linux0.12-3-5

linux0.12-3-5

linux0.12-3-5

[80页]

3-5

1、 bootsect.s和setup.s是用as86编译和ld86链接
2、 其他文件:汇编器as(gas)、C语言编译器gcc以及相应的链接程序gld
这一章主要讲:
1、 编译器产生的目标文件结构;
2、 链接器如何把需要链接在一起的目标文件模块组合在一起,以生产二进制可执行映像文件或一个大的模块文件;
3、 内核二进制代码文件image的生产原理和过程;

编译器生产的目标文件–目标模块文件
链接程序输出产生的可执行目标文件–可执行文件(统称为目标文件);

3-5-1 目标文件格式

文件头(执行头部分)
代码区(正文段)
已初始化数据区(数据段)
代码重定位信息
数据重定位信息
符号
字符表

执行头部分:
例如:代码和数据区的长度、未初始化数据区的长度、
对应源程序文件名以及目标文件创建时间等

1、 执行头部分

struct exec {
unsigned long a_magic; /* 执行文件魔数。使用N_MAGIC等宏访问。 /
unsigned a_text; /
代码长度,字节/
unsigned a_data; /
数据长度,字节数 /
unsigned a_bss; /
文件中的未初始化数据区长度,字节数 /
unsigned a_syms; /
文件中的符号表长度,字节数 /
unsigned a_entry; /
执行开始地址 /
unsigned a_trsize; /
代码重定位信息长度,字节数 /
unsigned a_drsize; /
数据重定位信息长度,字节数 */
};

Linux0.12魔数使用两种类型
OMAGIC类型,指明文件是目标文件或者是不纯的可执行文件,其魔数是0x107
ZMAGIC类型,指明文件为需求分页处理的可执行文件,其魔数是0x10b

ZMAGIC类型执行文件来说,专门留1KB的空间给头结构使用
OMAGIC类型执行文件,文件开始部分的32字节头结构后面紧接着就是代码区和数据区

对于可执行文件来说并不需要符号表和重定位信息;

2、 重定位信息部分

代码段和数据段的重定位结构体如下:
struct relocation_info
{
int r_address; //段内需要重定位的地址
unsigned int r_symbolnum:24;//含义与r_extern有关。指定符号表中一个符号或者一个段
unsigned int r_pcrel:1;//1位。PC相关标志
unsigned int r_length:2;//2位。指定要被重定义字段长度(2的次方)
unsigned int r_extern:1;//外部标志为。1-以符号的值重定位。0-以段的地址重定位。
unsigned int r_pad:4;//没有使用的4个位,但最好将它们复位掉。
};
自己在仔细看看作者描述;

3、 符号表和字符串部分

struct nlist {
union {
char *n_name;//字符串指针
struct nlist *n_next;//或者是指向另一个符号项结构的指针
long n_strx;//或者是符号名称在字符串表中的字节偏移值
} n_un;
unsigned char n_type;//该字节分成3个字段,参见a.out.h文件146-154行。
char n_other;//通常不用
short n_desc;//
unsigned long n_value;//符号的值
};

3-5-2 Linux0.12中的目标文件格式

1、 作者编译出2中文件,打印编译出的文件内容;说明上面的理论。

3-5-3 链接程序输出

1、 存储空间分配,执行符号绑定操作和代码修正操作;
2、 将所有相同类型的端组合连接在一起;

ZMAGIC类型,代码段被设置成从固定地址0开始;

tools/目录下的buil.c程序
主要功能呢就是分别去掉bootsect、setup和system文件中的执行头结构,
然后把它们顺序组合在一起产生一个名为Image的内核映像文件。

3-5-4 链接程序预定义变量

1、 连接器预定义的外部变量通常至少有
etext,edata,end
_etext,_edata,_end

3-5-5 System.map文件

1、 当运行GUN连接器gld(ld)时若使用了"-M"选项,或者使用nm命令,

则会在标准输出设备打印出连接映像信息
1.1、 目标文件及符号信息映射到内存中的位置。
1.2、 公共符号如何放置。
1.3、 链接中包含的所有文件成员及其引用的符号。

2、 通常我们会把发送到标准输出设备的链接映像信息重定位到一个文件

System.map文件

3、 通过System.map文件中的符号表解析,就可以查看到一个地址值对应的变量名;

(内存错误时很好分析的方法)