Подтвердить что ты не робот

Скомпилируйте статический двоичный код, в коде которого есть функция gethostbyname

Как разрешить компиляцию статического двоичного кода, в код которого входит функция gethostbyname и если она скомпилирована без предупреждения:

предупреждение: использование "gethostbyname" в статически связанных приложениях требует во время выполнения разделяемых библиотек из используемой версии glibc для связи

Я компилирую на ubuntu 12.04 с командой:

$ gcc -static lookup.c -o lookup

Это код для 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;
  }

Я хочу, если я проверю через $ 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, не раздевается

Если вы прокомментировали предложенное, я должен использовать его без статики, потому что каждый libc каждый linux я знал это, надеюсь, вам не нужно комментировать. Почему я настаиваю на статике? Поскольку мне нужно сделать обязательное использование static, двоичные файлы должны быть статичными, а не динамическими.

У меня есть более 2 недель, чтобы найти это, но до сих пор не удалось.

Спасибо, что помогли мне решить мою тяжелую проблему.

4b9b3361

Ответ 1

То, о чем вы просите, будет очень сложно.

Смотрите fooobar.com/questions/222445/.... В основном под getaddrinfo/gethostbyname находится glibc-уровень NSS. Это позволяет системному администратору сказать "использовать DNS для разрешения имен хостов на IP-адреса" или "использовать LDAP" или "не использовать ничего, кроме /etc/hosts". Этот элемент управления находится во время выполнения; sysadmin может в любой момент изменить способ определения имен хостов на IP-адреса.

Из-за этой гибкости все вызовы с разрешениями имен в glibc используют вспомогательные библиотеки (в основном, плагины), чтобы выполнить работу по разрешению. Там одна общая библиотека для адресации LDAP, одна для файлов, одна для DNS, одна для YP и т.д. И т.д.

Если вы хотите, чтобы ваша программа была статически привязана на 100%, вам нужно перейти в другое место (NOT gethostbyname), чтобы преобразовать имя хоста в IP-адрес. Вы можете сделать это с помощью библиотеки resolver, такой как uDNS (не это точно - есть похожие инструменты), но вы должны помните, что ваш двоичный файл не будет делать правильные вещи в системах, которые настроены не на использование DNS!

Вместо этого я бы рекомендовал просто оставить динамически связанную программу (технически). Если вы действительно хотите убедиться, что он будет работать на любой платформе, вы даже можете отправить glibc с двоичным кодом, хотя для этого потребуется соответствие LGPL. Оставляя эту динамическую ссылку на месте, будет означать, что вы не будете работать с системами с неправильной версией glibc, а не с большой проблемой совместимости.

Говоря о соблюдении лицензии, стоит отметить, что если вы статически связываете glibc, вам, скорее всего, придется отправить исходный код для всего вашего приложения в соответствии с лицензией glibc LGPL. Я не юрист, и это не квалифицированная юридическая консультация, но чтение LGPL дает понять, что приложения, статически связывающие glibc, должны быть открытыми. См. fooobar.com/questions/443446/....

Ответ 2

Я получаю такое же предупреждение и исправляю его. Я перекомпилировал glibc. Включите переключатель --enable-static-nss при настройке, чтобы заставить его работать.

Ответ 3

У меня есть 2 ответа -

  • Держите основную часть вашей программы статически связанной и выделите одну программу функций, чтобы просто вызвать gethostbyname(). Позволить последнему динамически связываться. Используя fork, exec выполнит эту отдельную программу, чтобы получить адрес для имени домена. Вместо fork then exec вы можете использовать system(), хотя требуется больше времени (целая миллисекунда), что не должно вызывать беспокойства, поскольку вы все равно ищете серверы имен в Интернете, что занимает некоторое время.

  • Напишите исходный код для DNS, как и я. Скомпилируйте его в архив (.a) и найдите в статической ссылке.