编译一个静态二进制文件,编码函数gethostbyname

Lor*_*mly 19 c c++ linux gcc gethostbyname

如何解析编译一个静态二进制文件,其代码包含一个函数gethostbyname,如果编译时没有像这样的警告:

警告:在静态链接的应用程序中使用'gethostbyname'需要在运行时从用于链接的glibc版本中获取共享库

我使用命令在ubuntu 12.04上编译:

$ gcc -static lookup.c -o lookup
Run Code Online (Sandbox Code Playgroud)

这是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;
  }
Run Code Online (Sandbox Code Playgroud)

我想如果我检查通过$ 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,未剥离

如果您评论了建议我必须使用没有静态,因为我知道每个linux不同的libc,我希望你不需要评论.为什么我坚持静态?因为我需要强制使用静态,所以二进制文件必须是静态的而不是动态的.

我有超过2周的时间来寻找这个,但到目前为止还没有成功.

谢谢你帮我解决我的问题.

Bor*_*lid 26

你所要求的将是非常困难的.

请参阅有关getaddrinfo的StackOverflow问题.基本上,getaddrinfo/ 下面gethostbyname是glibc的NSS层.这允许系统管理员说"使用DNS将主机名解析为IP地址",或"使用LDAP",或"不使用除/etc/hosts" 以外的任何内容.该控件在运行时; 系统管理员可以随时改变主机名解析为IP的方式.

由于这种灵活性,glibc中的所有名称解析调用都使用帮助程序库(基本上是插件)来完成分辨率的繁重工作.有一个用于LDAP寻址的共享库,一个用于文件,一个用于DNS,一个用于YP,依此类推.

如果您希望程序100%静态链接,则必须转到其他地方(NOT gethostbyname)将主机名转换为IP地址.您可以使用像uDNS这样的解析器库(不是这一个 - 有类似的工具可用)来做到这一点,但是您应该记住,您的二进制文件不会在配置为不使用DNS的系统上做正确的事情!

相反,我建议只是让程序(技术上)动态链接.如果你真的想确保它可以在任何平台上运行,你甚至可以glibc使用二进制文件 - 尽管这样做需要LGPL一致性.留下这一个动态链接只会意味着你不会使用错误glibc版本的系统- 而不是一个巨大的兼容性问题.

说到许可证合规性,值得注意的是,如果您静态链接glibc,您很可能必须为整个应用程序提供源代码以符合glibcLGPL许可证.我不是律师,这不是合格的法律建议,但阅读LGPL非常清楚,静态链接的应用程序glibc必须是开源的.请参阅有关该主题的StackOverflow问题.

  • 许可证+1提醒libc中的LGPL.请注意,有些libc-s不是LGPL,而是麻省理工学院,例如http://musl-libc.org/ (4认同)
  • 解决了musl-libc.我编译mul-libc然后我编译我的程序使用库musl-libc与命令-L/path/tomuslcompiled/lib.我非常高兴,谢谢Borealid先生 (4认同)

小智 10

我得到了相同的警告并修复它我重新编译了glibc.--enable-static-nss配置时打开开关以使其工作.