gcc/ld: undefined reference to unused function - gcc

I'm using gcc 4.3.4 and ld 2.20.51 in Cygwin under Windows 7. Here's a simplified version of my problem:
foo.o contains function foo_bar() which calls bar() in bar.o
bar.o contains function bar()
main.c calls functions in foo.o, but foo_bar() is not in the call chain
If I try to compile main.c and link it to foo.o, I get an undefined reference to _foo_bar error from ld. As you can see from my Makefile except below, I've tried using flags for putting each function in its own section and having the linker discard unused sections.
COMPILE_CYGWIN = gcc -iquote$(INCDIR)
COMPILE = $(COMPILE_CYGWIN) -g -MMD -MP -Wall -ffunction-sections -Wl,-gc-sections $(DEFINE)
main_OBJECTS = main.o foo.o
main.exe : $(main_OBJECTS)
$(COMPILE) -o main.exe $(main_OBJECTS)
The function foo_bar() is a short function that provides a connection between two networking layers in a protocol stack. Some programs don't need it, so they won't link in the other object files related to the upper layer of the stack. It's a small function, and seems inappropriate to put it into its own .o file.
I don't understand why ld throws the error -- nothing is calling foo_bar(), so there's no need to include bar() in the final executable. A coworker has just told me that ld is not a "smart linker", so maybe what I'm trying to do isn't possible?

Unless the linker is from Cyberdyne Systems it has no way to know exactly which functions will actually be called. It only knows which ones are referenced. Even Skynet's linker can't predict what run-time decisions will be made or what will happen if you load a module dynamically at run-time and it starts calling various global functions1.
So, if you link in module m and it references function f, you will need to link with whatever module has f.
1. This problem is related to the Halting Problem and has been proven undecidable.

I hit the similar issue and I find this page:
http://lists.gnu.org/archive/html/bug-gnu-utils/2004-09/msg00098.html
Highligt:
The GNU linker still works at .o file granularity.
Gcc pulls in foo.o and then find bar() was undefined.
You'd better put foo_bar() into another .o file.

Related

LD: does --export-dynamic imply --whole-archive for a static lib if any of it's symbols are referenced?

My main executable links with a static library whose symbols need to be available for dynamic libraries loaded through dlopen(). I understand that I need to use -Wl,--export-dynamic,--whole-archive flags to make it work. However there are many libraries specified on the link command, some maybe unused, and I'm having difficulties applying --whole-archive selectively to the needed library through cmake within the current build infrastructure. What I'm seeing is that if only -Wl,--export-dynamic is used and the executable calls a function in the static library of interest, then the whole library gets included to the same effect of specifying --whole-archive for it, which is exactly what I need. Can I rely on this behavior to implicitly impose --whole-archive on libs whose symbols are referenced by the executable?
What I'm seeing is that if only -Wl,--export-dynamic is used and the executable calls a function in the static library of interest, then the whole library gets included to the same effect of specifying --whole-archive for it, which is exactly what I need.
This isn't supposed to happen, and it is very likely that you are mis-interpreting what you see.
Example:
// foo.c
int foo() { return 42; }
// bar.c
int bar() { return 24; }
// main.c
int main() { return foo() - 42; }
gcc -w -c foo.c bar.c main.c
ar ruv libfoobar.a foo.o bar.o
gcc -Wl,--export-dynamic main.o -L. -lfoobar
nm a.out | egrep ' (foo|bar)'
000000000000113c T foo
As you can see, the whole libfoobar.a was not included in the executable. Contrast with:
gcc -Wl,--export-dynamic main.o -L. -Wl,--whole-archive -lfoobar -Wl,--no-whole-archive
nm a.out | egrep ' (foo|bar)'
0000000000001147 T bar
000000000000113c T foo
Update:
if I add a function foo1() to foo.c it is pulled in, but it also happens regardless if --export-dynamic is supplied.
That is expected: the linker doesn't "split" a single .o file -- you get all or nothing.
You can change this behavior by using -ffunction-sections (and -fdata-sections for a good measure) at compile time and -Wl,--gc-sections at link time.
The cost is increased .o size and longer link time. The benefit is smaller executable.

Cannot pass flags to Makefile to compile my code

I have a project that basically compiles from the command line in the following form:
g++ -o stack_raster stack_raster.cpp -lgdal -lboost_filesystem -lboost_system
I made a Makefile, and this is the content:
CXX =g++
LDDFLAGS = -lgdal -lboost_system -lboost_filesystem
all: clean stack_raster
clean:
rm -f stack_raster
However I got a collect2: error: ld returned 1 exit status.
A second variation of my Makefile I tried was:
CXX = g++
CPPFLAGS = -lgdal -lboost_system -lboost_filesystem
all: clean stack_raster
clean:
rem -f stack_raster
but I still receive the following message (even though the compile flags appear as they should for my program to compile successfully).
collect2: error: ld returned 1 exit status
<builtin>: recipe for target `stack_raster` failed
make: *** [stack_raster] Error 1
Does anyone could help me with a reference or hint about my problem, and how could I tackle it?
Does anyone could help me with a reference or hint about my problem, and how could I tackle it?
To begin with, you should have a look at the actual link command that make executed. It should have been echoed to make's output just before the error message from collect2. Understanding what's wrong with the command is the first step in determining how to fix your makefile.
In the first case, the command is probably something like
g++ stack_raster.cpp -o stack_raster
In the second, it is probably something like
g++ -lgdal -lboost_system -lboost_filesystem stack_raster.cpp -o stack_raster
The latter is probably also very similar to what you would get with the first makefile if you corrected the spelling of LDDFLAGS to LDFLAGS.
You will note that the library flags come in a different place in that command than they do in your manual command, and I assume you know that the order of objects and library flags on the linker command line is significant to Unix-style linkers such as GNU's (which is the one that the g++ driver will use).
You can certainly fix this by writing an explicit rule, as you describe in your own answer, but your makes' built-in rules may be up to the task, too. If you are using GNU make then they certainly are. For this purpose it is useful to know what the built-in rules actually are, and essential to know what the variables on which these rules depend mean.
Specifically,
LDFLAGS provides options to pass when invoking the linker, and conventionally, they appear on the command line before the objects being linked. As a result, this variable typically is not appropriate for specifying libraries (but it is fine for other link-specific options, such as -L to add directories to the library search path).
CPPFLAGS provides options for modulating the behavior of the C preprocessor (including when compiling C++). These do not typically appear at all in link(-only) commands executed by make, but they will appear (early) in commands for compiling object files from C or C++ sources, and in rules for building executables directly from C or C++ sources.
Neither of those is what you want, but if you are using GNU make, then its documentation for the former explicitly tells you what (with that make implementation) you should do instead:
Extra flags to give to compilers when they are supposed to invoke the
linker, ‘ld’, such as -L. Libraries (-lfoo) should be added to the
LDLIBS variable instead.
(emphasis added)
In GNU make, and perhaps some others, the LDLIBS variable serves exactly the purpose you need: to specify the libraries to link. These will appear at the end of the link command line from built-in rules, as you can confirm from GNU make's catalog of implicit rules, or from the list obtainable by running make -p in a directory containing no makefile.
So, with GNU make you can get the build you seem to want from the built-in rules, with this:
CXX = g++
LDLIBS = -lgdal -lboost_system -lboost_filesystem
all: clean stack_raster
clean:
rm -f stack_raster
In closing, I note that cleaning before building by default, as your examples do and mine imitates, largely defeats the purpose of using make instead of a simple script. Part of the point of make is to do the minimum work necessary, and if your target executable is present and not out of date with respect to its sources then there is no reason to force it to be rebuilt.
Check out the answer:
Set up my makefile to compile C with just "make"
YOu have to specify in the Makefile the file you want to create in this case stack_raster.exe and the objective file in this case stack_raster.cpp and specify the command line arguments you normally pass for compiling. So the Makefile would be something like:
CXX=g++
stack_raster.exe: stack_raster.cpp
g++ -o stack_raster.exe stack_raster.cpp -lgdal -lboost_filesystem -lboost_system
all: clean stack_raster.exe
clean:
rm -f stack_raster.exe

gcc - linker error that makes no sense

Using the Makefile provided by the Pi GPIO library, I made the libpigpio.so shard object using:
# from line 119 in make file
make libpigpio.so
The shared object is created fine. The Makefile first created the pigpio.o object, then the command.o object, and links them together as a shared object. So far so good!
I wrote a very small main function that calls the gpioInitialise and gpioGetPWMfrequency.
It doesn't really matter which functions, what's important is they are defined in pigpio.h and written in pigpio.c.
Meaning the shared object should have them.
The compile command for my code is:
gcc -Wall -pthread -fpic -L. -lpigpio -o drive drive.c
Still I get the undefined reference error to both those functions.
It makes no sense! If it didn't find the shared object, it would reject the command. I also tried it -l:libpigpio.so and still the same problem.
I am compiling directly on the Rpi A+ (not using a cross compiler). So it should work!
What am I missing here?
It is a link order question. Please try the flowing command.
gcc drive.c -Wall -pthread -fpic -o drive -L. -lpigpio
you can read Why does the order in which libraries are linked sometimes cause errors in GCC? for more details.

GCC - how to tell linker not to skip unused sections

My problem is following:
I am trying to write embedded application, which must have it's own linker script supplied (using arm-none-eabi-gcc compiler/linker).
embedded bootloader loads binary and starts at 0x8000 address, this is why I need a dedicated linker script, which allows me to put desired startup function into this address. Script's code is following:
MEMORY
{
ram : ORIGIN = 0x8000, LENGTH = 0x1000
}
SECTIONS
{
.start : { *(.start) } > ram
.text : { *(.text*) } > ram
.bss : { *(.bss*) } > ram
}
Having this what I want to do now is to have a function, that will be inserted into .start section, so that it's at the beginning of 0x8000. For this in my library I use following function:
__attribute__((section(".start"))) void notmain() {
main();
}
This seems to be working fine, but later I link this library with function notmain with the project, which defines main() function. During the link process I can see .start section no more exists and notmain symbol
is totally missing. When I move notmain function out of the library (into the project) its'all fine.
My understanding is, that linker sees, that .start section is not used at all in my Application, which makes it skip all the sections. I already tried adding several attributes to function notmain such as (__attribute__((used)) __attribute__((externally_visible))) but it did not work too (notmain is still missing from the final binary).
CMake source code is following:
** Project **
project(AutomaticsControlExample)
enable_language(ASM)
set(CMAKE_CXX_STANDARD 14)
set(SOURCES main.cpp PID.hpp)
set(DEPENDENCIES RPIRuntime PiOS)
add_executable(${PROJECT_NAME} ${SOURCES})
target_link_libraries(${PROJECT_NAME} ${DEPENDENCIES})
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_OBJDUMP} -D ${PROJECT_NAME}
COMMAND ${CMAKE_OBJDUMP} -D ${PROJECT_NAME} > ${PROJECT_NAME}.list
COMMAND ${CMAKE_OBJCOPY} ${PROJECT_NAME} -O binary ${PROJECT_NAME}.bin
COMMAND ${CMAKE_OBJCOPY} ${PROJECT_NAME} -O ihex ${PROJECT_NAME}.hex)
** Library **
project(RPIRuntime)
enable_language(ASM)
set(CMAKE_CXX_STANDARD 14)
set(LINKER_SCRIPT memmap)
set(LINKER_FLAGS "-T ${CMAKE_CURRENT_SOURCE_DIR}/${LINKER_SCRIPT}")
set(SOURCES
notmain.cpp
assert.cpp)
add_library(${PROJECT_NAME} STATIC ${SOURCES})
target_link_libraries(${PROJECT_NAME} ${LINKER_FLAGS})
My question is: is there any way to prevent linker from omitting linking .start section?
As you know, a static library is an ar archive of object files.
Suppose libfoobar.a contains just foo.o and bar.o. A linkage:
g++ -o prog a.o foo.o bar.o # A
is not the same as the linkage:
g++ -o prog a.o -lfoobar. # B
The linker unconditionally consumes every object file in the linkage sequence,
so in case A, it links a.o, foo.o, bar.o in prog.
The linker does not unconditionally consume every object file that is a member of
a static library in the linkage sequence. A static library is a way of offering to
the linker a bunch of object files from which to pick the ones it needs.
Suppose that a.o calls function foo, which is defined in foo.o, and that
a.o references nothing defined in bar.o.
In that case, the linker unconditionally links a.o into prog, after which
prog contains an undefined reference to foo, for which the linker needs a
definition. Next it reaches libfoobar.a and inspects the archive (by its index,
normally) to see if any member of the archive defines foo. It finds that foo.o does
so. So it extracts foo.o from the archive and links it. It needs no definitions
for any symbols defined in bar.o, so bar.o is not added to the linkage. The
linkage B is exactly the same as:
g++ -o prog a.o foo.o
Suppose on the other hand that a.o calls bar, which is defined in bar.o,
and references nothing defined in foo.o. In that case, the linkage B is
exactly the same as:
g++ -o prog a.o bar.o
So an object file that you insert into a static library for linkage with
your executable will never be linked, by default, unless it provides a definition
for at least one symbol that is referenced, but not defined, in an object file
that has already been linked.
Your function notmain is not referenced in the only object file, main.o that
you are explicitly linking in your program. Therefore, when main.o is linked into your program,
the program contains no undefined reference to notmain: the linker requires no definition
of notmain - it has never heard of notmain - and will not link any object file
from within a static library to obtain a definition of notmain. This has nothing
to do with linkage sections.
When linking an ordinary program with static libraries, as a matter of course
you do it like:
g++ -o prog main.o x.o ... -ly -lz ....
where one of the *.o files - say main.o - is the object file that defines the main function. You never
put main.o in one of the static libraries. That's because, in a ordinary program,
main is not called in any of the other object files you are explicitly linking,
so if main.o was in one of your libraries, the linkage:
g++ -o prog x.o ... -ly -lz ...
would have no need to find a definition of main at any of -ly -lz ..., and no definition
of main would be linked.
The case is just the same with your notmain. If you want it linked you can do one of:-
Add -Wl,--undefined=notmain to your linkage options (replacing notmain with
the mangled name of notmain, for C++). This will make the linker assume it has an
undefined reference to notmain even though it hasn't seen any.
Add the command EXTERN(notmain) to your linker script (again with mangling
for C++). This is equivalent to 1.
Explicitly link an object file that defines notmain. Don't put it in a static library.
3 is effectively what you did when you discovered that:
When I move notmain function out of the library (into the project) its'all fine.
For 3, however, you don't need to compile notmain.cpp in your project and any other
project that needs notmain.o. You can build it independently, install it
in /usr/local/lib and explicitly add /usr/local/lib/notmain.o to the
linkage of your project. That would be following the example of GCC itself, which explicitly
links the crt*.o startup files of an ordinary program just by appending their
absolute names to the linkage, e.g.
/usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/crti.o
...
/usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/crtn.o

Makefile: Link several *.a to executable

I try to write a Makefile that takes several static libraries that have been created before and link the to an executable. Although one libary has a main-routine.
I get the error:
/lib/../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
make: *** [dockSIM_gcc_release] Error 1
I tried it with just linking the library that has the main routine but the error stays the same and comes directly after invoking make.
The Makefile:
SHELL = /bin/sh
RM=/bin/rm -f
CXX=g++
PROGNAME=dockSIM_gcc_release
DEFINES=-DDOCKSIM_VERBOSE=FALSE -DNDEBUG -DPRINT_LOG_MSG=0 -DPRINT_DEBUG_MSG=0
LDFLAGS = -fopenmp -g -O3 -std=c++11 -mavx -mstackrealign -fstrict-aliasing
LIBS= -lnagc_mkl -lm -L../externalCode -lpardiso500-GNU481-X86-64 -lacml
FILENAMES = commandInterpreter_lib.a
OBJNAMES =
all: $(PROGNAME)
$(PROGNAME): $(FILENAMES)
$(CXX) $(LDFLAGS) $(DEFINES) -o $(PROGNAME) $(FILENAMES)
clean:
$(RM) *.mo *.ho *.o $(PROGNAME) core *~
test:
echo $(FILENAMES)
showlibs:
echo $(LIBS)
The flags are compatible with those that were used to compile the code.
g++ 4.9.3 is used.
Signature of the main-Routine:
int main(int argc, char* argv[])
Thanks for help and kind regards.
I can only guess what's wrong.
There is more to linking a static library than just a convenient bundle of object files to reduce command line length. In addition to that, the linker only links in object files which it thinks are needed. An object file is needed if there's some undefined symbol that the linker is looking for, that is contained in that object. If there's no symbol that the linker needs in the object, then the linker ignores the object and doesn't link it.
The normal way to build a program is to have the main program listed as object files on the command line: the linker always links every object file. This gives the linker a set of symbols which are defined (by the object files) and undefined (things the object files use but that aren't defined by them). Then the linker will go through the libraries on the link line and add in object files that resolve undefined symbols. These object files in turn may have other undefined symbols that the linker will need to resolve later, etc.
All I can guess is that by not having any object files on your link line, the linker doesn't see the object file in the library containing main as needed and so it doesn't link it.
I don't know why building with debug vs. non-debug makes a difference.
I didn't understand your comment about why you need to do things this way: even if the person who knew about this left, someone will need to learn about it to maintain the software.
In any event you have a few options.
One simple one is to use the "ar" program to extract out the object file containing main and link it directly: in addition to adding objects to libraries ar can extract them. Then you can link that object directly. See the man page for ar.
Another would be to look at the documentation for your compiler and linker and find flags that will force it to include the entire library, not just the unresolved symbols in the library. For the GCC/binutils linker, for example, you can pass -Wl,--whole-archive before the libraries you want to be fully included on the command line, then -Wl,--no-whole-archive after them to turn off that feature.

Resources