Article:LowLevelAsm
Материал из QNX.ORG.RU
Содержание |
LowLevel Assembly в QNX6
Вступление
Идея заняться этой темой родилась у меня во время обсуждения данной темы в одной из веток нашего форума. И тогда задал я себе вопрос "А почему бы не сделать что-то вроде Linux Assembly для QNX 6?", т.е. заняться написанием программ на чистом ассемблере без применения языка Си и его библиотек.
Итак, напишем простенькую программу типа helloworld на ассемблере. Однако, несмотря на кажущуюся простоту, задача перед нами стоит не простая. Надо написать программу так, чтоб она корректно вела себя в программной среде микроядерной ОС QNX 6.x и при этом не использовала ни одной статической или динамической библиотеки. Чтож, посмотрим что у нас получится... :)
Секции
Не секрет, что QNX6 использует формат исполняемого файла ELF. Данный формат представляет из себя набор секций разного назначения, которые интерпретируются загрузчиком в процессе запуска исполняемого файла. Часть секций загружается прямо в память, часть служит для коррекции загруженных данных, часть присутствует "просто так" и при загрузке игнорируется.
Посмотрим что по умолчанию при трансляции формирует gcc в среде QNX6. Для этого напишем простую программу на Си, оттранслируем ее и посмотрим список секций.
#include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { printf("Hello World!\n"); exit(0); }
# gcc helloworldc.c -o helloworldc
# strip helloworldc
# ./helloworldc
Hello World!
# ls -l helloworldc
-rwxrwxr-x 1 root root 3148 Oct 21 11:03 helloworldc
# objdump -x helloworldc
helloworldc: file format elf32-i386
helloworldc
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x080484d8
Program Header:
PHDR off 0x00000034 vaddr 0x08048034 paddr 0x08048034 align 2**2
filesz 0x000000c0 memsz 0x000000c0 flags r-x
INTERP off 0x000000f4 vaddr 0x080480f4 paddr 0x080480f4 align 2**0
filesz 0x00000014 memsz 0x00000014 flags r--
LOAD off 0x00000000 vaddr 0x08048000 paddr 0x08048000 align 2**12
filesz 0x000006d8 memsz 0x000006d8 flags r-x
LOAD off 0x000006d8 vaddr 0x080496d8 paddr 0x080496d8 align 2**12
filesz 0x0000010c memsz 0x00000130 flags rw-
DYNAMIC off 0x000006ec vaddr 0x080496ec paddr 0x080496ec align 2**2
filesz 0x000000b0 memsz 0x000000b0 flags rw-
NOTE off 0x00000108 vaddr 0x08048108 paddr 0x08048108 align 2**0
filesz 0x00000018 memsz 0x00000018 flags r--
Dynamic Section:
NEEDED libc.so.3
INIT 0x08048410
FINI 0x080486bc
HASH 0x08048120
STRTAB 0x080482d4
SYMTAB 0x080481b4
STRSZ 0x000000c4
SYMENT 0x00000010
DEBUG 0x00000000
PLTGOT 0x080497a0
PLTRELSZ 0x00000050
PLTREL 0x00000011
JMPREL 0x080483c0
REL 0x08048398
RELSZ 0x00000028
RELENT 0x00000008
Sections:
Idx Name Size VMA LMA File off Algn
0 .interp 00000014 080480f4 080480f4 000000f4 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note 00000018 08048108 08048108 00000108 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .hash 00000094 08048120 08048120 00000120 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .dynsym 00000120 080481b4 080481b4 000001b4 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .dynstr 000000c4 080482d4 080482d4 000002d4 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .rel.dyn 00000028 08048398 08048398 00000398 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .rel.plt 00000050 080483c0 080483c0 000003c0 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .init 0000000d 08048410 08048410 00000410 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
8 .plt 000000b0 08048420 08048420 00000420 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
9 .text 000001ec 080484d0 080484d0 000004d0 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
10 .fini 00000008 080486bc 080486bc 000006bc 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
11 .rodata 0000000d 080486c4 080486c4 000006c4 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
12 .eh_frame 00000004 080486d4 080486d4 000006d4 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
13 .ctors 00000008 080496d8 080496d8 000006d8 2**2
CONTENTS, ALLOC, LOAD, DATA
14 .dtors 00000008 080496e0 080496e0 000006e0 2**2
CONTENTS, ALLOC, LOAD, DATA
15 .jcr 00000004 080496e8 080496e8 000006e8 2**2
CONTENTS, ALLOC, LOAD, DATA
16 .dynamic 000000b0 080496ec 080496ec 000006ec 2**2
CONTENTS, ALLOC, LOAD, DATA
17 .data 00000004 0804979c 0804979c 0000079c 2**2
CONTENTS, ALLOC, LOAD, DATA
18 .got 00000044 080497a0 080497a0 000007a0 2**2
CONTENTS, ALLOC, LOAD, DATA
19 .bss 00000024 080497e4 080497e4 000007e4 2**2
ALLOC
20 .comment 00000036 00000000 00000000 000007e4 2**0
CONTENTS, READONLY
SYMBOL TABLE:
no symbols
Что мы видим тут? Мы видим малый размер файла и имеющий 21 секцию. Мы собрали запускаемый файл, требующий динамическую линковку при загрузке. Об этом однозначно говорит наличие секции .interp и зависимость от библиотеки libc.so.3 .
Попробуем теперь собрать программу статически.
# gcc --static helloworldc.c -o helloworldcs
# strip helloworldcs
# ./helloworldcs
Hello World!
# ls -l helloworldcs
-rwxrwxr-x 1 root root 43644 Oct 21 11:03 helloworldcs
# objdump -x helloworldcs
helloworldcs: file format elf32-i386
helloworldcs
architecture: i386, flags 0x00000102:
EXEC_P, D_PAGED
start address 0x080480c8
Program Header:
LOAD off 0x00000000 vaddr 0x08048000 paddr 0x08048000 align 2**12
filesz 0x00009a48 memsz 0x00009a48 flags r-x
LOAD off 0x00009a48 vaddr 0x08052a48 paddr 0x08052a48 align 2**12
filesz 0x0000064c memsz 0x00000a74 flags rw-
NOTE off 0x00000094 vaddr 0x08048094 paddr 0x08048094 align 2**0
filesz 0x00000018 memsz 0x00000018 flags r--
Sections:
Idx Name Size VMA LMA File off Algn
0 .note 00000018 08048094 08048094 00000094 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .init 0000000d 080480ac 080480ac 000000ac 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
2 .text 00008f2c 080480c0 080480c0 000000c0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
3 .fini 00000008 08050fec 08050fec 00008fec 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
4 .rodata 000009cf 08051000 08051000 00009000 2**5
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .eh_frame 00000078 080519d0 080519d0 000099d0 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .ctors 00000008 08052a48 08052a48 00009a48 2**2
CONTENTS, ALLOC, LOAD, DATA
7 .dtors 00000008 08052a50 08052a50 00009a50 2**2
CONTENTS, ALLOC, LOAD, DATA
8 .jcr 00000004 08052a58 08052a58 00009a58 2**2
CONTENTS, ALLOC, LOAD, DATA
9 .data 00000618 08052a60 08052a60 00009a60 2**5
CONTENTS, ALLOC, LOAD, DATA
10 .got 0000001c 08053078 08053078 0000a078 2**2
CONTENTS, ALLOC, LOAD, DATA
11 .bss 0000041c 080530a0 080530a0 0000a094 2**5
ALLOC
12 .comment 0000072c 00000000 00000000 0000a094 2**0
CONTENTS, READONLY
SYMBOL TABLE:
no symbols
Что мы имеем: больший размер, 13 секций, отсутствие зависимостей от библиотек. Данный результат близок к тому чего мы добиваемся, но мы хотим ассемблера! :)
Для тех кто хочет больше узнать о формате ELF могу предложить почитать документацию.
WIP!
Здесь планируется разместить небольшой материал о написании программ для QNX 6.x на языке Ассемблер без применения Си.
Ждите... :)
