2014-10-31 227 views
3

我有一个程序,其系统调用getpwnam()在运行时失败。要调试这一点,我决定在这个代码单独运行getpwnam()(它从一个论坛来):Linux getpwnam()库依赖关系

#include <pwd.h> 
#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char **argv) 
{ 
struct passwd *pw; 

if (argc != 2) { 
    printf("usage: %s username\n", argv[0]); 
    exit(0); 
} 
pw = getpwnam(argv[1]); 
if (pw == NULL) 
    printf("getpwnam failed\n"); 
else 
    printf("home dir = %s\n", pw->pw_dir); 
    exit(0); 
} 

奇怪的是它似乎取决于libnss_compat-2.3.5.so存在:

随着libnss_compat:

./pwnam root home dir = /root

没有libnss_compat:

./pwnam root getpwnam failed

所以我的问题是;为什么getpwnam()依赖于libnss_compat*.so?我发现与nm -D命令libc-2.3.5.so是提供getpwnam()的lib。

readelf -d告诉我,libc又取决于ld.so.1。这又取决于什么。那么为什么地球上有libnss_compat有影响?

感谢您的帮助大家!

回答

4

NSS是名称服务开关,它可以在各种来源(传统密码文件,Network Information Service,LDAP)中查找用户信息。​​可能在libc中定义,但会在运行时加载实际的NSS库。看里面libc,我发现

$ strings /lib/x86_64-linux-gnu/libc.so.6 | grep libnss 
libnss_ 
libnss_ 
libnss_%s.so.%d.%d 

最后一行显然是snprintf格式字符串用来构建实际的实现库的名称中使用dlopen加载。执行使用​​确定。

编辑我在Glibc来源找到的地方the library is loaded。这不是(不再?)使用snprintf,但原理仍然相同。

+2

另请注意,如何完成查找以及为查找加载的模块通常是在Linux的/etc/nsswitch.conf中配置的 – nos 2014-10-31 11:17:44

+0

谢谢!但是在将来,如果我的程序无法正常工作,那么我应该如何知道library-abc依赖于library-xyz,如果它不显示为'readelf -d'? – 2014-11-03 02:14:44

+2

@ AndyJ0076一般来说,你不能。要静态确定由动态链接的C程序加载的库,必须确定程序是否包含使用'dlopen'加载库的代码,然后确定哪些库是代码库,以及代码是否达到'dlopen'调用。后两个问题是不可判定的。 'strings','readelf'和'strace'是你的朋友,但他们不会抓住一切。 – 2014-11-03 09:59:35