Use `ld -r` and get compilation errors if symbols are missing - c

I've recently begun using a new ELF loader. The loader requires you to link your applications with ld -r.
The problem is that GCC no longer warns me of undefined functions, and then the loader (obviously) fails to find them.
How do I link with ld -r, and get the undefined symbols method.
I am using ld -r for relocation purposes, so a different way to include relocations will also work for me.

In your makefile, define an intermediate target where you link with all the options but the -r one, to a file in the temporary directory (so you're sure not to use it).
If this phase succeeds, then proceed to the real link with the -r option.

Related

/usr/bin/ld: cannot find -l<name of the library> while compiling with gcc

I am writting an mqtt communication script where I am using the paho library.
the files .so exist in the /home/chaima/paho.mqtt.c/build/output directory.
but when trying to compile the code using the gcc compiler, I am getting this error
/usr/bin/ld: cannot find -l/home/chaima/paho.mqtt.c/build/output
I've tried so many solutions but none of them worked for me.
please if you need further information let me know about it.
Thank you in advance.
The -l switch asks the linker to use a certain library. It should followed by the name of a library or a file system path to the library.
/home/chaima/paho.mqtt.c/build/output is a path to a directory, not a library.
The -L switch tells the linker to use a certain directory as a place to look in for libraries. After -L/A/B/C and -L/D/E/F, the linker will look in the directories /A/B/C and /D/E/F for libraries. For example, with -L/A/B/C -L/D/E/F -l foo, the linker will look for a file named /A/B/C/foo.extension and /A/B/C/foo.extension, where extension is one of the file name extensions used for libraries, such as a or so in foo.a or foo.so.
To get the linker to use your libraries in /home/chaima/paho.mqtt.c/build/output, use -L/home/chaima/paho.mqtt.c/build/output followed by -lName0 -lName1 -lName2 …, where Name0, Name1, Name2, and such are the names of your libraries. You an also ask the linker to use a library by giving its full path and name with no switch, as in /home/chaima/paho.mqtt.c/build/output/foo.so.
Both the ld command (to invoke the linker directly) and the gcc command (an overall command that will compile, link, and perform other tasks) accept these switches. In the future, read the manual page (also called the “man page”) or other documentation of the tools use use. The man page for ld explains what its -l and -L switches do. On Unix systems, you can usually see the man page for ld by executing man ld and the man page for gcc by executing man gcc. The current GCC documentation is also here.

(Cygwin) C program linked to custom header file having memory problems when trying to execute

I am using Cygwin. I have two files in the same directory, test.c and iah202_graphics.h. test.c uses functions from the header file, where I have used #include "iah202_graphics.h". I have added the Cygwin directory to my Environment Variables (PATH) already.
However I receive these errors for every function call:
$ gcc -o test test.c
/cygdrive/c/Users/Matthew/AppData/Local/Temp/cclm2bNk.o:test.c:(.text+0x27): undefined reference to `draw_line'.
/cygdrive/c/Users/Matthew/AppData/Local/Temp/cclm2bNk.o:test.c:(.text+0x27): relocation truncated to fit:
R_X86_64_PC32 against undefined symbol `draw_line'.
/cygdrive/c/Users/Matthew/AppData/Local/Temp/cclm2bNk.o:test.c:(.text+0x4a): undefined reference to
`draw_line'.
collect2: error: ld returned 1 exit status.
It's having trouble linking to the header file even though I've simply stated which file to use in the local directory. I don't understand what I'm doing wrong?
Undefined reference to 'blah' is a linker error rather than a compiler error and is almost always caused by not including a needed library.
Including a header file in your source file does not usually link in the code required to provided the functions declared in that header.
For example, were you to prevent linking of the C runtime library, you could include stdio.h as many times as you wanted to, and still not be able to resolve printf.
Bottom line, you generally need two steps:
include the relevant header file in your source code so it knows about the declarations of things provided; and
link against the relevant library or object file so it has access to the definitions of the things provided.
That could be something as simple as:
gcc -o test -I/path/to/iah202includes test.c -L/path/to/iah202libs -liah202
where -I indicates where include files can be found, -L adjusts the search path for library files, and -l actually specifies the library file to use.
Even simpler is if you have the source file for the graphics stuff (which seems to be the case based on your comments). In that case no library is needed, you can simply use:
gcc -o test test.c iab202_graphics.c
and that will compile both those translation units then link them together.

proj.c:(.text+0x140): undefined reference to `pcap_open_offline'

I'm trying to use pcap functions, but it giving me compiler error:
project.c:(.text+0x140): undefined reference to `pcap_open_offline'
I have installed library and while compiling I give "-lpcap" at the and as it advised in many forums.
What can be wrong, please?
You need to understand what the arguments evoke into the linker.
I am supposing you are using Linux system with gcc, using ld as linker (note that this could change depending on the system and the linker used).
In such case, -Lpath tell the linker where to look for the libraries that you tell it that are needed to be linked with your program to create the final binary. For example -L/usr/lib.
when you type in for example:
# gcc -L/usr/lib -lcap my_program.c -o my_program
You are telling the linker to append /usr/lib to the list of paths to locate libraries, and to link the dynamic library "libcap.so" with your program.
Other modifiers for the path used to locate libraries is LD_LIBRAY_PATH (the name of this environment variable could change from one system to another, review the manual of your linker).
As you are using "-lcap" the error you get look to be related with the fact that no path is found where libcap.so exist. Locate that file into your system and pass the argument
-L/path/to/the/directory/that/contain/libcap.so
By the way, try to run this before any other thing and recompile:
# sudo ldconfig

cannot find library error when using gcc

I am trying to compile an example C program and link it to some static library files using:
gcc -I /usr/local/include -L /usr/local/lib -l libsundials_cvode.a -l libsundials_nvecserial.a cvRoberts_dns.c -o cvRoberts_dns.o
(I am sure that the library files and include files directories above are correct.)
The error I get is:
/usr/bin/ld: cannot find -llibsundials_cvode.a
collect2: ld returned 1 exit status
I have two questions:
1) Am using the -L and -l options correctly?
2) The above error is b/c gcc is looking for the library file in the wrong location right? I tried to fix this by setting $LD_LOAD_PATH via my terminal to /usr/local/bin. I still get the above error. How do I fix this?
Thanks!
-Rohan.
Try -lsundials_cvode instead - delete the 'lib' and '.a' parts
Note that LD_LOAD_PATH is for locating dynamic libraries at run-time, not during compilation.
Edit:
I just tried that. The change addresses the cannot find library error but
now I am faced with many "undefined reference to" errors. Does this mean
the linking of the library files has failed somehow? How do I correct this?
It means that there are other symbols that need to be resolved that are not in the library you linked. Note that you need to change both libraries (you have two on the command line). Also perhaps they are in the wrong order.

How are newlibc stubs supposed to be included/linked into one's code

During my project's linking process the linker fails with the following errors unless I make an explicit call in my code to one of of the stub functions (i.e. _sbrk):
c:/toolchains/yagarto/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libg.a(lib_a-abort.o): In function `abort':
C:\msys\1.0\home\yagarto\newlib-build\arm-none-eabi\newlib\libc\stdlib/../../../../../newlib-1.19.0/newlib/libc/stdlib/abort.c:63: undefined reference to `_exit'
c:/toolchains/yagarto/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libg.a(lib_a-signalr.o): In function `_kill_r':
C:\msys\1.0\home\yagarto\newlib-build\arm-none-eabi\newlib\libc\reent/../../../../../newlib-1.19.0/newlib/libc/reent/signalr.c:61: undefined reference to `_kill'
c:/toolchains/yagarto/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libg.a(lib_a-signalr.o): In function `_getpid_r':
C:\msys\1.0\home\yagarto\newlib-build\arm-none-eabi\newlib\libc\reent/../../../../../newlib-1.19.0/newlib/libc/reent/signalr.c:96: undefined reference to `_getpid'
c:/toolchains/yagarto/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libg.a(lib_a-sbrkr.o): In function `_sbrk_r':
C:\msys\1.0\home\yagarto\newlib-build\arm-none-eabi\newlib\libc\reent/../../../../../newlib-1.19.0/newlib/libc/reent/sbrkr.c:60: undefined reference to `_sbrk'
collect2: ld returned 1 exit status
I am aware that I need some stubs functions that newlibc requires and I have a "C" file that contains all of the ones mentioned above as missing and I am also positive that the file is being compiled and added to an archive file (*.a) that is later linked.
I am calling the linker using the following commands
arm-none-eabi-gcc -L -T linkerscript.ld -nostartfiles -Wl,-Map,$(TARGET).map -lc archive.a
My question is simple (I hope) How can I make sure that the linker links my stub functions into the elf file without having to make an explicit function call from one of my project files?
I think those errors you're getting refer to the linker not being able to find the appropriate library. My first suspicion is in how you're using your arguments, specifically your specification of archive directory (-L) and the archive.a file. I'm thinking it should go like this:
arm-none-eabi-gcc -L. -T linkerscript.ld -nostartfiles -Wl,-Map,$(TARGET).map -lc -larchive
where the changes I'd make are:
-L. means use the current directory to look for library files to link.
-lc specifies to use the archive file libc.a.
-larchive specifies to use the archive file libarchive.a.
For more info I'd suggest checking out theGNU GCC reference.
Pass --verbose to gcc to see exactly where archive.a is showing up in the list of libraries and objects passed to the linker.
You need to arrange things so that archive.a is searched after libg.a since that's the archive that contains the objects that end up with undefined references.
You might be able to fix this by adding -lg before archive.a on the gcc command line.
-lg should in libg.a earlier than where it's getting pulled in now by default and more importantly pull it in before archive.a.

Resources