I'm creating a dotnet core project and would like to call into some linux system functions using P/Invoke. How do I find which .so file does the desired functionality reside in?

Eg. to use getpid, I need to add this import-


The netlink connector man page suggests that we only use NLMSG_DATA to parse the data received from the connector, and i'd like to invoke this method from within my c# code. How do I find out which so file to import?

1 Answer 1


To find out which dynamic libraries export which symbol, on a GNU system, you can try something like:

ldconfig -p |
  sed -n 's/.* => //p' |
  sort -u |
  xargs -d '\n' nm --defined-only -oDg |
  grep -w getpid

(in first approximation; that could be improved by removing duplicates at inode level).

Something similar can be done with static libraries or any ELF or other object supported by nm, though you may need to adapt the flags, and how to gather the list of files you want to search in.

However here, NLMSG_DATA being all uppercase is more likely to be a C preprocessor macro.

$ grep -r NLMSG_DATA /usr/include
/usr/include/linux/netlink.h:#define NLMSG_DATA(nlh)  ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))

To look for definitions in C headers, instead of grep, you may want to use some code indexing tools like ctags, cscope or gtags and index the whole of /usr/include.

You can also get the C pre-processor to expand it:

printf '%s\n' '#include <linux/netlink.h>' 'please_describe[NLMSG_DATA(nlh)]' |
  gcc -P -E -x c - | sed '/please_describe/,$!d'
please_describe[((void*)(((char*)nlh) + ((0) + ((int) ( ((sizeof(struct nlmsghdr))+4U -1) & ~(4U -1) )))))]

So it just returns a pointer some offset off the input pointer based on the size of struct nlmsghdr (which you could determine using the C compiler or debugging symbols of some object that uses that struct).

Note that headers being not needed to run software, only to build them, they won't be installed by default for all libraries, so you may need to install some xxx-dev or xxx-devel packages to bring them in.

When you do have the man page for the library function (does not really apply here as it's some kernel API), chances are you also have the header files. You can work your way from the man page to the package and then to the headers and library. For instance on Debian and derivatives for the attr_setf function:

$ man -w attr_setf
$ dpkg -S /usr/share/man/man3/attr_set.3.gz
libattr1-dev:amd64: /usr/share/man/man3/attr_set.3.gz
$ dpkg -L libattr1-dev | grep /include/

For the libraries, you can guess the package is libattr1 or use the fact that the -dev package will depend on the runtime one:

$ apt-cache show libattr1-dev | grep Depends
Depends: libc6-dev | libc-dev, libattr1 (= 1:2.4.47-2build1)
$ dpkg -L libattr1 | grep /lib/
$ nm -Dg /lib/x86_64-linux-gnu/libattr.so.1 | grep attr_setf
00000000000016e0 T attr_setf

If you do not have the man page, but know it exists, you can look-up which package it's available from:

$ apt-file search -x 'man.*/attr_set\.\d'
libattr1-dev: /usr/share/man/man3/attr_set.3.gz
ncurses-doc: /usr/share/man/man3/attr_set.3ncurses.gz

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .