创建一个共享对象 C,它依赖于静态库 B,它本身依赖于静态库 A
Create a shared object C, which depends on static lib B, which itself depends on static lib A
目标
我想创建一个共享库 libsquare.so
,静态 linked 到 libmul.a
,它本身静态 linked 到 libadd.a
情况
我通过 linking libadd.a
创建了 libmul.a
。
然后我在刚刚创建的 libmul.a
.
中通过 linking 创建 libsquare.so
libmul.a
有 add
函数的代码。
问题
当我 link 将其放入共享对象并查看符号 table 时,add
符号仍然存在,但未定义 (*UND*
),而不是 .text
部分。
我有一个 MWE here on Github 演示它。
这里是objdump -t libsquare.so
的一部分
libsquare.so: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 *UND* 0000000000000000 add
0000000000001119 g F .text 000000000000001c square
0000000000001135 g F .text 000000000000003b mul
... // some symbols omitted here... See repo for entire table
此处完整objdump -t libmul.a
mul.o: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 mul.c
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 g F .text 000000000000003b mul
0000000000000000 *UND* 0000000000000000 _GLOBAL_OFFSET_TABLE_
0000000000000000 *UND* 0000000000000000 add
In nested archive libadd.a:
add.o: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 add.c
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 g F .text 0000000000000014 add
本质上命令 运行 是:
cc -fPIC -rdynamic -o add.o -c add.c
cc -fPIC -rdynamic -o mul.o -c mul.c
cc -fPIC -rdynamic -o square.o -c square.c
ar rcs libadd.a add.o
ranlib libadd.a
ar rcs libmul.a mul.o libadd.a
ranlib libmul.a
gcc -shared -Wl,-soname=square -o libsquare.so square.o libmul.a
cc -fPIC -rdynamic -o test-w-lib.o -c test-w-lib.c
cc -o test-w-lib libsquare.so test-w-lib.o -ldl
/usr/bin/ld: libsquare.so: undefined reference to `add'
collect2: error: ld returned 1 exit status
没关系,我找到了解决办法。
开个玩笑:)
问题是我的 ar
命令。通过 ar rcs libmul.a mul.o libadd.a
创建 libmul.a
时,它会创建一个名为 libmul.a
的存档,其中包含 mul.o
和 libadd.a
,如下所示:
libmul.a
├── mul.o
└── libadd.a
└── add.o
另见 objdump:
$ objdump libmul.a -t
In archive libmul.a:
mul.o: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 mul.c
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 g F .text 000000000000003b mul
0000000000000000 *UND* 0000000000000000 _GLOBAL_OFFSET_TABLE_
0000000000000000 *UND* 0000000000000000 add
In nested archive libadd.a:
add.o: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 add.c
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 g F .text 0000000000000014 add
当最终像 gcc use-lib-mul.c libmul.a
那样链接 libmul.a
时,这也失败了。 (因此整体问题与共享对象部分无关)。
解决方案
如评论和 here 中所写,必须从依赖库 libadd.a
中解压缩对象以创建另一个库 libmul.a
.
所以要正确生成libmul.a
:
libmul.a: mul.o libadd.a
rm -rf libadd; mkdir libadd; cd libadd; ar x ../libadd.a
ar rcs ${@} ${<} ./libadd/*.o
ranlib ${@}
这会创建:
libmul.a
├── mul.o
└── add.o
最后,要正确生成 libsquare.so
:
libsquare.so: square.o libmul.a
rm -rf libmul; mkdir libmul; cd libmul; ar x ../libmul.a
$(CC) -shared -Wl,-soname=square -o ${@} ${<} libmul/*.o
然后在 .text
部分中包含所有必需的符号,并且这些符号的所有长度 >0 0x14
、0x1c
和 0x3b
分别为:
$ objdump libsquare.so -t
libsquare.so: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 square.c
0000000000000000 l df *ABS* 0000000000000000 add.c
0000000000000000 l df *ABS* 0000000000000000 mul.c
0000000000001135 g F .text 0000000000000014 add
0000000000001119 g F .text 000000000000001c square
0000000000001149 g F .text 000000000000003b mul
...
目标
我想创建一个共享库 libsquare.so
,静态 linked 到 libmul.a
,它本身静态 linked 到 libadd.a
情况
我通过 linking libadd.a
创建了 libmul.a
。
然后我在刚刚创建的 libmul.a
.
libsquare.so
libmul.a
有 add
函数的代码。
问题
当我 link 将其放入共享对象并查看符号 table 时,add
符号仍然存在,但未定义 (*UND*
),而不是 .text
部分。
我有一个 MWE here on Github 演示它。
这里是objdump -t libsquare.so
libsquare.so: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 *UND* 0000000000000000 add
0000000000001119 g F .text 000000000000001c square
0000000000001135 g F .text 000000000000003b mul
... // some symbols omitted here... See repo for entire table
此处完整objdump -t libmul.a
mul.o: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 mul.c
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 g F .text 000000000000003b mul
0000000000000000 *UND* 0000000000000000 _GLOBAL_OFFSET_TABLE_
0000000000000000 *UND* 0000000000000000 add
In nested archive libadd.a:
add.o: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 add.c
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 g F .text 0000000000000014 add
本质上命令 运行 是:
cc -fPIC -rdynamic -o add.o -c add.c
cc -fPIC -rdynamic -o mul.o -c mul.c
cc -fPIC -rdynamic -o square.o -c square.c
ar rcs libadd.a add.o
ranlib libadd.a
ar rcs libmul.a mul.o libadd.a
ranlib libmul.a
gcc -shared -Wl,-soname=square -o libsquare.so square.o libmul.a
cc -fPIC -rdynamic -o test-w-lib.o -c test-w-lib.c
cc -o test-w-lib libsquare.so test-w-lib.o -ldl
/usr/bin/ld: libsquare.so: undefined reference to `add'
collect2: error: ld returned 1 exit status
没关系,我找到了解决办法。
开个玩笑:)
问题是我的 ar
命令。通过 ar rcs libmul.a mul.o libadd.a
创建 libmul.a
时,它会创建一个名为 libmul.a
的存档,其中包含 mul.o
和 libadd.a
,如下所示:
libmul.a
├── mul.o
└── libadd.a
└── add.o
另见 objdump:
$ objdump libmul.a -t
In archive libmul.a:
mul.o: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 mul.c
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 g F .text 000000000000003b mul
0000000000000000 *UND* 0000000000000000 _GLOBAL_OFFSET_TABLE_
0000000000000000 *UND* 0000000000000000 add
In nested archive libadd.a:
add.o: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 add.c
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 g F .text 0000000000000014 add
当最终像 gcc use-lib-mul.c libmul.a
那样链接 libmul.a
时,这也失败了。 (因此整体问题与共享对象部分无关)。
解决方案
如评论和 here 中所写,必须从依赖库 libadd.a
中解压缩对象以创建另一个库 libmul.a
.
所以要正确生成libmul.a
:
libmul.a: mul.o libadd.a
rm -rf libadd; mkdir libadd; cd libadd; ar x ../libadd.a
ar rcs ${@} ${<} ./libadd/*.o
ranlib ${@}
这会创建:
libmul.a
├── mul.o
└── add.o
最后,要正确生成 libsquare.so
:
libsquare.so: square.o libmul.a
rm -rf libmul; mkdir libmul; cd libmul; ar x ../libmul.a
$(CC) -shared -Wl,-soname=square -o ${@} ${<} libmul/*.o
然后在 .text
部分中包含所有必需的符号,并且这些符号的所有长度 >0 0x14
、0x1c
和 0x3b
分别为:
$ objdump libsquare.so -t
libsquare.so: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 square.c
0000000000000000 l df *ABS* 0000000000000000 add.c
0000000000000000 l df *ABS* 0000000000000000 mul.c
0000000000001135 g F .text 0000000000000014 add
0000000000001119 g F .text 000000000000001c square
0000000000001149 g F .text 000000000000003b mul
...