Why does clang create a linking problem when the symbols are present? - c

I have a strange linking problem. I have a bunch files that I am trying to compile, but I am running into an undefined symbol error. Below is the error:
clang U_outsup.o U_OUTSUR.o
Undefined symbols for architecture x86_64:
"U_outsup(surface*, __sFILE*)", referenced from:
U_outsur(surface*, char*) in U_OUTSUR.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
The same happens when I compile trying to with the source files to an out executable. If I look at those object files (clang -c U_outsup.c U_OUTSUR.C), I see the following:
U_outsup.o: file format Mach-O 64-bit x86-64
SYMBOL TABLE:
0000000000000420 l __DATA,__data _rname
0000000000000000 g F __TEXT,__text _U_outsup
0000000000000000 *UND* _A_extcpc
0000000000000000 *UND* _E_seterr
0000000000000000 *UND* _U_issurr
0000000000000000 *UND* _U_surbre
0000000000000000 *UND* _fprintf
U_OUTSUR.o: file format Mach-O 64-bit x86-64
SYMBOL TABLE:
0000000000000090 l __DATA,__data __ZL5rname
0000000000000000 g F __TEXT,__text __Z8U_outsurP7surfacePc
0000000000000000 *UND* __Z8E_seterrlPc
0000000000000000 *UND* __Z8U_outsupP7surfaceP7__sFILE
0000000000000000 *UND* _fclose
0000000000000000 *UND* _fopen
So, I am assuming the symbol "U_outsup(surface*, __sFILE*)" can't be found because it has a ridiculous name in the symbol table. Can anyone help me figure out what is going on here? Thanks again.

It doesn't have a ridiculous name. It has a c++ mangled name.
That means it was built with a c++ compiler and not a c one. Recompile the library with gcc or clang, not g++ or clang++.

Related

Why nm hides .rela.eh_frame and .rela.text in .o files?

I'm trying to recreate the behaviour of the command nm in C, and although I was successful getting the names of the symbols and sections, I find out that some extra names appear in my version.
$> ./my_nm -a obj.o
0000000000000000 b .bss
0000000000000000 n .comment
0000000000000000 d .data
0000000000000000 r .eh_frame
0000000000000000 n .note.GNU-stack
0000000000000000 r .note.gnu.property
0000000000000000 d .rela.eh_frame
0000000000000000 d .rela.text
0000000000000000 t .text
U _GLOBAL_OFFSET_TABLE_
0000000000000000 T elf64_syms
0000000000000000 a elf64_syms.c
U malloc
$> nm -a obj.o
0000000000000000 b .bss
0000000000000000 n .comment
0000000000000000 d .data
0000000000000000 r .eh_frame
0000000000000000 n .note.GNU-stack
0000000000000000 r .note.gnu.property
0000000000000000 t .text
U _GLOBAL_OFFSET_TABLE_
0000000000000000 T elf64_syms
0000000000000000 a elf64_syms.c
U malloc
I did some research about them and found that they are some sort of a reference to a section or symbol. I wonder if there is anything special about them. If so, how can I differentiate between them and other .rela...?
I find out that some extra names appear in my version.
The Linux nm version uses libbfd, which maps different object file formats into its own internal data model, and then nm prints that internal representation.
libbfd predates ELF by at least 2 decades, and its internal model is inadequate for representing complexities of the ELF format (things get lost in translation).
For this reason, one generally shouldn't use nm, objdump and other libbfd-based tools to examine ELF files (use readelf instead, which shows things as they are without translation losses).
So, you've done nothing wrong and your version of nm is better.

what does it mean that my static library symbols are defined with an address 0

I'm trying to componentize my build into multiple static libraries, and link them together into one shared library. I'm losing symbols from the final .so file. One strange behavior I noticed is that the symbols in one of the static libraries define a bunch of symbols with an address of 0. According to the nm man page T means that a symbol is defined and exported. What does address 0 mean if the symbols are defined?
0000000000000000 T _ZN16djinni_generated19NativeRendererStateC1Ev
0000000000000000 T _ZN16djinni_generated19NativeRendererStateC2Ev
0000000000000000 T _ZN16djinni_generated19NativeRendererStateD1Ev
0000000000000000 T _ZN16djinni_generated19NativeRendererStateD2Ev
0000000000000000 T _ZN16djinni_generated20NativePlatformObject5toCppEP7_JNIEnvP8_jobject
0000000000000000 T _ZN16djinni_generated20NativePlatformObject7fromCppEP7_JNIEnvRKNSt6__ndk110shared_ptrIN5ALYCE14PlatformObjectEEE
0000000000000000 T _ZN16djinni_generated20NativePlatformObjectC1Ev
0000000000000000 T _ZN16djinni_generated20NativePlatformObjectC2Ev
0000000000000000 T _ZN16djinni_generated20NativePlatformObjectD1Ev
0000000000000000 T _ZN16djinni_generated20NativePlatformObjectD2Ev

objdump format for a function written in C vs asm [duplicate]

When assembling an object using nasm, I'm finding that all labels are included as symbols in the resultant .o file, as well as the final binary.
This makes sense for function entry points that I've declared GLOBAL, and for section start parts (e.g., for the .text section), but it seems odd that labels simply used as loop entry points and such all near to appear in the output file. In addition to leaking internal implementation details, it wastes space in the symbol table.
For example, given this short assembly program:
GLOBAL _start
_start:
xor eax, eax
normal_label:
xor eax, eax
.local_label:
xor eax, eax
xor edi, edi
mov eax, 231 ; exit(0)
syscall
... built using:
nasm -f elf64 label-test.s
ld label-test.o -o label-test
Results in l (i.e., local) symbols in both the object file and linked executable:
objdump --syms label-test.o
label-test.o: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 label-test.s
0000000000000000 l d .text 0000000000000000 .text
0000000000000002 l .text 0000000000000000 normal_label
0000000000000004 l .text 0000000000000000 normal_label.local_label
0000000000000000 g .text 0000000000000000 _start
Note that both normal_label and the local label local_label ended up in the symbol table. All of them end up in the symbol table of the executable also.
I don't want to emit these symbols to the final executable. Can I tell nasm not to include them? There are some options I could pass to ld, such as --strip-all, which will remove those symbols, but also every other symbol in the executable. That makes it quite the cudgel: it eliminates the symbols I really want to keep for readable stack traces, debugging, etc.
FWIW, as mentioned by Peter Cordes, yasm doesn't have exactly the same issue. With an elf64 .o file built in exactly the same way as above (but with yasm substituted for nasm, we get:
objdump --syms label-test-yasm.o
label-test-yasm.o: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 label-test.s
0000000000000004 l .text 0000000000000000
0000000000000002 l .text 0000000000000000
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 g .text 0000000000000000 _start
The global _start label is still included, but the other two labels aren't named - they are still there though, they are the unnamed symbols at offset 4 and 2 (lines 2 and 3 in the list above). This is confirmed by adding more labels - more unnammed symbols are produced.
As far as I can tell, it's just a limitation in nasm. See for example this forum post where the poster has approximately the same issue (although 32-bit rather than 64-bit ELF), and no solution is provided other than using a stripping tool.
In my case, it seems stripping the object file like:
strip --discard-all label-test.o
should do the trick. Despite the name of the --discard-all option, it only strips local symbols and leaves global symbols alone. Here's the symbol table before stripping the file:
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 label-test.s
0000000000000000 l d .text 0000000000000000 .text
0000000000000002 l .text 0000000000000000 normal_label
0000000000000004 l .text 0000000000000000 normal_label.local_label
0000000000000000 g .text 0000000000000000 _start
and after:
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 label-test.s
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 g .text 0000000000000000 _start
Note in particular that it was smart enough to leave the .text section symbol alone, even though it is local. Of course this strip option can't really distinguish between useless (loop label) and potentially useful symbols, for example local function entry points which are needed to give correct stack traces with various tools.
If you wanted to be smarter about it, you could selectively strip only the asm-local (i.e., labels starting with a .) using the --wildcard and --strip-symbol options to selectively strip only labels with an embedded ..
I'm still looking for a better answer if one is lurking out there.
A little late, but I had this problem and wrote a patch for nasm 2.15 that fixes this. It adds a command-line switch called —discard-labels. You can get it here: https://forum.nasm.us/index.php?topic=2666.0

objdump -t /usr/bin/sort command shows no symbols

If I try objdump -t /usr/bin/sort command it says no symbols. But it seems to work on my programs. What is the reason for this?
The symbols of /usr/bin/sort has been removed, e.g. with the strip program - for most executables the symbol table is not needed (or only needed for debugging). Here is a bit more info.
As the other answer mentions, your sort binary most likely has its symbols stripped out. However there should still be some dynamic symbol information, which may still be useful for debugging. These are generally the names of functions called by the binary which were dynamically linked. This usually includes libc functions, along with any other lib*.so shared libraries that your binary may have been linked with.
To see these, just add the -T argument:
$ objdump -tT /bin/sort
/bin/sort: file format elf64-x86-64
SYMBOL TABLE:
no symbols
DYNAMIC SYMBOL TABLE:
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 fileno
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 dup2
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 strcoll
...
$

Mongo C driver: Dynamic Linking with undefined symbol giving runtime error

I am trying to use Mongo C driver in my application but stuck badly in a linking problem. MongoC drivers provides 4 objects (libbson.a + libbson.so + libmongoc.a + libmongoc.so). My Makefile has libraries added like this.
srv_la_LIBADD = -lrt -lcre2 -lre2 -lcurl -lpthread -lmongoc \
-lbson #MODULES_LIBADD#
The drivers is compiled and installed successfully at /usr/local/lib. I have even made links to these in /lib and /lib64 directories.
The problem is that my application gets compiled and linked correctly but the final srv.so contains UNDEFINED symbols from the mongo C driver which give runtime errors.
Error loading module srv.so:/usr/local/c_icap/lib/c_icap/srv.so: undefined symbol: mongo_cursor_set_query
The linker line from Make process is:
libtool: link: gcc -shared -fPIC -DPIC .libs/srv_la-srv.o
.libs/srv_la-erd.o
.libs/srv_la-erd_list.o
.libs/srv_la-str_util.o
.libs/srv_la-url_util.o
.libs/srv_la-easyzlib.o
.libs/srv_la-state_db.o
.libs/srv_la-data_access_api.o
.libs/srv_la-cJSON.o
.libs/srv_la-clib_es.o
-lrt -lcre2 -lre2 /usr/lib/x86_64-linux-gnu/libcurl.so
-lpthread -lmongoc -lbson -O2 -O2 -Wl,-soname -Wl
,srv.so -o .libs/srv.so
Specifically the objdump of the srv.so says:
root#talha:/webproxy# objdump -t services/.libs/srv.so|grep "mongo"
0000000000000000 *UND* 0000000000000000 mongo_cursor_set_query
0000000000000000 *UND* 0000000000000000 mongo_destroy
0000000000000000 *UND* 0000000000000000 mongo_cmd_authenticate
0000000000000000 *UND* 0000000000000000 mongo_create_index
0000000000000000 *UND* 0000000000000000 mongo_cursor_destroy
0000000000000000 *UND* 0000000000000000 mongo_update
0000000000000000 *UND* 0000000000000000 mongo_cursor_next
0000000000000000 *UND* 0000000000000000 mongo_cursor_init
0000000000000000 *UND* 0000000000000000 mongo_remove
0000000000000000 *UND* 0000000000000000 mongo_connect
0000000000000000 *UND* 0000000000000000 mongo_cursor_bson
Whereas the bson symbols are added correctly. This is strange as both the libs are installed at the same location and have been added in the Makefile.
I tried to link libmongoc.a(static) statically but that results in the linker giving a portability warning of srv.so linking against libmongoc.a and produces final srv.a instead of src.so(but this kind of makes sense). Even then, the symbols are not present in srv.a. Which is even more strange to me.
The mongo C driver was built with -fPIC flag so that part is catered. Any helpful hints?
Why is it not linking properly and why is the linker not giving any errors?

Resources