how to disable C++ dead code stripping in xcode - c++

I'm trying to link in all unreferenced symbols from a few static libraries (my own libraries) for my C++ xcode app. I have tried all the properties related to 'strip' (by searching the properties for 'strip'), but the unreferenced symbols, specifically classes, are not linked in.
I have also tried the -r linker flag, but then the linker only complains with:
'ld: -r and -dead_strip cannot be used together'
I have tried adding '-no_dead_strip' to the linker flags, but then the linker just tells me
'-no_dead_strip' is ignored.
I get the same results with both 'Apple LLVM' and 'LLVM GCC'.
So, my question is: what linker flag(s) or target properties should I use to switch off all dead code stripping and force unreferenced classes to be linked in?

The standard linking mechanism - i.e. using the -l option to link a .a file will intelligently filter out object files that are not used, so the reason why the symbols are not present in the resultant binary is that they're not actually linked in.
If you want to get all the symbols from one archive, you can use the flag: -force_load libraryarchive, used like: -Wl,-force_load,libfoobar.a where libfoobar.a is the archive that you want to get all the symbols from.
In order to get all the symbols from the all archives, you should use the linker flag: -all_load, or if you're driving it from gcc/clang the flag -Wl,-all_load.
It produces hideous symbol tables, though!

Related

Why does ld need library that my executable depends on?

I'm trying to build my executable (that depends on library utils.so) using the following command
g++ -L/path/to/libutils -lutils -I/path/to/utils_headers executable.cpp -o executable
Actually I don't have utils.so - only the header files of utils library.
I'm getting the error:
ld: cannot find -lutils
Does linker really need to access all the libraries my executable depends on in order to build my executable? If it does then I'd like to know why it needs to access them.
My executable is a shared library. I'm sure that header files of the utils lib are enough to build it (i.e without having utils.so).
The linkage option -lutils by default directs the linker to search,
first in the specified library search directories (-Ldir) and then
in its default search directories, for either of the files libutils.so (
shared library) or libutils.a (static library), preferring libutils.so
if both of them are found in the same search directory.
If such a file is found, the linker stops searching and adds that file
to the input files of the linkage, whether or not it resolves any references in
the linkage. The linker cannot know whether the file resolves any references
if it does not input the file.
If no such file is found, the linker gives the error: cannot find -lutils. Because
you told it to find libutils.{so|a} and it could not.
You say:
My executable is a shared library
But it isn't. Your compile-and-link command:
$ g++ -L/path/to/libutils -lutils -I/path/to/utils_headers executable.cpp -o executable
is not an attempt to link a shared library. It is an attempt to link a program.1
This would be an attempt to link a shared library:
$ g++ -shared -I/path/to/utils_headers -o libexecutable.so executable.cpp -L/path/to/libutils -lutils
You cannot link a program with unresolved references. But you can link a shared library
with unresolved references.
So, you could link a libexecutable.so like that, or you could link it simply like:
$ g++ -shared -I/path/to/utils_headers -o libexecutable.so executable.cpp
These are two different linkages: if they succeed they produce different output files.
In the first linkage, some symbols will (let's assume) be resolved to definitions provided in libutils.so or libutils.a
(whichever one is found), and this will be reflected by:
libutils.so is found: The .dynamic section of libexecutable.so contains a DT_NEEDED
structure that expresses a runtime dependency on libutils.so. libutils.so will need to be included in any linkage that includes libexecutable.so, but the output file of such a linkage will itself contain a runtime dependency only on libexecutable.so.
libutils.a is found: libexecutable.so itself contains the definitions for all the symbols
it uses that are defined by object files in libutils.a.2 libexecutable.so may be included in subsequent linkages with no need for libutils.{so|a}.
In the second linkage, the .dynamic section of libexecutable.so will not express a runtime
dependency on libutils.so nor will the file contain definitions of any symbols provided by libutils.{so|a}. libutils.so will (again) need to be included in an subsequent linkage that includes libexecutable.so, but the output file of such a linkage will acquire independent runtime dependencies on both libexecutable.so and libutils.so.
But, if you specify -lutils in the linkage - or any linkage - and the linker cannot find libutils.{so|a}
in any of its search directories, then you get the error you observe, because you told the linker
to input a file, whose effects on the linkage can only be determined and implemented if that file is found - and it cannot be found.
[1] An attempt that is likely to fail, because it consumes libraries before the object
files that refer to them
[2] See static-libraries to understand
why.
In general, an ELF linker needs a sufficiently accurate representation of the shared object that is linked in. It does not have to be an actually working shared objects, just a sufficiently close representation of it. A few things absolute require data that is not available in the object itself:
When compiling C programs, a reference to a global data object of incomplete type does not contain size information. The linker cannot place the object into the data segment unless it obtains the size information from somewhere. By default (when compiling for executables, including PIE) the object needs to be allocated in the data segment on many targets because of the relocations the compiler uses for compiling accesses to global data objects.
Similarly, the link editor might get the alignment of global data objects wrong if it has insufficient information.
Many libraries use symbol versioning. Symbol version information is only available when the link editor can see the shared object. If that information is missing, the link editor will not emit a symbol version, which instructs the dynamic linker to bind the symbol to the base version at run time, leading to subtle bugs.
However, if you only use C function symbols (not data symbols, or the varieties of symbols that C++ requires) and the target library does not use symbol versioning, you can use a stub library for linking. This is a library that defines all the functions you need and has the appropriate soname, but the functions are just dummies which do not actually do anything.

Get dlopen to ignore undefined symbols

I am compiling a dynamically generated C++ file as shared object which contains references to symbols available only in it's full build.
g++ -o tmp_form.so -fPIC -shared -lsomelib -std=gnu99 tmp_form.cc
I don't need the missing symbols for my current program, only those from the linked library. But dlopen does require them to be available or fails otherwise. The missing symbols are all variables which are being referenced in structs.
One option would be to add the weak reference attribute to the missing symbols in the generated code. But I would like to avoid making changes to the code generator if possible.
Any advise is appreciated.
Your link command is incorrect:
... -lsomelib ... tmp_form.cc
should be
... tmp_form.cc -lsomelib
The order of sources/objects and libraries on the link line does matter.
If you are using an ELF platform and a very recent build of Gold linker, you can "downgrade" unresolved symbols to weak with --weak-unresolved-symbols option (added here) without modifying the source.
Otherwise, you'll have to modify sources, there is no other way.
P.S. Function references would not have a problem with RTLD_LAZY due to lazy binding, but for data references weak unresolved is your only choice, lazy binding is not possible for them.
Try dlopen("/path/to/the/library", RTLD_LAZY);

Workaround for when -whole-library is not available

I'm trying to compile on an environment where the -Wl,-whole-library flag is not supported (emscripten). How can I trick to force the compiler to include the exported symbols ? The solution should met as many of these properties as possible :
Could be applied on a single library (I don't want to include unused symbols from other libraries)
Could be automatically generated (for example by fetching the exported symbol table with nm?)
Would work with functions & member functions
I thought about computing a file with something like :
int x = (int)(&func_a)+(int)(&func_b)+...;
But it doesn't work with member functions, which cannot be casted to int (and can be private).
Do you have any idea ?
Ideas:
Use --whole-library flag before linking the lib you want and just
after add -no-whole-library before listing other libs so that only
the one you need To be wholly linked is and try add --export-dynamic flag using a linker that supports it.
Then dig the nm/objdump/exportmap road http://accu.org/index.php/journals/1372 to export/build link info and for using link info http://runtimecompiledcplusplus.blogspot.fr/ for using exported maps and code so that you can mimic the -Wl in your code.

How to handle linker errors in C++/GNU toolchain?

Given a C++/GNU toolchain, what's a good method or tool or strategy to puzzle out linker errors?
Not sure exactly what you mean but if you are talking about cryptic linker symbols like:
mylib.so: undefined symbol: _ZN5CandyD2Ev
you can use c++filt to do the puzzling for you.
c++filt _ZN5CandyD2Ev
will return Candy::~Candy() so somehow Candy's destructor didn't get linked.
With gcc toolchain, I use:
nm: to find the symbols in object files
ld: to find how a library links
c++filt: to find the C++ name of a symbol from its mangled name
Check this for details.
Well the first thing would be RTFM. No, seriously, read the documentation.
If you don't want to do that, try a search on the error that comes up.
Here are a few other things to remember: "missing" symbols are often an indication that you haven't included the appropriate source or library; "missing" symbols are sometimes an indication that you're attempting to link a library created with a different mangling convention (or a different compiler); make sure that you have extern "C" where appropriate; declaring and defining aren't the same thing; if your compiler doesn't support "export" make sure your template code is available for when you instantiate objects.
Look at the names of the symbols that are reported to be problematic.
If there are missing symbols reported, find out in which source files or libraries those function/... should be defined in. Inspect the compilation/linker settings to find out why these files aren't compiled or linked.
If there are multiply defined symbols the linker usually mentions which object files or libraries contain them. Look at those files/their sources to find out why the offending functions/... are included in both of them.

How to make gcc or ld report undefined symbols but not fail?

If you compile a shared library with GCC and pass the "-z defs" flag (which I think just gets passed blindly on to ld) then you get a nice report of what symbols are not defined, and ld fails (no .so file is created). On the other hand, if you don't specify "-z defs" or explicitly specify "-z nodefs" (the default), then a .so will be produced even if symbols are missing, but you get no report of what symbols were missing if any.
I'd like both! I want the .so to be created, but I'd also like any missing symbols to be reported. The only way I know of to do this so far is to run it twice, once with "-z defs" and once without. This means the potentially long linking stage is done twice though, which will make the compile/test cycle even worse.
In case you're wondering my ultimate goal -- when compiling a library, undefined symbols in a local object file indicates a dependency wasn't specified that should have been in my build environment, whereas if a symbol is missing in a library that you're linking against that's not an error (-l flags are only given for immediate dependencies, not dependencies of dependencies, under this system). I need the report for the part where it lists "referenced in file" so I can see whether the symbol was referenced by a local object or a library being linked. The --allow-shlib-undefined option almost fixes this but it doesn't work when linking against static libraries.
Preference to solutions that will work with both the GNU and Solaris linkers.
Instead of making ld report the undefined symbols during linking, you could use nm on the resulting .so file. For example:
nm --dynamic --undefined-only foo.so
EDIT: Though I guess that doesn't give you which source files the symbols are used in. Sorry I missed that part of your question.
You could still use nm for an approximate solution, along with grep:
for sym in `nm --dynamic --undefined-only foo.so |cut -d' ' -f11 |c++filt -p` ; do
grep -o -e "\\<$sym\\>" *.cpp *.c *.h
done
This might have problems with local symbols of the same name, etc.
From the GNU ld 2.15 NEWS file:
Improved linker's handling of unresolved symbols. The switch
--unresolved-symbols= has been added to tell the linker when it
should report them and the switch --warn-unresolved-symbols has been added to
make reports be issued as warning messages rather than errors.