У меня есть аварийный дамп, который показывает следующую информацию об исключении:
0:000> .ecxr
eax=00000000 ebx=00000001 ecx=000000dc edx=000032f0 esi=00000020 edi=78746341
eip=00000000 esp=00000007 ebp=00000020 iopl=0 nv up di pl nz na po cy
cs=0014 ss=0034 ds=0000 es=1000 fs=df5c gs=0000 efl=00000001
0014:00000000 ?? ???
Почему адрес исключения отображается как 0014:00000000
, а не просто 00000000
? Насколько я понимаю, 0014
— это сегмент кода, но документации по синтаксису я не нашел.
Кроме того, есть ли способ перевести этот синтаксис в простой абсолютный адрес?
Обычно в 32-битном коде основание сегмента для сегмента кода равно 0. Вам следует придерживаться этого предположения, если у вас нет доказательств обратного. Таким образом, линейный адрес равен 0. Адрес 0 обычно не отображается ни в одном адресном пространстве, что объясняет сбой. (Windbg может сообщить вам истинную базу сегментов для сегмента 14, если у вас есть основания полагать, что это не 0.)
Да, seg:off
— это 100% стандартная запись. Он просто показывает вам полное значение CS:EIP.
База CS равна 0
, если только вы не сделали что-то действительно странное (например, retf
вставили что-то в CS, что случайно проиндексировало запись GDT с ненулевой базой, если она вообще есть).
Таким образом, линейный адрес — это просто 00000000
. например вы пытались перейти к указателю функции NULL или что-то в этом роде, или пытались ret
, когда ESP указывал на 0 вместо вашего адреса возврата.
Спасибо. Любая идея, почему сегмент отображается вообще? Обычно это не часть отображаемого адреса.
@Paul: IDK, почему WinDBG решил, что это хорошая идея. Текущее значение CS уже отображается отдельно. Чисто выбор дизайна пользовательского интерфейса. GDB нет; GDB — это портативный отладчик (для различных ISA), построенный на плоской модели памяти. IDK, если WinDBG имеет свои корни в 16-битной стране, где seg:off
был действительно важен, потому что обычная модель памяти не была плоской. Или, если у авторов был большой опыт работы с 16-битным x86, то казалось естественным показывать текущий программный счетчик как seg:off.
@Paul: Или, может быть, это полезно для отладки кода ядра, который может далеко переходить между сегментами кода для переключения режимов? IDK, если WinDBG может отлаживать ядро.
WinDbg можно использовать как отладчик ядра, но это был аварийный дамп пользовательского режима.
@Paul: Верно, но я бы не ожидал, что формат вывода будет меняться в зависимости от того, отлаживаете ли вы ядро или нет. Тот факт, что отладка ядра является одним из вариантов использования, означает, что печать адреса ошибки как cs:eip
или cs:rip
имеет смысл. (Хотя ядро также будет использовать CS base = 0, так что, я думаю, это больше просто для того, чтобы помочь разработчику ядра заметить значение CS.)
Да, часть перед двоеточием — это сегмент, а часть после — смещение (в данном случае EIP).