如何解析编译静态二进制文件,其中的代码包含函数gethostbyname,并且如果编译时未发出如下警告:
警告:在静态链接的应用程序中使用’gethostbyname’要求在运行时需要glibc版本中用于链接的共享库
我用命令在ubuntu 12.04上编译:
$ gcc -static lookup.c -o lookup
这是lookup.c的代码:
/* lookup.c */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> extern int h_errno; int main(int argc,char **argv) { int x, x2; struct hostent *hp; for ( x=1; x<argc; ++x ) { hp = gethostbyname(argv[x]); if ( !hp ) { fprintf(stderr, "%s: host '%s'\n", hstrerror(h_errno), argv[x]); continue; } printf("Host %s : \n" ,argv[x]); printf(" Officially:\t%s\n", hp->h_name); fputs(" Aliases:\t",stdout); for ( x2=0; hp->h_aliases[x2]; ++x2 ) { if ( x2 ) { fputs(", ",stdout); } fputs(hp->h_aliases[x2],stdout); } fputc('\n',stdout); printf(" Type:\t\t%s\n", hp->h_addrtype == AF_INET ? "AF_INET" : "AF_INET6"); if ( hp->h_addrtype == AF_INET ) { for ( x2=0; hp->h_addr_list[x2]; ++x2 ) { printf(" Address:\t%s\n", inet_ntoa( *(struct in_addr *) hp->h_addr_list[x2])); } } putchar('\n'); } return 0; }
我想检查是否$ file lookup将获得如下输出:
$ file lookup
查找:ELF 32位LSB可执行文件,Intel 80386版本1(GNU / Linux),静态链接,用于GNU / Linux 2.6.24,BuildID [sha1] = 0x6fcb2684ad8e5e842036936abb50911cdde47c73(未剥离)
不是这样的:
查找:ELF 32位LSB可执行文件,Intel 80386版本1(SYSV),动态链接(使用共享库),用于GNU / Linux 2.6.24,BuildID [sha1] = 0xf9f18671751927bea80de676d207664abfdcf5dc(未剥离)
如果您建议使用注释,则我必须不使用static,因为我知道的每个Linux都使用不同的libc,希望您无需注释。为什么我坚持静态?因为我需要强制使用静态文件,所以二进制文件必须是静态文件,而不是动态文件。
我有2个多星期的时间在寻找这个,但到目前为止还没有成功。
感谢您帮助我解决我的重任。
您要的将非常困难。
。基本上,getaddrinfo/之下gethostbyname是glibc的NSS层。这使系统管理员可以说“使用DNS将主机名解析为IP地址”,或“使用LDAP”,或“不使用除/etc/hosts”以外的任何内容。该控件在运行时;sysadmin可以随时更改将主机名解析为IP的方式。
getaddrinfo
gethostbyname
/etc/hosts
由于这种灵活性,glibc中的所有名称解析调用都使用帮助程序库(基本上是插件)来完成繁琐的解析工作。有一个用于LDAP寻址的共享库,一个用于文件的共享库,一个用于DNS的共享库,一个用于YP的共享库,依此类推。
如果要使程序100%静态链接,则必须转到其他位置(NOT gethostbyname)才能将主机名转换为IP地址。您可以使用诸如uDNS之类的解析器库(不是确切的解析器库- 可以使用类似的工具)来执行此操作,但是请记住, 在配置为不使用DNS的系统上,二进制文件做不到正确的事情 !
相反,我建议您仅使程序保持(技术上)动态链接。如果您真的想确保它可以在任何平台上运行,甚至可以glibc附带二进制文件- 尽管这样做需要LGPL一致性。保留此动态链接仅意味着您将无法在glibc版本错误的系统上工作-并不是一个巨大的兼容性问题。
glibc
说到许可证合规性,值得注意的是,如果您静态链接glibc,则很可能必须交付 整个应用程序 的源代码才能符合glibc的LGPL许可证。我不是律师,这也不是合格的法律建议,但是阅读LGPL可以很清楚地知道,静态链接的应用程序glibc必须是开源的。