Как решить ошибку отладки QEMU gdb: удаленный ответ пакета " g " слишком длинный?
в настоящее время я занимаюсь загрузчиками и разработкой ядра (очень начало) Я следую комбинации https://www.cs.bham.ac.uk / ~exr / лекции / opsys/10_11/лекции / os-dev.pdf и код, найденный в https://github.com/cfenollosa/os-tutorial
единственное, что я делаю по-другому, это то, что я нацелен на x86_64 вместо i386. Также я использую qemu для эмуляции (qemu-system-x86_64).
Теперь, после следования РЕПО GitHub, чтобы расстаться 16-video-driver я застрял, поскольку драйвер экрана печатает некоторые вещи на экран, но что-то происходит с рассогласованием данных или чем-то еще. Поэтому я хотел попробовать отладить свою программу. Об этом также говорится в части 14-контрольный пункт РЕПО. Поэтому я построил gdb для target x86_64-elf. Но когда я пытаюсь запустить qemu и gdb с помощью system-qemu-x86_64 -s -S -fda os-image
а потом просто бежать gdb
и попробуйте подключиться к qemu, запустив target remote localhost:1234
, как только я запускаю это, я получаю следующую ошибку сообщение
Remote debugging using localhost:1234
warning: No executable has been specified and target does not support
determining executable automatically. Try using the "file" command.
Remote 'g' packet reply is too long (expected 308 bytes, got 536 bytes):
000000000000000000000000000000000000000000000000630600000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000f0ff0000000000000200000000f00000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000007f03000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000801f0000
любые идеи о том, что я упускаю / делаю не так? Если нужна дополнительная информация, пожалуйста, дайте мне знать.
спасибо
изменить:
Я применил патч, упомянутый @MichaelPetch, и теперь ошибка пакета g исчезла. Однако похоже, что gdb не может интерпретировать мой исполняемый файл как после запуска target remote localhost:1234
а то symbol-file kernel.elf
терминал теперь возвращает
Remote debugging using localhost:1234 warning: No executable has been
specified and target does not support determining executable automatically.
Try using the "file" command. 0x0000fb38 in ?? ()
однако я могу установить точки останова на функциях и линии числа. Но при попытке распечатать переменные, которые должны быть доступны в текущем местоположении, используя print terminal_buffer
Я вам
No symbol "terminal_buffer" in current context.
terminal_buffer-переменная, объявленная в текущей области.
однако, когда я печатаю переменную, объявленную вне области действия функции, в которую я поместил свою точку останова, например, int,print
возвращает значение, но значение равно 0 (я предполагаю, что это начальное значение типа), однако оно уже должно быть установлено на новое значение согласно моему кодексу. Также при попытке next
возвращает Cannot find bounds of current function
что приводит меня к мысли, что он не может интерпретировать какую-то часть.
в моем загрузчике я перехожу в защищенный защищенный режим для запуска 64-битного ядра с помощью этого метода:
[bits 16]
switch_to_pm:
cli ; 1. disable interrupts
lgdt [gdt_descriptor] ; 2. load the GDT descriptor
mov eax, cr0
or eax, 0x1 ; 3. set 32-bit mode bit in cr0
mov cr0, eax
jmp CODE_SEG:init_pm ; 4. far jump by using a different segment
[bits 32]
init_pm: ; we are now using 32-bit instructions
mov ax, DATA_SEG ; 5. update the segment registers
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ebp, 0x90000 ; 6. update the stack right at the top of the free space
mov esp, ebp
call BEGIN_PM ; 7. Call a well-known label with useful code
какие мысли?
2 ответов
причина всех проблем заключается в том, что вы компилируете 64-разрядный код и запускаете его в 32-разрядном защищенном режиме. 64-разрядный код не будет работать в этой среде должным образом. Как ни странно, это часто проявляется сначала при попытке записи на видеодисплей. Часто вещи будут печатать, но не совсем так, как вы хотите. Неправильно декодированные инструкции заставят отладчик работать беспорядочно, как вы заметили.
один из способов исправить вашу проблему-скомпилировать и связать ядро как 32-разрядный исполняемый файл. Вы используете 64-разрядный компилятор, поэтому вам нужно добавить -m32
CFLAGS (или ваша командная строка GCC). при использовании LD для ссылки -melf_i386
потребуется. Сборка с NASM должна быть -felf32
, а не -felf64
.
кроме того вы должны поместить процессор в 64-битный режим в бутлоадера. Вы можете прочитать больше об этом процессе на OSDev wiki.
если отладка 32-битного кода Вы, вероятно, захотите использовать qemu-system-i386
. Вы будет меньше неприятностей.
подключение и отключение
Я получил его, как подробно описано в:как отладить ядро Linux с помощью GDB и QEMU?
ключевым моментом было подключение и отключение на GDB как:
gdb \
-ex "add-auto-load-safe-path $(pwd)" \
-ex "file vmlinux" \
-ex 'set arch i386:x86-64:intel' \
-ex 'target remote localhost:1234' \
-ex 'break start_kernel' \
-ex 'continue' \
-ex 'disconnect' \
-ex 'set arch i386:x86-64' \
-ex 'target remote localhost:1234'