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

Быстренько слепил самопальное решение, спасибо системному вызову 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"
Запускаем:
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.
Вроде ничо так фунциклирует. Надо будет перепереть на другие архитектуры: arm64, arm32, riscv64.

Date: 2024-12-14 21:41 (UTC)
juan_gandhi: (Default)
From: [personal profile] juan_gandhi
Ценная вещь!

Date: 2024-12-15 04:43 (UTC)
sab123: (Default)
From: [personal profile] sab123
Почему не взять просто gdb? Я по нему не большой специалист, но вроде для больших специалистов там есть способ определить макро, которое быдет вызываться каждый раз при остановке.

Date: 2024-12-15 20:44 (UTC)
From: [identity profile] ledernierheros.livejournal.com
QEMU так тоже может. По умолчанию, правда, будет трассировка на уровне jit-блоков, но если добавить к командной строке -singlestep , можно видеть полное состояние после каждой инструкции.

Date: 2024-12-15 23:33 (UTC)
spamsink: (Default)
From: [personal profile] spamsink
Полезная вещь!

Date: 2024-12-16 07:42 (UTC)
spamsink: (Default)
From: [personal profile] spamsink
И что же делает GDB по команде stepi на тех архитектурах, где пошаговое выполнение не поддерживается линуксом?

Date: 2024-12-16 23:33 (UTC)
spamsink: (Default)
From: [personal profile] spamsink
Не понял. Если команда CAS атомарная, то рано или поздно должна попасть в тот момент, когда никто ресурс не держал. А если не атомарная, а процедура реализует алгоритм Деккера (без гугления вспомнил, во!), то всё равно в конце концов должна поймать момент, но в разы медленнее. Правда, в любом случае, с точки зрения количества строк в трассе это можно считать "практически бесконечным" циклом.

Date: 2024-12-17 06:44 (UTC)
spamsink: (Default)
From: [personal profile] spamsink
К сожалению, я не дока в армовской ISA. Но формально да, если в какой-то ячейке, скажем, хардверный счетчик наносекунд, и надо успеть что-то сделать, пока он не изменился, а если не успел, то попробовать ещё раз, то с трассировкой это будет пробоваться бесконечно.

Date: 2024-12-17 15:26 (UTC)
spamsink: (Default)
From: [personal profile] spamsink
Спасибо. Насколько я понял, LDAXR ставит режим исключительного доступа для прочитанного слова, который автоматически выключается после STXR, или если до того было обращение к любому другому слову в памяти (или вообще, или с помощью LDAXR). Понятно, что при переключении контекстов столько всякого делается, что это в любом случае гарантировано.

Т. е. идеальный трассировщик для ARM должен смотреть, а не LDAXR ли следующая инструкция, и в этом случае искать STXR и выход из цикла, в котором STXR находится, и ставить breakpoint туда. Кошмар.

Date: 2024-12-19 07:32 (UTC)
netch80: (Default)
From: [personal profile] netch80
На exclusive read (LDXR, LDAXR...) запоминать самому прочтённое значение, а на STXR (STLXR...) - сравнивать его с тем, что сам прочитал ранее.
То есть есть эмулировать через CAS логику этого exclusive.
В таком виде должно работать, почти везде, и на честной многонитевости.
Не пройдёт, если кто-то решит за счёт LR/SC решать и ABA problem, но такого кода уже сильно меньше.

Date: 2024-12-19 07:36 (UTC)
netch80: (Default)
From: [personal profile] netch80
> Понятно, что при переключении контекстов столько всякого делается, что это в любом случае гарантировано.

При переключении переключающий _обязан_ сам сбросить факт исключительного доступа (или явным CLREX, как для ARM/64, или через LDXR специального адреса у системного кода). Причина - можно случайно переключить на другую задачу, которая делает свой LR/SC с тем же адресом памяти, сбив её с толку. Поэтому, если не уверен, что не вмешивался в этот механизм и не переключал задачу - то сбрось. Да, эмулятору надо в таком случае эмулировать логику учёта прежнего значения самому...