[SOLVED] Tool like Dependency Walker for Linux that can show which funtion is imported from which .so file?
Linux - NewbieThis Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place!
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Tool like Dependency Walker for Linux that can show which funtion is imported from which .so file?
On Windows, tools like Dependency Walker, or its modern rewrite Dependencies, can be used to show which DLL files (shared libraries) a given EXE or DLL file depends on. These tools even show recursive dependencies. And, most important, these tools nicely show which exactfunction is imported from which exact DLL file. Is there any tool that can provide this information on Linux?
I know that a somewhat similar functionality is available on Linux via the ldd tool. Or, even better, lddtree from the pax-utils package, which shows recursive dependencies as a tree diagram. Those tools are nice, but they only show which .so files the given executable (or shared library) depends on. They do not show which exact functions are imported from each of those .so files! Meanwhile, objdump -T (or, alternatively, nm -D) can be used to show a list of all functions that the given executable (or shared library) imports from shared libraries, but it does not show from which exact .so file each function is imported.
Is there any tool available on Linux that shows both information combined
I searched on Google for a Linux tool that can show which exact function is imported from which exact .so file, but couldn't find anything. People either recommend using ldd or objdump -T (or, alternatively, nm -D). Unfortunately, as explained before, those tools only show half of the required information, but not the full picture. Since both information are available separately, it shouldn't be too hard to combine them...
Last edited by DerPropeller; 03-21-2024 at 07:43 PM.
but if you cannot find something specific you can probably script something.
But how? ldd only outputs a list of the required .so files, with no information about the functions that are supposed to be imported from each file.
Meanwhile, objdump (or nm) only outputs a list of the required function names, with no information about the .so file from which each function is supposed to be imported.
So, there appears to be no way to match up the separate outputs
In theory it should be possible to parse the import table directly from the executable file, but I have no real idea how to do approach this...
Last edited by DerPropeller; 03-21-2024 at 09:04 PM.
I don't think so. If I understand it right, the script in question only shows the dependencies, in terms of .so files, differentiating between direct and indirect dependencies, just like lddtree from pax-utils.
It apparently does not show the functions that are to be imported from each .so file at all.
Again, what I'm looking for is a list of all the .so files that are required by an executable (or shared library), and for each of those .so files the list of functions that are supposed to be imported from the individual file.
TTBOMK, in the executable file, there is an "import table" that tells the loader which specific function shall be imported from which specific .so file. It must be possible to dump that table...
Last edited by DerPropeller; 03-21-2024 at 09:46 PM.
Best way to do that is, get the source code for the software that you are using.
Then look at the tree and see what it is doing.
What are you trying to accomplish? .so files are compiled code. You need to get the source tree and walk through it. Are you trying to reverse engineer an executable? That would be the real hard way to go.
Best way to do that is, get the source code for the software that you are using.
Then look at the tree and see what it is doing.
No, looking at the source code does not help, I think
In the source code you'd see that a certain function gets called by the program. That function probably is declared in some header (.h) file. But that's it. You can not see at all, in the source code, which library actually provides the implementation of the function! It is the linker that figures out where each required function is located. If any required function can not be located by the linker, it will error out and the build process fails. Also, it is the linker that generates the "import table" of the executable file. At runtime, the loader reads the "import table" to know which specific function must be imported from which specific shared library (.so file).
Quote:
Originally Posted by teckk
What are you trying to accomplish? .so files are compiled code. You need to get the source tree and walk through it. Are you trying to reverse engineer an executable? That would be the real hard way to go.
Given an existing executable file (or shared library), I want to check/analyze its dependencies.
On Windows, we can simply use Dependency Walker to see which DLL files a given executable file depends on, and also which specific functions are imported from each specific DLL file https://i.imgur.com/IsTmC1q.png
On Linux, ldd shows which .so files a given executable file depends on, but it does not tell you which functions are imported!
Meanwhile, objdump or nm shows a list of all the functions that a given executable file imports, but it does not tell you from which specific .so file each of those functions is imported
Last edited by DerPropeller; 03-22-2024 at 05:08 PM.
know that a somewhat similar functionality is available on Linux via the ldd tool. Or, even better, lddtree from the pax-utils package, which shows recursive dependencies as a tree diagram. Those tools are nice, but they only show which .so files the given executable (or shared library) depends on. They do not show which exact functions are imported from each of those .so files! Meanwhile, objdump -T (or, alternatively, nm -D) can be used to show a list of all functions that the given executable (or shared library) imports from shared libraries, but it does not show from which exact .so file each function is imported.
Is there any tool available on Linux that shows both information combined
Quote:
Originally Posted by DerPropeller
TTBOMK, in the executable file, there is an "import table" that tells the loader which specific function shall be imported from which specific .so file. It must be possible to dump that table...
Not quite. Linux uses the ELF (Extensible Linking Format) format for executable files (and shared libraries).
In the ".dynamic" section of the ELF file, there is, amongst other things, one DT_NEEDED entry for each shared library that is needed. The DT_NEEDED entry just contains (a pointer to) the name of the shared library (*.so) file that needs to be loaded, but it does not indicate at all which symbols are to be "imported" from that shared library. To know which symbols need to be imported, we have to look at the ".dynsym" section.
The ".dynsym" section of the ELF file, contains the dynamic linking symbol table. Any symbols that are "undefined" (U) here will need to be resolved by the dynamic linker/loader. In other words, those "undefined" symbols are the ones that will be "imported" at runtime, e.g. from shared libraries. But the dynamic linking symbol table does not indicate at all which shared library contains a particular "undefined" symbol.
So, ldd pretty much dumps the DT_NEEDED entries from the ".dynamic" section. And nm -D dumps the ".dynsym" section; filter lines that start with U to get "imported" symbols.
Alternatively, readelf -d and readelf --dyn-syms provide the same information. Use readelf -a to dump all sections at once.
In conclusion, I think the information you are seeking can not be determined by just looking at the ELF file, because it is not specified from which shared library each "undefined" symbol will be resolved at runtime.
Last edited by mysterious X; 03-23-2024 at 11:20 AM.
After reading your post, I conducted a little test: I created a test program that calls foo() from libfoo.so and then calls bar() from libbar.so. As expected, ldd showed that my executable depends on both, libfoo.so and libbar.so. Then I changed my libfoo.so to additionally contain a "fake" function named bar(), which prints a different text than the original one. The executable file and the libbar.so were totally unchanged. Only the libfoo.so was re-built. Guess what, the program now suddenly calls the "fake" bar() from libfoo.so and does not use libbar.so at all! Interestingly, ldd still shows both library dependencies.
From this result I can only conclude that, indeed, Linux does not store which specific function shall be imported from which specific shared library, but only stores a "unspecific" list of shared libraries that need to be loaded. Apparently, the dynamic linker/loader searches all the loaded shared libraries and simply imports the required function from the first library where it is found – which is very different from Windows!
At least this explains why no tool shows the information that I was looking for. It just doesn't exist in Linux. Lesson learned
Last edited by DerPropeller; 03-24-2024 at 08:17 AM.
After reading some more on the topic, I found that while Linux executables apparently do not store from which specific shared library a certain function shall be imported, we can still see from which specific shared library each function actually does get imported, at runtime, by setting the LD_DEBUG environment variable to "bindings":
Code:
$ LD_DEBUG=bindings ./a.out
[...]
4541: binding file ./a.out [0] to /home/propeller/Desktop/libbar.so [0]: normal symbol `bar'
4541: binding file ./a.out [0] to /home/propeller/Desktop/libfoo.so [0]: normal symbol `foo'
4541: calling init: /home/propeller/Desktop/libfoo.so
4541: calling init: /home/propeller/Desktop/libbar.so
[...]
Hello from foo!
Hello from bar!
Versus the modified libfoo.so file:
Code:
$ LD_DEBUG=bindings ./a.out
[...]
4722: binding file ./a.out [0] to /home/propeller/Desktop/libfoo.so [0]: normal symbol `bar'
4722: binding file ./a.out [0] to /home/propeller/Desktop/libfoo.so [0]: normal symbol `foo'
4722: calling init: /home/propeller/Desktop/libfoo.so
Hello from foo!
Fake bar() funnction has been invoked !!!
Last edited by DerPropeller; 03-24-2024 at 11:04 AM.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.