Скомпилируйте статический двоичный код, в котором кодируется функция 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, получится такой вывод:

поиск: 32-разрядный исполняемый файл LSB ELF, Intel 80386, версия 1 (GNU / Linux), статически связанный, для GNU / Linux 2.6.24, BuildID [sha1] = 0x6fcb2684ad8e5e842036936abb50911cdde47c73, без удаления

Не так:

поиск: 32-разрядный исполняемый файл LSB ELF, Intel 80386, версия 1 (SYSV), динамически связанный (использует общие библиотеки), для GNU / Linux 2.6.24, BuildID [sha1] = 0xf9f18671751927bea80de676d207664abfdcf5dc, без удаления

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

Я искал это более 2 недель, но пока не удалось.

Спасибо за помощь в решении моей тяжелой проблемы.


person Loren Ramly    schedule 01.03.2013    source источник
comment
Вкратце: не связывайте такую ​​программу статически. Свяжите его динамически, как обычно, с вашим libc.so   -  person Basile Starynkevitch    schedule 01.03.2013
comment
Как это сделать? что с -Bdynamic -lc -Wl?   -  person Loren Ramly    schedule 01.03.2013
comment
Ответ BorealId объяснен. Обычно /etc/nsswitch.conf использует dlopen вместо gethostbyname, поэтому нужна динамически связанная программа (потому что там должен быть динамический компоновщик). Просто скомпилируйте с gcc -Wall -g -O lookup.c -o lookup, и ваш lookup будет динамически связан.   -  person Basile Starynkevitch    schedule 02.03.2013
comment
Я знаю это, но мне нужно статическое, на самом деле моя основная проблема здесь stackoverflow.com/questions/15118408/. Там я задаю вопрос, но до сих пор не решен. Моя проблема, зачем мне статическая программа. Потому что для того, чтобы можно было работать на устройстве Android. Если двоичный файл является динамическим, на Android невозможно получить доступ.   -  person Loren Ramly    schedule 02.03.2013
comment
Попробуйте MUSL LIBC или Bionic LIBC   -  person Basile Starynkevitch    schedule 02.03.2013
comment
Хорошо, я поищу его и попробую ваше предложение. Спасибо, мистер Базиль.   -  person Loren Ramly    schedule 02.03.2013
comment
@LorenRamly Если вы переключаетесь на другую libc, почему бы просто не использовать Android NDK для компиляции ваших приложений? Это то, что вы должны делать, и это даст вам бионический LIBC и все остальное, что вам нужно для компиляции программ, работающих на Android.   -  person user964970    schedule 02.03.2013
comment
Решено с помощью musl-libc. Я компилирую mul-libc, а затем компилирую свою программу с использованием библиотек musl-libc с помощью команды -L / path / tomuslcompiled / lib. Я очень2 счастлив, спасибо господину Базилу и user964970.   -  person Loren Ramly    schedule 02.03.2013
comment
Запустите сейчас мою программу, которую gethostbyname может запускать на устройстве Android, если я скомпилирую с помощью arm-none-linux-gnueabi-gcc. хе-хе-хе я очень2 доволен :)   -  person Loren Ramly    schedule 02.03.2013
comment
Вы используете musl-libc в приложении на C или C ++? Часто задаваемые вопросы по musl предлагают в некоторых случаях перестроить libstdc ++ вместо musl.   -  person    schedule 05.09.2014


Ответы (3)


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

См. этот вопрос StackOverflow о getaddrinfo. По сути, под _1 _ / _ 2_ находится слой NSS в glibc. Это позволяет системному администратору сказать «использовать DNS для преобразования имен хостов в IP-адреса», или «использовать LDAP», или «не использовать ничего, кроме /etc/hosts». Этот элемент управления находится во время выполнения; системный администратор может в любой момент изменить способ преобразования имен хостов в IP-адреса.

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

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

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

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

person Borealid    schedule 01.03.2013
comment
Здравствуйте, Borealid, спасибо за ваше предложение, сначала я учту. - person Loren Ramly; 01.03.2013
comment
+1 за лицензию напомнить про LGPL в libc. Обратите внимание на то, что некоторые libc-ы не LGPL, а MIT, например, musl-libc.org - person Basile Starynkevitch; 01.03.2013
comment
Решено с помощью musl-libc. Я компилирую mul-libc, а затем компилирую свою программу с использованием библиотек musl-libc с помощью команды -L / path / tomuslcompiled / lib. Я очень счастлива, спасибо, мистер Бореалид - person Loren Ramly; 02.03.2013
comment
@LorenRamly, что вы делаете для gethostbyname ()? Вы их dlopen / dlsym из glibc? - person ; 11.08.2015
comment
@cap - Нет необходимости в dlopen / dlsym. musl включает реализацию gethostbyname (), для которой не нужны вспомогательные плагины glibc. Посмотрите здесь - git.musl-libc.org/cgit/musl/tree / src / network - person Andrew Bainbridge; 20.07.2016

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

person kimi shi    schedule 18.02.2014

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

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

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

person Clive    schedule 26.01.2014