编译功能的gethostbyname C到静态链接错误 [英] Compile C with function gethostbyname to static linked error

查看:3783
本文介绍了编译功能的gethostbyname C到静态链接错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用的功能编译程序的gethostbyname()通过交叉编译 ARM-NONE-Linux的gnueabi ,但它没有,当我在Android上运行我的二进制工作。

我的code如下:

  / *的gethostbyname-example.c * /  #包括LT&;&stdio.h中GT;
  #包括LT&;&unistd.h中GT;
  #包括LT&;&stdlib.h中GT;
  #包括LT&;&string.h中GT;
  #包括LT&;&errno.h中GT;
  #包括LT&; SYS / socket.h中>
  #包括LT&; netinet / in.h中>
  #包括LT&; ARPA / inet.h>
  #包括LT&;&netdb.h中GT;  EXTERN INT h_errno;  INT主(INT ARGC,字符** argv的){
     INT X,X 2;
     结构hostent *马力;     为(X = 1; X&下;的argc ++ x)的{
        HP =的gethostbyname(的argv [X]);
        如果(!HP){
           fprintf中(标准错误,
                   %S:主机'%s'的\\ n
                   hstrerror(h_errno)
                   的argv [X]);
           继续;
        }        的printf(主机%S:\\ n,argv的[X]);
        的printf(官方:\\ t%S \\ n,HP-> h_name);
        的fputs(别名:\\ t的,标准输出);
        对于(χ2= 0;&HP- GT; h_aliases的[X2]; ++ X2){
           如果(2次){
              的fputs(,标准输出);
             }
        的fputs(HP-GT&; h_aliases的[X2],标准输出);
        }
        的fputc('\\ n',标准输出);
        的printf(类型:\\ t \\ t%S \\ n,
               HP-GT&; h_addrtype == AF_INET
               ? AF_INET:AF_INET6);
        如果(HP-GT&; h_addrtype == AF_INET){
           对于(χ2= 0;&HP- GT; h_addr_list [X2]; ++ X2){
              的printf(地址:\\ t%S \\ n,
                     INET_NTOA(*(struct in_addr,这个*)
                      HP-GT&; h_addr_list [X2]));
           }
        }
     的putchar('\\ n');
     }
     返回0;
  }

我用编译臂无-Linux的gnueabi-GCC ,在我的笔记本电脑,OS 的Ubuntu 12.04 和交叉编译的Sourcery codebench

  $臂无-Linux的gnueabi-GCC的gethostbyname-example.c -o --static的gethostbyname,例如
/tmp/ccE0xjBG.o:在函数'主':
。lookup.c :(文字+ 0x38):警告:在静态链接的应用程序中使用的gethostbyname需要在运行时从glibc的版本用于连接的共享库
$ LS
的gethostbyname - example.c的gethostbyname,例如
$文件的gethostbyname,例如
的gethostbyname - 例如:ELF 32位LSB的可执行文件,ARM版本1(SYSV),静态链接,为GNU / Linux 2.6.16,不可剥离

然后我测试在我的chroot手臂二进制的gethostbyname - 例如,我复制粘贴的二进制的chroot 文件夹,然后我登录到的chroot ,和我执行,顺便说一句我做的chroot从这里的 https://wiki.ubuntu.com/ARM/BuildEABIChroot ,如果​​我在chroot环境运行它,我得到如下结果:

 #./gethostbyname-example www.google.com
主持人google.com:
 官方:www.google.com
 别名:
 类型:AF_INET
 地址:74.125.135.139
 地址:74.125.135.100
 地址:74.125.135.101
 地址:74.125.135.102
 地址:74.125.135.113
 地址:74.125.135.138

然后我也上传二进制的gethostbyname,例如与亚行推到我的Andr​​oid设备,如果我运行的二进制的gethostbyname,比如我得到如下错误:


 #./gethostbyname-example www.google.com
#未知的服务器错误:主机www.google.com
#平www.google.com
#PING www.google.com(74.125.135.99)数据56(84)个字节。
从ni-in-f99.1e100.net#64字节(74.125.135.99):icmp_seq = 1 TTL = 49 =时间798毫秒
icmp_seq = 2 TTL = 49时间为1039毫秒:从ni-in-f99.1e100.net(74.125.135.99)#64字节


在我的Andr​​oid设备我已经在/ etc /和/系统的/ etc /文件主机与谷歌DNS

  8.8.8.8
8.8.4.4

大约有多少这种故障的原因,

感谢您。


解决方案

简短的解释

在glibc的DNS查找需要/lib/libnss_dns.so.2,这是不是可以在Android。

另一个区别是,Android的存储DNS设置 /system/etc/resolv.conf ,并用仿生C库内建原生的Andr​​oid应用程序将在那里寻找找到DNS服务器查询。用glibc构建的应用程序将查找的/etc/resolv.conf ,这并不在Android上存在。

较长的解释

您已经建成使用的glibc的二进制文件,而Android使用仿生C库。

链接到libc的静态时,这应该大部分被罚款,因为我不知道在Android内核,打破简单的用户应用程序的土地足够严重的变化。你应该使用Android NDK的建设虽然Android原生应用程序,

有不过的几件事情联系起来,以静态的glibc时出错。在glibc的,例如某些功能用于查找用户信息,主机名和正常的/etc/nsswitch.conf中配置的其他东西调用到其他共享库实际上做的工作。这种情况无论是否链接到静态或而非glibc本身。这些文件通常是/ lib中/ libnss_ *上glibc的系统中找到的文件。

大多数这些共享库都是glibc的一部分,并会在glibc的系统上安装。但他们无法在Android上。依托应用程序使用,当这些共享库可用这些辅助共享库无法正常工作的funcions - 的gethostbyname()就是其中之一,作为正常的DNS查询时requres /lib/libnss_dns.so.2

I'm trying compile program using function gethostbyname() with the cross compiler arm-none-linux-gnueabi, but it did not work when I run my binary on android.

My code in below:

  /* gethostbyname-example.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;
  }

I compile with arm-none-linux-gnueabi-gcc, On my laptop with OS ubuntu 12.04 and cross compiler Sourcery Codebench:

$ arm-none-linux-gnueabi-gcc gethostbyname-example.c --static -o gethostbyname-example
/tmp/ccE0xjBG.o: In function `main':
lookup.c:(.text+0x38): warning: Using 'gethostbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
$ ls
gethostbyname-example.c gethostbyname-example
$ file gethostbyname-example
gethostbyname-example: ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically linked, for GNU/Linux 2.6.16, not stripped

And then I test the binary gethostbyname-example on my chroot arm, I copy-paste the binary to chroot folder and then I login to chroot, and I execute, BTW I make chroot from here https://wiki.ubuntu.com/ARM/BuildEABIChroot , if I run it on chroot I get result as below:

# ./gethostbyname-example www.google.com
Host google.com : 
 Officially:    www.google.com
 Aliases:   
 Type:      AF_INET
 Address:   74.125.135.139
 Address:   74.125.135.100
 Address:   74.125.135.101
 Address:   74.125.135.102
 Address:   74.125.135.113
 Address:   74.125.135.138

Then also I upload binary gethostbyname-example with adb push to my android device, and if I run the binary gethostbyname-example I get error as below:

# ./gethostbyname-example www.google.com
# Unknown server error: host 'www.google.com'
# ping www.google.com
# PING www.google.com (74.125.135.99) 56(84) bytes of data.
# 64 bytes from ni-in-f99.1e100.net (74.125.135.99): icmp_seq=1 ttl=49 time=798 ms
# 64 bytes from ni-in-f99.1e100.net (74.125.135.99): icmp_seq=2 ttl=49 time=1039 ms

In my android device I have a file hosts in /etc/ and /system/etc/ with google DNS

8.8.8.8 
8.8.4.4

Approximately what the cause of this failure,

Thank you.

解决方案

Short Explanation

DNS lookup in glibc requires /lib/libnss_dns.so.2 , which is not available on Android.

Another difference is that Android stores the DNS settings /system/etc/resolv.conf , and native Android apps built with the bionic C library will look there to find the DNS servers to query. Applications built with glibc will look in /etc/resolv.conf , which doesn't exist on Android.

Longer Explanation

You've built the binaries using glibc, while Android uses the bionic C library.

This should for the most part be fine when linking to a libc statically, as I'm not aware of severe enough changes in the android kernel to break simple user land apps. You're supposed to use the Android NDK for building android native apps though,

There's however a few things that goes wrong when linking to glibc statically. Certain functions in glibc, e.g. for looking up user info, host names and other things that's normally configured in /etc/nsswitch.conf calls out to other shared libraries to actually do the work. This happens regardless of whether you link to glibc itself statically or not. These files are usually the /lib/libnss_* files found on glibc systems.

Most of those shared libraries are part of glibc, and would be installed on glibc systems. But they're not available on Android. Applications relying the funcions that uses these helper shared libs not work properly when these shared libraries are available - gethostbyname() is one of them, as for normal DNS queries it requres /lib/libnss_dns.so.2

这篇关于编译功能的gethostbyname C到静态链接错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆