johnfound
johnfound

Reputation: 7061

How to determine in which .SO library is given C function?

I have this problem all the time in Linux programming. As long as all the manuals and almost all the source code for Linux are C-centric, all references to some function needs only some include <something.h> line and the function is accessible from the C/C++ code.

But I am programming in assembly language and know almost nothing about C/C++.

In order to be able to call some function, I have to import it from the corresponding .so library.

How to determine the file name of the library? It often differs from the name of the library itself and is not specified in the manuals.

For example, the name of the XLib is actually libX11.so.6. The name of the XShm extension library seems to be libXext.so.6.

Is there easy way to determine the secret real name of the library, using provided C manuals and references?

Upvotes: 1

Views: 3184

Answers (4)

tecu
tecu

Reputation: 550

This is another not-100%-accurate method that may give you some ideas as to how you can narrow things down a bit. It doesn't exactly fit the question because it uses common linux utilities instead of man files, but it may still be helpful.

Use your distribution's package management software.

For example, on Arch Linux, if you were interested in a function in GLFW/glfw3.h, you could find out who owns that file:

$ pacman -Qo /usr/include/GLFW/glfw3.h
/usr/include/GLFW/glfw3.h is owned by glfw 3.1-1

Find out which .so files are in that package:

$ pacman -Ql glfw | grep 'so$'
glfw /usr/lib/libglfw.so

And, if needed, find the actual file that link points to:

$ readlink -f /usr/lib/libglfw.so
/usr/lib/libglfw.so.3.1

This will depend on your distribution. I believe on Ubuntu/Debian you'd use dpkg-query instead.


Edit: DevSolar points out in a comment that you can use apt-file search <header> and apt-file list <package> instead of dpkg-query -S <header> and dpkg-query -L <package>. apt-file appears to work even for packages that aren't installed (though it seems slower?).

I also noticed that (on my Ubuntu VM at least) that, e.g., libglfw-dev contains the libglfw.so symlink, while libglfw2 contains the actual libglfw.so.2 object.


Once you have a set of .so files, you can check them for whatever function you are interested in:

$ nm -D /usr/lib/libglfw.so | grep "glfwCreateWindow"
0000000000007cd0 T glfwCreateWindow

Note that I pulled this last step from a comment on the previous question and don't fully understand it. Maybe you could even skip the earlier steps and rely on nm and grep alone?

Upvotes: 3

This is not a sure fire way, but it can help in many cases.

Basically, you can usually find the library name at the bottom of the man page.

Eg, man XCreateWindow says libX11 on the last line. Then you look for libX11.so and use nm or readelf to see all exported functions.

Another example, man XShm says libXext at the bottom. And so on.

UPDATE

If the function is in section (2) of the man pages, it's a system call (see man man) and is provided by glibc, which would be libc-2.??.so.

Lastly (thanks Basile), if the function does not mention the library, it is also most likely provided by glibc.

DISCLAIMER: Again this is not a 100% accurate method -- but it should help in most cases.

Upvotes: 2

As I commented, you could use gcc to link your program, and then it should be able to accept -lX11 ; by using gcc -v instead of gcc you'll find out what is actually linked and how.

However, you have a much more significant issue than finding the lib*.so.*; most C or C++ APIs are described in header files, and these C or C++ header files also contain symbolic constants (like O_RDONLY for open(2)...) or macros (like WIFEXITED in POSIX wait ...) whose value or expansion you should manually find in header files or documentations. (Quite often, such constants are either preprocessor #define-d constants or enum values). Also, some headers -in particular in C++- contains a lot of inline-d functions (or macros)!

A possible way might be to generate some C files to find all these constants, enums, macros, inlined functions..., and/or to customize the GCC compiler (e.g. with MELT ...) to find them.

So my message is that for better or worse, the C language is deeply tied to Linux & POSIX.

You might restrict yourself to use only syscalls(2) from your assembler code. Then you won't use libX11 and you don't need any header or constant (except the ones for syscalls, starting from <asm/unistd.h>).

BTW, in 2015, coding entirely in assembler for performance reasons is a mistake. The compiler is generating better code than you reasonably can (as soon as you have more than a few hundred machine instructions). In practice, you can code in assembler with GCC by using extended asm instructions in your C functions.

Or are you building your own compiler ? Then you should have told so in your question!

Read also the Program Library HowTo & the Linux Assembly HowTo

Upvotes: 0

Wintermute
Wintermute

Reputation: 44063

You can ask gcc to tell you which file it would use for linking like so:

gcc --print-file-name=libX11.so

Sample output:

/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/libX11.so

This file will usually be a symlink, so you'll have to pipe it through readlink or realpath to get the actual file. For example:

readlink -f $(gcc --print-file-name=libXext.so)

Sample output:

/usr/lib/x86_64-linux-gnu/libXext.so.6.4.0

Upvotes: 0

Related Questions