Pull to refresh

Отладка Go кода с помощью GDB. Введение

Reading time 2 min
Views 10K
Original author: The Go Programming Language
Нижесказанное относится к инструментарию gc. Gccgo имеет встроенную поддержку gdb. Помимо этого обзора Вы можете консультироваться с руководством по GDB.

Когда Вы компилируете и компонуете ваши Go программы с помощью инструментария gc в Linux, Mac OS X или FreeBSD, полученные в результате бинарные файлы содержат отладочную информацию DWARFv3, которую отладчик GDB последней версии (>7.1) может использовать для исследования живого процесса или дампа.

Чтобы опустить отладочную информацию передайте флаг '-s' компоновщику (например, go build -ldflags "-s" prog.go).

Код, генерируемый компилятором gc, включает встраивание вызовов функций и регистеризацию переменных. Эти оптимизации иногда могут сделать отладку с помощью GDB сложнее. Чтобы отключить их на время отладки, передайте флаг -gcflags "-N -l" команде go, которая используется для сборки отлаживаемого кода.

Распространенные операции


  • Показать файл и номер строки кода, установить точку останова и дизассемблировать:
    (gdb) list
    (gdb) list line
    (gdb) list file.go:line
    (gdb) break line
    (gdb) break file.go:line
    (gdb) disas

  • Показать трассировку и раскрученные стековые кадры:
    (gdb) bt
    (gdb) frame n

  • Показать имя, тип и расположение в стековом кадре локальных переменных, аргументов и возвращаемых значений:
    (gdb) info locals
    (gdb) info args
    (gdb) p variable
    (gdb) whatis variable

  • Показать имя, тип и расположение глобальных переменных:
    (gdb) info variables regexp


Go расширения


Новый механизм расширений GDB позволяет загружать скрипты расширений для заданного двоичного файла. Инструментарий использует этот факт, для того чтобы расширить GDB небольшим числом команд, позволяющих исследовать внутренности исполняемого кода (такие как горутины) и красиво отображать встроенные типы словарей, срезов и каналов.

  • Красивое отображение строк, срезов, словарей, каналов или интерфейсов:
    (gdb) p var

  • $len() и $cap() функции для строк, срезов и словарей:
    (gdb) p $len(var)

  • Функция для приведения интерфейсов к их динамическим типам:
    (gdb) p $dtype(var)
    (gdb) iface var

    Известная проблема: GDB не может автоматически находить динамический тип значения интефейса, если его длинно имя отличается от короткого (раздражает, когда выводится трассировка стека, вместо красивого отображения мы получаем короткое имя типа и указатель).

  • Исследование горутин:
    (gdb) info goroutines
    (gdb) goroutine n cmd
    (gdb) help goroutine

    Например:
    (gdb) goroutine 12 bt


Если Вы хотите узнать как скрипт расширения работает или хотите расширить его, посмотрите src/pkg/runtime/runtime-gdb.py в директории исходных кодов Go. Он зависит от нескольких специальных магических типов (hash<T,U>) и переменных (runtime.m и runtime.g), описание которых в DWARF коде обеспечивает компоновщик (src/cmd/ld/dwarf.c).

Если Вам интересно как выглядит отладочная информация, запустите 'objdump -W 6.out' и просмотрите секции .debug_*.

Известные проблемы


  1. Красивое отображение строк срабатывает только для типа строка, а не для для типов, наследуемых от него.
  2. Информация о типах отсутствует для частей библиотеки времени выполнения написанных на C.
  3. GDB не понимает определения имен Go и рассматривает "fmt.Print" в качестве неструктурированного литерала с ".", который должен быть помещен в кавычки. Это еще более относится именам методов pkg.(*MyType).Meth.
  4. Все глобальные переменные причисляются к пакету main.
Tags:
Hubs:
+17
Comments 2
Comments Comments 2

Articles