vak: (Daemon)
[personal profile] vak
Подрихтовал ещё немного тулзу, и таки добился своего. Можем теперь наблюдать интимные подробности работы динамического загрузчика.

Пример состоит из двух частей, обе написаны на ассемблере.
  • Главная программа foobar.S выдаёт пару текстовых сообщений, вызывая функцию say() из динамической библиотеки. Затем завершается системным вызовом _exit().
  • Бибилиотека lib.S реализует функцию say(), которая выполняет системный вызов write().
Всё это на процессоре arm32 под FreeBSD.



Компилируем, запускаем. Работу динамического загрузчика я сократил для ясности. Инструкции главной программы выделены зелёным, инструкции библиотечной функции сиреневым. Видно, как при первом вызове функции say() её адрес ещё не готов. Активируется динамический загрузчик, находит адрес функции и уходит в неё. При втором вызове say() переход происходит напрямую. Вставка-переходник say@plt занимает три машинных команды.
$ cpp foobar.S | as -o foobar.o -
$ cpp lib.S | as -o lib.o -
$ ld -shared -o lib.so lib.o
$ ld -o foobar foobar.o lib.so
$ export LD_LIBRARY_PATH=.
$ bintrace ./foobar
Starting program: ./foobar
        sp = 0xbfbfeb50
        lr = 0x20025538
      cpsr = 0x10
----------------------------------------------------------- dynamic loader
0x20025538:  e1a0600d   mov r6, sp
        r6 = 0xbfbfeb50
...
(initialize dynamic loader)
...
0x20025590:  e1a0f003   mov pc, r3
----------------------------------------------------------- 00010158 <_start>:
0x00010158:  e300017c   movw r0, #0x17c
        r0 = 0x17c
0x0001015c:  e3400001   movt r0, #1
        r0 = 0x1017c
0x00010160:  ebfffff9   bl #0x1014c
        lr = 0x10164
----------------------------------------------------------- 0001014c <say@plt>:
0x0001014c:  e28fc600   add ip, pc, #0, #12
       r12 = 0x10154
0x00010150:  e28cca01   add ip, ip, #0x1000
       r12 = 0x11154
0x00010154:  e5bcf0c4   ldr pc, [ip, #0xc4]!
       r12 = 0x11218
----------------------------------------------------------- 00010138 <.plt>:
0x00010138:  e52de004   str lr, [sp, #-4]!
        sp = 0xbfbfeb4c
0x0001013c:  e59fe004   ldr lr, [pc, #4]
        lr = 0x10c4
0x00010140:  e08fe00e   add lr, pc, lr
        lr = 0x1120c
0x00010144:  e5bef008   ldr pc, [lr, #8]!
        lr = 0x11214
----------------------------------------------------------- into dynamic loader
0x200255a0:  e92d0c3f   push {r0, r1, r2, r3, r4, r5, sl, fp}
        sp = 0xbfbfeb2c
...
(find symbol 'say' in lib.so)
...
0x200255d4:  e1a0f00c   mov pc, ip
----------------------------------------------------------- 000000d4 <say>:
0x200170d4:  e92d4080   push {r7, lr}
        sp = 0xbfbfeb48
0x200170d8:  e1a01000   mov r1, r0
        r1 = 0x1017c
0x200170dc:  e3a00001   mov r0, #1
        r0 = 0x1
0x200170e0:  e3a02004   mov r2, #4
        r2 = 0x4
0x200170e4:  e3a07004   mov r7, #4
        r7 = 0x4
0x200170e8:  ef000000   svc #0
foo
        r0 = 0x4
        r1 = 0
0x200170ec:  e8bd8080   pop {r7, pc}
        r7 = 0
        sp = 0xbfbfeb50
----------------------------------------------------------- back to _start
0x00010164:  e3000180   movw r0, #0x180
        r0 = 0x180
0x00010168:  e3400001   movt r0, #1
        r0 = 0x10180
0x0001016c:  ebfffff6   bl #0x1014c
        lr = 0x10170
----------------------------------------------------------- 0001014c <say@plt>:
0x0001014c:  e28fc600   add ip, pc, #0, #12
       r12 = 0x10154
0x00010150:  e28cca01   add ip, ip, #0x1000
       r12 = 0x11154
0x00010154:  e5bcf0c4   ldr pc, [ip, #0xc4]!
       r12 = 0x11218
----------------------------------------------------------- 000000d4 <say>:
0x200170d4:  e92d4080   push {r7, lr}
        sp = 0xbfbfeb48
0x200170d8:  e1a01000   mov r1, r0
        r1 = 0x10180
0x200170dc:  e3a00001   mov r0, #1
        r0 = 0x1
0x200170e0:  e3a02004   mov r2, #4
0x200170e4:  e3a07004   mov r7, #4
        r7 = 0x4
0x200170e8:  ef000000   svc #0
bar
        r0 = 0x4
        r1 = 0
0x200170ec:  e8bd8080   pop {r7, pc}
        r7 = 0
        sp = 0xbfbfeb50
----------------------------------------------------------- back to _start
0x00010170:  e3a07001   mov r7, #1
        r7 = 0x1
0x00010174:  e3a00000   mov r0, #0
        r0 = 0
0x00010178:  ef000000   svc #0
Process exited normally.