【发布时间】:2016-11-15 09:40:33
【问题描述】:
我实际上编写了一个共享对象加载器,它在 cortex-m4 控制器上加载 gcc 创建的共享对象 (ELF)。加载、依赖解析和重定位等工作正常。但是共享对象在.dynsym 部分有一些奇怪的符号,我不知道如何处理。
readelf --dyn-sym libfoo.so
Num: Wert Size Typ Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 000005c8 0 SECTION LOCAL DEFAULT 8
2: 00000874 0 SECTION LOCAL DEFAULT 16
3: 00000000 0 NOTYPE GLOBAL DEFAULT UND printf
4: 0000082d 32 FUNC GLOBAL DEFAULT 12 foo3
5: 0000087c 0 NOTYPE GLOBAL DEFAULT 18 __bss_start__
6: 00000000 0 NOTYPE GLOBAL DEFAULT UND __libc_init_array
7: 00000728 0 NOTYPE GLOBAL DEFAULT 12 _mainCRTStartup
8: 000005c8 0 FUNC GLOBAL DEFAULT 8 _init
9: 00000000 0 NOTYPE GLOBAL DEFAULT UND __libc_fini_array
10: 00000000 0 NOTYPE WEAK DEFAULT UND __deregister_frame_info
11: 00000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
12: 00000898 0 NOTYPE GLOBAL DEFAULT 18 __bss_end__
13: 00000728 0 NOTYPE GLOBAL DEFAULT 12 _start
14: 00000000 0 NOTYPE WEAK DEFAULT UND software_init_hook
15: 00000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab
16: 00000000 0 NOTYPE GLOBAL DEFAULT UND memset
17: 00000000 0 NOTYPE GLOBAL DEFAULT UND main
18: 00000000 0 NOTYPE WEAK DEFAULT UND hardware_init_hook
19: 000005e0 0 FUNC GLOBAL DEFAULT 9 _fini
20: 00000000 0 NOTYPE GLOBAL DEFAULT UND atexit
21: 00000000 0 NOTYPE WEAK DEFAULT UND __stack
22: 00000000 0 NOTYPE GLOBAL DEFAULT UND exit
23: 00000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
24: 00000000 0 NOTYPE WEAK DEFAULT UND __register_frame_info
为什么共享对象需要对主函数和__libc_init_array 函数的引用?尤其是__libc_init_array 的符号对我来说毫无意义...这个函数通常初始化__preinit_array、_init 和__init_array,但这项工作应该由我的加载程序完成,而不是由对象本身完成,或者我是错了吗?
是否有关于如何初始化加载的共享对象及其所有依赖项的分步文档?
这就是我构建共享对象的方式:
gcc -std=gnu99 -W -Wall -Wstrict-prototypes -Wmissing-prototypes -ffunction-sections -fdata-sections -mfloat-abi=soft -mcpu=cortex-m4 -mthumb -mlong-calls -Os -g -c -fPIC -o foo.o foo.c
gcc -shared -fPIC -Wl,-soname,libfoo.so -T./shared.ld -o libfoo.so foo.o
还有一个问题:没有-mlong-calls 选项,我的gcc 在.plt 部分生成无效的操作码......我做错了什么?
编辑: 我的 foo.c 很简单:
#include <stdio.h>
#include <string.h>
void foo3 (void)
{
printf("Hello from shared-object");
}
这是我的 shared.ld:
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SECTIONS
{
.interp : { *(.interp) }
.note.ABI-tag : { *(.note.ABI-tag) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.dynamic : { *(.dynamic) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.rel.dyn : { *(.rel.dyn) }
.rela.dyn : { *(.rela.dyn) }
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
.plt : { *(.plt) }
.got : { *(.got.plt) *(.got) }
.init ALIGN(32 / 8) :
{
KEEP (*(.init))
}
.fini ALIGN(32 / 8) :
{
KEEP (*(.fini))
}
.preinit_array ALIGN(32 / 8) :
{
PROVIDE(__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE(__preinit_array_end = .);
}
.init_array ALIGN(32 / 8) :
{
PROVIDE(__init_array_start = .);
KEEP (*(.init_array*))
PROVIDE(__init_array_end = .);
}
.fini_array ALIGN(32 / 8) :
{
PROVIDE(__fini_array_start = .);
KEEP (*(.fini_array*))
PROVIDE(__fini_array_end = .);
}
.text ALIGN(32 / 8) :
{
*(.text .text.*)
}
.rodata ALIGN(32 / 8) :
{
*(.rodata .rodata.*)
}
.data ALIGN(32 / 8) :
{
*(.data .data.*)
}
.bss ALIGN(32 / 8) :
{
PROVIDE(__bss_start__ = .);
*(.bss .bss.*)
*(COMMON)
PROVIDE(__bss_end__ = .);
}
}
注意:在链接时对_printf_ 的引用设置为我的主程序的printf - 仅用于测试目的。
感谢您的帮助 :-)
【问题讨论】:
-
如果您还为 foo.c 和 shared.ld 提供(修剪过的)代码会有所帮助。
-
“如果没有 -mlong-calls 选项,我的 gcc 在 .plt 部分会生成无效的操作码……我做错了什么?” - 如果这在最近的 binutils 上重现,你应该file a bug。
-
我想知道您的工具链是否能够构建共享库。您能查看stackoverflow.com/questions/18586291/… 中的建议吗?
-
感谢您的链接。我的工具链是使用 --disable-shared 选项构建的,但目前我可以构建共享对象!?!?!???也许这可能是无效操作码的原因......
标签: gcc elf shared-objects cortex-m dynamic-loading