Seeing where symbols are looked up, during gcc linking? - c

I have just seen this post: How to tell where the symbols are defined when linking C code ; and tried to run that approach (that is, I tried to look up via -Wl,-trace-symbol=foo during the linking command) on my code, which suffers from undefined reference - but the output is not much different from what is given as an example in that post:
/usr/bin/ld: main.o: reference to foo
/usr/bin/ld: ./libfoo.a(foo.o): definition of foo
/usr/bin/ld: ./libfoo.a(foo.o): reference to fputs
/usr/bin/ld: //lib/x86_64-linux-gnu/libc.so.6: definition of fputs
The thing is, I've manually added both -L and -l specifications to my command line, which I expect should pass - but they do not.
So what I am ultimately looking for, is a way to generate a log, that tells me, say:
/usr/bin/ld: main.o: reference to foo
/usr/bin/ld: ./libyoo.a(yooA.o): symbol foo looked up, not found
/usr/bin/ld: ./libyoo.a(yooB.o): symbol foo looked up, not found
/usr/bin/ld: ./libfoo.a(foo.o): definition of foo
... which, I hope, will make me understand a bit easier, which include and linker flag directories and files end up being scanned.
Is there a way to generate a log like this?

Related

How can I cross-compile for Solaris with cgo?

I am trying to compile some cgo code for Solaris. I get these errors when I try to build:
$ CGO_LDFLAGS="-L$(pwd)/solaris-11.4-amd64-libs" CGO_CFLAGS='-I/home/shane/src/ioctl-experimentation/solaris-11.4-headers -Wno-unknown-pragmas' CGO_ENABLED=1 GOOS=solaris GOARCH=amd64 go build
# runtime/cgo
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x16): undefined reference to `__libc_csu_fini'
/usr/bin/ld: (.text+0x1d): undefined reference to `__libc_csu_init'
/usr/bin/ld: (.text+0x2a): undefined reference to `__libc_start_main'
/usr/bin/ld: $WORK/b003/_x003.o: in function `_cgo_release_context':
gcc_context.c:(.text+0x5c): undefined reference to `__stack_chk_fail'
/usr/bin/ld: $WORK/b003/_x004.o: in function `x_cgo_sys_thread_create':
gcc_libinit.c:(.text+0x87): undefined reference to `__stack_chk_fail'
/usr/bin/ld: $WORK/b003/_x004.o: in function `_cgo_wait_runtime_init_done':
gcc_libinit.c:(.text+0x121): undefined reference to `__stack_chk_fail'
/usr/bin/ld: $WORK/b003/_x004.o: in function `_cgo_try_pthread_create':
gcc_libinit.c:(.text+0x291): undefined reference to `__stack_chk_fail'
/usr/bin/ld: $WORK/b003/_x006.o: in function `x_cgo_init':
gcc_solaris_amd64.c:(.text+0xb6): undefined reference to `__stack_chk_fail'
/usr/bin/ld: $WORK/b003/_x006.o:gcc_solaris_amd64.c:(.text+0x214): more undefined references to `__stack_chk_fail' follow
collect2: error: ld returned 1 exit status
I am cross-compiling on Linux. Here is my Go version:
$ go version
go version go1.18.3 linux/amd64
The solaris-11.4-amd64-libs directory contains a copy of all files under /lib/amd64 from a Solaris 11.4 AMD64 machine. The solaris-11.4-headers directory contains a copy of all files under /usr/include from a Solaris 11.4 AMD64 machine.
Here is my Go code in main.go:
//go:build solaris
// +build solaris
package main
import "C"
func main() {
}
I know cgo is fully supported for Solaris as of Go 1.5, and I am using Go 1.18.
I'm looking for help understanding why these linker errors are happening, even when I copied across all libs from the /lib/amd64 directory. Is it possible there are more libs I also need to copy over from somewhere else?
Edit
At the suggestion of Liam Kelly, I looked at this question about how to link against a different libc. I tried passing -Xlinker -rpath=$(pwd)/solaris-11.4-amd64-libs as part of CGO_LDFLAGS, but I got the same errors as before. I tried using -nodefaultlibs and -nostdlib both separately and together along with -Xlinker -rpath=$(pwd)/solaris-11.4-amd64-libs, but using either of these two flags either separately or together just increased the number of linker errors.
I am going to assume that libxnet is needed for Solaris and that is why is is being automatically added.
First confirm that the libxnet library is where is should be with sudo find /lib libxnet*. I expect you will see one line of the output show:
lib/64/libxnet.so
Assuming you see the above output, I believe you just need to tell the linker to look in that location with CGO_LDFLAGS="-L/lib/64" CGO_ENABLED=1 GOOS=solaris GOARCH=amd64 go build. If that works then you should be able to embedded that LDFlag in your main.go file with:
// #cgo LDFLAGS: -L/lib/64
import "C"
Once embedded you will not need to explicitly set CGO_LDFLAGS

multiple definition in C project

I have a problem with this project (it is a minigame similar to space invaders).
Every time I try to compile it it gives me these errors:
❯ make
gcc main.o collisioni.o stampa.o gestione.o -o progetto -lncurses
/usr/bin/ld: collisioni.o:(.bss+0x0): multiple definition of `maxx'; main.o:(.bss+0x0): first defined here
/usr/bin/ld: collisioni.o:(.bss+0x4): multiple definition of `maxy'; main.o:(.bss+0x4): first defined here
/usr/bin/ld: collisioni.o:(.bss+0x8): multiple definition of `flag_navicelle'; main.o:(.bss+0x8): first defined here
/usr/bin/ld: stampa.o:(.bss+0x0): multiple definition of `maxx'; main.o:(.bss+0x0): first defined here
/usr/bin/ld: stampa.o:(.bss+0x4): multiple definition of `maxy'; main.o:(.bss+0x4): first defined here
/usr/bin/ld: stampa.o:(.bss+0x8): multiple definition of `flag_navicelle'; main.o:(.bss+0x8): first defined here
/usr/bin/ld: gestione.o:(.bss+0x0): multiple definition of `maxx'; main.o:(.bss+0x0): first defined here
/usr/bin/ld: gestione.o:(.bss+0x4): multiple definition of `maxy'; main.o:(.bss+0x4): first defined here
collect2: error: ld returned 1 exit status
make: *** [makefile:2: progetto] Errore 1
The source code of the project is this: https://github.com/Stenafo/game
I compile the code using the makefile.
I don't understand where the problem is, a friend of mine manages to compile it without errors.
This project uses processes, however I have the same problem with threads.

understanding compilation commands C and configuring CodeBlocks

I'm learning C in college. And I wanted to try new things, so I decided to use the allegro Game library to create some stuff. I followed the tutorial, and everything went fine. I wrote a piece of code in the text editor and executed the commands provided by the tutorial and it compiled and run. (I'm on linux btw).
These are the commands:
gcc hello.c -o hello $(pkg-config allegro-5 allegro_font-5 --libs --cflags)
./hello
So, I understand that gcc is calling the gcc compiler and hello.c is the name of the source code file and -o hello specifies the name of the compiled file. but the next part is ambiguous and beyond my knowledge:
$(pkg-config allegro-5 allegro_font-5 --libs --cflags)
So can anyone explain what it means (it has something to do with linking). and if I remove that part the compiler returns these error codes:
/usr/bin/ld: /tmp/ccIQsEis.o: in function `main':
hello.c:(.text+0x2f): undefined reference to `al_install_system'
/usr/bin/ld: hello.c:(.text+0x34): undefined reference to `al_install_keyboard'
/usr/bin/ld: hello.c:(.text+0x45): undefined reference to `al_create_timer'
/usr/bin/ld: hello.c:(.text+0x4e): undefined reference to `al_create_event_queue'
/usr/bin/ld: hello.c:(.text+0x61): undefined reference to `al_create_display'
/usr/bin/ld: hello.c:(.text+0x6a): undefined reference to `al_create_builtin_font'
/usr/bin/ld: hello.c:(.text+0x73): undefined reference to `al_get_keyboard_event_source'
/usr/bin/ld: hello.c:(.text+0x85): undefined reference to `al_register_event_source'
/usr/bin/ld: hello.c:(.text+0x91): undefined reference to `al_get_display_event_source'
/usr/bin/ld: hello.c:(.text+0xa3): undefined reference to `al_register_event_source'
/usr/bin/ld: hello.c:(.text+0xaf): undefined reference to `al_get_timer_event_source'
/usr/bin/ld: hello.c:(.text+0xc1): undefined reference to `al_register_event_source'
/usr/bin/ld: hello.c:(.text+0xd4): undefined reference to `al_start_timer'
/usr/bin/ld: hello.c:(.text+0xe7): undefined reference to `al_wait_for_event'
/usr/bin/ld: hello.c:(.text+0x125): undefined reference to `al_is_event_queue_empty'
/usr/bin/ld: hello.c:(.text+0x13d): undefined reference to `al_map_rgb'
/usr/bin/ld: hello.c:(.text+0x16a): undefined reference to `al_clear_to_color'
/usr/bin/ld: hello.c:(.text+0x17e): undefined reference to `al_map_rgb'
/usr/bin/ld: hello.c:(.text+0x1ca): undefined reference to `al_draw_text'
/usr/bin/ld: hello.c:(.text+0x1cf): undefined reference to `al_flip_display'
/usr/bin/ld: hello.c:(.text+0x1e7): undefined reference to `al_destroy_font'
/usr/bin/ld: hello.c:(.text+0x1f3): undefined reference to `al_destroy_display'
/usr/bin/ld: hello.c:(.text+0x1ff): undefined reference to `al_destroy_timer'
/usr/bin/ld: hello.c:(.text+0x20b): undefined reference to `al_destroy_event_queue'
collect2: error: ld returned 1 exit status
And for the second part of the question, I tried to compile this code in code:blocks but it returns the same errors given by the compiler without the term: $(pkg-config allegro-5 allegro_font-5 --libs --cflags)
So, what configuration should I change in codeblocks so that it compiles well code using allegro libraries.
PS. I didn't include the source code intentionally as it adds no useful information to the question, only clutters it.
This is a Bash command-syntax feature which executes another command and then provides its output as a string. This idiom is being used here to programmatically provide command-line parameters to the gcc command. The pkg-config command is being executed, and it returns a string which becomes part of – is textually included in – the command-string for invoking gcc. (Which of course neither knows nor cares where its command-line parameters "come from.")
(Clever, huh?)
For example, try this:
echo $(ls)
You will be rewarded with a list of all the files in the current directory, concatenated as a string.
To elaborate on the answer by #Mike Robinson,
$(pkg-config allegro-5 allegro_font-5 --libs --cflags) will execute the command pkg-config and substitute the result. pkg-config is build utility that helps when compiling C programs. It's not specific to allegro, it is used by many C libraries.
In this particular case, pkg-config is called with the parameters allegro-5 allegro_font-5 --libs --cflags, which asks pkg-config "what are the compiler options (--cflags) and libraries (--libs) I need when compiling and linking with allegro?" Allegro consists of several modules, in this case you chose the main module 'allegro' and the font module 'allegro_font'. In both cases you're referring to major version 5 of allegro.
On your system, the result of the command is -I/usr/include/x86_64-linux-gnu -lallegro_font -lallegro. The meaning of these options is as follows:
-I/usr/include/x86_64-linux-gnu tells the compiler to add the path /usr/include/x86_64-linux-gnu to the header search path (because the allegro headers are located there)
-lallegro_font and '-lallegro` tells the linker to add the allegro_font and allegro libraries respectively. That also explains why you get all those undefined reference errors when you remove this - you are no longer telling the linker to add the allegro library, so it can't find all those functions anymore.

Undefined reference to a function, linker error

This is a rookie question and I might be doing something stupid, but I wrote a C program that includes two non default libraries: curl and libxml2. I am trying to go through the compilation process in detail to learn the process and statically link the libraries. These are the steps I took:
Downloaded libxml2 and curl and compiled it with the included makefile and did the following:
ar rcs libcurl.a /home/${USER}/Desktop/Curl/curl-7.73.0/lib/*.o
ar rcs libxml2.a /home/${USER}/Desktop/xml2/libxml2-2.7.2/*.o
Even though I only use a few functions from those libraries I packed all together in case they needed each other, or at least I think that's how it works. I copied the generated arhive library to a separate location and lastly I did:
cp ~/Desktop/libxml2-2.7.2/libxml2.a ~/Desktop/libs/
cp ~/Desktop/Curl/curl-7.73.0/lib/libxml2.a ~/Desktop/libs/
gcc WolframParser.c -I/home/${USER}/Desktop/Curl/curl-7.73.0/include/ -I/home/${USER}/Desktop/libxml2-2.7.2/include/ -L/home/${USER}/Desktop/libs/ -lcurl -lxml2 -lm
The linker reports a bunch of errors of undefined references, the likes of:
/usr/bin/ld: /home/${USER}/Desktop/libs//libcurl.a(libcurl_la-multi.o): in function `multi_getsock':
multi.c:(.text+0x18e): undefined reference to `Curl_ssl_getsock'
/usr/bin/ld: /home/${USER}/Desktop/libs//libcurl.a(libcurl_la-easy.o): in function `curl_global_init':
easy.c:(.text+0x172): undefined reference to `Curl_ssl_init'
/usr/bin/ld: /home/${USER}/Desktop/libs//libcurl.a(libcurl_la-easy.o): in function `curl_global_init_mem':
easy.c:(.text+0x22e): undefined reference to `Curl_ssl_init'
/usr/bin/ld: /home/${USER}/Desktop/libs//libcurl.a(libcurl_la-easy.o): in function `curl_global_cleanup':
easy.c:(.text+0x295): undefined reference to `Curl_ssl_cleanup'
. . .
Can someone please point out what I did wrong, and can this be done like this at all?

C access symbol in executable (linux)

I have an executable binary with many symbols. I am trying to figure out how to access those symbols in my code. dbg can so I know its possible im just not sure how. I cannot create a shared object from it with "gcc -shared -o myexe.so myexe" because there are multiple definitions of the same function
...(.data+0x8e8): first defined here
/usr/bin/ld: warning: Cannot create .eh_frame_hdr section, --eh-frame-hdr ignored.
/usr/bin/ld: error in fipstest(.eh_frame); no .eh_frame_hdr table will be created.
/usr/bin/ld: fipsttest.so: No symbol version section for versioned symbol `NSSUTIL_ArgGetLabel##NSSUTIL_3.14'
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status
This means that gcc cannot link to it during compile time with -L because the of the same issue.
the nm command shows all the symbols and the one I want. If I could modify the symbol table to remove all the exports but the ONE I need then it might work but I can't find how to do that. Or if anyone could point me in the right direction to access a binary during runtime and load a function with a physical address that would work too. Any help is appreciated. Thank you.

Resources