Подумалось, что для понимания работы компьютера полезно бы иметь возможность, запуская какую-нибудь программу, глянуть последовательность выполняемых машинных команд, а также изменение содержимое регистров процессора. Стал искать такую тулзу, а нету. Имеющиеся отладчики слабо помогают.
Быстренько слепил самопальное решение, спасибо системному вызову ptrace(). К примеру, возьмём Hello World на линуксном ассемблере x86-64:
Быстренько слепил самопальное решение, спасибо системному вызову ptrace(). К примеру, возьмём Hello World на линуксном ассемблере x86-64:
Запускаем:#include <sys/syscall.h>
.text
.globl _start
_start:
mov $ SYS_write, %rax // syscall write(fd, message, size)
mov $1, %rdi // fd - stdout
lea message(%rip), %rsi // pointer to message
mov $13, %rdx // size
syscall
mov $ SYS_exit, %rax // syscall exit(status)
xor %rdi, %rdi // status - 0
syscall
message:
.ascii "Hello world!\n"
Вроде ничо так фунциклирует. Надо будет перепереть на другие архитектуры: arm64, arm32, riscv64.Starting program: ./hello-amd64-linux
rsp = 0x7ffd8ce45cc0
cs = 0x33
ss = 0x2b
eflags = 0x200
0x0000000000401000: 48 c7 c0 01 00 00 00 mov rax, 1
rax = 0x1
eflags = 0x202
0x0000000000401007: 48 c7 c7 01 00 00 00 mov rdi, 1
rdi = 0x1
0x000000000040100e: 48 8d 35 15 00 00 00 lea rsi, [rip + 0x15]
rsi = 0x40102a
0x0000000000401015: 48 c7 c2 0d 00 00 00 mov rdx, 0xd
rdx = 0xd
0x000000000040101c: 0f 05 syscall
Hello world!
rax = 0xd
rcx = 0x40101e
r11 = 0x302
0x000000000040101e: 48 c7 c0 3c 00 00 00 mov rax, 0x3c
rax = 0x3c
0x0000000000401025: 48 31 ff xor rdi, rdi
rdi = 0
eflags = 0x246
0x0000000000401028: 0f 05 syscall
Process exited normally.

no subject
Date: 2024-12-14 21:41 (UTC)no subject
Date: 2024-12-15 04:43 (UTC)no subject
Date: 2024-12-15 04:53 (UTC)no subject
Date: 2024-12-15 20:44 (UTC)no subject
Date: 2024-12-15 21:32 (UTC)no subject
Date: 2024-12-15 23:33 (UTC)no subject
Date: 2024-12-16 01:41 (UTC)no subject
Date: 2024-12-16 07:42 (UTC)no subject
Date: 2024-12-16 09:49 (UTC)no subject
Date: 2024-12-16 22:57 (UTC)no subject
Date: 2024-12-16 23:33 (UTC)no subject
Date: 2024-12-17 00:52 (UTC)0x000000000044d1a8: 88117c41 stxr w17, w1, [x2] x17 = 0x1 0x000000000044d1ac: 35ffff91 cbnz w17, #0x44d19c 0x000000000044d19c: 885ffc40 ldaxr w0, [x2] 0x000000000044d1a0: 6b10001f cmp w0, w16 0x000000000044d1a4: 54000061 b.ne #0x44d1b0Это если я линкую программу статически. Простой тест, фактически классический hello.c.
А если линкую динамически, то программа отлично отрабатывает и заканчивается. Это всё под Линуксом arm64.
no subject
Date: 2024-12-17 06:44 (UTC)no subject
Date: 2024-12-17 07:36 (UTC)"Store Exclusive Register stores a 32-bit word or a 64-bit doubleword from a register to memory if the PE has exclusive access to the memory address, and returns a status value of 0 if the store was successful, or of 1 if no store was performed."
То есть она пытается записать слово в режиме исключительного доступа, этот режим данному процессору почему-то не достаётся, и в w17 записывается 1. И так до бесконечности. Трассировка каким-то образом нехорошо влияет. Возможно, из-за переключения контекста.
https://www.scs.stanford.edu/~zyedidia/arm64/stxr.html
https://www.scs.stanford.edu/~zyedidia/arm64/ldaxr.html
no subject
Date: 2024-12-17 15:26 (UTC)Т. е. идеальный трассировщик для ARM должен смотреть, а не LDAXR ли следующая инструкция, и в этом случае искать STXR и выход из цикла, в котором STXR находится, и ставить breakpoint туда. Кошмар.
no subject
Date: 2024-12-17 17:40 (UTC)Выходит, простая утилита трассировки бесполезна для анализа реальных программ. Можно гонять только небольшие "учебные" фрагмента кода. Не дай бог вызвать стандартную библиотеку.
no subject
Date: 2024-12-19 02:57 (UTC)no subject
Date: 2024-12-19 07:32 (UTC)То есть есть эмулировать через CAS логику этого exclusive.
В таком виде должно работать, почти везде, и на честной многонитевости.
Не пройдёт, если кто-то решит за счёт LR/SC решать и ABA problem, но такого кода уже сильно меньше.
no subject
Date: 2024-12-19 07:36 (UTC)При переключении переключающий _обязан_ сам сбросить факт исключительного доступа (или явным CLREX, как для ARM/64, или через LDXR специального адреса у системного кода). Причина - можно случайно переключить на другую задачу, которая делает свой LR/SC с тем же адресом памяти, сбив её с толку. Поэтому, если не уверен, что не вмешивался в этот механизм и не переключал задачу - то сбрось. Да, эмулятору надо в таком случае эмулировать логику учёта прежнего значения самому...