Your SlideShare is downloading. ×
0
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Александр Сомов "C++: препроцессор, компилятор, компоновщик"
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Александр Сомов "C++: препроцессор, компилятор, компоновщик"

1,178

Published on

Из этого доклада вы узнаете, как разбирать различные ошибки сборки C++, как их исправлять и что для этого нужно знать. …

Из этого доклада вы узнаете, как разбирать различные ошибки сборки C++, как их исправлять и что для этого нужно знать.

Речь пойдет о стадиях сборки программы на C++ и о том, как устроены объектные файлы (на примере формата ELF), о работе компилятора и компоновщика, а также особенностях, связанных со спецификой языка. В заключительной части доклада будут разобраны принципы работы препроцессора C++ и способы его отладки.

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,178
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
6
Comments
0
Likes
3
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. C++: препроцессор, компилятор, компоновщик Сомов Александр C++ party, Новосибирск
  • 2. Содержание Сборка программы Как устроен процесс сборки Какие файлы создаются, как они устроены, что содержат Особенности сборки C и C++ Использующиеся программы Препроцессор и его отладка Детали языка (inline, static и так далее) Стандартная библиотека 3
  • 3. Сборка и объектные файлы 4
  • 4. int sum(int a, int b); int main() { int result = sum(1, 2); return result * 2; } main.c 5 int sum(int a, int b) { return a + b; } sum.c
  • 5. $ gcc -o program main.c sum.c $ ./program; echo $? 6 Собираем 6
  • 6. $ gcc -c main.c $ gcc -c sum.c $ ls main.c main.o sum.c sum.o $ gcc -o program main.o sum.o $ ./program; echo $? 6 Собираем 7
  • 7. Объектные файлы Содержимое Машинный код Секции дополнительных данных – От чего зависит и какие зависимости предоставляет – Как загружать – Как запускать Использование Промежуточные объектные файлы – Код отдельных частей программы Исполняемый файл 8
  • 8. Executable and Linkable ОС Linux FreeBSD Утилиты objdump – Binary File Descriptor library readelf 9
  • 9. $ gcc -c main.c $ gcc -c sum.c $ ls main.c main.o sum.c sum.o $ gcc -o program main.o sum.o $ ./program; echo $? 6 Собираем 10
  • 10. Процесс Компиляция (compile) C++ → машинный код Один исходный файл → один объектный файл Компоновка (link) Объектные файлы → исполняемый файл Сборка (build) Всё вместе 11
  • 11. Символы и релокации 12
  • 12. sum.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <sum>: 0:! 55 ! push %rbp 1:! 48 89 e5 ! mov %rsp,%rbp 4:! 89 7d fc ! mov %edi,-0x4(%rbp) 7:! 89 75 f8 ! mov %esi,-0x8(%rbp) a:! 8b 45 f8 ! mov -0x8(%rbp),%eax d:! 8b 55 fc ! mov -0x4(%rbp),%edx 10:! 01 d0 ! add %edx,%eax 12:! 5d ! pop %rbp 13:! c3 ! retq objdump -d -r sum.o 13
  • 13. main.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <main>: 0:! 55 ! push %rbp 1:! 48 89 e5 ! mov %rsp,%rbp 4:! 48 83 ec 10 ! sub $0x10,%rsp 8:! be 02 00 00 00 ! mov $0x2,%esi d:! bf 01 00 00 00 ! mov $0x1,%edi 12:! e8 00 00 00 00 ! callq 17 <main+0x17> ! ! ! 13: R_X86_64_PC32! sum-0x4 17:! 89 45 fc ! mov %eax,-0x4(%rbp) 1a:! 8b 45 fc ! mov -0x4(%rbp),%eax 1d:! 01 c0 ! add %eax,%eax 1f:! c9 ! leaveq objdump -d -r main.o 14
  • 14. Symbol table '.symtab' contains 10 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 00000000 0 FILE LOCAL DEFAULT ABS main.c 2: 00000000 0 SECTION LOCAL DEFAULT 1 3: 00000000 0 SECTION LOCAL DEFAULT 3 4: 00000000 0 SECTION LOCAL DEFAULT 4 5: 00000000 0 SECTION LOCAL DEFAULT 6 6: 00000000 0 SECTION LOCAL DEFAULT 7 7: 00000000 0 SECTION LOCAL DEFAULT 5 8: 00000000 33 FUNC GLOBAL DEFAULT 1 main 9: 00000000 0 NOTYPE GLOBAL DEFAULT UND sum readelf -s main.o 15
  • 15. Символы Имя — произвольная строка Значение — 64-битное число (адрес, смещение и т. д.) Свойства Тип Видимость – локальный символ – глобальный символ – внешний символ 16
  • 16. Symbol table '.symtab' contains 10 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 00000000 0 FILE LOCAL DEFAULT ABS main.c 2: 00000000 0 SECTION LOCAL DEFAULT 1 3: 00000000 0 SECTION LOCAL DEFAULT 3 4: 00000000 0 SECTION LOCAL DEFAULT 4 5: 00000000 0 SECTION LOCAL DEFAULT 6 6: 00000000 0 SECTION LOCAL DEFAULT 7 7: 00000000 0 SECTION LOCAL DEFAULT 5 8: 00000000 33 FUNC GLOBAL DEFAULT 1 main 9: 00000000 0 NOTYPE GLOBAL DEFAULT UND sum readelf -s main.o 17
  • 17. Секции 18
  • 18. main.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <main>: 0:! 55 ! push %rbp 1:! 48 89 e5 ! mov %rsp,%rbp 4:! 48 83 ec 10 ! sub $0x10,%rsp 8:! be 02 00 00 00 ! mov $0x2,%esi d:! bf 01 00 00 00 ! mov $0x1,%edi 12:! e8 00 00 00 00 ! callq 17 <main+0x17> ! ! ! 13: R_X86_64_PC32! sum-0x4 17:! 89 45 fc ! mov %eax,-0x4(%rbp) 1a:! 8b 45 fc ! mov -0x4(%rbp),%eax 1d:! 01 c0 ! add %eax,%eax 1f:! c9 ! leaveq objdump -d -r main.o 19
  • 19. Секции Именованный блок данных в объектном файле .text — код программы .data — статически инициализированные данные .symtab — таблица символов Тип секции Код Статические данные Таблицы символов Таблицы строк 20
  • 20. … [ 1] .text PROGBITS PROGBITS 00000000 00000040 0 00000021 00000000 0 1 [00000006]: ALLOC, EXEC … [ 3] .data PROGBITS PROGBITS 00000000 00000061 0 00000000 00000000 0 1 [00000003]: WRITE, ALLOC … [10] .symtab SYMTAB SYMTAB 00000000 00000420 11 000000f0 00000018 8 8 [00000000]: … readelf -t main.o 21
  • 21. Компоновщик Оперирует секциями Слить несколько секций в одну Оставить один экземпляр Определяет базовые адреса секций Релоцирует код, используя символы Формирует исполняемый файл 22
  • 22. Исполняемый файл 23
  • 23. 000000000040050e <sum>: 40050e:!55 ! push %rbp 40050f:!48 89 e5 ! mov %rsp,%rbp 400512:!89 7d fc ! mov %edi,-0x4(%rbp) 400515:!89 75 f8 ! mov %esi,-0x8(%rbp) 400518:!8b 45 f8 ! mov -0x8(%rbp),%eax 40051b:!8b 55 fc ! mov -0x4(%rbp),%edx 40051e:!01 d0 ! add %edx,%eax 400520:!5d ! pop %rbp 400521:!c3 ! retq objdump -d -r program 24
  • 24. 00000000004004ed <main>: 4004ed:!55 ! push %rbp 4004ee:!48 89 e5 ! mov %rsp,%rbp 4004f1:!48 83 ec 10 ! sub $0x10,%rsp 4004f5:!be 02 00 00 00 ! mov $0x2,%esi 4004fa:!bf 01 00 00 00 ! mov $0x1,%edi 4004ff:!e8 0a 00 00 00 ! callq 40050e <sum> 400504:!89 45 fc ! mov %eax,-0x4(%rbp) 400507:!8b 45 fc ! mov -0x4(%rbp),%eax 40050a:!01 c0 ! add %eax,%eax 40050c:!c9 ! leaveq 40050d:!c3 ! retq objdump -d -r program 25
  • 25. ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: REL (Relocatable file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x0 Start of program headers: 0 (bytes into file) Start of section headers: 288 (bytes into file) Flags: 0x0 readelf -h main.o 26
  • 26. ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x400400 Start of program headers: 64 (bytes into file) Start of section headers: 4456 (bytes into file) Flags: 0x0 readelf -h program 27
  • 27. Соглашение о вызове (calling convention) 28
  • 28. main.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <main>: 0:! 55 ! push %rbp 1:! 48 89 e5 ! mov %rsp,%rbp 4:! 48 83 ec 10 ! sub $0x10,%rsp 8:! be 02 00 00 00 ! mov $0x2,%esi d:! bf 01 00 00 00 ! mov $0x1,%edi 12:! e8 00 00 00 00 ! callq 17 <main+0x17> ! ! ! 13: R_X86_64_PC32! sum-0x4 17:! 89 45 fc ! mov %eax,-0x4(%rbp) 1a:! 8b 45 fc ! mov -0x4(%rbp),%eax 1d:! 01 c0 ! add %eax,%eax 1f:! c9 ! leaveq objdump -d -r main.o 29
  • 29. System V AMD64 ABI Первые 6 целочисленных аргументов и указателей rdi, rsi, rdx, rcx, r8, r9 Типы с плавающей точкой xmm0-xmm7 Остальное на стеке Возвращаемое значение rax 30
  • 30. Препроцессор 31
  • 31. int sum(int a, int b); int main() { int result = sum(1, 2); return result * 2; } main.c 32 int sum(int a, int b) { return a + b; } sum.c
  • 32. #include "sum.h" int main() { int result = sum(1, 2); return result * 2; } main.c 33 int sum(int a, int b); sum.h
  • 33. # 1 "main.c" # 1 "<command-line>" # 1 "/usr/include/stdc-predef.h" 1 3 4 # 1 "<command-line>" 2 # 1 "main.c" # 1 "sum.h" 1 int sum(int a, int b); # 2 "main.c" 2 int main() { int result = sum(1, 2); return result * 2; } gcc -E main.c 34
  • 34. Препроцессор Обрабатывает текст #include — подстановка содержимого другого файла – расширение не важно — хоть *.txt, хоть *.exe – *.h — удобное соглашение #ifdef/#endif — выборочное включение/исключение текста 35
  • 35. Процесс сборки и использующиеся программы 36
  • 36. Сборка Препроцессинг (preprocess) C/C++ с директивами препроцессора → C/C++ Исходный файл + заголовочные файлы → один исходный файл Компиляция (compile) C/C++ → машинный код Один исходный файл → один объектный файл Компоновка (link) Объектные файлы → исполняемый файл 37
  • 37. Программы Препроцессор cc1 Компилятор cc1, as Компоновщик ld (collect2) 38
  • 38. … /usr/lib/gcc/x86_64-linux-gnu/4.8/cc1 -quiet -v -imultiarch x86_64-linux-gnu main.c -quiet -dumpbase main.c - mtune=generic -march=x86-64 -auxbase main -version - fstack-protector -Wformat -Wformat-security -o /tmp/ ccsJ9O2h.s … as -v --64 -o /tmp/ccPe5usI.o /tmp/ccsJ9O2h.s … /usr/lib/gcc/x86_64-linux-gnu/4.8/cc1 -quiet -v -imultiarch x86_64-linux-gnu sum.c -quiet -dumpbase sum.c - mtune=generic -march=x86-64 -auxbase sum -version - fstack-protector -Wformat -Wformat-security -o /tmp/ ccsJ9O2h.s … as -v --64 -o /tmp/ccSAbeU8.o /tmp/ccsJ9O2h.s … gcc -o program -v main.c 39
  • 39. /usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ -- build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu -- as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o program /usr/lib/gcc/x86_64-linux-gnu/ 4.8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64- linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/ gcc/x86_64-linux-gnu/4.8/crtbegin.o -L/usr/lib/gcc/ x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/ 4.8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64- linux-gnu/4.8/../../../../lib -L/lib/x86_64-linux-gnu -L/ lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. /tmp/ ccPe5usI.o /tmp/ccSAbeU8.o -lgcc --as-needed -lgcc_s -- no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as- needed /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/ lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/ crtn.o gcc -o program -v main.c 40
  • 40. Сборка Препроцессинг — сс1 С/C++ с директивами препроцессора → C++ Компиляция — cc1, as С/C++ → ассемблер → машинный код Один исходный файл → один объектный файл Компоновка — ld (collect2) Объектные файлы → исполняемый файл 41
  • 41. Детали работы препроцессора 42
  • 42. #include "sum.h" int main() { int result = sum(1, 2); return result * 2; } main.c 43 #include <sum.h> int main() { int result = sum(1, 2); return result * 2; } main.c
  • 43. "sum.h" vs <sum.h> Разные списки директорий, в которых препроцессор ищет файл Если файл "sum.h" не найден, он ищется как <sum.h> Соглашение "sum.h" — локальный файл – Сначала ищется в текущей директории <sum.h> — системный файл 44
  • 44. … ignoring nonexistent directory "/usr/local/include/x86_64- linux-gnu" ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux- gnu/4.8/../../../../x86_64-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /usr/lib/gcc/x86_64-linux-gnu/4.8/include /usr/local/include /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed /usr/include/x86_64-linux-gnu /usr/include End of search list. … gcc -o program -v main.c 45
  • 45. Опции препроцессора Директории -Idir — добавить dir в начало обоих списков -iquotedir — добавить dir в начало списка для #include "file" Отладка -H — вывести дерево #include -dM — вывести #define для всех предопределённых переменных -dD — оставить директивы #define в обработанном файле -dI — оставить директивы #include в обработанном файле -P — не генерировать номера строк 46
  • 46. #include <stdio.h> int main() { puts("Hello, world!"); return 0; } main.c 47
  • 47. . /usr/include/stdio.h .. /usr/include/features.h ... /usr/include/x86_64-linux-gnu/sys/cdefs.h .... /usr/include/x86_64-linux-gnu/bits/wordsize.h ... /usr/include/x86_64-linux-gnu/gnu/stubs.h .... /usr/include/x86_64-linux-gnu/gnu/stubs-64.h .. /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h .. /usr/include/x86_64-linux-gnu/bits/types.h ... /usr/include/x86_64-linux-gnu/bits/wordsize.h ... /usr/include/x86_64-linux-gnu/bits/typesizes.h .. /usr/include/libio.h ... /usr/include/_G_config.h .... /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h .... /usr/include/wchar.h ... /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h .. /usr/include/x86_64-linux-gnu/bits/stdio_lim.h … gcc -E -H main.c > main.i 48
  • 48. $ wc main.i 841 2073 17138 main.i 49
  • 49. Ошибки сборки 50
  • 50. Ошибки сборки Ошибки multiple definition of `sum' undefined reference to `sum' too many arguments to function ‘sum’ Поиск причины gcc -v — что компилируется и компонуется gcc -E — результат препроцессинга, какие сигнатуры используются readelf -s — какие символы в объектном файле, какие символы — внешние objdump -d -r — где используются внешние символы 51
  • 51. С++ 52
  • 52. int sum(int a, int b); int main() { int result = sum(1, 2); return result * 2; } main.cpp 53 int sum(int a, int b) { return a + b; } sum.cpp
  • 53. sum.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <_Z3sumii>: 0:! 55 ! push %rbp 1:! 48 89 e5 ! mov %rsp,%rbp 4:! 89 7d fc ! mov %edi,-0x4(%rbp) 7:! 89 75 f8 ! mov %esi,-0x8(%rbp) a:! 8b 45 f8 ! mov -0x8(%rbp),%eax d:! 8b 55 fc ! mov -0x4(%rbp),%edx 10:! 01 d0 ! add %edx,%eax 12:! 5d ! pop %rbp 13:! c3 ! retq objdump -d -r sum.o 54
  • 54. $ echo _Z3sumii | c++filt sum(int, int) Декорирование (mangling) 55
  • 55. sum.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <sum(int, int)>: 0:! 55 ! push %rbp 1:! 48 89 e5 ! mov %rsp,%rbp 4:! 89 7d fc ! mov %edi,-0x4(%rbp) 7:! 89 75 f8 ! mov %esi,-0x8(%rbp) a:! 8b 45 f8 ! mov -0x8(%rbp),%eax d:! 8b 55 fc ! mov -0x4(%rbp),%edx 10:! 01 d0 ! add %edx,%eax 12:! 5d ! pop %rbp 13:! c3 ! retq objdump -d -r -C sum.o 56
  • 56. … /usr/lib/gcc/x86_64-linux-gnu/4.8/cc1plus -quiet -v - imultiarch x86_64-linux-gnu -D_GNU_SOURCE sum.cpp -quiet -dumpbase sum.cpp -mtune=generic -march=x86-64 -auxbase sum -version -fstack-protector -Wformat -Wformat-security -o /tmp/cco5ypSz.s … gcc -v main.cpp sum.cpp 57
  • 57. С++ inline 58
  • 58. inline int sum(int a, int b) { return a + b; } int main() { int result = sum(1, 2); return result * 2; } main.cpp 59 inline int sum(int a, int b) { return a + b; } int calc() { return sum(2, 3); } sum.cpp
  • 59. Disassembly of section .text: 0000000000000000 <_Z4calcv>: 0:! 55 ! push %rbp 1:! 48 89 e5 ! mov %rsp,%rbp 4:! be 03 00 00 00 ! mov $0x3,%esi 9:! bf 02 00 00 00 ! mov $0x2,%edi e:! e8 00 00 00 00 ! callq 13 <_Z4calcv+0x13> ! ! ! f: R_X86_64_PC32! _Z3sumii-0x4 13:! 5d ! pop %rbp 14:! c3 ! retq objdump -d -r sum.o 60
  • 60. Disassembly of section .text._Z3sumii: 0000000000000000 <_Z3sumii>: 0:! 55 ! push %rbp 1:! 48 89 e5 ! mov %rsp,%rbp 4:! 89 7d fc ! mov %edi,-0x4(%rbp) 7:! 89 75 f8 ! mov %esi,-0x8(%rbp) a:! 8b 45 f8 ! mov -0x8(%rbp),%eax d:! 8b 55 fc ! mov -0x4(%rbp),%edx 10:! 01 d0 ! add %edx,%eax 12:! 5d ! pop %rbp 13:! c3 ! retq objdump -d -r sum.o 61
  • 61. … [ 6] .text._Z3sumii PROGBITS PROGBITS 00000000 0000005d 0 00000014 00000000 0 1 [00000206]: ALLOC, EXEC, GROUP … readelf -t sum.o 62
  • 62. С и C++ static 63
  • 63. static int sum(int a, int b) { return a + b; } sum.c 64
  • 64. Symbol table '.symtab' contains 9 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 00000000 0 FILE LOCAL DEFAULT ABS sum.c 2: 00000000 0 SECTION LOCAL DEFAULT 1 3: 00000000 0 SECTION LOCAL DEFAULT 2 4: 00000000 0 SECTION LOCAL DEFAULT 3 5: 00000000 20 FUNC LOCAL DEFAULT 1 sum 6: 00000000 0 SECTION LOCAL DEFAULT 5 7: 00000000 0 SECTION LOCAL DEFAULT 6 8: 00000000 0 SECTION LOCAL DEFAULT 4 readelf -s sum.o 65
  • 65. main.o: In function `main': main.c:(.text+0x13): undefined reference to `sum' collect2: error: ld returned 1 exit status gcc -o program sum.o main.o 66
  • 66. C++ extern "C" 67
  • 67. extern "C" { int sum(int a, int b) { return a + b; } } extern.cpp 68
  • 68. Disassembly of section .text: 0000000000000000 <sum>: 0:! 55 ! push %rbp 1:! 48 89 e5 ! mov %rsp,%rbp 4:! 89 7d fc ! mov %edi,-0x4(%rbp) 7:! 89 75 f8 ! mov %esi,-0x8(%rbp) a:! 8b 45 f8 ! mov -0x8(%rbp),%eax d:! 8b 55 fc ! mov -0x4(%rbp),%edx 10:! 01 d0 ! add %edx,%eax 12:! 5d ! pop %rbp 13:! c3 ! retq objdump -d -r extern.o 69
  • 69. Стандартная библиотека 70
  • 70. int sum(int a, int b); int main() { int result = sum(1, 2); return result * 2; } main.c 71 int sum(int a, int b) { return a + b; } sum.c
  • 71. 00000000004004ed <main>: 4004ed:!55 ! push %rbp 4004ee:!48 89 e5 ! mov %rsp,%rbp 4004f1:!48 83 ec 10 ! sub $0x10,%rsp 4004f5:!be 02 00 00 00 ! mov $0x2,%esi 4004fa:!bf 01 00 00 00 ! mov $0x1,%edi 4004ff:!e8 0a 00 00 00 ! callq 40050e <sum> 400504:!89 45 fc ! mov %eax,-0x4(%rbp) 400507:!8b 45 fc ! mov -0x4(%rbp),%eax 40050a:!01 c0 ! add %eax,%eax 40050c:!c9 ! leaveq 40050d:!c3 ! retq objdump -d -r program 72
  • 72. ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x400400 Start of program headers: 64 (bytes into file) Start of section headers: 4456 (bytes into file) Flags: 0x0 readelf -h program 73
  • 73. Disassembly of section .text: 0000000000400400 <_start>: 400400: 31 ed xor %ebp,%ebp 400402: 49 89 d1 mov %rdx,%r9 … 40041d: 48 c7 c7 ed 04 40 00 mov $0x4004ed,%rdi 400424: e8 b7 ff ff ff callq 4003e0 <__libc_start_main@plt> 400429: f4 hlt objdump -d -r program 74
  • 74. __libc_start_main(…) { argc = … argv = … some_libc_init(); exit(main(argc, argv)); } __libc_start_main 75
  • 75. /usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ -- build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu -- as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o program /usr/lib/gcc/x86_64-linux-gnu/ 4.8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64- linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/ gcc/x86_64-linux-gnu/4.8/crtbegin.o -L/usr/lib/gcc/ x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/ 4.8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64- linux-gnu/4.8/../../../../lib -L/lib/x86_64-linux-gnu -L/ lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. /tmp/ ccPe5usI.o /tmp/ccSAbeU8.o -lgcc --as-needed -lgcc_s -- no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as- needed /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/ lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/ crtn.o gcc -o program -v main.c 76
  • 76. Compiler Driver 77
  • 77. … *cc1_options: %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}} %{!iplugindir*:%{fplugin*:%:find- plugindir()}} %1 %{!Q:-quiet} %{!dumpbase:-dumpbase %B} % {d*} %{m*} %{aux-info*} %{fcompare-debug-second: %:compare-debug-auxbase-opt(%b)} %{!fcompare-debug- second:%{c|S: %{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}}%{!c:%{!S:-auxbase %b}}… … *startfile: %{!mandroid|tno-android-ld:%{!shared: %{pg|p|profile:gcrt1.o %s;pie:Scrt1.o%s;:crt1.o%s}} crti.o%s % {static:crtbeginT.o%s;shared|pie:crtbeginS.o %s;:crtbegin.o%s};:%{shared: crtbegin_so%O%s;: %{static: crtbegin_static%O%s;: crtbegin_dynamic%O%s}}} … gcc -dumpspecs 78
  • 78. … OUTPUT_ARCH(i386:x86-64) ENTRY(_start) SEARCH_DIR("/usr/x86_64-linux-gnu/lib64"); SEARCH_DIR("=/ usr/local/lib/x86_64-linux-gnu"); SEARCH_DIR("=/usr/ local/lib64"); SEARCH_DIR("=/lib/x86_64-linux-gnu"); SEARCH_DIR("=/lib64"); SEARCH_DIR("=/usr/lib/x86_64- linux-gnu"); SEARCH_DIR("=/usr/lib64"); SEARCH_DIR("=/ usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/ lib"); SECTIONS { /* Read-only sections, merged into text segment: */ PROVIDE (__executable_start = SEGMENT_START("text- segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS; … ld -verbose 79
  • 79. … .text : { *(.text.unlikely .text.*_unlikely .text.unlikely.*) *(.text.exit .text.exit.*) *(.text.startup .text.startup.*) *(.text.hot .text.hot.*) *(.text .stub .text.* .gnu.linkonce.t.*) /* .gnu.warning sections are handled specially by elf32.em. */ *(.gnu.warning) } … ld -verbose 80
  • 80. Сборка Препроцессинг — сс1, cc1plus C++ с директивами препроцессора → C++ Компиляция — cc1, cc1plus, as C++ → ассемблер → машинный код Один исходный файл → один объектный файл Компоновка — ld (collect2) Объектные файлы → исполняемый файл Сборка — gcc Всё вместе 81
  • 81. $ gcc -o program main.cpp sum.cpp $ ls main.cpp program sum.cpp Всё вместе 82
  • 82. За кадром 83
  • 83. За кадром Другие компиляторы LLVM + Clang (clang) Microsoft Visual C++ (cl) Другие ОС Windows – Portable Executable (PE) – Common Object File Format (COFF) Mac OS X – Mach Object (Mach-O) 84
  • 84. За кадром Link-Time Optimization GCC – GIMPLE в отдельной секции – linker plugin LLVM + Clang – LLVM byte-code (AST) – linker plugin 85
  • 85. Александр Сомов somov@yandex-team.ru
  • 86. Спасибо за внимание!

×