Привет из свободного от libc мира! (Часть 1)

Original author: Jessica McKellar
  • Translation
В качестве упражнения я хочу написать программу на С. Достаточно простую для того, чтобы дизассемблировать ее и объяснить весь код самой себе.

Звучит несложно, правильно?

У читателя предполагается наличие опыта компиляции программ и работы в Линуксе. Небольшое умение читать ассемблерный код тоже пригодится.

Итак, вот наш простейший хелловорлд:

jesstess@kid-charlemagne:~/c$ cat hello.c
#include <stdio.h>

int main()
{
	printf("Hello World\n");
	return 0;
}

Скомпилируем его и посчитаем количество символов:

jesstess@kid-charlemagne:~/c$ gcc -o hello hello.c
jesstess@kid-charlemagne:~/c$ wc -c hello
10931 hello

Фигасе! Откуда берутся эти 11 килобайт? objdump -t hello показывает 79 записей в таблице идентификаторов, за большинство из которых ответственна стандартная библиотека.

Так что мы не будем ее использовать. И printf мы тоже не будем использовать, чтобы избавиться от инклюда:

jesstess@kid-charlemagne:~/c$ cat hello.c
int main()
{
	char *str = "Hello World";
	return 0;
}

Перекомпилируем и пересчитаем количество символов:

jesstess@kid-charlemagne:~/c$ gcc -o hello hello.c
jesstess@kid-charlemagne:~/c$ wc -c hello
10892 hello

Почти ничего не изменилось? Ха!

Проблема в том, что gcc все ещё использует startup files (?) во время линкования. Доказательства? Скомпилируем с ключом -nostdlib, после чего (в соответствии с документацией) gcc «не будет использовать при линковании системные библиотеки и startup files. Использоваться будут только явно переданные линкеру файлы».

jesstess@kid-charlemagne:~/c$ gcc -nostdlib -o hello hello.c
/usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 00000000004000e8

Всего лишь предупреждение, все равно попробуем:

jesstess@kid-charlemagne:~/c$ wc -c hello
1329 hello

Выглядит неплохо! Мы уменьшили размер до значительно более вменяемого (аж на целый порядок!)…

jesstess@kid-charlemagne:~/c$ ./hello
Segmentation fault

…и заплатили за это сегфолтом. Блин.

Для развлечения сделаем нашу программу запускаемой до того, как начнем разбираться в ассемблере.

Что же делает символ _start, который похоже нужен для запуска программы? Где он обычно определяется при использовании libc?

По умолчанию с точки зрения линкера именно _start, а не main, является настоящей точкой входа в программу. Обычно _start определяется в перемещаемом ELF crt1.o. Убедимся в этом, слинковав хелловорлд c crt1.o и заметив, что _start теперь обнаруживается (но взамен появились другие проблемы из-за того, что не определены другие startup symbols libc):

# компилируем исходники не линкуя
jesstess@kid-charlemagne:~/c$ gcc -Os -c hello.c
# теперь попытаемся слинковать
jesstess@kid-charlemagne:~/c$ ld /usr/lib/crt1.o -o hello hello.o
/usr/lib/crt1.o: In function `_start':
/build/buildd/glibc-2.9/csu/../sysdeps/x86_64/elf/start.S:106: undefined reference to `__libc_csu_fini'
/build/buildd/glibc-2.9/csu/../sysdeps/x86_64/elf/start.S:107: undefined reference to `__libc_csu_init'
/build/buildd/glibc-2.9/csu/../sysdeps/x86_64/elf/start.S:113: undefined reference to `__libc_start_main'

Проверка сообщила, что на этом компьютере_start живет в исходнике libc: sysdeps/x86_64/elf/start.S. Этот восхитительно комментированный файл экспортирует символ _start, инициализирует стек, некоторые регистры и вызывает __libc_start_main. Если посмотреть в самый низ csu/libc-start.c, можно увидеть вызов _main нашей программы:

/* Ничего особенного, просто вызвать функцию  */
result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);

… и поехало.

Так вот зачем нужен _start. Для удобства подытожим происходящее между _start и вызовом main: инициализировать кучу вещей для libc и вызвать main. А раз libc нам не нужен, экспортируем собственный символ _start, который только и умеет, что вызывать main, и слинкуем с ним:

jesstess@kid-charlemagne:~/c$ cat stubstart.S
.globl _start

_start:
	call main

Скомпилируем и выполним хелловорлд с ассемблерной заглушкой _start:

jesstess@kid-charlemagne:~/c$ gcc -nostdlib stubstart.S -o hello hello.c
jesstess@kid-charlemagne:~/c$ ./hello
Segmentation fault

Ура, с компиляцией проблем больше нет. Но сегфолт никуда не делся. Почему? Скомпилируем с отладочной информацией и заглянем в gdb. Установим брейкпоинт на main и пошагово исполним программу до сегфолта:

jesstess@kid-charlemagne:~/c$ gcc -g -nostdlib stubstart.S -o hello hello.c
jesstess@kid-charlemagne:~/c$ gdb hello
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu"...
(gdb) break main
Breakpoint 1 at 0x4000f4: file hello.c, line 3.
(gdb) run
Starting program: /home/jesstess/c/hello

Breakpoint 1, main () at hello.c:5
5	  char *str = "Hello World";
(gdb) step
6	  return 0;
(gdb) step
7	}
(gdb) step
0x00000000004000ed in _start ()
(gdb) step
Single stepping until exit from function _start,
which has no line number information.
main () at helloint.c:4
4	{
(gdb) step

Breakpoint 1, main () at helloint.c:5
5	  char *str = "Hello World";
(gdb) step
6	  return 0;
(gdb) step
7	}
(gdb) step

Program received signal SIGSEGV, Segmentation fault.
0x0000000000000001 in ?? ()
(gdb)

Что? main исполняется два раза? …Пришло время взяться за ассемблер:

jesstess@kid-charlemagne:~/c$ objdump -d hello
hello:     file format elf64-x86-64
Disassembly of section .text:

00000000004000e8 <_start>:
  4000e8:	e8 03 00 00 00       	callq  4000f0
  4000ed:	90                   	nop
  4000ee:	90                   	nop
  4000ef:	90                   	nop    

00000000004000f0 :
  4000f0:	55                   	push   %rbp
  4000f1:	48 89 e5             	mov    %rsp,%rbp
  4000f4:	48 c7 45 f8 03 01 40 	movq   $0x400103,-0x8(%rbp)
  4000fb:	00
  4000fc:	b8 00 00 00 00       	mov    $0x0,%eax
  400101:	c9                   	leaveq
  400102:	c3                   	retq

Хех! Подробный разбор ассемблера оставим на потом, отметив вкратце следующее: после возврата из callq в main мы исполняем несколько nop и возвращаемся прямо в main. Поскольку повторный вход в main был осуществлен без установки указателя инструкции возврата на стеке (как части стандартной подготовки к вызову функции), второй вызов retq пытается достать из стека фиктивный указатель инструкции возврата и программа вылетает. Нужен способ завершения.

Буквально. После возврата из callq в %eax делается push 1, код системного вызова sys_exit, и т.к. нужно сообщить о правильном завершении кладем в %ebx 0, единственный аргумент SYS_exit. Теперь входим в ядро с прерыванием int $0x80.

jesstess@kid-charlemagne:~/c$ cat stubstart.S
.globl _start

_start:
	call main
	movl $1, %eax
	xorl %ebx, %ebx
	int $0x80
jesstess@kid-charlemagne:~/c$ gcc -nostdlib stubstart.S -o hello hello.c
jesstess@kid-charlemagne:~/c$ ./hello
jesstess@kid-charlemagne:~/c$

Ура! Программа компилируется, запускается, при прогоне через gdb даже нормально завершается.

Привет из свободного от libc мира!

Оставайтесь со мной, во второй части разберем ассемблерный код подробно, посмотрим что случится, если сделать программу более сложной, и еще немного разберемся в линковании, соглашениях о вызовах и структуре двоичного ELF файл в х86 архитектуре.

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 61

  • UFO just landed and posted this here
      +9
      Имхо, написано неплохо вне зависимости от пола.
      • UFO just landed and posted this here
        +21
        «для девушки очень неплохо написано» — для тролля так себе провокация.
        • UFO just landed and posted this here
          • UFO just landed and posted this here
            • UFO just landed and posted this here
          0
          Я хочу подчеркнуть что вы идиот и поставить вам за это минус :-)
          Хотя нет. Вы жирный и толстый. Обойдетесь.
          • UFO just landed and posted this here
            –2
            А я с тобой согласен полностью и не минусую ни разу, а кто минусует, тот не шарит. Только ты заметил, что это западная «девушка», блог расположен, там где занимаются ядром linux (видимо, поэтому и отвязка от userspace идет). А перевел, вроде, всеравно парень.
            • UFO just landed and posted this here
                –3
                А неважно. Я всегда могу просто ответить.
            +3
            А чем так плох libc кроме лишних 11Кб?
            ИМХО, сейчас очень редко 11Кб могут стать проблемой.
              +1
              Ничем не плох, смысл статьи вот же в чем:
              >В качестве упражнения я хочу написать программу на С. Достаточно простую для того, чтобы дизассемблировать ее и объяснить весь код самой себе.
                –3
                А зачем эти негодяи засовывают в мою программу 11 Кб ненужного кода? Какой-то индус-стайл подход!

                Кстати, сам libc мне тоже не нравится, весит по моему больше мегабайта, при том что ничего значительного не содержит, так, всякие вспомогательные функции.
                  +7
                  Да дело не в 11 кб, а в том, что автор заметила в поведении компилятора нечто, что не смогла объяснить, но не прошла мимо, а докопалась до истины. По-моему, это заслуживает глубокого респекта.
                  0
                  Расскажите какой быстрый и простой сделать расцветку кода, а то я не нашел как.
                    0
                      0
                      В хабраредакторе есть подсветка кода.
                        +1
                        Криво там реализовано, нужно же как:
                        а) идеальный вариант — вбил текст вперемежку с кодом, тапнул «тут есть код» и готово (а совсем идеальный — и тапать не надо);
                        б) годный вариант — выделил блок когда мышкой, тапнул кнопку «подсветить».

                        А не копипейстить туда-сюда. Пока что опробую pastebin.com или буду использовать тег pre.
                      +4
                      > char *str = «Hello World»;

                      const char *str
                        0
                        а почему? просто хороший тон?
                          0
                          Потому что строки-литералы — это константы и могут размещаться (и размещаются некоторыми компиляторами) в памяти только для чтения.
                        +3
                        «фигасе» (с), забавный хак :-), действительно было интересно, не часто встретишь достойное почитать, написаное достаточно легко, чтоб не напрягаться и достаточно сложно, чтоб не было скушно,
                        А вообще свободный од glibc мир — это uClibc, dietlibc, Newlib. С первой работал, вот такой простой примерчик занял у меня около 3 кб на SH4 архитектуре и около 14 на PPC405. Практически уверен, что для 386 архитектуры, собраный интеловским компилятором будет меньше 3кб.
                          +25
                          Кстати, фото автора ;)

                            –3
                            а по посту и не скажешь, habrahabr.ru/blogs/nix_coding/88101/#comment_2640714
                              +4
                              это как бы перевод ее поста/статьи…
                                +6
                                чёрт, я не понял намёка Z>Я!

                                где тут кнопка искреннего покаяния на хабре?
                                  +11
                                  Reset в профиле
                              +1
                              Вот сайт автора переведенной статьи
                              web.mit.edu/jesstess/www/
                              +1
                              Люблю вот такие вещи, поковыряться да посмотреть как оно там работает :-)
                                –2
                                Странный призыв: программировать на Си и Ассемблере, чтобы избавиться от libc :). А главное ещё 'добро пожаловать'. Чего-то мне кажется, что она в итоге начнёт фигачить ображение к системе через syscall'ы, и добра совсем от этого не прибавится. Надо было статью назвать как-то вроде: как происходит запуск программ в Linux.

                                P.S. Йэхъ. Побольше бы подобных русскоязычных деффушек :)
                                  0
                                  Если вам надо меньше кода, то лучше все же взять ulibc :)
                                    +1
                                    На второй странице программа перестает выводить Hello world, но главное, что автор — девушка.
                                      0
                                      Есть намек:
                                      >во второй части разберем ассемблерный код подробно, посмотрим что случится, если сделать программу более сложной
                                      +2
                                      Когда-то тоже игрался, убирал райнтайм. Бессмысленное занятие.
                                        +2
                                        Но интересно же!
                                          +3
                                          Бессмысленных занятий не так уж и много, и это тоже не быссмысленное. «Лучше ковыряться отладчиком в чужом коде, чем пальцем в собственной заднице» ©. А такие упражнения дают полезный опыт.
                                          +1
                                          захотелось даже снова за Си взяться :)
                                            +4
                                            Так, хорошо, от libc мы освободились. Теперь бы аналог банального printf…
                                              +3
                                              write() — оно почти ровно в syscall перейдет.

                                              Только форматирование — ручками. Но для hello world — вполне пойдет.
                                              0
                                              Крутооо!!!
                                              • UFO just landed and posted this here
                                                  0
                                                  Было бы там что-то длинное я бы нашел как подсветить, но там мало, и я счел, что усилия того не стоят. Да, в её блоге тоже не расцвечено. Но там удобнее немного читать, на хабре шрифт меньше.
                                                  +5
                                                  Выдержка из резюме «девочки»:

                                                  Projects and Awards
                                                  • (2009 ) Mobile Application Competition: wrote a location-aware, collaborative task manager
                                                  with persistent storage for the iPhone. Winner of the Qualcomm award.
                                                  • (2009 )Web Programming Competition (6.470): wrote a music-exploration website using AJAX,
                                                  JSON, PHP, and SQL. Finalist; honorable mention for “Best Minimalist Site”.
                                                  • (2008 ) Operating Systems Engineering (6.828): wrote a microkernel/exokernel hybrid OS in C
                                                  from scratch, including memory management, process creation, an Ethernet driver, and several
                                                  networking extensions to a lightweight TCP/IP stack including NAT, firewalls, and DNS resolution.
                                                  • (2008 ) MASLAB (Mobile Autonomous System Laboratory): built a fully autonomous,
                                                  vision-based robot with control software written in Java to navigate an unknown playing field.
                                                  • (2007 ) Autonomous Robotics Design Competition (6.270): built a fully autonomous, sensorbased
                                                  robot with control software written in C to compete against an opponent robot on a known
                                                  playing field.
                                                    +2
                                                    "wrote a microkernel/exokernel hybrid OS in C" вот это круто!!! Эх… надо догонять и перегонять Америку.
                                                      0
                                                      И? Я тоже ось пишу.
                                                      +1
                                                      А еще она участвует в разработке Twisted
                                                      +2
                                                      Написано красиво. С литературной точки зрения :)
                                                      А вот сама идея статьи и выеденного яйца не стоит. Потому как туториалов о программировании на асме под линукс дофига.

                                                      dchekmarev@dchekmarev:~$ cat test.s && as test.s -o test.o && ld test.o -o test && ls -l test* && ./test
                                                      .section .data
                                                      hello:
                                                      .ascii «hello, world!\n»
                                                      hello_len:
                                                      .long. — hello

                                                      .section .text
                                                      .globl _start

                                                      _start:

                                                      xorl %ebx, %ebx
                                                      movl $4, %eax
                                                      xorl %ebx, %ebx
                                                      incl %ebx
                                                      leal hello, %ecx
                                                      movl hello_len, %edx
                                                      int $0x80

                                                      xorl %eax, %eax
                                                      incl %eax
                                                      xorl %ebx, %ebx
                                                      int $0x80

                                                      -rwxr-xr-x 1 dchekmarev dchekmarev 640 2010-03-19 14:38 test
                                                      -rw-r--r-- 1 dchekmarev dchekmarev 624 2010-03-19 14:38 test.o
                                                      -rw-r--r-- 1 dchekmarev dchekmarev 317 2010-03-19 14:34 test.s
                                                      hello, world!
                                                      dchekmarev@dchekmarev:~$

                                                      Обидно, хоть и очевидно почему глупые статьи пытающихся разобраться нубов набирают тучу плюсов в то время как сложные для основной массы, пусть и полезные, статьи плюсов получают на порядки меньше.
                                                        +1
                                                        Это риторический вопрос, или ответить?
                                                          0
                                                          У меня это даже не вопрос был, а продолжение «повествовательного предложения»
                                                            +1
                                                            Я все же немножко разовью свою мысль. Хабр как точка запуска, перед ним не стоит задачи научить чему-то глубокому. Скорее дать некоторое представление или развлечь.

                                                            Вот есть вебдев, он кодит на flex и php, си знает чуть менее, чем никак. Прочитал статью — немножко расширил кругозор. Хорошо.

                                                            И так со всеми статьями. За глубокими же знаниями лезут в msdn или на форумы программистов. Это очевидно.

                                                            Или вот знакомство завязать. Тоже хорошо. Я через Хабр нашел на прошлую работу человека.

                                                            У Хабра своя задача, которую он, как я считаю, замечательно выполняет.

                                                            Это мысли вслух, конечно вы все это знаете ^__^
                                                        0
                                                        и все же круто!
                                                          0
                                                          Коллега, а Вы не хотите сделать доклад на РИТ++ (http://www.ritconf.ru/)?
                                                          Если интересно, то я могу выслать подробную информацию.
                                                            0
                                                            Когда-то проводил эксперименты с gcc и as. Но там ассемблер был.
                                                              0
                                                              Ну не знаю, на самом деле просто пишем (пример для x64)
                                                              void _start(void) {
                                                                  // stuff
                                                                  asm("xorq %rdi, %rdi");  // код выхода 0
                                                                  asm("movq $60, %rax"); // номер системного вызова 60 - exit
                                                                  asm("syscall"); // выход
                                                              };
                                                              

                                                              $ gcc -nostdlib -fomit-frame-pointer -Wl,--strip-all app.c -o app
                                                              

                                                              -fomit-frame-pointer — позволит избавиться от мусора в коде (возня со стеком)
                                                              -Wl,--strip-all — выпиливает символы (экспресс похудение)
                                                              776B — таков размер ELF-а
                                                              Обращаю Ваше внимание, что -nostdlib напрочь отменяет все подготовительные и завершающие процедуры. Конкретно: аргументов argc, argv, env не будет, ну и как Вы уже смогли убедиться — вызывать выход нужно вручную. Попробуйте заменить
                                                              asm("xorq %rdi, %rdi");
                                                              на
                                                              asm("movq $97, %rdi");
                                                              И после компиляции проверить с каким кодом завершилась суперфункциональная программа.
                                                              Для bash например это
                                                              $ echo $?
                                                              

                                                              Системная функция exit() принимает код возврата в %rid. А xorq %rdi, %rdi, уверен Вам известно — это обнуление регистра. Если нужны аргументы или переменные окружения, то они лежат в стеке и на самой верхушке лежит argc.

                                                              P.S.: приятно компилировать свою программку (не эту) на С с флагом -O3 и осознавать что бородатые дядьки, что пилят gcc применяют хвостовую рекурсию.
                                                                0
                                                                Не советую писать много asm подряд. Слейте их в один и разделите команды запятыми, потому что компилятор может их оптимизировать и даже местами поменять.
                                                                  0
                                                                  По большому счёту ещё и волатильность нужна, всякие там __подчёркивания__.
                                                                  void _start(void) {
                                                                  	// puts
                                                                  	char hw[] = "Hello, World!\n";
                                                                  	__asm__ __volatile__ ("movq $1, %%rax\n\t"
                                                                  		"movq $1, %%rdi\n\t"
                                                                  		"syscall"
                                                                  		:
                                                                  		: "S" (hw), "d" (sizeof(hw)-1) // S - %rsi, d - %rdx
                                                                  		: "%rax", "%rdi"
                                                                  		);
                                                                  	// exit
                                                                  	__asm__ __volatile__ ("xorq %%rdi, %%rdi\n\t"
                                                                  		"movq $60, %%rax\n\t"
                                                                  		"syscall"
                                                                  		:
                                                                  		:
                                                                  		: "%rdi", "%rax");
                                                                  };
                                                                  
                                                                    0
                                                                    Извините, если ошибся, но обязательны ли подчеркивания?
                                                                      0
                                                                      Нет не нужны. Для ANSI C они необходимы. Просто это хорошая практика и код так выглядит более устрашающим. По большому счёту и волатильность не нужна. У меня оптимизатор (-O3) всё портит не смотря на то — есть она или нет, фигня какая-то.
                                                                0
                                                                Пробовал чуть пошаманить, но в итоге не получилось, не понял, у меня похожая проблема, как вылечить то?

                                                                На CentOS6 — хочу сделать STATIC, для этого делаю:
                                                                sudo yum -y install centos-release-scl cmake3
                                                                sudo yum -y install devtoolset-7-gcc devtoolset-7-gcc-c++
                                                                sudo scl enable devtoolset-7 bash
                                                                export CC=/opt/rh/devtoolset-7/root/usr/bin/gcc
                                                                export CPP=/opt/rh/devtoolset-7/root/usr/bin/cpp
                                                                export CXX=/opt/rh/devtoolset-7/root/usr/bin/c++
                                                                export LIBS=/opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/libstdc++_nonshared.a
                                                                cmake3 . -DCMAKE_BUILD_TYPE=Release -DBUILD_STATIC=ON
                                                                make
                                                                


                                                                Получаю в итоге:

                                                                [ 95%] Building CXX object CMakeFiles/xmrig-notls.dir/src/crypto/Asm.cpp.o
                                                                [ 97%] Building CXX object CMakeFiles/xmrig-notls.dir/src/crypto/cn_gpu_avx.cpp.o
                                                                [ 98%] Building CXX object CMakeFiles/xmrig-notls.dir/src/crypto/cn_gpu_ssse3.cpp.o
                                                                [100%] Linking CXX executable xmrig-notls
                                                                /opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: cannot find -lpthread
                                                                /opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: cannot find -lrt
                                                                /opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: cannot find -ldl
                                                                /opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: cannot find -lm
                                                                /opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: cannot find -lc
                                                                collect2: error: ld returned 1 exit status
                                                                make[2]: *** [CMakeFiles/xmrig-notls.dir/build.make:1633: xmrig-notls] Error 1
                                                                make[1]: *** [CMakeFiles/Makefile2:106: CMakeFiles/xmrig-notls.dir/all] Error 2
                                                                make: *** [Makefile:84: all] Error 2
                                                                [root@localhost build]#
                                                                


                                                                Запускаю ld -lpthread --verbose и вижу:
                                                                ==================================================
                                                                attempt to open //opt/rh/devtoolset-6/root/usr/x86_64-redhat-linux/lib64/libpthread.so failed
                                                                attempt to open //opt/rh/devtoolset-6/root/usr/x86_64-redhat-linux/lib64/libpthread.a failed
                                                                attempt to open //opt/rh/devtoolset-6/root/usr/lib64/libpthread.so failed
                                                                attempt to open //opt/rh/devtoolset-6/root/usr/lib64/libpthread.a failed
                                                                attempt to open //usr/local/lib64/libpthread.so failed
                                                                attempt to open //usr/local/lib64/libpthread.a failed
                                                                attempt to open //lib64/libpthread.so failed
                                                                attempt to open //lib64/libpthread.a failed
                                                                attempt to open //usr/lib64/libpthread.so succeeded
                                                                opened script file //usr/lib64/libpthread.so
                                                                opened script file //usr/lib64/libpthread.so
                                                                attempt to open /lib64/libpthread.so.0 succeeded
                                                                /lib64/libpthread.so.0
                                                                attempt to open /usr/lib64/libpthread_nonshared.a succeeded
                                                                libc.so.6 needed by /lib64/libpthread.so.0
                                                                found libc.so.6 at //lib64/libc.so.6
                                                                ld-linux-x86-64.so.2 needed by /lib64/libpthread.so.0
                                                                found ld-linux-x86-64.so.2 at //lib64/ld-linux-x86-64.so.2
                                                                ld: warning: cannot find entry symbol _start; not setting start address


                                                                Куда дальше копать то?

                                                                Only users with full accounts can post comments. Log in, please.