Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1950060
  • 博文数量: 77
  • 博客积分: 2175
  • 博客等级: 大尉
  • 技术积分: 2491
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-20 20:49
个人简介

欢迎光临我的博客

文章分类

全部博文(77)

文章存档

2023年(1)

2018年(4)

2017年(1)

2016年(2)

2015年(2)

2013年(5)

2012年(29)

2010年(33)

分类: LINUX

2010-08-06 13:21:08

文件

本版UNIX的可执行文件是.out格式,如果你在UNIX下用gcc编译程序,它默认会生成一个名为“a.out”的可执行文件。尽管现在的UNIX/Linux基本上用ELFEXECUTABLE AND LINKABLE FORMAT)代替了.out做为可执行(以及目标和库)文件的标准格式,而且ELF对于动态链接、扩展库和面向对象语言(比如C++)有着更好的支持,但作为一个时代的标记,.out文件曾经扮演过重要的角色,而且ELF也由它发展而来,因此了解.out的格式是很有意义的。

.out文件最多可包含七个部分:可执行头(exec header)、程序段(Text segment)、数据段(data segment)、程序重定向表(text relocation)、数据重定向表(data relocation)、符号表(symbol table)和字符串表(string table)如图11-1所示。


11-1  .out文件格式



其中只有可执行头是必须的,其他段都是可选的。

可执行头

其结构定义如下:

struct exec {

                   unsigned long   a_midmag;

                        unsigned long   a_text;

                   unsigned long   a_data;

                   unsigned long   a_bss;

                   unsigned long   a_syms;

                   unsigned long   a_entry;

                   unsigned long   a_trsize;

                   unsigned long   a_drsize;

};

对于16CPU,它占用16字节,对于32CPU,占用32字节。

     a_midmag

a_midmag是魔术数,它标识了可执行文件的格式,取值如下:

#define OMAGIC          0407    /* old impure format */

#define NMAGIC          0410    /* read-only text */

#define ZMAGIC          0411    /* demand load format */

#define QMAGIC          0314    /* "compact" demand load    format */

OMAGIC表示程序段是可写的,在空间上和数据段连续。

NMAGIC表示程序段是只读的,并且空间上和数据段不连续,它和数据段的起始地址都是8K边界。

ZMAGIC表示程序段和数据段是通过两套活动页寄存器映射的,程序段是只读的。

QMAGIC目前还不支持。

     a_text

程序段(text segment)大小,字节数。

     a_data

已初始化的数据段大小。

     a_bss

未初始化的数据段大小(bss = block started by symbol)。

     a_syms

符号表(symbol table)大小,字节数。

     a_entry

程序入口地址。

     a_trsize

程序重定向表(text relocation)大小。

     a_drsize

数据重定向表(data relocation)大小。

程序段

编译后的机器代码,它从0地址开始,只读。

数据段

它包含了已初始化的全局变量值。未初始化的全局变量并不在可执行文件中记录,而会在创建对应进程时分配空间,而因为没有初值,所以不需要记录。

程序和数据重定向表

它记录了程序段中哪些符号(全局变量和函数)需要重定向,链接器(link editor)会根据该表和符号表来设定它们的绝对地址,因为这在编译阶段是不可能知道的。

比如,有一段代码在main.c中:

int xx, yy;

void main()

{

   xx = 1;

   yy = 2;

}

在编译(还未链接)后,其汇编代码如下:

.globl _main

_main:

   mov &xx, R0

   mov 1,  (R0)

   mov &yy, R1

   mov 2,  (R1)

   rts PC

由于还未链接,xxyy的空间还未被分配,所以&xx&yy用其他值比如0代替,并把它们记录到程序重定向表中,它们会在链接阶段被替换为真正的地址。

所以对应的机器码如图11-2所示:


11-2  程序对应机器指令

目标文件main.o中的代码(数据)重定向记录结构如下:

struct relocation_info

{

                   int                    r_address;

                   unsigned int          r_symbolnum : 24,

                                           r_pcrel : 1,

                                           r_length : 2,

                                           r_extern : 1,

                                           r_baserel : 1,

                                           r_jmptable : 1,

                                           r_relative : 1,

                                           r_copy : 1;

};

1r_address

它表示需要重定向的符号相对于代码段(或数据段)的偏移量,字节数。上例中&xx对应值就是2,而&yy10


上一章 进程交换过程                      目录                            下一章 系统调用    

                       


阅读(13577) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~