Использование gdb для пошагового ассемблерного кода за пределами указанного исполняемого файла вызывает ошибку «не удается найти границы текущей функции»

86

У меня нет целевого исполняемого файла gdb, и у меня даже нет стека, соответствующего этой цели. В любом случае я хочу пошагово, чтобы я мог проверить, что происходит в моем коде сборки, потому что я не эксперт в сборке x86. К сожалению, GDB отказывается выполнять эту простую отладку на уровне сборки. Это позволяет мне устанавливать и останавливаться на соответствующей точке останова, но как только я пытаюсь перейти на один шаг вперед, gdb сообщает об ошибке «Не удается найти границы текущей функции», и EIP не изменяется.

Дополнительные детали:

Машинный код был сгенерирован операторами gcc asm, и я скопировал его в то место памяти ядра, где он выполняется, из вывода objdump -d. Я бы не возражал против простого способа использовать загрузчик для загрузки моего объектного кода на перемещенный адрес, но имейте в виду, что загрузка должна выполняться в модуле ядра.

Я полагаю, другой альтернативой было бы создание поддельного модуля ядра или файла отладочной информации для передачи gdb, чтобы заставить его поверить, что эта область находится в программном коде. gdb отлично работает с самим исполняемым файлом ядра.

(Для тех, кто действительно хочет знать, я вставляю код во время выполнения в пространство данных ядра Linux внутри виртуальной машины VMware и отлаживаю его из gdb удаленно отлаживая ядро ​​через встроенную заглушку gdb VMware Workstation. Обратите внимание, что я не пишу ядро эксплойтов; я аспирант по безопасности, пишу прототип.)

(Я могу установить точку останова для каждой инструкции внутри моей сборки. Это работает, но через некоторое время станет довольно трудоемким, поскольку размер сборочных инструкций x86 меняется, а расположение сборки будет меняться каждый раз при перезагрузке.)

Павел
источник
Умные ksplice.com люди INJECT данных и кода в ядро по сборке «поддельные» модули ядра и загружать их. И если они могут это сделать, почему ты не можешь? ;-)
ephemient

Ответы:

116

Вы можете использовать stepiили nexti(что может быть сокращено до siили ni) для пошагового выполнения вашего машинного кода.

R Сэмюэл Клатчко
источник
1
Вау. Оглядываясь назад, я не понимаю, как я забыл о степи. Думаю, я просто предположил, что из-за того, что у gdb не было исходного кода, этот шаг вернется к инструкциям по сборке.
Пол
1
примечание: для программ сборки часто нельзя набирать "break main", "run". Вместо этого введите "layout asm", "start". Я понял это, прочитав сообщение ниже, но кто-то другой, читающий этот пост, может быть не так терпелив.
Дмитрий
1
@Dmitry startэквивалентно, за tbreak mainкоторым следует run(примечание: tbreakвместо break)
Руслан
151

Вместо того gdb, чтобы бегать gdbtui. Или бегите gdbс -tuiпереключателем. Или нажмите C-x C-aпосле ввода gdb. Теперь вы находитесь в режиме TUI GDB .

Введите, layout asmчтобы отобразить сборку верхнего окна - это будет автоматически следовать за указателем инструкции, хотя вы также можете изменять рамки или прокручивать во время отладки. Нажмите, C-x sчтобы войти в режим SingleKey, где run continue up down finishт. Д. Сокращенно обозначается одной клавишей, что позволяет вам очень быстро проходить через программу.

   + ------------------------------------------------- -------------------------- +
B +> | 0x402670 <main> push% r15 |
   | 0x402672 <main + 2> mov% edi,% r15d |
   | 0x402675 <main + 5> push% r14 |
   | 0x402677 <main + 7> push% r13 |
   | 0x402679 <main + 9> mov% rsi,% r13 |
   | 0x40267c <main + 12> push% r12 |
   | 0x40267e <main + 14> push% rbp |
   | 0x40267f <main + 15> push% rbx |
   | 0x402680 <main + 16> sub $ 0x438,% rsp |
   | 0x402687 <main + 23> mov (% rsi),% rdi |
   | 0x40268a <main + 26> movq $ 0x402a10,0x400 (% rsp) |
   | 0x402696 <main + 38> movq $ 0x0,0x408 (% rsp) |
   | 0x4026a2 <main + 50> movq $ 0x402510,0x410 (% rsp) |
   + ------------------------------------------------- -------------------------- +
дочерний процесс 21518 In: main Line: ?? ПК: 0x402670
(gdb) файл / opt / j64-602 / bin / jconsole
Чтение символов из /opt/j64-602/bin/jconsole...done.
(символы отладки не найдены) ... готово.
(gdb) макет asm
(gdb) начало
(GDB)
эфемерный
источник
26

Самое полезное, что вы можете сделать здесь, - это display/i $pcперед использованием, stepiкак уже было предложено в ответе R Samuel Klatchko. Это указывает GDB дизассемблировать текущую инструкцию каждый раз перед печатью приглашения; тогда вы можете просто продолжать нажимать Enter, чтобы повторить stepiкоманду.

(Подробнее см. Мой ответ на другой вопрос - контекст этого вопроса был другим, но принцип тот же.)

Мэтью Слэттери
источник