I have an .o
file compiled from a C project which references a function named init_static_pools
. I use objdump -t
to show its symbol dependency info:
00000000 UND 00000000 init_static_pools
According to this thread, the UND simply says "I need someone else to provide me that function".
So I linked this .o
file to an .elf
file, which contains the definition of init_static_pools
. The objdump -t
shows that the symbol is indeed in this file:
00004dcf g F .text 00000048 init_static_pools
According to this thread, the g
and F
flags mean it is a glbal function. I guess it means this function can be statically linked.
I tried to link the .o
file and the .elf
file with below command line:
/usr/bin/c++ -m32 -rdynamic unittest1.o -o unittest1 target.elf lib/libgtest.a lib/libgtest_main.a -lpthread
I got below error:
unittest1.cc:(.text+0x2d): undefined reference to `init_static_pools'
The function is just in the .so file, why it cannot be linked?
Could this be related to the different symbol resolving mechanisms between dynamic and static linking? Because I use objdump -f
and see that the target.elf
is a dynamic object. As shown below:
target.elf: file format elf32-i386
architecture: i386, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x00001144
Based on the comment by @EmployedRussian, I tried readelf
.
For the target.elf
, it only contains 1 line saying:
486: 00004dcf 72 FUNC GLOBAL DEFAULT 13 init_static_pools
For the unittest1.o
, it contains 2 lines saying:
0000002d 0000fb04 R_386_PLT32 00000000 init_static_pools
and
251: 00000000 0 NOTYPE GLOBAL DEFAULT UND init_static_pools
And for the completion, their headers are:
target.elf
:
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x1144
Start of program headers: 52 (bytes into file)
Start of section headers: 246936 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 9
Size of section headers: 40 (bytes)
Number of section headers: 43
Section header string table index: 42
unittest1.o
:
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 36988 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 262
Section header string table index: 261
So far, I cannot tell the root cause of the linkage failure yet. Luckily I just found the series on linker by the Ian Lance Taylor. Hope that can enlighten me. But it will take some time I guess.
Based on @EmployedRussian's reply, I tried below commands:
nm target.elf | grep init_static_pools
nm -D target.elf | grep init_static_pools
Just as @EmployedRussian suspected, the second command line doesn't have output. So that means target.elf is not exporting init_static_pools in its dynamic symbol table, and that makes the symbol not eligible for linking to from outside of target.elf.
Below are some flags related to the linking of the target.elf
:
-Wl,-T zephyr/linker.cmd (this is quite long, but it seems to be mostly layout info)
-Wl,-Map=target_prebuilt.map
-Wl,--whole-archive
-Wl,--gc-sections
-Wl,--build-id=none
-Wl,--sort-common=descending
-Wl,--sort-section=alignment
-ldl
-lm
Or should I check the compile flags as well?
And I found the --export-all-symbols, --export-dynamic, --gc-keep-exported options, I am trying them.
It seems the --export-all-symbols
is ignored. I guess it is meant for DLL.
I put --export-dynamic
and --gc-keep-exported
together, and the build can pass.
But the nm -D
still shows below message:
target.elf : no symbols
An article about dynamic symbol table (.dynsym) and symbol table(.symtab). https://blogs.oracle.com/solaris/inside-elf-symbol-tables-v2
Some quote:
In fact, in the days before sharable libraries and dynamic linking, none of it was needed at runtime. There was a single, non-allocable symbol table (reasonably named "symtab"). When dynamic linking was added to the system, the original designers faced a choice: Make the symtab allocable, or provide a second smaller allocable copy. The symbols needed at runtime are a small subset of the total, so a second symbol table saves virtual memory in the running process. This is an important consideration. Hence, a second symbol table was invented for dynamic linking, and consequently named "dynsym".
So, I think the .dynsym
is meant for dynamic linking at runtime. But I think I am expecting my unittest1.o
and target.elf
to be staticly linked at build time.
So it leads me to this question: Can I statically link to an .ELF
file? On Windows, I usually statically link to a .lib
file rather than a .DLL
file. The .ELF
file here looks more like a .DLL
. And btw, my build process also generate a libtarget.a
file. Should I use it instead of target.elf
?
Unfortunately, I tried nm -t
and readelf -s
on libtarget.a
, neither of them show the existence of init_static_pools
.
BTW, if you know something about my issue, feel free to drop some hint. Thanks!
For the target.elf, it only contains 1 line saying:
486: 00004dcf 72 FUNC GLOBAL DEFAULT 13 init_static_pools
Unfortunately, this still isn't sufficient to tell for sure what's happening.
To tell for sure, run these two commands:
nm target.elf | grep init_static_pools
nm -D target.elf | grep init_static_pools
I suspect that the first command would produce output, while the second one would not.
If that's the case, then target.elf
is not exporting init_static_pools
in its dynamic symbol table, and that makes the symbol not eligible for linking to from outside of target.elf
.
As to how you ended up with this symbol not exported, I can only guess (since you didn't provide the link command used to link it). You are likely using a linker script which hides it.
User contributions licensed under CC BY-SA 3.0