29

How to resolve compile a static binary which code include a function gethostbyname and if compiled without warning like this:

warning: Using 'gethostbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking

I compile on ubuntu 12.04 with command:

$ gcc -static lookup.c -o lookup

This is code for 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;
  }

I want to if I check via $ file lookup will get output like this:

lookup: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.24, BuildID[sha1]=0x6fcb2684ad8e5e842036936abb50911cdde47c73, not stripped

Not like this:

lookup: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0xf9f18671751927bea80de676d207664abfdcf5dc, not stripped

If you commented with suggested I must use without static because different libc every linux I knew it, I hope you do not need to comment. Why do I persist in for static? Because there I need to do to mandatory use static, binary files must be static and not dynamic.

I have more than 2 weeks looking for this but so far have not succeeded.

Thanks for help me to resolve my heavy problem.

Loren Ramly
  • 1,091
  • 4
  • 13
  • 21
  • 2
    In short: don't link statically such a program. Link it dynamically, as usual, to your `libc.so` – Basile Starynkevitch Mar 01 '13 at 19:53
  • 1
    How to do it? what with -Bdynamic -lc -Wl ? – Loren Ramly Mar 01 '13 at 19:59
  • BorealId's answer explained. Basically `/etc/nsswitch.conf` uses `dlopen` for `gethostbyname` so needs a dynamically linked program (because the dynamic linker needs to be there). Just compile with `gcc -Wall -g -O lookup.c -o lookup` and your `lookup` will be dynamically linked. – Basile Starynkevitch Mar 01 '13 at 20:00
  • 2
    I know it, but I need to static, actually my main problem in here http://stackoverflow.com/questions/15118408/compile-c-with-function-gethostbyname-to-static-linked-error . There I create question, but until this time I not get solved. My problem why I need a static program. Because in order to can run on android device. If binary is dinamyc on android cannot accessed. – Loren Ramly Mar 01 '13 at 20:05
  • Try MUSL LIBC or Bionic LIBC – Basile Starynkevitch Mar 01 '13 at 20:10
  • OK I will looking for it and I will try your suggestion. Thanks Mr Basile. – Loren Ramly Mar 01 '13 at 20:15
  • 2
    @LorenRamly If you're switching to another libc, why not just use the Android NDK to compile your applications ? That's what you're supposed to do, and that will give you the bionic LIBC, and everything else you need to compile programs that run on android. –  Mar 01 '13 at 20:36
  • Solved with musl-libc. I compile mul-libc and then I compile my program use libraries musl-libc with command -L/path/tomuslcompiled/lib . I'm very2 happy, Thanks for Mr Basile and user964970. – Loren Ramly Mar 01 '13 at 21:16
  • Start now my program which there gethostbyname can run on android device if I compile with arm-none-linux-gnueabi-gcc. heheheheh I'm very2 happy :) – Loren Ramly Mar 01 '13 at 21:20
  • Are you using musl-libc in a C or C++ app? musl FAQ suggests rebuilding libstdc++ against musl in some cases. –  Sep 05 '14 at 17:42

4 Answers4

39

What you are asking for is going to be very difficult.

See this StackOverflow question about getaddrinfo. Basically, underneath getaddrinfo/gethostbyname is glibc's NSS layer. This allows a sysadmin to say "use DNS for resolving hostnames to IP addresses", or "use LDAP", or "don't use anything other than /etc/hosts". This control is at runtime; the sysadmin can at any point change the way hostnames are resolved to IPs.

Because of this flexibility, all of the name-resolution calls in glibc use helper libraries (plugins, basically) to do the grunt work of resolution. There's one shared library for LDAP addressing, one for files, one for DNS, one for YP, and so on and so on.

If you want your program to be 100% statically linked, you're going to have to go elsewhere (NOT gethostbyname) to convert a hostname to an IP address. You could do this with a resolver library like uDNS (not this exact one - there are similar tools available), but you should keep in mind that your binary is not going to do the right thing on systems which are configured not to use DNS!

Instead, I would recommend just leaving the program (technically) dynamically linked. If you really want to make sure it will run on any platform, you could even ship glibc with the binary - although doing this would require LGPL conformance. Leaving this one dynamic link in place will only mean you won't work on systems with the wrong glibc version - not a huge compatibility issue.

Speaking of license compliance, it's worth noting that if you statically link glibc, you most likely have to ship the source code for your entire application to comply with glibc's LGPL license. I am not a lawyer, and this is not qualified legal advice, but reading the LGPL makes it very clear that applications statically linking glibc must be open-source. See this StackOverflow question on the topic.

Community
  • 1
  • 1
Borealid
  • 95,191
  • 9
  • 106
  • 122
  • Hello Borealid thanks for your suggestion, I will accommodate first. – Loren Ramly Mar 01 '13 at 19:44
  • 6
    +1 for the license remind about LGPL in libc. Notice that some libc-s are not LGPL but MIT eg http://musl-libc.org/ – Basile Starynkevitch Mar 01 '13 at 19:54
  • 4
    Solved with musl-libc. I compile mul-libc and then I compile my program use libraries musl-libc with command -L/path/tomuslcompiled/lib . I'm very2 happy, Thanks Mr Borealid – Loren Ramly Mar 01 '13 at 21:14
  • @LorenRamly what do you do for gethostbyname() ? Do you dlopen/dlsym them from glibc? –  Aug 11 '15 at 07:14
  • 1
    @cap - No need for dlopen/dlsym. musl includes an implementation of gethostbyname() that doesn't need the glibc helper plugins. Look here - https://git.musl-libc.org/cgit/musl/tree/src/network – Andrew Bainbridge Jul 20 '16 at 17:21
  • AFAIk there is an exception to static linking against glibc, you can do that without shipping the entire source code of your project – A. Smoliak Dec 12 '21 at 14:54
14

I get the same warning and to fix it I recompiled glibc. Turn on switch --enable-static-nss when configuring to get it to work.

nkjt
  • 7,825
  • 9
  • 22
  • 28
kimi shi
  • 141
  • 1
  • 2
0

I have 2 answers -

  1. Keep the main part of your program statically linked, and separate out a single function program to just call gethostbyname(). Allow the latter to be dynamically linked. Using fork then exec execute this separate program to get the address for a domain name. Instead of fork then exec you could use system() though it takes longer (a whole millisecond) that should not be of concern since you're searching nameservers on the internet anyway, which takes a time.

  2. Write the source code to do the DNS, as I have done. Compile it into an archive (.a) and have it searched in the static linking.

Clive
  • 1
-1

use ip instead of using domain name, that work for me

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 13 '22 at 05:09