Как управлять gdb внутри кода C или Python без API-интерфейса GDB Python?

Я пытаюсь написать программу в python или c, которая может отлаживать c-код с помощью gdb.

Я прочитал решение Tom и Вызвать и управлять GDB из Python. Но это более или менее решение для сценариев gdb в python. Поскольку я собираюсь использовать arm-gdb для отладки встроенной программы, я не могу включить скрипты python в моем gdb.

Моя цель - создать абстракцию высокого уровня gdb. Например, запустите gdb, установите некоторые точки останова и продолжите в моем коде. Я также прочитал некоторый интерфейс gdb/mi. Но может ли кто-нибудь сказать мне, как использовать интерфейс gdb/mi для создания процесса gdb и установить связь с gdb из кода c/python? (К счастью, мой arm-gdb поддерживает интерфейс gdb/mi).

Ответ 1

Как и было сказано в комментариях выше, я опубликовал мою (раннюю, неполную, почти наверняка багги) рубиновую работу для http://github.com/mcarpenter/rubug.

Вот пример (вы можете найти это в examples/breakpoint). Функция check_for_crash - это обратный вызов, который может быть вызван после запуска программы с именем factorial. Точка останова принимает имя функции (fac; ведущий двоеточие просто указывает, что это рубиновый символ, который во всех смыслах и целях здесь является легким строка).

EXE = 'factorial'

def check_for_crash(gdb, event)
  case event.type
  when :command_response
    raise RuntimeError, 'oops' unless
  [ :done, :running ].include? event.response.result
  when :breakpoint
    puts 'Breakpoint reached'
    pp event
    gdb.continue
  when :exit
    puts 'Exit'
    gdb.stop_event_loop
    exit
  end
end

gdb = Rubug::Gdb.new
resp = gdb.file EXE
gdb.register_callback(method :check_for_crash)
gdb.break(:fac)
gdb.run '5 > /dev/null'
gdb.start_event_loop

Можно только предупредить вас, что код может быть... крутым. В настоящее время (это я остановился) ничего не работает (после обновления gdb в середине моей работы см. Грамматика ниже).

В каталоге одного и того же но это может оказаться полезным. Чтобы (попытаться!) Запустить их, вам нужно будет сделать что-то вроде этого:

rake clean
rake grammar
rake make 
cd examples/simple_fuzzer
ruby -I ../../lib -r rubygems simple_fuzzer.rb

Учитывая, что это было написано, вам следует, вероятно, пойти с ruby1.8 если у вас есть выбор (в то время я не был в 1,9 раза, и, вероятно, строка кодирования вопросов в 1.9).

Анализ ответов выполняется с помощью верхушки верхушки http://treetop.rubyforge.org, парсер PEG. Глядя на грамматику с свежие глаза Я уверен, что это можно упростить. Вам нужно будет установить это (и любые другие необходимые драгоценные камни) с помощью gem install ....

Еще несколько советов, если вы выполните Pythonize:

Документация

Существует немного снаружи "Отладка с GDB" (глава 22). Я бросил этот PDF файл и просто ch. 22 как отдельный файл в раздел docs в репозитории.

Асинхронный

Протокол асинхронный (сначала я предполагал, что это протокол типа команды/ответа, это было ошибкой). Если бы я был повторите это, я бы, вероятно, использовал что-то вроде event-машины или libevent вместо того, чтобы катить мой собственный цикл select().

Грамматика

Грамматика немного... запутанная. Хотя документация (27.2.2) утверждает, что ответ "состоит из нуля или более вне полосы записи, за которым следует, по выбору, одна запись результата:

`output -> ( out-of-band-record )* [ result-record ] "(gdb)" nl`

вы должны знать, что, поскольку все может прибыть в любое время a read() на сокете, по-видимому, может вернуться async/result/more асинхронный/терминатор (!). Например, я вижу это с моим текущим gdb:

=thread-group-started,id="i1",pid="1086"
=thread-created,id="1",group-id="i1"
^running
*running,thread-id="all"
(gdb)

Начальная строка ^ - это запись результата, все остальные - асинхронные (тогда Терминатор). Это кажется довольно значительным недостатком в спецификация.

Speed ​​

Мое основное внимание уделяется безопасности, и меня интересовал MI для автоматическое расщепление, двоичный контроль и т.д. Для этого GDB/MI тоже медленный (стоимость запуска программы в отладчике). YMMV.

Отображение MI/CLI

В стандартном наборе команд CLI gdb были некоторые вещи, которые я не могли увидеть, как реализовать использование команд MI. У меня скелет код для чего-то вроде этого:

gdb = Gdb::MI.new
gdb.cli(:file, '/bin/ls')
gdb.cli(:set, :args, '> /dev/null')
gdb.cli(:run)
gdb.cli(:quit)

(что приятно и понятно, я думаю, для нас не-MI-expert-but-gdb-знающих пользователей). Теперь я не могу вспомнить, что это за проблемы (это в течение года так как я смотрел на это), но если эти нейроны будут стрелять, я вернусь и обновите это.

Альтернативы

Когда я впервые начал на этой дороге я нашел сообщение в блоге от Jamis Buck: http://weblog.jamisbuck.org/2006/9/25/gdb-wrapper-for-ruby Это обертывает gdb сеанс командной строки в popen(), который заставил меня немного вздрогнуть. В в частности, можно ожидать, что он будет хрупким, поскольку gdb не делает гарантирует стабильность выхода CLI. Вы можете (или не можете) предпочитают этот подход.

Если вы находитесь в окнах, то может представлять интерес PyDbg/PeiMei: http://code.google.com/p/paimei/

Вам также может понравиться книга Gray Hat Python: программирование на Python для хакеров (Seitz). Опять же, в основном окна основаны, но могут оказаться вдохновляющими.

Ответ 2

Ссылки, которые вы указали, больше связаны с вызовом Python из GDB, но вы спрашиваете, как вызывать GDB из Python или C. GDB/MI - это, безусловно, путь. Eclipse, Emacs и KDevelop используют GDB/MI для абстрагирования интерфейса отладки. Я лично использовал KDevelop с тремя различными кросс-скомпилированными версиями gdb для ARM, AVR и H8S. Протокол MI предназначен для анализа программным обеспечением, поэтому синтаксис очень правильный.

В результате поиска Google появилась оболочка Python GDB, которая должна вас запустить.