2013-02-27 290 views
3

我想用編譯程序使用函數gethostbyname()與交叉編譯器arm-none-linux-gnueabi,但它沒有工作時,我在Android上運行我的二進制文件。編譯C與函數gethostbyname靜態鏈接錯誤

我在下面的代碼:

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

我編譯arm-none-linux-gnueabi-gcc,在我的筆記本電腦,OS ubuntu 12.04和交叉編譯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 

然後我在我的chroot臂試驗二進制gethostbyname-example ,我複製粘貼二進制到chroot文件夾,然後我登錄到chroot,我執行,順便說一句,我從這裏做chroot https://wiki.ubuntu.com/ARM/BuildEABIChroot,如果我在chroot上運行它I得到的結果如下:

# ./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 

然後我也上傳二進制的gethostbyname,例如與亞行推到我的Android設備,如果我運行的二進制的gethostbyname,例如我得到如下錯誤:

# ./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 

在我的Android設備我已經在/ etc /和/系統的/ etc /文件主機與谷歌DNS

8.8.8.8 
8.8.4.4 

大概是什麼原因造成這種故障,

謝謝。在glibc的

+0

什麼樣的設備是你的手臂設備,你在chroot中運行它?這聽起來像你鏈接到glibc,它的運行時間可以在你的手臂設備上使用。在android上,沒有glibc。 – nos 2013-02-27 17:50:23

+0

我在這裏使用chroot https://wiki.ubuntu.com/ARM/BuildEABIChroot – 2013-02-27 17:53:41

+0

所以它基本上是Ubuntu的手臂構建,而不是任何Android的? – nos 2013-02-27 17:54:35

回答

3

簡短說明

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

另一個不同之處在於,Android存儲DNS設置/system/etc/resolv.conf,並且使用仿生C庫構建的原生Android應用程序將在那裏查找要查詢的DNS服務器。使用glibc構建的應用程序將顯示在Android上不存在的/etc/resolv.conf中。

較長的解釋

您已經構建使用glibc的二進制文件,而Android使用的仿生C庫。

這在靜態鏈接到libc時應該很好,因爲我沒有意識到android內核中有足夠嚴重的變化來破壞簡單的用戶登陸應用程序。儘管如此,您應該使用Android NDK來構建Android本機應用程序,但是,當鏈接到靜態的glibc時,會出現一些錯誤。 glibc中的某些函數,例如爲了查找用戶信息,通常在/etc/nsswitch.conf中配置的主機名和其他內容會調用其他共享庫來實際完成工作。無論您是否靜態鏈接到glibc,都會發生這種情況。這些文件通常是在glibc系統上找到的/ lib/libnss_ *文件。

大部分這些共享庫都是glibc的一部分,並且會安裝在glibc系統上。但他們不適用於Android。當這些共享庫可用時,依賴使用這些助手共享庫的funcions的應用程序無法正常工作 - gethostbyname()就是其中之一,對於正常的DNS查詢,它需要/lib/libnss_dns.so.2

+0

嗨,不管有沒有解決方案,請詳細給我提供解決方案,謝謝。 – 2013-02-28 03:22:35

+1

@LorenRamly解決方案是安裝Android NDK並使用它編譯適用於Android的本機應用程序。 – nos 2013-02-28 07:59:33

+0

除了使用仿生之外還有其他方法嗎?我必須使用使用glibc的arm-none-linux-gnueabi,將在arm-none-linux-gnueabi的glibc補丁中?感謝 – 2013-03-18 08:37:11

0

請參閱第答覆,該解決方案請按照下列步驟操作:

  • 下載Android NDK從這裏:https://developer.android.com/ndk/downloads/index.html(我用的Linux 64位)
  • 解壓android-ndk-r13b-linux-x86_64.zip
  • 在剛剛解壓的目錄進入
  • 啓動./build/tools/make_standalone_toolchain.py查看可能的選項
  • ./build/tools/make_standalone_toolchain.py --arch手臂--api 9
  • 工具可以鍛鍊手臂,Linux的androideabi.tar.bz2爲
  • 你解包用tar xjvf在arm-linux的-androideabi.tar。 BZ2
  • 它會創建./arm-linux-androideabi目錄
  • 現在你可以用./arm-linux-androideabi/bin/arm-linux-androideabi-gcc yourprog.c -o yourprog -pie
  • 編譯
  • -pie需要Android版本= 5
  • 您生成的可執行文件是本地文件,解析器將按預期工作