月度归档:2013年04月

论静态库链接的坑

【场景】
1.具体代码就不贴了,太繁琐。直接描述下(所有接口打印自身的信息):
假设源文件a.c和b.c都含有一个common()的接口,main.c中调用common()。
假设d.c有一个接口是co(), 然后在a.c的common()接口中被调用,main.c中调用common()接口

2.场景变换:
a) 库文件和目标文件相互交叉
b) 位置前后顺序

【试验结果】
1.出错的情况:
【multiple definition of ‘common’】
gcc main.c a.o a.o -o test_o
gcc main.c a.o b.o -o test_o
gcc main.c a.a b.o -o test_ao
【undefined reference to ‘co’】
gcc main.c -L. -ld -la -o test

2.正常的情况:
gcc main.c -L. -la -lb -o test_a (输出a的信息)
gcc main.c -L. -lb -la -o test_a (输出b的信息)
gcc main.c b.o -L. -la -o test_ao (输出b的信息)
gcc main.c b.o b.a -o test_ao (输出b的信息)
gcc main.c -L. -la -ld -o test (输出a和d的信息)

【结果分析】
以上几个情况说明的问题:
1. .a的文件在gcc的编译参数中都会被作为静态库加载,-l仅仅起到指明位置和简化库名的作用
2. .o文件没有位置顺序关系且是被强制链接的(因此如果同名的符号已经被链接,那么就会报multiple definition错)
3. .a文件的链接是有位置顺序关系的,从左到右
4. .a文件中的符号不是被强制链接的,如果同名的符号已经被链接,那么这个静态库中的同名符号不会再次被链接。
5. .a文件中的符号不是被强制链接的,若当前库中的符号没有被更前(更左边)的目标引用,那么库中该符号被忽略(报undefined reference to错误)。

因此, linux下gcc链接静态库的特征就很明确了:
1. 有顺序 从左向右
2. 可忽略(非强制链接)忽略已经链接过的符号,忽略当前没有用到的符号

【总结】
1. .o文件是强制链接,因此必须编码时保证没有符号冲突
2. .a静态库文件有自左向右的顺序,同时在符号已经链接和当前未被引用的情况下被忽略,因此必须编译选项中保证把最底层被调用的库放在最后面被链接,同时编码时保证之前不会有同名符号已被链接。

【解决办法】
1. 主动调整链接顺序
2. gcc编译选项中做强制申明
a). -whole-archive选项告诉链接器把静态库中的所有.o都进行链接,-no-whole-archive是为了告诉编译器不要链接gcc默认的库
(gcc -o test_a main.c -Wl,–whole-archive -L. -la -lb -Wl,–no-whole-archive)
b). 位于–start-group –end-group选项之间的所有静态库将被反复搜索,直到所有被使用的符号都被链接为止
(gcc -o test_a main.c –Wl,–start-group -L. -la -lb  -Wl,–end-group)

geexbox从iso文件启动的自动化改造

有朋友需要指定uuid的支持,弄来弄去也挺麻烦的,干脆一劳永逸搞个脚本

[用法]
./diy_geexbox.sh 官方geexbox的iso文件
生成以”原文件名_new.iso”的新iso文件

[处理逻辑]
1.创建目录结构,解原始iso
2.解initrd,更新修改
3.重新封包

[修改点]
1.重新编译busybox替代geexbox中的,添加了findfs的applet
2.修改init初始化脚本,添加from参数的支持
注:3.0的版本内置了ntfs-3g,因此不需要单独添加

[与以往不同]
以前仅仅支持/dev/sda5这种真实设备名的指定,现在支持指定标签和uuid。
探测逻辑是: 设备名 > 磁盘标签 > uuid

from参数的示例:
1.设备名方式
from=ISO:/dev/sda7:/SYSTEM/geexbox-3.0-x86_64.iso
2.磁盘标签方式
from=ISO:HOME-LINUX:/SYSTEM/geexbox-3.0-x86_64.iso
3.uuid方式
from=ISO:9fa15ff6-991e-40b9-8fbd-b8ecdb3b9485:/SYSTEM/geexbox-3.0-x86_64.iso

以前的文章:
http://www.rainhome.org/geexbox3-0-直接从iso启动
http://www.rainhome.org/geexbox2-0硬盘启动支持ntfs和iso

工具下载地址:
https://github.com/tangfu/geexbox-diy