为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

存档文件格式简介

2018-01-14 12页 doc 36KB 63阅读

用户头像

is_713593

暂无简介

举报
存档文件格式简介存档文件格式简介 出于好奇,想了解一下linux的存档文件(*.a)的格式。在网上大概找了一下,没找到比较好的(没细找), 所以想自己摸索一下,把它的文件格式弄清楚。结果发现这个文件的格式竟然那么简单。在这里和大家分享 一下,有错误的地方希望大家指正。 1.存档文件(archive)简介 存档文件(*.a)文件相当于windows的静态链接库,他把很多的目标文件(*.o)文件打包为单一的库 文件。在链接程序的时候,需要用到库里面的函数时,只需在链接时加上-lX (X表示库的名字),链接 器会自动得根据要调用函数,...
存档文件格式简介
存档文件格式简介 出于好奇,想了解一下linux的存档文件(*.a)的格式。在网上大概找了一下,没找到比较好的(没细找), 所以想自己摸索一下,把它的文件格式弄清楚。结果发现这个文件的格式竟然那么简单。在这里和大家分享 一下,有错误的地方希望大家指正。 1.存档文件(archive)简介 存档文件(*.a)文件相当于windows的静态链接库,他把很多的目标文件(*.o)文件打包为单一的库 文件。在链接程序的时候,需要用到库里面的函数时,只需在链接时加上-lX (X表示库的名字),链接 器会自动得根据要调用函数,找到相应的目标文件,链接到可执行程序中,不需要的目标不会被链接到可执 行程序中。 2.archive文件的格式[参考/usr/include/ar.h中的说明] archive文件的格式主要保护两个部分,主要是: 一个头部标志ARMAG, 多个数据区。 ['头部标志'和'数据区'是我自己为了方便说明起的名字,跟官方的说法应该是有出入的]。 2.1 头部标志 头部标志的作用仅用于说明这是一个archive文件 在ar.h中定义了两个宏: #define ARMAG "!\n" /* String that begins an archive file. */ #define SARMAG 8 /* Size of that string. */ ARMAG指明了头部标志的内容,SARMAG说明了头部标志的长度。 2.2 数据区 一个archive文件有多个数据区,每个数据区包含一个头部(ar_hdr)和一段数据段,他们是 紧跟在一起的。 在ar.h中ar_hdr的声明是这样的 struct ar_hdr { char ar_name[16]; /* Member file name, sometimes / terminated. */ char ar_date[12]; /* File date, decimal seconds since Epoch. */ char ar_uid[6], ar_gid[6]; /* User and group IDs, in ASCII decimal. */ char ar_mode[8]; /* File mode, in ASCII octal. */ char ar_size[10]; /* File size, in ASCII decimal. */ char ar_fmag[2]; /* Always contains ARFMAG. */ }; 在archive中每个目标文件(*.o)都会被分配一个数据区,数据区的数据段是该目标文 件(*.o) 原封不动的拷贝,ar_hdr则存放了对该目标文件的说明。 ar_name文件说明了目标文件的名字(以/作为终止符), ar_date说明了该文件的日期, ar_uid、ar_gid指明了该目标文件的用户ID和组ID, ar_mode指明了文件的访问属性(权限), ar_size指明了目标文件的大小,同时是该数据区数据段的大小 ar_fmag总是包含ARFMAG,该宏被定义为#define ARFMAG "`\n" , 用户指明ar_hdr 的 尾部。 除了为每个目标文件分配一个数据区之外,archive文件还添加一个特殊的数据区,它位 于第 一个数据区,它的数据段包含了该archive文件的符号数(函数/全局变量)、符号名称、符号 所在目标文件 的偏移量。 3.archive文件的分析 首先,建立两个测试文件,并把它们加到archive文件中: [root:/root/test/ar]cat test_ar.c int test(void) <---------------------定义一个函数和一个变量 { return 0; }; int error; [root:/root/test/ar]gcc -o test_ar.o -c test_ar.c [root:/root/test/ar]cat test_ar_1.c int test(void) <------------------------定义一个函数 { return 1; } [root:/root/test/ar]gcc -o test_ar_1.o -c test_ar_1.c [root:/root/test/ar]ar -rv libtest_ar.a test_ar.o test_ar_1.o r - test_ar.o r - test_ar_1.o [root:/root/test/ar]ar -vt libtest_ar.a rw-rw-r-- 0/0 706 Jul 17 15:45 2008 test_ar.o rw-rw-r-- 0/0 686 Jul 17 15:45 2008 test_ar_1.o 这样,我们把test_ar.o test_ar_1.o放到了libtest_ar.a中。我们用hexdump 对libtest_ar.a进程剖析(不熟悉hexdump用法的参见man hexdump) [root:/root/test/ar]hexdump -C -s 0x0 -n 8 libtest_ar.a 00000000 21 3c 61 72 63 68 3e 0a |!.| <----头部标志 00000008 上面是头部标志部分,位于文件最前面。 [root:/root/test/ar]hexdump -C -s 0x8 -n 60 libtest_ar.a 00000008 2f 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 |/ | 00000018 31 32 31 36 32 38 30 37 39 36 20 20 30 20 20 20 |1216280796 0 | 00000028 20 20 30 20 20 20 20 20 30 20 20 20 20 20 20 20 | 0 0 | 00000038 33 32 20 20 20 20 20 20 20 20 60 0a |32 `.| 00000044 上面是第一个数据区的头部ar_hdr,名字为空, '/'是终止符,1216280796是文件的时间, 是被字符串化的time_t类型的数据,三个0中前两个分别为uid和gid,后面一个标志目标文 件属性,在这 忽略,32是该数据区后面数据段的长度, `.是终止符。 [root:/root/test/ar]hexdump -C -s 0x44 -n 32 libtest_ar.a 00000044 00 00 00 03 00 00 00 64 00 00 00 64 00 00 03 62 |.......d...d...b| 00000054 74 65 73 74 00 65 72 72 6f 72 00 74 65 73 74 00 |test.error.test.| 上面是特殊数据区的数据段,第一行中00 00 00 03表示的是该archive文件向外 导出的符号数,这里为3(注意,这里的数据都是按大尾的编码方式的)。00 00 00 64 、 00 00 00 64、 00 00 03 62分别是三个符号所在目标文件的ar_hdr在该archive文件中的 偏移量,分别是0x64、0x64、0x362,紧接着是符号名称的字符串表。 [root:/root/test/ar]hexdump -C -s 0x64 -n 60 libtest_ar.a 00000064 74 65 73 74 5f 61 72 2e 6f 2f 20 20 20 20 20 20 |test_ar.o/ | 00000074 31 32 31 36 32 38 30 37 31 38 20 20 30 20 20 20 |1216280718 0 | 00000084 20 20 30 20 20 20 20 20 31 30 30 36 36 34 20 20 | 0 100664 | 00000094 37 30 36 20 20 20 20 20 20 20 60 0a |706 `.| 000000a0 [root:/root/test/ar]hexdump -C -s 0x362 -n 60 libtest_ar.a 00000362 74 65 73 74 5f 61 72 5f 31 2e 6f 2f 20 20 20 20 |test_ar_1.o/ | 00000372 31 32 31 36 32 38 30 37 35 30 20 20 30 20 20 20 |1216280750 0 | 00000382 20 20 30 20 20 20 20 20 31 30 30 36 36 34 20 20 | 0 100664 | 00000392 36 38 36 20 20 20 20 20 20 20 60 0a |686 `.| 0000039e 上面验证了0x64、0x362是目标文件的ar_hdr在该archive文件中的偏移量,可以看出, 第一个test和error定义在test_ar.o中,第二个test定义在test_ar_1.o中,这和我们之前写的 文 件是相符的。 上面第一命令,同样test_ar.o/是目标文件的名字,1216280718是时间,两个0分别是 uid和gid,100644表示文件权限(rw_rw_r__), 706是该目标文件的大小,也是下面数据段 的大小。 [root:/root/test/ar]ls -l *.o -rw-rw-r-- 1 root root 686 07-17 15:45 test_ar_1.o -rw-rw-r-- 1 root root 706 07-17 15:45 test_ar.o 和archive文件中的数据相符的。 接下来我们对比一下存档中的内容和目标文件的内容。 [root:/root/test/ar]hexdump -C -s 0xa0 -n 706 libtest_ar.a <-------0xa0是紧接着test_ar.o的ar_hdr之后的地址 000000a0 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| 000000b0 01 00 03 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| 000000c0 b4 00 00 00 00 00 00 00 34 00 00 00 00 00 28 00 |........4.....(.| 000000d0 09 00 06 00 55 89 e5 b8 00 00 00 00 5d c3 00 00 |....U.......]...| 000000e0 00 47 43 43 3a 20 28 47 4e 55 29 20 34 2e 31 2e |.GCC: (GNU) 4.1.| 000000f0 32 20 32 30 30 37 30 39 32 35 20 28 52 65 64 20 |2 20070925 (Red | 00000100 48 61 74 20 34 2e 31 2e 32 2d 33 33 29 00 00 2e |Hat 4.1.2-33)...| 00000110 73 79 6d 74 61 62 00 2e 73 74 72 74 61 62 00 2e |symtab..strtab..| 00000120 73 68 73 74 72 74 61 62 00 2e 74 65 78 74 00 2e |shstrtab..text..| 00000130 64 61 74 61 00 2e 62 73 73 00 2e 63 6f 6d 6d 65 |data..bss..comme| 00000140 6e 74 00 2e 6e 6f 74 65 2e 47 4e 55 2d 73 74 61 |nt..note.GNU-sta| 00000150 63 6b 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |ck..............| 00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000170 00 00 00 00 00 00 00 00 00 00 00 00 1b 00 00 00 |................| 00000180 01 00 00 00 06 00 00 00 00 00 00 00 34 00 00 00 |............4...| 00000190 0a 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 |................| 000001a0 00 00 00 00 21 00 00 00 01 00 00 00 03 00 00 00 |....!...........| 000001b0 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| 000001c0 00 00 00 00 04 00 00 00 00 00 00 00 27 00 00 00 |............'...| 000001d0 08 00 00 00 03 00 00 00 00 00 00 00 40 00 00 00 |............@...| 000001e0 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 |................| 000001f0 00 00 00 00 2c 00 00 00 01 00 00 00 00 00 00 00 |....,...........| 00000200 00 00 00 00 40 00 00 00 2e 00 00 00 00 00 00 00 |....@...........| 00000210 00 00 00 00 01 00 00 00 00 00 00 00 35 00 00 00 |............5...| 00000220 01 00 00 00 00 00 00 00 00 00 00 00 6e 00 00 00 |............n...| 00000230 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |................| 00000240 00 00 00 00 11 00 00 00 03 00 00 00 00 00 00 00 |................| 00000250 00 00 00 00 6e 00 00 00 45 00 00 00 00 00 00 00 |....n...E.......| 00000260 00 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 |................| 00000270 02 00 00 00 00 00 00 00 00 00 00 00 1c 02 00 00 |................| 00000280 90 00 00 00 08 00 00 00 07 00 00 00 04 00 00 00 |................| 00000290 10 00 00 00 09 00 00 00 03 00 00 00 00 00 00 00 |................| 000002a0 00 00 00 00 ac 02 00 00 16 00 00 00 00 00 00 00 |................| 000002b0 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| 000002c0 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |................| 000002d0 00 00 00 00 00 00 00 00 04 00 f1 ff 00 00 00 00 |................| 000002e0 00 00 00 00 00 00 00 00 03 00 01 00 00 00 00 00 |................| 000002f0 00 00 00 00 00 00 00 00 03 00 02 00 00 00 00 00 |................| 00000300 00 00 00 00 00 00 00 00 03 00 03 00 00 00 00 00 |................| 00000310 00 00 00 00 00 00 00 00 03 00 05 00 00 00 00 00 |................| 00000320 00 00 00 00 00 00 00 00 03 00 04 00 0b 00 00 00 |................| 00000330 00 00 00 00 0a 00 00 00 12 00 01 00 10 00 00 00 |................| 00000340 04 00 00 00 04 00 00 00 11 00 f2 ff 00 74 65 73 |.............tes| 00000350 74 5f 61 72 2e 63 00 74 65 73 74 00 65 72 72 6f |t_ar.c.test.erro| 00000360 72 00 |r.| 00000362 [root:/root/test/ar]hexdump -C -s 0x0 -n 706 test_ar.o 00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| 00000010 01 00 03 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 b4 00 00 00 00 00 00 00 34 00 00 00 00 00 28 00 |........4.....(.| 00000030 09 00 06 00 55 89 e5 b8 00 00 00 00 5d c3 00 00 |....U.......]...| 00000040 00 47 43 43 3a 20 28 47 4e 55 29 20 34 2e 31 2e |.GCC: (GNU) 4.1.| 00000050 32 20 32 30 30 37 30 39 32 35 20 28 52 65 64 20 |2 20070925 (Red | 00000060 48 61 74 20 34 2e 31 2e 32 2d 33 33 29 00 00 2e |Hat 4.1.2-33)...| 00000070 73 79 6d 74 61 62 00 2e 73 74 72 74 61 62 00 2e |symtab..strtab..| 00000080 73 68 73 74 72 74 61 62 00 2e 74 65 78 74 00 2e |shstrtab..text..| 00000090 64 61 74 61 00 2e 62 73 73 00 2e 63 6f 6d 6d 65 |data..bss..comme| 000000a0 6e 74 00 2e 6e 6f 74 65 2e 47 4e 55 2d 73 74 61 |nt..note.GNU-sta| 000000b0 63 6b 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |ck..............| 000000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000d0 00 00 00 00 00 00 00 00 00 00 00 00 1b 00 00 00 |................| 000000e0 01 00 00 00 06 00 00 00 00 00 00 00 34 00 00 00 |............4...| 000000f0 0a 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 |................| 00000100 00 00 00 00 21 00 00 00 01 00 00 00 03 00 00 00 |....!...........| 00000110 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| 00000120 00 00 00 00 04 00 00 00 00 00 00 00 27 00 00 00 |............'...| 00000130 08 00 00 00 03 00 00 00 00 00 00 00 40 00 00 00 |............@...| 00000140 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 |................| 00000150 00 00 00 00 2c 00 00 00 01 00 00 00 00 00 00 00 |....,...........| 00000160 00 00 00 00 40 00 00 00 2e 00 00 00 00 00 00 00 |....@...........| 00000170 00 00 00 00 01 00 00 00 00 00 00 00 35 00 00 00 |............5...| 00000180 01 00 00 00 00 00 00 00 00 00 00 00 6e 00 00 00 |............n...| 00000190 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |................| 000001a0 00 00 00 00 11 00 00 00 03 00 00 00 00 00 00 00 |................| 000001b0 00 00 00 00 6e 00 00 00 45 00 00 00 00 00 00 00 |....n...E.......| 000001c0 00 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 |................| 000001d0 02 00 00 00 00 00 00 00 00 00 00 00 1c 02 00 00 |................| 000001e0 90 00 00 00 08 00 00 00 07 00 00 00 04 00 00 00 |................| 000001f0 10 00 00 00 09 00 00 00 03 00 00 00 00 00 00 00 |................| 00000200 00 00 00 00 ac 02 00 00 16 00 00 00 00 00 00 00 |................| 00000210 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| 00000220 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |................| 00000230 00 00 00 00 00 00 00 00 04 00 f1 ff 00 00 00 00 |................| 00000240 00 00 00 00 00 00 00 00 03 00 01 00 00 00 00 00 |................| 00000250 00 00 00 00 00 00 00 00 03 00 02 00 00 00 00 00 |................| 00000260 00 00 00 00 00 00 00 00 03 00 03 00 00 00 00 00 |................| 00000270 00 00 00 00 00 00 00 00 03 00 05 00 00 00 00 00 |................| 00000280 00 00 00 00 00 00 00 00 03 00 04 00 0b 00 00 00 |................| 00000290 00 00 00 00 0a 00 00 00 12 00 01 00 10 00 00 00 |................| 000002a0 04 00 00 00 04 00 00 00 11 00 f2 ff 00 74 65 73 |.............tes| 000002b0 74 5f 61 72 2e 63 00 74 65 73 74 00 65 72 72 6f |t_ar.c.test.erro| 000002c0 72 00 |r.| 000002c2 对比上面两个输出,内容是完全一致的,正是我之前期盼的那样。 4.链接 在上面的例子中,我故意在test_ar.c、test_ar_1.c中定义了同名的函数。但一个返回0, 一个返回1,主要是为了检查符号的解析。 我又写了一个测试文件。 [root:/root/test/ar]cat main.c #include int main() { int i = test(); printf("%d\n", i); return 0; } [root:/root/test/ar]gcc -o main main.c -L. -ltest_ar [root:/root/test/ar]./main 0 输出结果为0,也就是它调用的时test_ar.o中的test()函数而不是调用test_ar_1.o中的函数。 我们看上面符号表中的数据 00000044 00 00 00 03 00 00 00 64 00 00 00 64 00 00 03 62 |.......d...d...b| 00000054 74 65 73 74 00 65 72 72 6f 72 00 74 65 73 74 00 |test.error.test.| test_ar.o中test在前面,链接的过程我猜想是这样的[如有错误请纠正]: 1.函数遇到一个未解析的符号,它在-l指定的连接归档库中查找。 2.当查找到第一个符合的符号时,他即停止搜索。 3.根据符号获得目标文件在archive中的偏移量,把相关的目标文件(*.o)从库中复制一份出来, 链接到可执行程序中。
/
本文档为【存档文件格式简介】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索