问题
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.
回答1:
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
回答2:
for the explanation refer to nos reply, for the solution follow these steps:
- download android NDK from here: https://developer.android.com/ndk/downloads/index.html (I used linux 64bit)
- unzip
android-ndk-r13b-linux-x86_64.zip
- enter in the just unpacked directory
- launch ./build/tools/make_standalone_toolchain.py to see possible options
- e.g. ./build/tools/make_standalone_toolchain.py --arch arm --api 9
- the tool will build arm-linux-androideabi.tar.bz2 for you
- unpack with tar xjvf arm-linux-androideabi.tar.bz2
- it will create ./arm-linux-androideabi directory
- now you can compile with ./arm-linux-androideabi/bin/arm-linux-androideabi-gcc yourprog.c -o yourprog -pie
- -pie is needed for Android >= 5
- your generated executable is native and the resolver will work as expected
来源:https://stackoverflow.com/questions/15118408/compile-c-with-function-gethostbyname-to-static-linked-error