Подрихтовал ещё немного тулзу, и таки добился своего. Можем теперь наблюдать интимные подробности работы динамического загрузчика.
Пример состоит из двух частей, обе написаны на ассемблере.

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

Компилируем, запускаем. Работу динамического загрузчика я сократил для ясности. Инструкции главной программы выделены зелёным, инструкции библиотечной функции сиреневым. Видно, как при первом вызове функции 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.