I am working on a very complex Linux driver. I am moving some files around trying to "cut the fat" a little bit. I have 4 "undefined!" symbols at the linking stage. I have searched my source code and I really don't know where these symbols are getting included.
I thought that if I did an objdump -DS on my compiled .ko and searched for the symbols, I might be able to tell from the surrounding decompiled source where they were coming from. But, when I search for the symbols, they aren't even found!
Is there a way to tell WHERE or HOW undefined symbols are getting included?
Ok, I figured out a good way to do this.
I used nm -u to list the undefined symbols from my object files. (the .o files)
nm - list symbols from object files
Doing that one by one on each .o and searching for the symbols I knew were undefined showed me what file they were coming from. Then I had a starting place for finding the symbol in my actual .c file, or a header file included from that .c file.
Now it's not a needle in a haystack, but rather a needle in a chunk of hay that broke off of the haystack.
Related
It's possible to override C runtime functions using the preprocessor (e.g. /Dfree=my_debug_free), however having to match the linkage of the redefined symbol is sometimes undesirable or awkward within the context of a given project.
Is there a way to force the dllimport linkage of a symbol to be satisfied with a symbol coming from a static .lib or a .obj?
Let's assume modifying the calling code directly, or defining away the __declspec keyword itself is out of the question.
Answering my own question with what I've found:
One of the things that the __declspec(dllimport) does is say that the function in question has a prefix __imp_ added to it from the importer's point of view, so manually add the prefixed function, and you satisfy the link.
As far as I understand these __imp_ are the bit that the .lib file corresponding to the .dll would normally provide. If you cut out the linking of the .lib for the .dll you cut that those also, and so have to fill in the __imp_ shaped hole manually yourself.
https://msdn.microsoft.com/en-us/library/aa271769(v=vs.60).aspx has a good overview.
All that said, I've found that using a pre-included file (/FI or -include) that #includes the original (unredefined) definitions first, then redefines them with #defines before entering your code works better than using /D to to redefine them everywhere, even in the original definitions. Doing it that way meas you don't need to worry about the .dll stuff.
I'm trying to link a C++ binary, but I get undefined symbol errors. My binary shouldn't need those symbols, and I'd like to understand the dependency chain causing the linker (GNU ld or GNU gold) think that they are needed. There is libfoo.a containing hundreds of .o files. My program is calling function in libfoo.a. I'd like to get a dependency graph containing all .o files in libfoo.a which the linker thinks are needed to link my program.
I need it because I suspect that there is a mistake somewhere in libfoo.a, calling functions which are not really needed. I can modify the source code of libfoo.a (and thus remove the unneeded calls), and for that I need to understand where the unneeded calls are. The dependency graph could help me find it.
Please note that there is no resulting executable, because of the undefined symbols.
Please note that my ultimate goal is not to build this particular binary, but to make sure that unneeded functions are not called in libfoo.a.
I've looked at man ld, but I couldn't find any command-line flag that could give me more verbose output.
Example error from the linker:
libfoo++.a(foo1.o):foo1.cc:function foo1f: error: undefined reference to 'bar'
How do I figure out what caused foo1.o to be linked to the executable? (It's OK for me that bar is undefined, because I don't need it. My problem is that foo1.o is needed, but it shouldn't be, and I'd like to remove the call which caused foo1.o to be linked in.)
I'd like to get a dependency graph containing all .o files in libfoo.a which the linker thinks are needed to link my program.
The linker map, printed with -M (or --print-map) flag contains exactly that info. If you are using compiler driver (e.g. gcc) to perform the link (you should), then add -Wl,-M to the link line.
I'm trying to learn more about library versioning in Linux and how to put it all to work. Here's the context:
-- I have two versions of a dynamic library which expose the same set of interfaces, say libsome1.so and libsome2.so.
-- An application is linked against libsome1.so.
-- This application uses libdl.so to dynamically load another module, say libmagic.so.
-- Now libmagic.so is linked against libsome2.so. Obviously, without using linker scripts to hide symbols in libmagic.so, at run-time all calls to interfaces in libsome2.so are resolved to libsome1.so. This can be confirmed by checking the value returned by libVersion() against the value of the macro LIB_VERSION.
-- So I try next to compile and link libmagic.so with a linker script which hides all symbols except 3 which are defined in libmagic.so and are exported by it. This works... Or at least libVersion() and LIB_VERSION values match (and it reports version 2 not 1).
-- However, when some data structures are serialized to disk, I noticed some corruption. In the application's directory if I delete libsome1.so and create a soft link in its place to point to libsome2.so, everything works as expected and the same corruption does not happen.
I can't help but think that this may be caused due to some conflict in the run-time linker's resolution of symbols. I've tried many things, like trying to link libsome2.so so that all symbols are alised to symbol##VER_2 (which I am still confused about because the command nm -CD libsome2.so still lists symbols as symbol and not symbol##VER_2)... Nothing seems to work!!! Help!!!!!!
Edit: I should have mentioned it earlier, but the app in question is Firefox, and libsome1.so is libsqlite3.so shipped with it. I don't quite have the option of recompiling them. Also, using version scripts to hide symbols seems to be the only solution right now. So what really happens when symbols are hidden? Do they become 'local' to the SO? Does rtld have no knowledge of their existence? What happens when an exported function refers to a hidden symbol?
Try compiling both libsome1.so and libsome2.so to add symbol versioning, each with their own version (use the --version-script option to ld). Then link the application and libmagic.so using the new libraries. Then, libsome1.so and libsome2.so should be completely separate.
Problems can still occur if there are unversioned references to symbols. Such references can be satisfied by versioned definitions (so that it is possible to add symbol versioning to a library without breaking binary compatibility). If there are multiple symbols of the same name, it can sometimes be hard to predict which one will be used.
Regarding tools, nm -D does not display any information about symbol versioning. Try objdump -T or readelf -s instead.
I'm trying to learn more about library versioning in Linux and how to put it all to work. Here's the context:
-- I have two versions of a dynamic library which expose the same set of interfaces, say libsome1.so and libsome2.so.
-- An application is linked against libsome1.so.
-- This application uses libdl.so to dynamically load another module, say libmagic.so.
-- Now libmagic.so is linked against libsome2.so. Obviously, without using linker scripts to hide symbols in libmagic.so, at run-time all calls to interfaces in libsome2.so are resolved to libsome1.so. This can be confirmed by checking the value returned by libVersion() against the value of the macro LIB_VERSION.
-- So I try next to compile and link libmagic.so with a linker script which hides all symbols except 3 which are defined in libmagic.so and are exported by it. This works... Or at least libVersion() and LIB_VERSION values match (and it reports version 2 not 1).
-- However, when some data structures are serialized to disk, I noticed some corruption. In the application's directory if I delete libsome1.so and create a soft link in its place to point to libsome2.so, everything works as expected and the same corruption does not happen.
I can't help but think that this may be caused due to some conflict in the run-time linker's resolution of symbols. I've tried many things, like trying to link libsome2.so so that all symbols are alised to symbol##VER_2 (which I am still confused about because the command nm -CD libsome2.so still lists symbols as symbol and not symbol##VER_2)... Nothing seems to work!!! Help!!!!!!
Edit: I should have mentioned it earlier, but the app in question is Firefox, and libsome1.so is libsqlite3.so shipped with it. I don't quite have the option of recompiling them. Also, using version scripts to hide symbols seems to be the only solution right now. So what really happens when symbols are hidden? Do they become 'local' to the SO? Does rtld have no knowledge of their existence? What happens when an exported function refers to a hidden symbol?
Try compiling both libsome1.so and libsome2.so to add symbol versioning, each with their own version (use the --version-script option to ld). Then link the application and libmagic.so using the new libraries. Then, libsome1.so and libsome2.so should be completely separate.
Problems can still occur if there are unversioned references to symbols. Such references can be satisfied by versioned definitions (so that it is possible to add symbol versioning to a library without breaking binary compatibility). If there are multiple symbols of the same name, it can sometimes be hard to predict which one will be used.
Regarding tools, nm -D does not display any information about symbol versioning. Try objdump -T or readelf -s instead.
I've always been confused about how the linker works, and it's a difficult subject to search for.
To demonstrate my question and to provide a framework for an answer, I'll put down what I know (or think I know) so far. I may be very wrong. :)
First, each .cpp file is built into an intermediate file (.o for Posix/ELF and .obj for Win/PE I believe). This intermediate file contains all the symbols defined by the .cpp it was built from and has instructions for what external links it needs to be properly resolved. As an extension to this, Posix systems let you combine the .o files into a .a file (Which doesn't seem to do anything more than combine? What command does this?). Is .lib the Win/PE equivalent of the Posix .a file?
Next, the intermediate files are linked together, external dependencies resolved, and you have your executable. Am I missing any steps?
Thanks!
Here's a few pieces of the puzzle:
ar(1) is used to create .a files. They are similar to tar(1) or zip files (possibly
with a index to look up an object file by symbol name)
The linker copies together the sections of object files (text, data, bss). For GNU ld, the precise copying of sections can be controlled with a linker script (e.g. copy all sections from .o files containing "text" in their names into a single text section)
The linker also does relocations: patching instructions (jump and data load) with the respective target addresses, once the value of a symbol is known. In some cases, this can't be done at link time, so the linker copies/adjusts the relocation records from the .o files into the final executable.
the windows .lib serves two purposes: a static library (.lib) is similar to .a libraries. An import library (.lib) does not contain the actual code, but only symbol lists. The linker can resolve symbols from the import library, but then knows it needs to put a reference to the corresponding .dll into the executable. On Unix/ELF, the .so file has both the code and the symbol table.