静态库文件是使用打包工具ar将一个或者多个可重定位的目标文件组成一个静态库文件,也可以看做是多个可重定位的目标文件的一个简单包装文件。
1. 静态库的生成
假设我们要构建一个四则运算的而函数库
(1)其源代码如下:
[root@localhost liba]# cat add.c
int
add (int a, int b)
{
return a + b;
}
[root@localhost liba]# cat sub.c
int
sub (int a, int b)
{
return a - b;
}
[root@localhost liba]# cat mult.c
int
mult (int a, int b)
{
return a * b;
}
[root@localhost liba]# cat div.c
int
div (int a, int b)
{
int d = a / b;
return d;
}
(2) 构建Makefile
[root@localhost liba]# cat Makefile
AR = ar
STATIC_LIB = ./libmath.a
DYNAMIC_LIB = ./libmath.so
objects = add.o sub.o mult.o div.o
pic_objects = add.o sub.o mult.o div.o
all: $(STATIC_LIB) $(DYNAMIC_LIB)
obj: $(objects)
$(objects): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
$(pic_objects): %.o: %.c
$(CC) -c $(CFLAGS) -fpic $< -o $@
$(STATIC_LIB) : $(objects)
$(AR) rcs $@ $^
$(DYNAMIC_LIB): $(pic_objects)
$(CC) -shared -o $@ $^
clean:
rm -f $(objects)
rm -f $(STATIC_LIB) $(DYNAMIC_LIB)
(3) 编译生成libmath.a静态库文件
执行make all,生成libmath.a和libmath.so。
[root@localhost liba]# make all
2. 静态库文件的基本结构
静态库的结构在/usr/include/ar.h文件中描述了ar文件结构中的几个重要数据结构,从中可以分析出ar文件的结构主要包括两大部分:
(1)存档文件的魔数
存档文件的魔数(Magic Number)标识ARMAG,也可以看做是ar文件的首部,该首部是一个8字节的字符序列,其定义为:
#define ARMAG "!<arch>\n" /* String that begins an archive file. */
魔数ARMAG的字节大小SARMAG,其值为整数值8,其定义为:
#define SARMAG 8 /* Size of that string. */
(2)每个成员文件的相关信息
每个成员文件的信息包括也两部分:
A. 成员文件首部
使用struct ar_hdr结构体来描述该成员文件的基本信息,包括文件名称、日期、用户ID、组ID、文件存取属性、文件大小以及一个结构体结束标记。该结构体的定义如下:
#define ARFMAG "`\n" /* String in ar_fmag at end of each header. */
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. */
};
B.成员文件的内容
如果ar文件是静态库,那么该部分内容就是构造这个静态库的可重定位目标文件(也就是我们常见的o文件)的内容。
图 1. 使用ar工具打包的静态库格式
3. 静态库文件的索引部分
如果在ar打包时使用-s参数,则在ar文件中会添加一个索引部分,索引部分的组织与其他成员文件的组织方式相同,索引成员文件首部中的ar_name的值为“/ ”。
也可以使用nm查看该索引内容。
[root@localhost liba]# nm --print-armap libmath.a
Archive index:
add in add.o
sub in sub.o
mult in mult.o
div in div.o
add.o:
00000000 T add
sub.o:
00000000 T sub
mult.o:
00000000 T mult
div.o:
00000000 T div
索引成员文件的内容一般包括:
(1)符号数量
(2)每个符号所在的成员文件在整个ar文件中的偏移量
(3)所有符号的名称列表
上述libmath.a文件的具体内容分析如下:
图2. libmath.a 结构图示
也可以使用hexdump查看具体内容。
参考文献
[1] Executable and Linkable Format (ELF) - eLinux.org
[3] Understanding the ELF File Format
[4] The 101 of ELF files on Linux: Understanding and Analysis
[5] www.skyfree.org/linux/references/ELF_Format.pdf
[6] ELF:From The Programmer's Perspective