Техническое примечание TN2124

Волшебство отладки Mac OS X

Mac OS X содержит много 'секретных' средств отладки, включая переменные окружения, предпочтения, подпрограммы, вызываемые от GDB, и т.д. Этот technotes описывает эти средства. Если Вы разрабатываете для Mac OS X, необходимо просмотреть этот список, чтобы видеть, пропускаете ли Вы что-то, что сделает Вашу жизнь проще.

Введение
Основы
Некоторый требуемый блок
Инструменты
CrashReporter
BSD
DTrace
Демоны
Core Services
Диски и диски
Прикладные службы
Углерод (HIToolbox)
Какао и касание какао
Сети
История версии документа

Введение

Все системы Apple включают средства отладки, добавленные командами инженеров Apple, чтобы помочь разработать и отладить определенные подсистемы. Многие из этих средств остаются в выпущенном системном программном обеспечении, и можно использовать их для отладки кода. Этот technote описывает некоторые более широко полезные. В случаях, где средство отладки документируется в другое место, существует краткий обзор средства и ссылки к существующей документации.

Многие подробные данные, покрытые этим technote, варьируются от платформы до платформы и выпуска к выпуску. Также, можно встретиться с незначительными изменениями между платформами, и в более старых или более новых системах. Известные значительные изменения вызываются в тексте.

Этот technote был записан в отношении Mac OS X 10.6.

Этот technote покрытия усовершенствовал отладку методов. Если Вы просто начинаете, необходимо консультироваться со следующим материалом:

Этот technote не покрывает отладку производительности. При попытке отладить проблему производительности, лучшее место для запуска является Началом работы с документом Производительности.

Основы

Более поздние разделы этого technote описывают средства отладки подробно. Многие из этих средств используют подобные методы, чтобы включить и отключить средство и видеть его вывод. В этом разделе описываются эти общие методы.

Включение средств отладки

Некоторые средства отладки включены по умолчанию. Однако большинство средств должно быть включено с помощью одного из методов, описанных в следующих разделах.

Переменные окружения

Во многих случаях можно включить средство отладки путем установки определенной переменной окружения. Можно сделать это использование исполнимого инспектора в XCode. Рисунок 1 показывает пример этого.

Рисунок 1  , Устанавливающий переменные окружения в XCode

Кроме того, существуют многочисленный другие способы установить переменную окружения. Первое включает запуск Вашего приложения от Терминала и указания переменной окружения на командной строке. Перечисление 1 показывает, как установить переменную окружения в sh оболочка; Перечисление 2 показывает эквивалент в csh.

Перечисление 1  , Устанавливающее переменную окружения в оболочке sh-compatible

$ MallocScribble=1 /Applications/TextEdit.app/Contents/MacOS/TextEdit  TextEdit(13506) malloc: enabling scribbling to detect mods to free blocks […]

Перечисление 2  , Устанавливающее переменную окружения в csh-совместимой оболочке

% env MallocScribble=1 /Applications/TextEdit.app/Contents/MacOS/TextEdit TextEdit(13512) malloc: enabling scribbling to detect mods to free blocks […]

Кроме того, можно установить переменные окружения в GDB, как показано в Перечислении 3.

Перечисление 3  , Устанавливающее переменную окружения в GDB

$ gdb /Applications/TextEdit.app
GNU gdb 6.3.50-20050815 […]
(gdb) set env MallocScribble 1
(gdb) r
Starting program: /Applications/TextEdit.app/Contents/MacOS/TextEdit 
bash(13587) malloc: enabling scribbling to detect mods to free blocks
[…]

Технические Вопросы и ответы QA1067, 'Устанавливая переменные окружения для пользовательских процессов' описывают механизм для установки переменных окружения для всех процессов, запущенных определенным пользователем.

Наконец, можно использовать launchctl установить переменные окружения, наследованные всеми процессами, выполненными launchd; см. launchd для подробных данных.

Предпочтения

Некоторые средства отладки включены путем установки специального предпочтения. Можно установить такое предпочтение отладки путем конфигурирования параметра командной строки в XCode. Рисунок 2 показывает, как это сделано.

Рисунок 2  , Устанавливающий параметры командной строки в XCode

Можно также сделать это путем выполнения программы из командной строки и предоставления предпочтения в параметрах. Перечисление 4 показывает пример.

  Установка Listing 4 Temporarily предпочтение

$ /Applications/TextEdit.app/Contents/MacOS/TextEdit -NSTraceEvents YES
2004-10-25 17:28:41.143 TextEdit[5774] timeout = 62993575878.857864 seco…
2004-10-25 17:28:41.179 TextEdit[5774] got apple event of class 61657674…
[…]

В дополнение к временным методам, описанным выше, можно установить предпочтения постоянно с помощью defaults инструмент командной строки. Перечисление 5 показывает, как сделать это. Это перечисление устанавливает NSTraceEvents предпочтение приложения TextEdit (чей идентификатор пакета com.apple.TextEdit) к YES.

Перечисление 5  , Устанавливающее предпочтение с помощью значений по умолчанию

$ defaults write com.apple.TextEdit NSTraceEvents YES
$ /Applications/TextEdit.app/Contents/MacOS/TextEdit 
2010-02-01 13:32:36.260 TextEdit[18687:903] timeout = 62827180043.739540 seconds[…]
2010-02-01 13:32:36.273 TextEdit[18687:903] got apple event of class 61657674, I[…]
[…]

Как только Вы закончены, отладив, необходимо удалить предпочтение, также с помощью defaults, как показано в Перечислении 6.

Перечисление 6  Удаляя предпочтение с помощью значений по умолчанию

$ defaults delete com.apple.TextEdit NSTraceEvents

Для получения дополнительной информации о defaults, консультируйтесь с его страницей справочника.

Вызываемые подпрограммы

Много системных платформ включают подпрограммы та отладочная информация печати в stderr. Эти подпрограммы могут быть специально предназначены, чтобы быть вызываемыми из GDB, или они могут просто быть существующими подпрограммами API, которые полезны при отладке. Перечисление 7 показывает пример того, как вызвать отладочную программу от GDB; в частности это вызывает CFBundleGetAllBundles получить список всех пакетов, загруженных в приложении, и затем, распечатывает тот список путем вызова CFShow подпрограмма.

Перечисление 7  Вызывая отладочную программу от GDB

(gdb) call (void)CFShow((void *)CFBundleGetAllBundles())
<CFArray 0x10025c010 [0x7fff701faf20]>{type = mutable-small, count = 59, values = (
    0 : CFBundle 0x100234d00 </System/Library/Frameworks/CoreData.framework> …
    […]
    12 : CFBundle 0x100237790 </System/Library/Frameworks/Security.framework> …
    […]
    23 : CFBundle 0x100194eb0 </System/Library/Frameworks/CoreFoundation.framework> …
    […]
)}

Если Вы не видите вывод от подпрограммы, Вы, возможно, должны смотреть на консольный журнал, как описано в разделе Seeing Debug Output.

На практике это только влияет на Intel 32-разрядный код.

Файлы

Определенные средства отладки включены существованием определенных файлов в файловой системе. Перечисление 8 показывает пример этого: создание файла /var/log/do_dnserver_log заставляет сервер CFNotificationCenter (distnoted) записывать информацию обо всех уведомлениях системному журналу.

Перечисление 8  Создает определенный файл, чтобы позволить отладить

$ # IMPORTANT: This example is for Mac OS X 10.6 and later.
$ # See the "CFNotificationCenter" section for details on how 
$ # to do this on earlier systems.
$
$ sudo touch /var/log/do_dnserver_log

[… now restart …]

$ tail -f /var/log/system.log
Virtual-Victim:~ quinn$ tail -f /var/log/system.log
[…] distnoted[16]: checking_client "quicklookd" [43]
[…] distnoted[16]: checking_client "Dock" [43]
[…] distnoted[16]: checking_client "mds" [1]
[…] distnoted[16]: checking_client "mDNSResponder" [1]
[…] distnoted[16]: checking_client "fontd" [43]
[…]

Для получения дополнительной информации об этом определенном примере, посмотрите CFNotificationCenter.

Сигналы

Много подсистем Mac OS X, особенно те с наследием BSD, реализуют средства отладки, к которым Вы получаете доступ через сигналы. Например, если Вы отправляете SIGINFO сигнал к mDNSResponder, это выведет свое текущее состояние к системному журналу.

Можно отправить сигналы программно или из командной строки. Для отправки сигнала программно используйте подпрограмму уничтожения. Для отправки сигнала от командной строки используйте любого команда уничтожения (если Вы знаете процесс ID), или killall команда (если Вы знаете имя процесса).

При использовании этих инструментов строки команд, знать, что этот technote использует сигнальный идентификатор (например, SIGINFO) тогда как эти инструменты строки команд используют сигнальное имя (INFO). Так, для отправки a SIGINFO к mDNSResponder, Вы использовали бы команду, показанную в Перечислении 9.

Перечисление 9  , Отправляющее сигнал

$ sudo killall -INFO mDNSResponder

Наблюдение вывода отладки

Программы, генерирующие вывод отладки обычно, делают настолько использующий из следующих механизмов:

  • NSLog

  • печать к stderr

  • системный журнал

  • средство трассировки ядра

NSLog высокоуровневый API для журналирования, использующегося экстенсивно кодом Objective C. Точное поведение NSLog удивительно сложно, и изменялся значительно в течение долгого времени, делая его вне объема этого документа. Однако достаточно знать это NSLog печать к stderr, или журналы к системному журналу или обоим. Так, если Вы понимаете те два механизма, Вы видите что-либо зарегистрированное через NSLog.

Печать к stderr один из обычно используемого выходного механизма. Учитывая важность этой темы, это покрыто подробно в следующем разделе.

Можно просмотреть системный журнал с помощью Консольного приложения (в /Applications/Utilities). Можно узнать больше о системном средстве журнала в страницах справочника системного журнала (asl, системный журнал, syslog.conf, и syslogd).

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

Консольный вывод

Много программ, и действительно много системных платформ, распечатывают сообщения отладки к stderr. Местом назначения для этого вывода в конечном счете управляет программа: это может перенаправить stderr любому месту назначения это выбирает. Однако в большинстве случаев программа не перенаправляет stderr, таким образом, вывод переходит к месту назначения по умолчанию, наследованному программой от ее среды запуска. Это обычно - одно из следующего:

  • При запуске приложения GUI как оно было бы запущено обычным пользователем, система перенаправляет любые сообщения, распечатанные на stderr к системному журналу. Можно просмотреть эти сообщения с помощью методов, описанных ранее.

  • При выполнении программы из XCode Вы видите stderr вывод в окне консоли отладки XCode (выбирают пункт меню Console из меню Run для наблюдения этого окна).

  • Наконец, если Вы выполняете программу (быть им GUI или не-GUI) из Терминала, stderr подключен к Вашему Окну терминала; что-либо печать программы появится в этом окне. Это также применяется к программам, выполненным от GDB в Окне терминала.

Консольные сообщения (т.е. системные записи журнала, создаваемые в ответ на печать приложения к stderr) особенно тегируются для создания их простыми найти в системном журнале. Существует два метода для просмотра этих сообщений:

  • В Консольном приложении (в /Applications/Utilities), существует элемент боковой панели маркированные Консольные сообщения. При выборе того элемента окно выводит на экран только этот тип сообщения.

  • Можно запросить ASL для консольных сообщений с командой, показанной в Перечислении 10.

Перечисление 10  , Запрашивающее ASL для консольных сообщений

$ # This command just does a query and prints the results.
$ syslog -C
[…]
[…].com.apple.TextEdit[4373] <Notice>: Hello Cruel World!
$ # This command does the query, prints the results, and then waits 
$ # for any new results. Press ^C to stop it.
$ syslog -w -C
[…]
[…].com.apple.TextEdit[4373] <Notice>: Hello Cruel World!
[…].com.apple.TextEdit[4373] <Notice>: Goodbye Cruel World!
^C

  Консоль Listing 11 Viewing обменивается сообщениями до Mac OS X 10.5

$ # This command prints the entire console log.
$ cat /Library/Logs/Console/`id -u`/console.log
[…]
Hello Cruel World!
$ # This command prints the last few lines of the console log 
$ # and then waits for any new results. Press ^C to stop it.
$ tail -f /Library/Logs/Console/`id -u`/console.log
[…]
Hello Cruel World!
Goodbye Cruel World!
^C

Присоединение к рабочей программе (использующий Присоединение XCode для меню Process, или attach команда в GDB), автоматически не соединяет программу stderr к Вашему окну GDB. Можно сделать это из GDB использование приема, описанного в разделе «Seeing stdout and stderr After Attaching» Технического примечания TN2030, 'GDB для Ветеранов MacsBug'.

Некоторый требуемый блок

В то время как очень необычно записать существенное количество кода в ассемблере теперь, все еще полезно иметь основное понимание того темного искусства. Это - особенно истина, когда Вы отлаживаете, особенно при отладке катастрофических отказов, происходящих в библиотеках или платформах, для которых у Вас нет исходного кода. Этот раздел покрывает некоторые самые основные методы, необходимые для отладки программ на уровне ассемблера. В частности это описывает, как установить точки останова, параметры доступа, и получить доступ к обратному адресу на всей поддерживаемой архитектуре.

Все примеры отладки на уровне ассемблера, показанные в этом technote, из 64-разрядных программ, работающих на основанном на Intel компьютере Macintosh. Однако относительно просто адаптировать эти примеры к другой архитектуре. Старшие значащие различия:

И это точно элементы, покрытые следующими архитектурно-зависимыми разделами.

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

Для подробного описания соглашений о вызовах для всей архитектуры Mac OS X посмотрите Mac OS X Руководство по Вызову функции ABI.

Перед чтением следующих разделов критически важно, что Вы понимаете одну тонкость GDB. Поскольку GDB является, в глубине души, отладчиком исходного уровня при установке точки останова на подпрограмме GDB не устанавливает точку останова на первой инструкции подпрограммы; скорее это устанавливает точку останова в первой инструкции после вводной части подпрограммы. С точки зрения отладки на уровне исходного кода это имеет совершенный смысл. В отладчике исходного уровня Вы никогда не хотите продвинуться через вводную часть подпрограммы. Однако при выполнении отладки на уровне ассемблера, проще получить доступ к параметрам перед выполнениями вводной части. Поэтому расположение параметров в первой инструкции подпрограммы определяется вызовом функции ABI, но вводной части позволяют переставить вещи вокруг по ее усмотрению. Кроме того, каждая вводная часть может сделать это немного отличающимся способом. Так единственный способ получить доступ к параметрам после того, как вводная часть выполнилась, должен демонтировать вводную часть и разработать, куда все пошло. Это обычно, но не всегда, довольно просто, но это - все еще дополнительная работа.

Лучший способ сказать GDB устанавливать точку останова в первой инструкции подпрограммы состоит в том, чтобы снабдить префиксом стандартное имя «*». Перечисление 12 показывает пример этого.

Перечисление 12  Прежде и после вводной части

$ gdb
GNU gdb 6.3.50-20050815 (Apple version gdb-1346) […]
(gdb) attach Finder
[…]
(gdb) b CFStringCreateWithFormat
Breakpoint 1 at 0x7fff86098290
(gdb) info break
Num Type        Disp Enb Address            What
1   breakpoint  keep y   0x00007fff86098290 <CFStringCreateWithFormat+32>
(gdb) # The breakpoint is not at the first instruction.
(gdb) # Disassembling the routine shows that GDB has skipped the prologue.
(gdb) x/7i CFStringCreateWithFormat
0x7fff86098270 <CFStringCreateWithFormat>: push   %rbp
0x7fff86098271 <CFStringCreateWithFormat+1>: mov    %rsp,%rbp
0x7fff86098274 <CFStringCreateWithFormat+4>: sub    $0xd0,%rsp
0x7fff8609827b <CFStringCreateWithFormat+11>: mov    %rcx,-0x98(%rbp)
0x7fff86098282 <CFStringCreateWithFormat+18>: mov    %r8,-0x90(%rbp)
0x7fff86098289 <CFStringCreateWithFormat+25>: mov    %r9,-0x88(%rbp)
0x7fff86098290 <CFStringCreateWithFormat+32>: movzbl %al,%ecx
(gdb) # So we use a "*" prefix to disable GDB's 'smarts'.
(gdb) b *CFStringCreateWithFormat
Breakpoint 2 at 0x7fff86098270
(gdb) info break
Num Type        Disp Enb Address            What
1   breakpoint  keep y   0x00007fff86098290 <CFStringCreateWithFormat+32>
2   breakpoint  keep y   0x00007fff86098270 <CFStringCreateWithFormat>

Наконец при поиске информации о конкретных инструкциях, знать, что Меню справки у Акулы (включенный в инструменты разработчика XCode) имеет ссылку системы команд для ARM, Intel и архитектуры PowerPC.

64-разрядный Intel

В 64-разрядных программах Intel первые шесть параметров передаются в регистрах. Обратный адрес находится на штабеле, но имейте в виду, что это - 64-разрядное значение. Таблица 1 показывает, как получить доступ к этим значениям от GDB, когда Вы остановились в первой инструкции функции.

Табличные 1  параметры Доступа на 64-разрядном Intel

Что

Синтаксис GDB

обратный адрес

* (длинный *) $esp

первый параметр

$rdi

второй параметр

$rsi

третий параметр

$rdx

четвертый параметр

$rcx

пятый параметр

$r8

шестой параметр

$r9

По возврату из функции результат находится в регистре RAX ($rax).

Поскольку параметры передаются в регистрах, нет никакого прямого способа получить доступ к параметрам после вводной части.

Перечисление 13 показывает пример того, как использовать эту информацию для доступа к параметрам в GDB.

  Параметры перечисления 13 на 64-разрядном Intel

$ # Use the -arch x86_64 argument to GDB to get it to run the 
$ # 64-bit Intel binary. Obviously this will only work on 64-bit capable 
$ # hardware.
$ gdb -arch x86_64 /Applications/TextEdit.app
GNU gdb 6.3.50-20050815 (Apple version gdb-1346) […]
(gdb) fb CFStringCreateWithFormat
Breakpoint 1 at 0x624dd2f1959290
(gdb) r
Starting program: /Applications/TextEdit.app/Contents/MacOS/TextEdit 
Reading symbols for shared libraries […]
Breakpoint 1, 0x00007fff86098290 in CFStringCreateWithFormat ()
(gdb) # We've stopped after the prologue.
(gdb) p/a $pc
$1 = 0x7fff86098290 <CFStringCreateWithFormat+32>
(gdb) # We have to check whether the prologue 
(gdb) # has messed up the locations of the parameters.
(gdb) x/7i $pc-32
0x7fff86098270 <CFStringCreateWithFormat>: push   %rbp
0x7fff86098271 <CFStringCreateWithFormat+1>: mov    %rsp,%rbp
0x7fff86098274 <CFStringCreateWithFormat+4>: sub    $0xd0,%rsp
0x7fff8609827b <CFStringCreateWithFormat+11>: mov    %rcx,-0x98(%rbp)
0x7fff86098282 <CFStringCreateWithFormat+18>: mov    %r8,-0x90(%rbp)
0x7fff86098289 <CFStringCreateWithFormat+25>: mov    %r9,-0x88(%rbp)
0x7fff86098290 <CFStringCreateWithFormat+32>: movzbl %al,%ecx
(gdb) # Prologue hasn't messed up parameter registers, 
(gdb) # so we can just print them directly.
(gdb) #
(gdb) # first parameter is "alloc"
(gdb) p/a $rdi
$2 = 0x7fff70b8bf20 <__kCFAllocatorSystemDefault>
(gdb) # second parameter is "formatOptions"
(gdb) p/a $rsi
$3 = 0x0
(gdb) # third parameter is "format"
(gdb) call (void)CFShow($rdx)
%@
(gdb) # return address is at RBP+8
(gdb) p/a *(long*)($rbp+8)
$4 = 0x7fff8609a474 <__CFXPreferencesGetNamedVolatileSourceForBundleID+36>
(gdb) # Now clear the breakpoint and set a new one before the prologue.
(gdb) del 1
(gdb) b *CFStringCreateWithFormat
Breakpoint 2 at 0x7fff86098270
(gdb) c
Continuing.

Breakpoint 2, 0x00007fff86098270 in CFStringCreateWithFormat ()
(gdb) # We're at the first instruction. We can 
(gdb) # access parameters without checking the prologue.
(gdb) p/a $pc
$5 = 0x7fff86098270 <CFStringCreateWithFormat>
(gdb) # first parameter is "alloc"
(gdb) p/a $rdi
$6 = 0x7fff70b8bf20 <__kCFAllocatorSystemDefault>
(gdb) # second parameter is "formatOptions"
(gdb) p/a $rsi
$7 = 0x0
(gdb) # third parameter is "format"
(gdb) call (void)CFShow($rdx)
managed/%@/%@
(gdb) # return address is on top of the stack
(gdb) p/a *(long*)$rsp
$8 = 0x7fff8609806a <__CFXPreferencesGetManagedSourceForBundleIDAndUser+74>
(gdb) # Set a breakpoint on the return address.
(gdb) b *0x7fff8609806a
Breakpoint 3 at 0x7fff8609806a
(gdb) c
Continuing.

Breakpoint 3, 0x00007fff8609806a in __CFXPreferencesGetManagedSourceForBundleIDAndUser ()
(gdb) # function result
(gdb) p/a $rax
$9 = 0x10010b490
(gdb) call (void)CFShow($rax)
managed/com.apple.TextEdit/kCFPreferencesCurrentUser

32-разрядный Intel

В 32-разрядных программах Intel параметры передаются штабелю. В первой инструкции подпрограммы главное слово штабеля содержит обратный адрес, следующее слово содержит первый (крайний левый) параметр, следующее слово содержит второй параметр и т.д. Таблица 2 показывает, как получить доступ к этим значениям от GDB.

Табличные 2  параметры Доступа на 32-разрядном Intel

Что

Синтаксис GDB

обратный адрес

* (интервал *) $esp

первый параметр

* (интервал*)($esp+4)

второй параметр

* (интервал*)($esp+8)

... и т.д.

После вводной части подпрограммы можно получить доступ к параметрам относительно указателя кадра (зарегистрируйте EBP). Таблица 3 показывает синтаксис.

Табличные 3  параметры Доступа после вводной части

Что

Синтаксис GDB

предыдущий кадр

* (интервал *) $ebp

обратный адрес

* (интервал*)($ebp+4)

первый параметр

* (интервал*)($ebp+8)

второй параметр

* (интервал*)($ebp+12)

... и т.д.

По возврату из функции результат находится в регистре EAX ($eax).

Перечисление 14 показывает пример того, как использовать эту информацию для доступа к параметрам в GDB.

  Параметры перечисления 14 на 32-разрядном Intel

$ # Use the -arch i386 argument to GDB to get it to run the 
$ # 32-bit Intel binary.
$ gdb -arch i386 /Applications/TextEdit.app
GNU gdb 6.3.50-20050815 (Apple version gdb-1346) […]
(gdb) fb CFStringCreateWithFormat
Breakpoint 1 at 0x31ec6d6
(gdb) r
Starting program: /Applications/TextEdit.app/Contents/MacOS/TextEdit 
Reading symbols for shared libraries […]
Breakpoint 1, 0x940e36d6 in CFStringCreateWithFormat ()
(gdb) # We've stopped after the prologue.
(gdb) p/a $pc
$1 = 0x940e36d6 <CFStringCreateWithFormat+6>
(gdb) # However, for 32-bit Intel we don't need to inspect 
(gdb) # the prologue because the parameters are on the stack.
(gdb) # We can access them relative to EBP.
(gdb) #
(gdb) # first parameter is "alloc"
(gdb) p/a *(int*)($ebp+8)
$2 = 0xa0473ee0 <__kCFAllocatorSystemDefault>
(gdb) # second parameter is "formatOptions"
(gdb) p/a *(int*)($ebp+12)
$3 = 0x0
(gdb) # third parameter is "format"
(gdb) call (void)CFShow(*(int*)($ebp+16))
%@
(gdb) # return address is at EBP+4
(gdb) p/a *(int*)($ebp+4)
$4 = 0x940f59fb <__CFXPreferencesGetNamedVolatileSourceForBundleID+59>
(gdb) # Now clear the breakpoint and set a new one before the prologue.
(gdb) del 1
(gdb) b *CFStringCreateWithFormat
Breakpoint 2 at 0x940e36d0
(gdb) c
Continuing.

Breakpoint 2, 0x940e36d0 in CFStringCreateWithFormat ()
(gdb) # We're at the first instruction. We must access 
(gdb) # the parameters relative to ESP.
(gdb) p/a $pc
$6 = 0x940e36d0 <CFStringCreateWithFormat>
(gdb) # first parameter is "alloc"
(gdb) p/a *(int*)($esp+4)
$7 = 0xa0473ee0 <__kCFAllocatorSystemDefault>
(gdb) # second parameter is "formatOptions"
(gdb) p/a *(int*)($esp+8)
$8 = 0x0
(gdb) # third parameter is "format"
(gdb) call (void)CFShow(*(int*)($esp+12))
managed/%@/%@
(gdb) # return address is on the top of the stack
(gdb) p/a *(int*)$esp
$9 = 0x940f52cc <__CFXPreferencesGetManagedSourceForBundleIDAndUser+76>
(gdb) # Set a breakpoint on the return address.
(gdb) b *0x940f52cc
Breakpoint 3 at 0x940f52cc
(gdb) c
Continuing.

Breakpoint 3, 0x940f52cc in __CFXPreferencesGetManagedSourceForBundleIDAndUser ()
(gdb) # function result
(gdb) p/a $eax
$10 = 0x1079d0
(gdb) call (void)CFShow($eax)
managed/com.apple.TextEdit/kCFPreferencesCurrentUser

PowerPC

В программах PowerPC, быть их 32-или 64-разрядный, первые восемь параметров передаются в регистрах. Обратный адрес находится в регистре LR. Таблица 4 показывает, как получить доступ к этим значениям от GDB, когда Вы остановились в первой инструкции функции.

Табличные 4  параметры Доступа на PowerPC

Что

Синтаксис GDB

обратный адрес

$lr

первый параметр

$r3

второй параметр

$r4

третий параметр

$r5

четвертый параметр

$r6

пятый параметр

$r7

шестой параметр

$r8

седьмой параметр

$r9

восемь параметров

$r10

По возврату из функции результат находится в регистре GPR3 ($r3).

Поскольку параметры передаются в регистрах, нет никакого прямого способа получить доступ к параметрам после вводной части.

Перечисление 15 показывает пример того, как использовать эту информацию для доступа к параметрам в GDB. Этот пример показывает 32-разрядный PowerPC; однако, 32-и 64-разрядный вызов функции PowerPC, ABIs так подобны, что процедура фактически идентична для 64-разрядных программ.

  Параметры перечисления 15 на PowerPC

$ gdb /Applications/TextEdit.app
GNU gdb 6.3.50-20050815 (Apple version gdb-754) […]
(gdb) fb CFStringCreateWithFormat
Breakpoint 1 at 0x8b1bc
(gdb) r
Starting program: /Applications/TextEdit.app/Contents/MacOS/TextEdit 
Reading symbols for shared libraries […]
Breakpoint 1, 0x90e871e8 in CFStringCreateWithFormat ()
(gdb) # We've stopped after the prologue.
(gdb) p/a $pc
$1 = 0x90e871e8 <CFStringCreateWithFormat+44>
(gdb) # Let's see what the prologue has done to the registers 
(gdb) # holding our parameters.
(gdb) x/12i $pc-44
0x90e871bc <CFStringCreateWithFormat>: mflr    r0
0x90e871c0 <CFStringCreateWithFormat+4>: stw     r0,8(r1)
0x90e871c4 <CFStringCreateWithFormat+8>: stwu    r1,-96(r1)
0x90e871c8 <CFStringCreateWithFormat+12>: addi    r0,r1,132
0x90e871cc <CFStringCreateWithFormat+16>: stw     r6,132(r1)
0x90e871d0 <CFStringCreateWithFormat+20>: mr      r6,r0
0x90e871d4 <CFStringCreateWithFormat+24>: stw     r0,56(r1)
0x90e871d8 <CFStringCreateWithFormat+28>: stw     r7,136(r1)
0x90e871dc <CFStringCreateWithFormat+32>: stw     r8,140(r1)
0x90e871e0 <CFStringCreateWithFormat+36>: stw     r9,144(r1)
0x90e871e4 <CFStringCreateWithFormat+40>: stw     r10,148(r1)
0x90e871e8 <CFStringCreateWithFormat+44>: bl      0x90e871a4 […]
(gdb) # Hey, the prologue hasn't modified GPR3..5, so we're OK.
(gdb) #
(gdb) # first parameter is "alloc"
(gdb) p/a $r3
$2 = 0xa019e174 <__kCFAllocatorSystemDefault>
(gdb) # second parameter is "formatOptions"
(gdb) p/a $r4
$3 = 0x0
(gdb) # third parameter is "format"
(gdb) call (void)CFShow($r5)
%@
(gdb) # It turns out the prologue has left LR intact as well.
(gdb) # So we can get our return address.
(gdb) p/a $lr
$4 = 0x90ebe604 <__CFXPreferencesGetNamedVolatileSourceForBundleID+60>
(gdb) # However, things aren't always this easy. If the prologue 
(gbb) # has munged LR, you can the return address out of the frame.
(gdb) p/a *(int*)($r1+96+8)
$8 = 0x90ebe604 <__CFXPreferencesGetNamedVolatileSourceForBundleID+60>
(gdb) # Now clear the breakpoint and set a new one before the prologue.
(gdb) del 1
(gdb) b *CFStringCreateWithFormat
Breakpoint 2 at 0x90e871bc
(gdb) c
Continuing.

Breakpoint 2, 0x90e871bc in CFStringCreateWithFormat ()
(gdb) # We're at the first instruction. The parameters are guaranteed 
(gdb) # to be in the right registers.
(gdb) p/a $pc
$9 = 0x90e871bc <CFStringCreateWithFormat>
(gdb) # first parameter is "alloc"
(gdb) p/a $r3
$10 = 0xa019e174 <__kCFAllocatorSystemDefault>
(gdb) # second parameter is "formatOptions"
(gdb) p/a $r4
$11 = 0x0
(gdb) # third parameter is "format"
(gdb) call (void)CFShow($r5)
managed/%@/%@
(gdb) # return address is in LR
(gdb) p/a $lr
$12 = 0x90ebe938 <__CFXPreferencesGetManagedSourceForBundleIDAndUser+80>
(gdb) # Set a breakpoint on the return address.
(gdb) b *0x90ebe938
Breakpoint 3 at 0x90ebe938
(gdb) c
Continuing.

Breakpoint 3, 0x90ebe938 in __CFXPreferencesGetManagedSourceForBundleIDAndUser ()
(gdb) # function result
(gdb) p/a $r3
$13 = 0x10e550
(gdb) call (void)CFShow($r3)
managed/com.apple.TextEdit/kCFPreferencesCurrentUser

Глюки архитектуры

Следующие разделы описывают несколько глюков, с которыми Вы могли бы встретиться при отладке на уровне ассемблера.

Дополнительные параметры

При рассмотрении параметров на уровне ассемблера имейте в виду следующее:

  • Если подпрограмма является функцией членства C++, существует неявный первый параметр для this.

  • Если подпрограмма является методом Objective C, существует два неявных первых параметра (см. Objective C для подробных данных об этом).

  • На PowerPC 64-разрядное целое число передается в любом одном регистре (для 64-разрядных программ) или двух регистрах (для 32-разрядных программ).

  • Если компилятор может найти все вызывающие стороны функции, он может принять решение передать параметры той функции нестандартным способом. Это очень редко на архитектуре, имеющей эффективный основанный на регистре ABI, но это довольно характерно для Intel 32-разрядные программы. Так, если Вы устанавливаете точку останова на подпрограмме, не экспортирующейся в Intel 32-разрядная программа, не упустите это очень запутывающее поведение.

Порядок байтов и размеры модуля

При исследовании памяти в GDB дела идут более гладкие при использовании корректного размера модуля. Таблица 5 является сводкой размеров модуля, поддерживаемых GDB.

Таблица 5  размеры модуля GDB

Размер

C тип

Модуль GDB

Мнемосхема

1 байт

символ

b

байт

2 байта

короткий

h

полуслово

4 байта

интервал

w

слово

8 байтов

долго или долго долго

g

гигант

Это особенно важно в следующих случаях:

  • При отладке 64-разрядной программы много количеств (например, все указатели, включая обратный адрес подпрограммы) составят 64 бита. Размер модуля GDB по умолчанию ('w') только покажет Вам 32 бита. Необходимо будет указать 'g' для наблюдения всех 64 битов.

  • При отладке в системе с прямым порядком байтов (т.е. все кроме основанных на PowerPC компьютеров Macintosh), Вы получаете запутывающие результаты при указании неправильного размера модуля. Перечисление 16 показывает пример этого. Вторые и третьи параметры CFStringCreateWithCharacters укажите массив символов Unicode. Каждый элемент является a UniChar, который является 16-разрядным числом в формате собственного порядка байтов. Поскольку мы работаем на системе с прямым порядком байтов, необходимо вывести этот массив с помощью корректного размера модуля, иначе все выглядит испорченным.

Перечисление 16  Используя правильный размер модуля

$ gdb
GNU gdb 6.3.50-20050815 (Apple version gdb-1346) […]
(gdb) attach Finder
Attaching to process 4732.
Reading symbols for shared libraries . done
Reading symbols for shared libraries […]
0x00007fff81963e3a in mach_msg_trap ()
(gdb) b *CFStringCreateWithCharacters
Breakpoint 1 at 0x7fff86070520
(gdb) c
Continuing.

Breakpoint 1, 0x00007fff86070520 in CFStringCreateWithCharacters ()
(gdb) # The third parameter is the number of UniChars 
(gdb) # in the buffer pointed to by the first parameter.
(gdb) p (int)$rdx
$1 = 18
(gdb) # Dump the buffer as shorts. Everything makes sense.
(gdb) # This is the string "Auto-Save Recovery".
(gdb) x/18xh $rsi
0x10b7df292: 0x0041  0x0075  0x0074  0x006f  0x002d  0x0053  0x0061  0x0076
0x10b7df2a2: 0x0065  0x0020  0x0052  0x0065  0x0063  0x006f  0x0076  0x0065
0x10b7df2b2: 0x0072  0x0079
(gdb) # Now dump the buffer as words. Most confusing.
(gdb) # It looks like "uAotS-va eeRocevyr"!
(gdb) x/9xw $rsi
0x10b7df292: 0x00750041      0x006f0074      0x0053002d      0x00760061
0x10b7df2a2: 0x00200065      0x00650052      0x006f0063      0x00650076
0x10b7df2b2: 0x00790072
(gdb) # Now dump the buffer as bytes. This is a little less 
(gdb) # confusing, but you still have to remember that it's big 
(gdb) # endian data.
(gdb) x/36xb $rsi
0x10b7df292: 0x41    0x00    0x75    0x00    0x74    0x00    0x6f    0x00
0x10b7df29a: 0x2d    0x00    0x53    0x00    0x61    0x00    0x76    0x00
0x10b7df2a2: 0x65    0x00    0x20    0x00    0x52    0x00    0x65    0x00
0x10b7df2aa: 0x63    0x00    0x6f    0x00    0x76    0x00    0x65    0x00
0x10b7df2b2: 0x72    0x00    0x79    0x00

Наконец, знайте, что много подпрограмм уровня BSD имеют различные варианты в зависимости от OS, на котором Вы работаете, SDK раньше соединял программу, и MACOSX_DEPLOYMENT_TARGET установка сборки. Это может стать очень запутывающим при отладке на уровне ассемблера. Например, Перечисление 17 очевидно показывает завихрение, загружающее URL, никогда не вызывая подключение!

  Загрузка перечисления 17 без подключения

$ gdb -arch i386 /usr/bin/curl
GNU gdb 6.3.50-20050815 (Apple version gdb-1346) […]
(gdb) # Run it once, for reasons that are just too hard to explain.
(gdb) r http://apple.com
Starting program: /usr/bin/curl http://apple.com
Reading symbols for shared libraries […]
<head><body> This object may be found <a HREF="http://www.apple.com/">here</a> </body>
Program exited normally.
(gdb) # Set a breakpoint and run it again.
(gdb) b *connect
Breakpoint 1 at 0x94bb7583
(gdb) r
Starting program: /usr/bin/curl http://apple.com
<head><body> This object may be found <a HREF="http://www.apple.com/">here</a> </body>
Program exited normally.
(gdb) # Huh!?!  We downloaded the web page without every calling connect!

Причина этого - это curl был соединен с Mac OS X 10,6 SDK с целью развертывания 10,6 и позже. Поэтому это вызывает украшенную версию connect, connect$UNIX2003. Видеть curl вызвать connect, у Вас есть набор точка останова на том украшенном символе, как показано в Перечислении 18.

Перечисление 18  , Повреждающееся на украшенном подключении

$ gdb -arch i386 /usr/bin/curl
GNU gdb 6.3.50-20050815 (Apple version gdb-1346) […]
(gdb) # Run it once, for reasons that are just too hard to explain.
(gdb) r http://apple.com
Starting program: /usr/bin/curl http://apple.com
Reading symbols for shared libraries […]
<head><body> This object may be found <a HREF="http://www.apple.com/">here</a> </body>
Program exited normally.
(gdb) # Set the breakpoint on the decorated symbol. Note the user of 
(gdb) # single quotes to escape the dollar sign.
(gdb) b *'connect$UNIX2003'
Breakpoint 1 at 0x94b5636c
(gdb) r
Starting program: /usr/bin/curl http://apple.com

Breakpoint 1, 0x94b5636c in connect$UNIX2003 ()
(gdb) # Much better.

Управляемый катастрофический отказ

В некоторых случаях полезно разрушить Вашу программу с сохранением контроля над ситуацией. Один распространенный способ сделать это должно вызвать аварийное прекращение работы. Другая опция состоит в том, чтобы использовать __builtin_trap встроенная функция, генерирующая специфичную для машины инструкцию прерывания. Перечисление 19 показывает, как это сделано.

Перечисление 19  , Отказывающее через __ builtin_trap

int main(int argc, char **argv) {     __builtin_trap();     return 1; }

При выполнении программы в отладчике Вы сразу остановитесь в строке перед __builtin_trap вызвать. Иначе программа разрушит и сгенерирует отчет катастрофического отказа.

Инструменты

Инструменты являются приложением для того, чтобы динамично проследить и профилировать код. Это работает на Mac OS X и позволяет Вам предназначаться для программ, работающих на Mac OS X, устройствах на iOS и Средстве моделирования iPhone.

В то время как Инструменты прежде всего фокусируются на отладке производительности, можно также использовать ее для отладки ошибок. Например, инструмент ObjectAlloc может помочь Вам разыскать и сверх - и ошибки под выпуском.

Одна особенно хорошая функция Инструментов - то, что это предоставляет Вам легкий доступ к зомби. См. Инструментальное Руководство пользователя для подробных данных об этом и других функциях Instruments.

CrashReporter

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

CrashReporter описан подробно в Техническом примечании TN2123, 'CrashReporter'.

BSD

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

Средство выделения памяти

Средство выделения памяти по умолчанию включает много средств отладки, которые можно включить через переменные окружения. Они полностью документируются в страницу руководства. Таблица 6 перечисляет некоторые более полезные.

Таблица 6  Некоторые полезные переменные окружения средства выделения памяти

Переменная

Сводка

MallocScribble

Заполните выделенную память 0xAA и набросайте освобожденную память с 0x55

MallocGuardEdges

Добавьте защитные страницы прежде и после больших выделений

MallocStackLogging

Рекордный штабель регистрирует для каждого блока памяти для помощи средствам отладки памяти

MallocStackLoggingNoCompact

Рекордный штабель регистрирует для всех операций для помощи средствам отладки памяти

Средство выделения памяти по умолчанию также регистрирует сообщения, если оно обнаруживает определенные общие проблемы программирования. Например, при освобождении блока памяти дважды или свободной памяти, которую Вы никогда не выделяли, free может распечатать сообщение, показанное в Перечислении 20. Число в круглых скобках является процессом ID.

Перечисление 20  общее сообщение, распечатанное свободным

DummyPhone(1839) malloc: *** error for object 0x826600: double free *** set a breakpoint in malloc_error_break to debug

Можно отладить этот вид проблемы путем выполнения программы в GDB и надевания точки останова malloc_error_break. Как только Вы поражаете точку останова, можно использовать GDB's backtrace команда для определения непосредственной вызывающей стороны.

Наконец, можно программно проверить непротиворечивость «кучи» с помощью malloc_zone_check подпрограмма (от <malloc.h>).

Стандартная библиотека C++

Стандартная библиотека C++ поддерживает много функций отладки:

  • Установите _GLIBCXX_DEBUG переменная времени компиляции для включения режима отладки в стандартной библиотеке C++.

  • В версиях до GCC 4.0, набор GLIBCPP_FORCE_NEW переменная окружения к 1 для отключения памяти, кэширующейся в стандартной библиотеке C++. Это позволяет Вам отлаживать свои выделения C++ с другими средствами отладки памяти.

    В GCC 4.0 и позже это - поведение по умолчанию.

Динамический компоновщик (dyld)

Динамический компоновщик (dyld) поддерживает много средств отладки, которые можно включить через переменные окружения. Они полностью документируются в страницу руководства. Таблица 7 перечисляет некоторые более полезные переменные.

Таблица 7  Динамические переменные окружения компоновщика

Переменная

Сводка

DYLD_IMAGE_SUFFIX

Поиск библиотек с этим суффиксом сначала

DYLD_PRINT_LIBRARIES

Загрузки библиотеки журнала

DYLD_PRINT_LIBRARIES_POST_LAUNCH

Как выше, но только после того, как основное работало

DYLD_PREBIND_DEBUG

Печать предобязательная диагностика

DYLD_PRINT_OPTS [1]

Распечатайте разовые запуском параметры командной строки

DYLD_PRINT_ENV [1]

Распечатайте разовые запуском переменные окружения

DYLD_IGNORE_PREBINDING [1]

Отключите предварительную привязку для тестирования производительности

DYLD_PRINT_APIS [1]

Зарегистрируйте dyld вызовы API (например, dlopen)

DYLD_PRINT_BINDINGS [1]

Привязка символа журнала

DYLD_PRINT_INITIALIZERS [1]

Вызовы инициализации изображения журнала

DYLD_PRINT_SEGMENTS [1]

Отображение сегмента журнала

DYLD_PRINT_STATISTICS [1]

Статистика производительности запуска печати

Примечания:

  1. Доступный на Mac OS X 10.4 и позже.

На Mac OS X DYLD_IMAGE_SUFFIX самая полезная dyld переменная окружения, потому что можно использовать ее для включения библиотек отладки, как описано в Библиотеках Отладки.

Наконец, если Вы загружаете код динамично, и коду не удается загрузиться, можно использовать динамическую подпрограмму компоновщика NSLinkEditError получить информацию о том, что пошло неправильная ошибка. NSLinkEditError работы, даже если Вы используете высокоуровневый API, как CFBundle, для загрузки кода. Точно так же при загрузке кода с помощью dlopen можно вызвать dlerror для получения информации об ошибках загрузки.

Дампы ядра

Дампы ядра имеют незаслуженную репутацию примитивного средства отладки. Когда Вы не можете воспроизвести проблему локально, в действительности они могут быть очень полезными при отладке трудных проблем, особенно.

Можно включить дампы ядра на основе в масштабе всей системы путем добавления строки limit core unlimited к Вашему /etc/launchd.conf файл, создавая его при необходимости, и затем перезапуск. Для получения дополнительной информации об этом, см. launchd.conf страницу справочника.

Также при выполнении программы от Терминала можно просто повысить предел размера дампа ядра в оболочке заранее. Перечисление 21 показывает пример этого.

Перечисление 21  Неограниченный размер дампа ядра

$ ulimit -c unlimited $ /Applications/TextEdit.app/Contents/MacOS/TextEdit […]

Перечисление 22  Неограниченный размер дампа ядра в csh-совместимой оболочке

% limit coredumpsize unlimited

Дампы ядра записаны в каталог /cores. В современных системах этот каталог создается по умолчанию. Если это не присутствует в Вашей системе, необходимо создать его с командами, показанными в Перечислении 23.

Перечисление 23  , Создающее / каталог ядер

$ sudo mkdir /cores $ sudo chown root:admin /cores $ sudo chmod 1775 /cores

/cores должно быть перезаписываемо программой, это выводит ядро. По умолчанию это только перезаписываемо корнем и пользователями в admin группа. При необходимости в обычных пользователях, чтобы быть в состоянии вывести ядро, можно сделать мир каталога перезаписываемым с командой показанный в Перечислении 24.

Перечисление 24  , Создающее / каталог ядер

$ sudo chmod o+w /cores

Для тестирования средства дампа ядра отправьте программу a SIGABRT сигнал с помощью killall команда, как продемонстрировано Перечислением 25.

Перечисление 25  , Тестирующее дампы ядра путем отправки SIGABRT

$ killall -ABRT TextEdit

Ваше приложение тогда выйдет с «Прерыванием аварийного прекращения работы (выведенное ядро)» из сообщения. Можно найти дамп ядра в /cores. Можно выяснить, который дамп ядра который использование otool команда. Наконец, можно отладить дамп ядра с помощью GDB с -c параметр. Перечисление 26 показывает пример этого процесса.

Перечисление 26  Используя дампы ядра

Abort trap (core dumped)
$ ls -lh /cores
total 924200
-r-------- 1 quinn  admin   451M Feb  1 14:25 core.180
$ otool -c /cores/core.180 
/cores/core.180:
Argument strings on the stack at: 00007fff5fc00000
    /Applications/TextEdit.app/Contents/MacOS/TextEdit

    […] 
    /Applications/TextEdit.app/Contents/MacOS/TextEdit
    TERM_PROGRAM=Apple_Terminal
    TERM=xterm-color
    SHELL=/bin/bash
    TMPDIR=/var/folders/3y/3yhwfA4XHhCpyl9B3eaPfk+++TM/-Tmp-/
    Apple_PubSub_Socket_Render=/tmp/launch-TvHq05/Render
    TERM_PROGRAM_VERSION=272
    USER=quinn
    COMMAND_MODE=unix2003
    SSH_AUTH_SOCK=/tmp/launch-xYN0cJ/Listeners
    __CF_USER_TEXT_ENCODING=0x1F6:0:0
    PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin
    PWD=/Users/quinn
    LANG=en_US.UTF-8
    SHLVL=1
    HOME=/Users/quinn
    LOGNAME=quinn
    DISPLAY=/tmp/launch-NaLgZ1/:0
    _=/Applications/TextEdit.app/Contents/MacOS/TextEdit
$ gdb -c /cores/core.180 
GNU gdb 6.3.50-20050815 (Apple version gdb-1344) […]
#0  0x00007fff8071fefa in mach_msg_trap ()
(gdb) bt
#0  0x00007fff8071fefa in mach_msg_trap ()
#1  0x00007fff8072056d in mach_msg ()
#2  0x00007fff83865ce2 in CFRunLoopRunSpecific ()
#3  0x00007fff8386503f in CFRunLoopRunSpecific ()
#4  0x00007fff80223c4e in BlockUntilNextEventMatchingListInMode ()
#5  0x00007fff80223a53 in BlockUntilNextEventMatchingListInMode ()
#6  0x00007fff8022390c in BlockUntilNextEventMatchingListInMode ()
#7  0x00007fff86466570 in _NSSafeOrderFront ()
#8  0x00007fff86465ed9 in _NSSafeOrderFront ()
#9  0x00007fff8642bb29 in _NSKitBundle ()
#10 0x00007fff86424844 in NSApplicationMain ()
#11 0x0000000100000fb8 in ?? ()

Включение дампов ядра для процесса

Если Вы хотите включить дампы ядра для своей программы программно, можно вызвать setrlimit для изменения значения для RLIMIT_CORE. Система поставляет с мягким пределом нуля, но жестким пределом бесконечности. Таким образом дампы ядра не сгенерированы по умолчанию, но можно включить им для процесса путем повышения мягкого предела, как показано в Перечислении 27.

Перечисление 27  , Разрешающее дампы ядра программно

#include <sys/resource.h>

static bool EnableCoreDumps(void)
{
    struct rlimit   limit;

    limit.rlim_cur = RLIM_INFINITY;
    limit.rlim_max = RLIM_INFINITY;
    return setrlimit(RLIMIT_CORE, &limit) == 0;
}

Это, однако, не устраняет потребность в перезаписываемом /cores каталог.

Генерация дампа ядра от GDB

Если Вы хотите в, генерируют дамп ядра из GDB, просто поворачивают GDB's unwindonsignal отправление и сила GDB для вызова аварийного прекращения работы. Перечисление 28 показывает пример этого.

Перечисление 28  , Генерирующее ядро из GDB

$ # Core dumps are enabled.
$ ulimit -c
unlimited
$ # Look ma, no cores!
$ ls -lh /cores
$ gdb /Applications/TextEdit.app
GNU gdb 6.3.50-20050815 (Apple version gdb-1344) […]
(gdb) r
Starting program: /Applications/TextEdit.app/Contents/MacOS/TextEdit 
Reading symbols for shared libraries […]
^C
Program received signal SIGINT, Interrupt.
0x00007fff8071fefa in mach_msg_trap ()
(gdb) set unwindonsignal off
(gdb) call (void)abort()

Program received signal SIGABRT, Aborted.
0x00007fff8076e096 in __kill ()
The program being debugged was signaled while in a function called from GDB.
GDB remains in the frame where the signal was received.
To change this behavior use "set unwindonsignal on"
Evaluation of the expression containing the function (abort) will be abandoned.
(gdb) c
Continuing.

Program received signal SIGABRT, Aborted.
0x00007fff8076e096 in __kill ()
(gdb) c
Continuing.

Program terminated with signal SIGABRT, Aborted.
The program no longer exists.
(gdb) quit
$ # And lo, we have a core.
$ ls -l /cores
$ ls -lh /cores
total 925128
-r-------- 1 quinn  admin   452M Feb  1 14:43 core.273

Включение дампов ядра с обратной силой

Даже если Вы забыли включать дампы ядра при запуске процесса, можно взять дамп ядра. Прием должен использовать GDB для включения дампов ядра программно. Перечисление 29 показывает, как сделать это.

Перечисление 29  Используя GDB для включения дампов ядра с обратной силой

$ gdb
GNU gdb 6.3.50-20050815 (Apple version gdb-1344) […]
(gdb) # Attach to the process.
(gdb) attach TextEdit.300 
Attaching to process 300.
Reading symbols for shared libraries […]
0x00007fff8071fefa in mach_msg_trap ()
(gdb) # Allocate a buffer for a (struct limit).
(gdb) set $limit=(long long *)malloc(16)
(gdb) # Set both rlim_cur and rlim_max to RLIM_INFINITY.
(gdb) set $limit[0]=0x7fffffffffffffff
(gdb) set $limit[1]=0x7fffffffffffffff
(gdb) # Call setrlimit. Note that 4 is RLIMIT_CORE.
(gdb) call (int)setrlimit(4, $limit)
$1 = 0
(gdb) # Detach from the process.
(gdb) detach
Detaching from process 300.
(gdb) q
$ # Nothing in /cores yet.
$ ls -lh /cores
$ # Tell TextEdit to dump core.
$ killall -ABRT TextEdit
$ # And lo, we have a core.
$ ls -lh /cores
total 925144
-r-------- 1 quinn  admin   452M Feb  1 14:57 core.300

Генерация дампа ядра рабочего процесса

Существуют времена, когда удобно генерировать дамп ядра рабочего процесса, не уничтожая его. На других основанных на UNIX платформах можно сделать это с gcore утилита. Mac OS X в настоящее время не имеет этой утилиты встроенной (r. 3909440). Однако существует сторонняя версия, которую Вы могли бы счесть полезным.

Дампы ядра до Mac OS X 10.5

До Mac OS X 10.5 след Вы добираетесь от дампа ядра (как показано в Перечислении 26) не, содержал символьной информации. Однако, если у Вас есть удобный файл символов, можно сказать GDB консультироваться с ним с помощью add-symbol-file команда. Перечисление 30 показывает, как сделать это для системных платформ, используемых следом TextEdit.

Перечисление 30  , Добавляющее символы

(gdb) # on 10.4.x the backtrace has no symbols
(gdb) bt
#0  0x900075c8 in ?? ()
#1  0x90007118 in ?? ()
#2  0x901960bc in ?? ()
#3  0x927d5ecc in ?? ()
#4  0x927dc640 in ?? ()
#5  0x927fe6d0 in ?? ()
#6  0x92dd2a80 in ?? ()
#7  0x92de93fc in ?? ()
#8  0x92dfd730 in ?? ()
#9  0x92eb9a1c in ?? ()
#10 0x00007d98 in ?? ()
#11 0x00007c0c in ?? ()
(gdb) # add symbols from a bunch of frameworks
(gdb) add-symbol-file /System/Library/Frameworks/AppKit.framework/AppKit 
[…]
(gdb) add-symbol-file /System/Library/Frameworks/CoreFoundation.framework\
/CoreFoundation 
[…]
(gdb) add-symbol-file /System/Library/Frameworks/System.framework/System
[…]
#12 0x00007c0c in ?? ()
(gdb) add-symbol-file /System/Library/Frameworks/Carbon.framework/\
Frameworks/HIToolbox.framework/HIToolbox
[…]
(gdb) # and lo, symbols!
(gdb) bt
#0  0x900075c8 in mach_msg_trap ()
#1  0x90007118 in mach_msg ()
#2  0x90191930 in __CFRunLoopRun ()
#3  0x901960bc in CFRunLoopRunSpecific ()
#4  0x927d5ecc in RunCurrentEventLoopInMode ()
#5  0x927dc640 in ReceiveNextEventCommon ()
#6  0x927fe6d0 in BlockUntilNextEventMatchingListInMode ()
#7  0x92dd2a80 in _DPSNextEvent ()
#8  0x92de93fc in -[NSApplication nextEventMatchingMask:untilDate:inMode:…
#9  0x92dfd730 in -[NSApplication run] ()
#10 0x92eb9a1c in NSApplicationMain ()
#11 0x00007d98 in ?? ()
#12 0x00007c0c in ?? ()

Этот метод предполагает рассмотрение базового файла на машине, которые создают его, сразу после создания его. Если базовый файл создавался на различной машине, даже идентичной машине с тем же системным программным обеспечением, установленным, или если системное программное обеспечение было обновлено, так как базовый файл создавался, Вы получите неточные результаты.

Кроме того, до Mac OS X 10.5, GDB имел ошибку в своей обработке базовых файлов, таким образом, что Вы не могли смотреть на файл ядра PowerPC на основанном на Intel компьютере, или наоборот (r. 4280384). Кроме того, GDB имел ошибку, препятствующую тому, чтобы Вы отладили файлы ядра Intel должным образом (r. 4677738).

Вышеупомянутые ограничения делают дампы ядра намного менее полезными в пред10.5 системах. Однако они могут все еще быть полезными. Следует иметь в виду, что, если Ваша программа нечасто отказывает на сайте определенного клиента, дамп ядра может быть единственным способом обнаружить состояние Вашей программы во время катастрофического отказа.

MallocDebug и ObjectAlloc

Mac OS X включает два приложения GUI для отладки выделения памяти, MallocDebug и ObjectAlloc. Для получения дополнительной информации об этих инструментах, см. документ Инструкций по Производительности Использования памяти.

Защищенное средство выделения памяти

Mac OS X включает защищенное средство выделения памяти, libgmalloc, то, что можно использовать во время отладки для ловли проблем общей памяти, таких как переполнение буфера и использование-после-свободного. Самый простой способ включить защищенное средство выделения памяти путем проверки, Включают Защите Malloc в меню Run в XCode.

Также при выполнении программы непосредственно от GDB можно включить его как показано в Перечислении 31.

Перечисление 31  , Включающее libgmalloc

$ gdb /Applications/TextEdit.app
GNU gdb 6.3.50-20050815 (Apple version gdb-1344) […]
(gdb) set env DYLD_INSERT_LIBRARIES /usr/lib/libgmalloc.dylib
(gdb) r
Starting program: /Applications/TextEdit.app/Contents/MacOS/TextEdit 
GuardMalloc: Allocations will be placed on 16 byte boundaries.
GuardMalloc: - Some buffer overruns may not be noticed.
GuardMalloc: - Applications using vector instructions (e.g., SSE or Altivec) should work.
GuardMalloc: GuardMalloc version 18
[…]

Можно узнать больше libgmalloc из его страницы справочника.

Для получения информации о как использование libgmalloc на Mac OS X 10.3.x, посмотрите libgmalloc страница справочника в той системе.

Инструменты командной строки

Mac OS X включает много холодных инструментов командной строки для отладки. Таблица 8 перечисляет некоторые лучшие.

Табличные 8  выделения инструмента Командной строки

Инструмент

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

Сводка

gdb

страница руководства, Отлаживающая с GDB

Отладчик командной строки

dtrace

страница руководства

Динамическая, всесторонняя и сложная трассировка; см. DTrace для получения дополнительной информации [1]

fs_usage

страница руководства

Инструмент трассировки файловой системы

sc_usage

страница руководства

Инструмент трассировки системного вызова

plockstat

страница руководства

взаимное исключение pthread и чтение-запись блокируют статистику

задержка

страница руководства

Планирование средства отладки задержки

«куча»

страница руководства

Дамп «кучи»

vmmap

страница руководства

Дамп адресного пространства

malloc_history

страница руководства

История выделения памяти

утечки

страница руководства

Обнаружение утечки

tcpdump

страница руководства, Технические Вопросы и ответы QA1176, 'Получение Трассировки пакетов'

Трассировка сетевого пакета

netstat

страница руководства

Статистика сети; netstat - шоу все сетевые соединения

lsof

страница руководства

Список открытые файлы

термофиксатор

страница руководства

Покажите процессы с открытым файлом

PPCExplain

Мнемоника PPC объяснена

ktrace, kdump

страница руководства

Ядро, прослеживающее [2]

otool

страница руководства

Объектный файл дисплеев

nm

страница руководства

Таблица символов дисплеев в объектном файле

дамп класса

Информация о выполнении Objective C дисплеев в объектном файле

dyldinfo

страница руководства

Дисплеи dyld информация в объектном файле [3]

Примечания:

  1. Доступный в Mac OS X 10.5 и позже.

  2. ktrace и kdump не доступны в Mac OS X 10.5 и позже; использовать dtrace или dtruss вместо этого.

  3. Доступный в Mac OS X 10.6 и позже.

Библиотеки отладки

Много платформ Mac OS X включают и производство и вариант отладки. Вариант отладки имеет суффикс «_debug». Например, Базовый производственный вариант платформы Основы /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation в то время как его вариант отладки /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation_debug. Можно вынудить dyld загрузить вариант отладки библиотеки (если такой вариант существует) путем установки DYLD_IMAGE_SUFFIX переменная окружения к «_debug». Перечисление 32 показывает пример того, как сделать это из Терминала.

Перечисление 32  Используя _debug библиотеки

$ DYLD_IMAGE_SUFFIX=_debug /Applications/TextEdit.app/Contents/MacOS/TextEdit  2010-01-29 18:25:29.780 TextEdit[960:10b] Assertions enabled […]

Если Терминал не пускает в ход Ваше судно, можно сделать то же использование исполнимого инспектора в XCode. На рисунке 3 Вы видите, что «Использование … суффикс при загрузке платформ», раскрывающихся, было установлено «отладить».

Рисунок 3  , Разрешающий библиотекам отладки в XCode

Точное поведение библиотеки отладки варьируется от платформы до платформы. Большинство библиотек отладки включает:

  • если источник для платформы включен в Дарвина, полные отладочные символы — Это особенно полезно.

  • дополнительные утверждения — Они могут помочь точно определить программные ошибки с Вашей стороны.

  • дополнительные средства отладки — Много средств отладки, описанных позже в этом документе, только доступны в библиотеке отладки.

Включение всего одной библиотеки отладки

При некоторых обстоятельствах Вы могли бы хотеть включить всего одну библиотеку отладки. Например, скажем, Вы отлаживаете проблему события Apple, таким образом, Вы хотите к включенному «_debug» вариант платформы AE. Однако, когда Вы устанавливаете DYLD_IMAGE_SUFFIX к «_debug» Вы обнаруживаете, что использование всех библиотек отладки вызывает проблему в другом месте в Вашем приложении. В это время Вы просто хотите фокусироваться на отладке проблемы события Apple.Кто ты по профессии?

К счастью, существует простое решение этой загадки: просто сделайте копию варианта отладки с новым уникальным суффиксом и активируйте тот суффикс через DYLD_IMAGE_SUFFIX. Перечисление 33 показывает пример этого.

Перечисление 33  , Активирующее просто AE, отлаживает библиотеку

$ cd /System/Library/Frameworks/CoreServices.framework/Frameworks/AE.framework/Versions/A/
$ sudo cp AE_debug AE_qtest
$ # Now test this by running TextEdit from GDB.
$ gdb /Applications/TextEdit.app
GNU gdb 6.3.50-20050815 (Apple version gdb-768) […]
(gdb) set env DYLD_IMAGE_SUFFIX _qtest
(gdb) r
Starting program: /Applications/TextEdit.app/Contents/MacOS/TextEdit 
Reading symbols for shared libraries […]
^C
Program received signal SIGINT, Interrupt.
0x93cdb8e6 in mach_msg_trap ()
(gdb) # The info shared command reveals that the AE_qtest variant 
(gdb) # was loaded. Neato!
(gdb) info shared
The DYLD shared library state has been initialized from the executable's […]
                                          Requested State Current State
Num Basename                Type Address         Reason | | Source 
  | |                          | |                    | | | | 
[…]
 43 AE_qtest                   F 0x54000           dyld Y Y /System/Libra[…]
[…]

Управление версиями библиотеки отладки

Для получения значимых результатов, необходимо пользоваться библиотеками отладки, соответствующими производственным библиотекам. При использовании неверной версии библиотек отладки можно столкнуться со всеми видами странных проблем. Например, если Вы установите библиотеки отладки по Mac OS X 10.4 и затем обновите Вашу систему к Mac OS X 10.4.3, то библиотеки отладки больше не будут работать. Это вызвано тем, что, в Mac OS X 10.4.3, Apple добавил новую подпрограмму к платформе CoreServices и обновил платформу DesktopServicesPriv для использования той подпрограммы. Однако одна из этих платформ (CoreServices) имеет вариант отладки, и другой (DesktopServicesPriv) не делает. Таким образом при включении библиотек отладки Вы получаете вариант отладки CoreServices от Mac OS X 10.4 и производственный вариант DesktopServicesPriv от Mac OS X 10.4.3, и этой комбинации не удается загрузиться.

Установка библиотек отладки

Для Mac OS X 10.5 и позже, можно загрузить библиотеки отладки для любой данной версии ОС от задействованного сайта ADC. Посмотрите в разделе Developer Tools области Downloads для «Отладки и пакета» Библиотек Профиля, соответствующего Вашу версию ОС.

До Mac OS X 10.5, ситуация очень отличается. Библиотеки отладки установлены установщиком XCode, не системным установщиком. Библиотеки отладки не обновляются при обновлении системного программного обеспечения. Когда Вы обновляете XCode, они, однако, обновляются. Это делает его хитрым для хранения библиотек отладки и производства в синхронизации.

Самый надежный способ пользоваться библиотеками отладки в системах до Mac OS X 10.5 состоит в том, чтобы установить специализированный раздел отладки. На этом разделе необходимо сначала убрать, устанавливают желаемую главную версию ОС, и затем устанавливают инструменты разработчика, связанные с тем выпуском. Например, чистая установка Mac OS X 10.4, и затем устанавливает Xcode 2.0. Также не забудьте отключать обновления программного обеспечения для того раздела и не обновлять XCode. Это гарантирует, чтобы Ваши библиотеки производства и отладки начались в синхронизации и остались в синхронизации.

Библиотеки профиля

Много библиотек также поддерживают профильный вариант, имеющий суффикс «_profile». Библиотеки профиля имеют многие из тех же ограничений как библиотеки отладки.

Выход из сервера окна

При некоторых обстоятельствах может быть полезно работать без сервера окна. Например, если необходимо изменить параметры к loginwindow указанный в /etc/ttys, хорошо быть в состоянии сделать это в то время как loginwindow не работает. Mac OS X обеспечивает удобный способ сделать это:

  1. В панели Accounts Установок системы щелкните по Login Options. Если текст отображается серым, необходимо сначала разблокировать панель путем щелчка по значку блокировки.

  2. Измените настройки «Display login window as» к «Имени и паролю».

  3. Выйти из системы.

  4. В окне входа в систему введите»> консоль» как Ваше имя пользователя и нажмите кнопку Log In; loginwindow выйдет и Вы столкнетесь со стеклянным интерфейсом TTY, выводящим на экран подсказку «Входа в систему» (Вы, возможно, должны нажать Return, чтобы заставить подсказку быть выведенной на экран).

  5. Войдите в систему с помощью стандартного имени пользователя и пароля.

Когда Вы сделаны, работая на этом уровне, просто выходите от своей оболочки (использующий exit команда), и Вы возвратитесь к стандартному окну входа в систему.

DTrace

DTrace является всесторонним динамическим средством трассировки, начатым с Mac OS X 10.5. DTrace был первоначально разработан Sun Microsystems (теперь Oracle) для их операционной системы Соляриса, но был интегрирован в Mac OS X Apple. В то время как полное объяснение DTrace выходит за рамки этого документа, этот раздел покрывает некоторые выделения.

Самая важная вещь понять состоит в том, что DTrace не только для отладки производительности. В то время как это было первоначально разработано для поддержки отладки производительности, и это очень сильно в той области, это может также использоваться для других типов отладки. Например, иногда полезно знать, какие процессы открывают то, что файлы и DTrace могут сказать Вам настолько легко.

DTrace является также основой многих средств отладки на Mac OS X, включая:

Хорошее место для запуска с DTrace является страницей Oracle BigAdmin для DTrace. Также существует много сценариев DTrace, встроенных к Mac OS X (некоторые описаны в следующем разделе), и можно просто смотреть на источник для тех сценариев. Наконец, инструменты имеет хороший UI для создания пользовательских Инструментов на основе сценария DTrace.

Не торопитесь для изучения DTrace; это окупится в конечном счете!

Находящиеся в DTrace инструменты

Следующие таблицы приводят некоторые находящиеся в DTrace инструменты, встроенные к Mac OS X. Следует иметь в виду, что, в то время как эти сценарии не могли бы сделать точно, что Вы хотите, можно скопировать источник сценария и настроить его для лучше удовлетворения потребностям.

Таблица 9  Связанные с процессом инструменты DTrace

Инструмент

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

Сводка

execsnoop

страница руководства

Трассировки обрабатывают выполнение

newproc.d

страница руководства

Показывает новые процессы, поскольку они создаются

pidpersec.d

страница руководства

Показывает, что процесс создает количество в секунду

setuids.d

страница руководства

Показывает изменения setuid, как они происходят

Таблица 10  связанные с системным вызовом инструменты DTrace

Инструмент

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

Сводка

dtruss

страница руководства

Трассировки обрабатывают системные вызовы

errinfo

страница руководства

Отказы системного вызова трассировок

lastwords

страница руководства

Показывает последние системные вызовы, сделанные процессом

procsystime

страница руководства

Показывает времена выполнения системного вызова

syscallbypid.d

страница руководства

Показывает системные вызовы процессом ID

syscallbyproc.d

страница руководства

Показывает системные вызовы именем процесса

syscallbysysc.d

страница руководства

Показывает количества системного вызова

topsyscall

страница руководства

Каждую секунду, показывает наиболее распространенные системные вызовы

topsysproc

страница руководства

Каждую секунду, показывает процессы, делающие большинство системных вызовов

Таблица 11  Связанные с сигналом инструменты DTrace

Инструмент

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

Сводка

kill.d

страница руководства

Показывает сигналы, когда они отправляются

sigdist.d

страница руководства

Показывает сигналы процессом

Табличный 12  Файл инструменты DTrace I/O-related

Инструмент

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

Сводка

creatbyproc.d

страница руководства

Показывает, что файлы, создаваемые с, создают

fddist

страница руководства

Показывает распределение использования дескриптора файла

filebyproc.d

страница руководства

Файлы трассировок открылись процессом

opensnoop

страница руководства

Показывает открываемые файлы

pathopens.d

страница руководства

Показывает открытые количества путем

rwbypid.d

страница руководства

Показывает чтение и вызовы записи процессом

rwbytype.d

страница руководства

Показывает чтение и вызовы записи типом vnode

rwsnoop

страница руководства

Показывает чтение и вызовы записи, как они происходят

Табличная 13  Сеть инструменты DTrace I/O-related

Инструмент

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

Сводка

httpdstat.d

страница руководства

Показывает статистику соединений Apache

weblatency.d

страница руководства

Показывает статистику задержки Запроса HTTP

Табличный 14  Диск инструменты DTrace I/O-related

Инструмент

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

Сводка

bitesize.d

страница руководства

Показывает диску размер I/O процессом

diskhits

страница руководства

Показывает доступ к файлу смещением

hotspot.d

страница руководства

Показывает использование диска расположением

iofile.d

страница руководства

Показывает времена ожидания I/O файлом

iofileb.d

страница руководства

Показывает размеры передачи файлом

iopattern

страница руководства

Показывает образцы доступа к диску

iopending

страница руководства

Показывает число незаконченных дисковых передач

iosnoop

страница руководства

Показывает доступы к диску, как они происходят

iotop

страница руководства

Показывает диску I/O для каждого процесса

seeksize.d

страница руководства

Показывает поиск на диске процессом

Таблица 15  Связанные с планировщиком инструменты DTrace

Инструмент

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

Сводка

cpuwalk.d

страница руководства

Показывает, на котором CPUs работает процесс

dappprof

страница руководства

Код пространства пользователя профилей

dapptrace

страница руководства

Код пространства пользователя трассировок

dispqlen.d

страница руководства

Показывает, что планировщик диспетчеризирует длины очереди

loads.d

страница руководства

Покажите средние числа загрузки

priclass.d

страница руководства

Показывает распределение класса процесса

pridist.d

страница руководства

Показывает приоритетное распределение процесса

runocc.d

страница руководства

Показывает планировщику выполненное заполнение очереди CPU

sampleproc

страница руководства

Профили, какой процесс включен который CPU

Демоны

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

launchd

launchd является первым процессом, выполненным ядром (Mac OS X 10.4 и позже); это ответственно за запуск всех других процессов в системе. launchd имеет много полезных средств отладки, каждый описанный в последующем разделе.

launchctl

Можно взаимодействовать с launchd использование launchctl команды. launchctl поддержки много подкоманд; Таблица 16 перечисляет тех, которые наиболее относятся к отладке.

Таблица 16  Полезные launchctl команды

Команда

Сводка

список

Выводит на экран список загруженных заданий или подробную информацию об определенном задании

предел

Устанавливает пределы ресурса launchd; это значение будет наследовано любым процессом launchd, выполняется; наиболее распространенное использование является предельным неограниченным ядром, который включает дампы ядра

setenv

Изменяет переменные окружения, переданные любым запущенным программам

отладка

Позволяет Вам управлять свойством WaitForDebugger загруженного задания (Mac OS X 10.6 и позже)

bstree

Выводит на экран дерево пространств имен начальной загрузки Маха, являющихся управляемым launchd (Mac OS X 10.6 и позже)

Для команд, изменяющихся launchd состояние (как limit или setenv), можно внести временное изменение путем выполнения launchctl с одной из этих команд как параметр. Это будет влиять launchd самостоятельно, и любой процесс это launchd выполняется с тех пор.

Можно внести персистентное изменение в глобальный экземпляр launchd путем добавления команды к/etc/launchd.conf. launchd принимает эти настройки рано в процессе начальной загрузки, и таким образом, после перезапуска они влияют на каждый процесс в системе.

Отладка определенного задания

Наконец, launchd позволяет Вам отладить определенное задание путем изменения свойств в его файле списка свойств. Таблица 17 перечисляет свойства, которые являются самыми полезными для отладки.

Табличные 17  Свойства, полезные для отладки

Свойство

Сводка

StandardOutPath

Устанавливает stdout место назначения задания

StandardErrorPath

Устанавливает stderr место назначения задания

EnvironmentVariables

Переменные окружения наборов для задания

SoftResourceLimits, HardResourceLimits

Устанавливает пределы ресурса для задания; самый полезный для включения дампов ядра всего для одного задания

WaitForDebugger

Если это будет истиной, то процесс задания будет ожидать отладчика для присоединения прежде, чем выполнить любой код (Mac OS X 10.5 и позже)

Службы каталогов

DirectoryService демон является центральным репозиторием информации о каталоге о Mac OS X (вещи как список пользователей и групп). Страница справочника описывает, как можно использовать SIGUSR1 и SIGUSR2 сигналы включить два различных аромата журналирования. Если необходимо позволить регистрировать рано в процессе начальной загрузки, можно создать /Library/Preferences/DirectoryService/.DSLogAtStart файл перед перезапуском. Наконец, начиная с Mac OS X 10.5, можно изменить сумму журналирования отладки с помощью Debug Logging Priority Level предпочтение, как описано в Сервере Mac OS X v10.5, 10.6: Включение журналирования отладки Службы каталогов.

mDNSResponder

mDNSResponder демон ответственен за многоадресные службы DNS на все версии Mac OS X и, начиная с Mac OS X 10.5, это также обрабатывает, одноадресно передает DNS также. Демон поддерживает большое внутреннее состояние, включая кэш преобразователя DNS. Если Вы отправляете ему a SIGINFO сигнал, это выведет то состояние к системному журналу.

notifyd

Если Вы отправляете a SIGUSR1 сигнализируйте к notifyd, он выведет свое состояние к /var/run/notifyd_XXX.status, где XXX его процесс ID. Можно также отправить a SIGUSR2 сигнал получить более длинный отчет о состоянии.

lookupd

Если Вы испытываете проблемы с lookupd (например, запросы DNS занимают много времени), можно включить lookupd отладка со следующими шагами:

  1. Создайте Debug и Trace свойства в локальной машине /config/lookupd Каталог NetInfo.

  2. Измените конфигурацию системного журнала так, чтобы отладочная информация NetInfo (netinfo.debug) отправляется в файл журнала NetInfo (/var/log/netinfo.log).

  3. Отправьте a SIGHUP сигнал к syslogd заставить его распознавать предыдущее изменение.

  4. Отправьте a SIGHUP сигнал к lookupd заставить его распознавать изменение от шага 1.

Перечисление 34 показывает пример этого. Как только Вы выполнили эти шаги, можно заглянуть /var/log/netinfo.log для отладочной информации. Можно также выполниться lookupd -statistics получите статистику от lookupd.

Перечисление 34  , Включающее lookupd отладка

$ sudo dscl . create /dsRecTypeStandard:Config/lookupd Debug YES
$ sudo dscl . create /dsRecTypeStandard:Config/lookupd Trace YES
$ sudo cp /etc/syslog.conf /etc/syslog.conf-orig
$ sed 's/netinfo.err/netinfo.debug/' /etc/syslog.conf-orig | \
sudo cp /dev/stdin /etc/syslog.conf
$ sudo kill -HUP `cat /var/run/syslog.pid`
$ sudo kill -HUP `cat /var/run/lookupd.pid`

Перечисление 35 показывает, как отменить эти изменения.

Перечисление 35  , Отключающее lookupd отладка

$ sudo dscl . delete /dsRecTypeStandard:Config/lookupd $ sudo mv /etc/syslog.conf-orig /etc/syslog.conf $ sudo kill -HUP `cat /var/run/syslog.pid` $ sudo kill -HUP `cat /var/run/lookupd.pid`

Для получения дополнительной информации о lookupd, см. его страницу справочника.

Печать (CUPS)

Mac OS X использует CUPS в качестве своей базовой архитектуры печати (начиная с Mac OS X 10.2). CUPS имеет встроенную функцию журналирования отладки, которой управляет конфигурационный файл CUPS (/etc/cups/cupsd.conf). В этом файле LogLevel директива управляет уровнем журналирования, в то время как ErrorLog директива управляет местом назначения журнала (значение по умолчанию /var/log/cups/error_log). Для получения дополнительной информации об этом файле, см. страницу справочника.

Перечисление 36  , Перезапускающее демона CUPS

$ # Prior to Mac OS X 10.5, use this command:
$
$ sudo /System/Library/StartupItems/PrintingServices/PrintingServices \
restart
$
$ # In Mac OS X 10.5 and later, use this command:
$
$ sudo launchctl stop org.cups.cupsd

Начиная с Mac OS X 10.5, можно использовать cupsctl инструмент для управления журналированием отладки, как показано в Перечислении 37.

Перечисление 37  Включающее и отключающее журналирование отладки CUPS

$ # Enable CUPS debug logging. $ cupsctl --debug-logging $ # Disable CUPS debug logging. $ cupsctl --no-debug-logging

Можно получить общую справку CUPS из встроенной Онлайн-справки. Кроме того, документ Программирования Фильтра и Бэкэнда имеет набор полезной отладочной информации.

Если Вы пишете драйвер CUPS или фильтр, можно добавить записи в этот журнал путем печати их к stderr. Необходимо запустить каждую строку с уровня журналирования сообщения, как проиллюстрировано Перечислением 38.

  Журналирование перечисления 38 к CUPS

// Debug message

fprintf(stderr, "DEBUG: page_width = %.0f\n", page_width); 

// Warning message

fprintf(stderr, "WARNING: Printer not responding\n"); 

// Error message

fprintf(stderr, "ERROR: Lost connection with printer\n");

Core Services

Core Services включает много подпрограмм (например, Debugger, DebugStr, и SysBreak) это вводит отладчик с сообщением. Если Вы устанавливаете USERBREAK переменная окружения к 1, эти подпрограммы отправят a SIGINT сигнализируйте к текущему процессу, заставляющему Вас врываться в GDB. XCode имеет GUI к включенному это средство (флажок «Break on Debugger () and DebugStr ()» в панели Debugging исполнимого инспектора, как показано на рисунке 4).

Рисунок 4  , устанавливающий USERBREAK в XCode

Базовая основа

Платформа Core Foundation (CF) экспортирует CFShow подпрограмма, распечатывающая описание любого объекта CF к stderr. Можно выполнить этот вызов от собственного кода, однако, это особенно полезно, когда вызвано от GDB. Перечисление 39 показывает пример этого.

Перечисление 39  вызывая CFShow от GDB

$ gdb /Applications/TextEdit.app
GNU gdb 6.3.50-20050815 (Apple version gdb-1346) […]
(gdb) fb CFRunLoopAddSource
Breakpoint 1 at 0x624dd2f195cfa8
(gdb) r
Starting program: /Applications/TextEdit.app/Contents/MacOS/TextEdit 
Reading symbols for shared libraries […]
Breakpoint 1, 0x00007fff8609bfa8 in CFRunLoopAddSource ()
(gdb) # Check that the prologue hasn't changed $rdi.
(gdb) p/a 0x00007fff8609bfa8
$1 = 0x7fff8609bfa8 <CFRunLoopAddSource+24>
(gdb) p/a $pc
$2 = 0x7fff8609bfa8 <CFRunLoopAddSource+24>
(gdb) x/8i $pc-24
0x7fff8609bf90 <CFRunLoopAddSource>: push   %rbp
0x7fff8609bf91 <CFRunLoopAddSource+1>: mov    %rsp,%rbp
0x7fff8609bf94 <CFRunLoopAddSource+4>: mov    %rbx,-0x20(%rbp)
0x7fff8609bf98 <CFRunLoopAddSource+8>: mov    %r12,-0x18(%rbp)
0x7fff8609bf9c <CFRunLoopAddSource+12>: mov    %r13,-0x10(%rbp)
0x7fff8609bfa0 <CFRunLoopAddSource+16>: mov    %r14,-0x8(%rbp)
0x7fff8609bfa4 <CFRunLoopAddSource+20>: sub    $0x40,%rsp
0x7fff8609bfa8 <CFRunLoopAddSource+24>: mov    %rdi,%r12
(gdb) # Nope. Go ahead and CFShow it.
(gdb) call (void)CFShow($rdi)
<CFRunLoop 0x100115540 [0x7fff70b8bf20]>{
    locked = false, 
    wakeup port = 0x1e07, 
    stopped = false,
    current mode = (none),
    common modes = <CFBasicHash 0x1001155a0 [0x7fff70b8bf20]>{
        type = mutable set, 
        count = 1,
        entries =>
            2 : <CFString 0x7fff70b693d0 [0x7fff70b8bf20]>{
                contents = "kCFRunLoopDefaultMode"
            }
    },
    common mode items = (null),
    modes = <CFBasicHash 0x1001155d0 [0x7fff70b8bf20]>{
        type = mutable set, 
        count = 1,
        entries =>
            0 : <CFRunLoopMode 0x100115670 [0x7fff70b8bf20]>{
                name = kCFRunLoopDefaultMode, 
                locked = false, 
                port set = 0x1f03,
                sources = (null),
                observers = (null),
                timers = (null)
        },
    }
}

Существует много других подпрограмм CF, которые Вы могли бы счесть полезным для вызова от GDB, включая CFGetRetainCount, CFBundleGetMainBundle, и CFRunLoopGetCurrent.

Базовая платформа Основы также имеет вариант отладки, предлагающий обширную помощь отладки. Например, вариант неотладки Базовой Основы не проверяет законность параметров, которые Вы передаете ее подпрограммам, тогда как вариант отладки включает полную проверку параметра. Это может помочь Вам разыскать многочисленные Базовые Связанные с основой ошибки в своем коде.

Зомби!

Базовая Основа поддерживает вызванную переменную окружения CFZombieLevel. Это интерпретирует эту переменную как целое число, содержащее ряд флаговых битов. Таблица 18 описывает в настоящее время определяющиеся биты. Они могут помочь Вам разыскать различные проблемы управления памятью CF.

Табличные  определения 18 битов для переменной окружения CFZombieLevel

Бит

Действие

0

набросайте освободил память CF

1

когда набросок освободил память CF, не набрасывайте объектный заголовок (CFRuntimeBase)

4

никогда свободная память раньше не содержала объекты CF

7

если установлено, освобождение каракулей с помощью битов 8.. 15, иначе используйте 0xFC

8.. 15

если бит 7 установлен, освобождение каракулей с помощью этого значения

16

набросайте выделил память CF

23

если установлено, выделения каракулей с помощью битов 24.. 31, иначе используйте 0xCF

24.. 31

если бит 23 установлен, выделения каракулей с помощью этого значения

CFNotificationCenter

Можно включить журналирование CFNotificationCenter путем создания файла /var/log/do_dnserver_log. Если этот файл будет существовать и будет принадлежать корню, то демон CFNotificationCenter (distnoted) зарегистрирует его действие к системному журналу. Посмотрите Файлы для примера того, как создать этот файл.

В Mac OS X 10.5.x, процесс демона CFNotificationCenter (distnoted) выполнения как пользователь daemon, что означает что файл /var/log/dnserver.log должно быть перезаписываемо тем пользователем. Перечисление 40 показывает, как создать этот файл.

Перечисление 40  , Создающее файл журнала CFNotificationCenter для Mac OS X 10.5

$ sudo touch /var/log/dnserver.log $ sudo chown daemon:daemon /var/log/dnserver.log

До Mac OS X 10.5 distnoted работал как корень, таким образом, владение и полномочия /var/log/dnserver.log файл был не важен.

На Mac OS X 10.3.x, соответствующие файлы были /var/tmp/do_dnserver_log и /var/tmp/dnserver.log.

Кроме того, Mac OS X 10.3.x поддерживал журналирование клиентской стороны. Если Вы создаете файл /var/tmp/do_xnc_log, CFNotificationCenter зарегистрирует действие каждого клиента в своем собственном файле (/var/tmp/xnc_logs/<progname>). Когда Вы повторно запускаете программу, эта установка вступает в силу. Журналирование клиентской стороны не доступно в Mac OS X 10.4 и позже.

События Apple

У менеджера по корпоративным мероприятиям Apple есть обширная встроенная поддержка отладки. Лучшим способом узнать об этой поддержке является использование GDB для вызова GDBPrintHelpDebuggingAppleEvents подпрограмма, как показано в Перечислении 41.

Перечисление 41  менеджер по корпоративным мероприятиям Apple, отлаживающий справку

(gdb) call (void)GDBPrintHelpDebuggingAppleEvents()
The AppleEvent Manager has been completely rewritten for this
version of Mac OS X. The internal structure of an AEDesc is
now a pointer to a sparse tree. If you're having problems
it could be because you're accessing the dataHandle of an
AEDesc directly.

Also of note is that AEGetDescData and AEGetDescDataSize only
work with value descriptors created by AECreateDesc - you cannot
get the data size of an AERecord or AEList, for example.

To print the contents of an AppleEvent from GDB, you can:
  (gdb) call (void) GDBPrintAEDesc(descPtr)

To view all currently installed AppleEvent coercion handlers:
  (gdb) call (void) GDBPrintAECoercionTables()

To view all contents install AppleEvent handlers:
  (gdb) call (void) GDBPrintAEHandlerTables()

Additionally, to log information about AppleEvent manager calls,
you can set environment variables that will produce debugging output
to the console:

  % setenv AEDebugSends    1            # print sent events
  % setenv AEDebugReceives 1            # print received events and replies

Некоторые переменные окружения — в частности AEDebug, AEDebugVerbose, AEDebugOSL, AEDebugFlattenedEvents, и AEDebugFile— только поддерживаются библиотекой отладки.

Если Вы пользуетесь библиотекой отладки, можно также управлять отладкой события Apple путем создания трех файлов в /var/tmp:

  • Создание файла /var/tmp/AEDebugFull эквивалентно установке AEDebug, AEDebugSends, AEDebugReceives, AEDebugVerbose, AEDebugOSL, и AEDebugFlattenedEvents переменные окружения.

  • Создание файла /var/tmp/AEDebug.out эквивалентно установке AEDebugFile к «/var/tmp/aedebug.out».

  • Создание файла /var/tmp/AEDebugLogs причины менеджер по корпоративным мероприятиям Apple для отправки всего его вывода к названному файлу /var/tmp/AELog-<progname>.

Если Вы устанавливаете AE_PRINT_XML переменная окружения к 1 (10.4 и позже), GDBPrintAEDesc распечатает дескриптор как XML (если возможный).

Удаленные события Apple

Если у Вас есть проблемы с удаленными событиями Apple, можно счесть полезным позволить регистрировать для серверного процесса события Apple. Сделать это, редактирование /System/Library/LaunchDaemons/com.apple.eppc.plist и добавьте «-отладка» запись в ProgramArguments массив. Конечный результат должен быть файлом как один показанный в Перечислении 42.

Перечисление 42  , Разрешающее удаленную отладку события Apple

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>Label</key>
        <string>com.apple.AEServer</string>
        <key>ProgramArguments</key>
        <array>
                <string>/System/Library/Frameworks/CoreServices.framework/Frameworks/AE.framework/Versions/A/Support/AEServer</string>
                <string>--debug</string>
        </array>
        […]
</dict>
</plist>

Необходимо остановить и запустить службу Remote Apple Events для этого изменения для вступления в силу; можно сделать это в панели Sharing Установок системы. Информация о журналировании появится в системном журнале.

Code Fragment Manager (CFM)

Среда совместимости CFM на Mac OS X поддерживает две полезных переменные окружения, CFMDebugBasic и CFMDebugFull, который можно установить в 1 для получения ограниченного и многословного журналирования отладки, соответственно. Это средство особенно полезно для разыскивания проблем закрытия CFM и проблем, где подпрограммы инициализации фрагмента перестали работать.

Менеджер компонентов

Менеджер компонентов экспортирует подпрограмму, GDBComponentList, то, что можно вызвать от GDB для печати базы данных зарегистрированных компонентов и их экземпляров. Перечисление 43 дает пример своего использования.

  Печать перечисления 43 список компонентов и экземпляров

(gdb) call (void)GDBComponentList()
Cnt   tRef# (address) Type/SubT/Manu    Flags           EntryPnt File …
[…]
  1 0x10011 0x00000001008870a0 osa /ascr/appl 100001fe 0x00000001004efeb6    0 …
    Inst:0x810001; Err=0; Storage:0x85f9f0
  1 0x10013 0x00000001008871e0 osa /scpt/appl 100001fe 0x00000001004efea2    0 …
    Inst:0x810000; Err=0; Storage:0x2384c0
[…]
There are 1 component manager files:
    0: refs 2, path [/System/Library/Components/AppleScript.component], where k…

Кроме того, если Вы устанавливаете ComponentDebug переменная окружения к 1, Менеджер компонентов распечатает разнообразия сообщений отладки. Они могут быть полезными, если что-то идет не так, как надо с Вашим компонентом, в частности если ему не удается загрузиться.

Наконец, если компоненту не удается загрузиться, можно использовать динамические средства компоновщика для отладки проблемы; посмотрите Динамического Компоновщика (dyld) для подробных данных.

Файловый менеджер

Файловый менеджер Core Services (обычно известный как Файловый менеджер Углерода, или просто Файловый менеджер) приятно интегрируется с fs_usage инструмент командной строки. Если Вы включаете библиотеку отладки Core Services, fs_usage не только покажет примитивные вызовы файловой системы BSD, но также и вызовы Файлового менеджера, запросившие их. Дополнительную информацию см. в fs_usage странице справочника.

До Mac OS X 10.5, если Вы устанавливаете FilesASDDebug переменная окружения к 1, Файловый менеджер зарегистрирует свои деловые отношения с файлами AppleDouble в файловых системах, не имеющих собственной поддержки метаданных Macintosh и ветвей ресурсов. В Mac OS X 10.5 и позже больше не поддерживается эта функция, потому что поддержка AppleDouble переместилась в ядро.

До Mac OS X 10.6, и при использовании варианта отладки платформы CarbonCore, если Вы устанавливаете VNDebug переменная окружения к 1, Файловый менеджер зарегистрирует свое взаимодействие с Дисковым Арбитражем.

Файловый менеджер имеет много полезных GDB-вызываемых подпрограмм. Самое полезное, PrintVolumeInfo, распечатывает список объема. Требуется один булев параметр, проигнорированный современными системами. Перечисление 44 показывает пример это.

Перечисление 44  PrintVolumeInfo в действии

(gdb) call (void)PrintVolumeInfo(1) 2010-02-01 17:48:00.657 Finder[620:a0f] 1:vol=-100  "Macintosh HD" 2010-02-01 17:48:00.658 Finder[620:a0f] 2:returned error -35

Существует много других GDB-вызываемых подпрограмм, которые имеют прежде всего интерес для людей, разрабатывающих плагины VFS на Mac OS X. Они позволяют Вам распечатывать кэш перечисления каталога и дерево идентификатора файла, оба из которых являются структурами совместимости, сохраняемыми Файловым менеджером для объемов неволков (см. Технические Вопросы и ответы QA1113, '«/.vol» каталог и «волки»' для получения информации о волках).

PrintEnumerationCache подпрограмма распечатывает кэш перечисления каталога на объеме. Это берет единственный параметр, который является ссылочным номером объема (vRefNum) из объема интереса.

Дерево идентификатора файла сохраняется централизованно coreservicesd. Существует два различных способа смотреть на это дерево:

  • FileIDTreePrintVolumeTree подпрограмма распечатывает иерархию дерева идентификатора файла. Это берет единственный параметр, указывающий ссылочный номер объема.

  • FileIDTreeStorageServerDump подпрограмма распечатывает различные биты загадочной информации, самым полезным из которых является список продолжающихся транзакций дерева идентификатора файла.

Перечисление 45 показывает как пример доступа к этой информации о Mac OS X 10.5 и позже.

  Печать перечисления 45 дерево идентификатора файла

Virtual-Victim:~ quinn$ sudo gdb
GNU gdb 6.3.50-20050815 (Apple version gdb-1344) […]
(gdb) attach coreservicesd
[…]
(gdb) call (void)PrintVolumeInfo(0)
(gdb) # The volume reference number in the next command (-104) 
(gdb) # comes from the output of the previous command (see below).
(gdb) call (int)FileIDTreePrintVolumeIDs(-104)
$1 = 0
(gdb) call (void)CFShow((void*) FileIDTreeStorageServerDump("fsnode_all") )

Для наблюдения вывода этих команд необходимо вывести на экран /var/log/system.log в отдельном окне, как показано в Перечислении 46.

  Вывод дерева Идентификатора файла перечисления 46

$ tail -f /var/log/system.log
[…] 1:vol=-100  "Macintosh HD"
[…] 2:vol=-104  "UNTITLED"
[…] 3:returned error -35
[…]
[…] volume -104 flags: <dev_id:234881028, statFSFlags:2101272, devCheckTime:0>
[…] Index Entry: a0000025
[…] . Index Entry: a0000024
[…] . . . 2000001e: 1 at 
[…] . . . 5a: 2 at UNTITLED
[…] . Index Entry: a0000026
[…] . . . 60: 16 at UNTITLED/.Trashes
[…] . . . 67: 17 at UNTITLED/.Trashes/502
[…] . . . 2f: 18 at UNTITLED/.fseventsd
[…] No transactions in progress
[…] Observers:
[…] pid 717
[…] port 0x8783(4) watching 192(UnmountFailed, Unmounted)
[…] port 0x8947(3) watching 192(UnmountFailed, Unmounted)
[…] port 0x5427(2) watching 192(UnmountFailed, Unmounted)
[…] port 0xe017(1) watching 194(Mounted, UnmountFailed, Unmounted)
[…]
[…] 0x943f(9) watching 194(Mounted, UnmountFailed, Unmounted)
[…] port 0xdaab(8) watching 11(RepairStarted, Mounted, Renamed)
[…] port 0x9dc7(7) watching 202(Mounted, Renamed, UnmountFailed, Un[…]
[…] port 0x7447(6) watching 234(Mounted, Renamed, AboutToUnmount, U[…]
[…] port 0xcc9b(5) watching 194(Mounted, UnmountFailed, Unmounted)
[…] port 0x6263(4) watching 192(UnmountFailed, Unmounted)
[…] port 0xc943(3) watching 192(UnmountFailed, Unmounted)
[…] port 0x9927(2) watching 192(UnmountFailed, Unmounted)
[…] port 0x24a3(1) watching 250(Mounted, Renamed, PropertyChanged, […]
[…] pid 168
[…] port 0x7863(5) watching 194(Mounted, UnmountFailed, Unmounted)
[…] port 0x6ad3(4) watching 192(UnmountFailed, Unmounted)
[…] port 0x2f97(3) watching 192(UnmountFailed, Unmounted)
[…] port 0xca93(2) watching 192(UnmountFailed, Unmounted)
[…]
[…] Process info:

Менеджер по папке

Менеджер по Папке поддерживает переменную единой среды, FolderDebug. Если Вы установите это в 1, то менеджер по Папке распечатает много дополнительных сообщений отладки. Это средство требует библиотеки отладки Core Services.

Гештальт

Core Services экспортирует три подпрограммы —DebugDumpGestalt, DebugGestalt, и DebugGestaltStr— то, что можно вызвать от GDB для просмотра реестра Гештальта. Перечисление 47 показывает пример их использования.

Перечисление 47  Используя Гештальт отлаживает подпрограммы

(gdb) call (void)DebugDumpGestalt()
'a/ux': 0x7fff8887b74b (proc)
'addr': 0x00000007
[…]
'vm  ': 0x00000011
[…]
(gdb) call (void)DebugGestalt(0x766d2020)
'vm  ': 0x00000011
(gdb) call (void)DebugGestaltStr("  mv")
'vm  ': 0x00000011

До Mac OS X 10.5, эти подпрограммы распечатывают селектор Гештальта наоборот на компьютерах с прямым порядком байтов. Например, первая строка вывода DebugDumpGestalt был бы 'xu/a', не 'a/ux' (r. 5491464).

Область монтажа

Запуск в Mac OS X 10.6 pbs инструмент (/System/Library/CoreServices/pbs) имеет много полезных параметров отладки. Выполните инструмент с -? параметр для наблюдения списка.

Если требуется видеть то, что было помещено на область монтажа, проверьте Пример кода выборка 'ClipboardViewer'.

Поточная обработка

Core Services, распараллеливающая APIs (потоки MP и менеджер по Потоку), поддерживает переменную окружения, ThreadDebug, это включает несколько сообщений отладки и много внутренних проверок непротиворечивости. Это средство требует библиотеки отладки Core Services.

Веб-сервисы

Веб-сервисы поддерживают две полезных переменные окружения, WSDebug и WSDebugVerbose, который можно установить в 1 для получения ограниченного и многословного журналирования отладки, соответственно. Эти переменные являются эффективными при библиотеке неотладки, но включают еще больше входа в систему библиотеки отладки.

Диски и диски

Дисковый арбитраж

Если Вы добавляете, что «-d» представляет в виде строки к ProgramArguments массив в /System/Library/LaunchDaemons/com.apple.diskarbitrationd.plist и затем перезапуск, Дисковый Арбитраж зарегистрирует подробную информацию о своих действиях к /var/log/diskarbitrationd.log.

Запись диска

Если Вы устанавливаете DRVerboseLogging переменная окружения к 1, Запись Диска зарегистрирует информацию о своем действии к ~/Library/Logs/DiscRecording.log.

Кроме того, до Mac OS X 10.4 Записей Диска всегда регистрировали бы к stderr.

Дисковая утилита

Если Вы устанавливаете DUDebugMenuEnabled предпочтение к ДА, Дисковая утилита выведет на экран меню Debug со многими полезными командами.

Прикладные службы

Базовая графика

Кварцевая Отладка имеет много полезных функций отладки; посмотрите Технические Вопросы и ответы QA1236, 'Отладив Графику с QuartzDebug' для большего количества подробных данных.

Диспетчер процессов

Существуют обстоятельства, где Вы хотите отладить процесс, но Вы не хотите запускать его из GDB. Например, если у Вас есть ssh'd в удаленный компьютер для отладки приложения GUI, Вы не должны запускать его непосредственно от GDB, потому что приложение будет в неправильном пространстве имен начальной загрузки Маха, и таким образом не может соединиться с критическими службами как сервер области монтажа. Обычно это не проблема: Вы просто просите, чтобы удаленный пользователь запустил приложение для Вас и затем присоединил к запущенному приложению с помощью GDB's attach команда. Если Вы хотите отладить процедуру запуска приложения, Однако, что происходит? Вы заканчиваете тем, что играли в 'игру' гонки присоединения, где пользователь запускает приложение, и Вы мчитесь для присоединения с GDB. Не хороший.

Диспетчер процессов предлагает хорошее решение этой проблемы. Если Вы устанавливаете INIT_Processes переменная окружения к 1, Диспетчер процессов задержит запуск приложения в течение 15 секунд, давая Вам время для присоединения с GDB. Это даже регистрирует хорошее сообщение (см. Перечисление 48) к системному журналу, сообщающему, что это делает.

  Система перечисления 48 регистрирует сообщение, сгенерированное приостановленным процессом

[…] Blocking on INIT_Processes for 15 seconds; attach to pid 103 if you want.

QuickDraw

QuickDraw экспортирует много подпрограмм, которые можно вызвать от GDB для получения информации о состоянии QuickDraw. Первые три подпрограммы —QDDebugPrintPortInfo, QDDebugPrintCGSInfo, и QDDebugDumpRegion— информация о печати к stderr. Перечисление 49 показывает пример их использования.

Перечисление 49  QuickDraw, распечатывающий подпрограммы

(gdb) set $window = (void *) FrontWindow()
(gdb) set $port = (void *) GetWindowPort($window)
(gdb) call (int) QDDebugPrintPortInfo($port)
Dumping port 0x435670...
    PixMap: 0x1FE72C
        Base Address: 0xB0028000 [onscreen, buffered]
        RowBytes: 0xFFFF9400
        Bounds: (0, 0, 106, 352) (352w x 106h)
        Depth: 0020
    Port bounds: (0, 0, 106, 352) (352w x 106h)
    Port shape: 0x1FE798 (0, 0, 106, 352) (352w x 106h) …
    Vis rgn: 0x1FE730 (0, 0, 106, 352) (352w x 106h) …
    Clip rgn: 0x1FE738 (-32000, -32000, 32000, 32000) …
    Fore Color: 0000 0000 0000
    Back Color: FFFF FFFF FFFF
[…]
$21 = 0
(gdb) call (int) QDDebugPrintCGSInfo($port)
CGS info for port 0x435670
    CGSWindowID: 19798
    Shape: 0x59E734 (99, 785, 205, 1137) (352w x …
    Vis Region: 0x59E72C (0, 0, 0, 0) (0w x 0h) [rect]
    Dirty Region: 0x59E730 (0, 0, 0, 0) (0w x 0h) [rect]
$20 = 0
(gdb) # 0x1FE730 is "Vis rgn" from QDDebugPrintPortInfo
(gdb) set $rgn=0x1FE730
(gdb) call (int)QDDebugDumpRegion($rgn)
Size = 116  Bounds = (0, 0, 106, 352) (352w x 106h) NEW FORMAT
0: 2 350 
1: 1 351 
2: 0 352 
104: 1 351 
105: 2 350 
106: 

$21 = 0

Остающиеся подпрограммы разработаны, чтобы помочь Вам визуализировать области на экране путем высвечивания формы области. Перечисление 50 показывает, как вызвать эти подпрограммы; к сожалению, Вы не видите результаты в этом документе, таким образом, необходимо будет попробовать это сами. Это предполагает что $port и $rgn переменные удобства устанавливаются согласно предыдущему перечислению.

Перечисление 50  QuickDraw, высвечивающий подпрограммы

(gdb) call (int) QDDebugFlashRegion($port, $rgn)
$23 = 0
(gdb) call (void) QDDebugFlashClipRgn($port)
(gdb) call (void) QDDebugFlashPortShape($port)
(gdb) call (void) QDDebugFlashVisRgn($port)
(gdb) call (int) QDDebugFlashCGSWindowShape($port)
$24 = 0
(gdb) call (int) QDDebugFlashCGSWindowOpaqueShape($port)
$25 = 0
(gdb) call (int) QDDebugFlashCGSVisRgn($port)
$26 = 0
(gdb) call (int) QDDebugFlashCGSDirtyRgn($port)
$27 = 0

Службы

Руководство по внедрению Служб описывает много полезных подсказок об отладке служб, включая:

  • NSDebugServices пользовательское значение по умолчанию

  • pbs инструмент

Беглый взгляд

Беглый взгляд имеет некоторые хорошие функции, чтобы помочь Вам отладить свой код генератора; они документируются подробно в Руководстве по программированию Беглого взгляда.

Углерод (HIToolbox)

HIToolbox углерода включает богатство средств для Вашего удобства отладки:

Таблица 19  Новые и старые названия для объекта HIToolbox печать подпрограмм

Mac OS X 10.5 и позже

Mac OS X 10.4.x и ранее

DebugPrintMainEventQueue

GDBPrintEventQueue

DebugPrintEventQueue

_DebugPrintEventQueue

DebugPrintEvent

_DebugPrintEvent

DebugPrintDialogInfo

GDBShowDialogInfo

DebugPrintControlHierarchy

GDBShowControlHierarchy

DebugPrintControl

GDBShowControlInfo

DebugSetEventTraceEnabled

SetEventTraceEnabled

DebugTraceEventByName

TraceEventByName, UntraceEventByName

DebugTraceEvent

TraceEvent, UntraceEvent

Объект HIToolbox печать подпрограмм

Следующие списки показывают различному объекту HIToolbox печать подпрограмм.

  Печать события Listing 51 HIToolbox

(gdb) call (int)DebugPrintMainEventQueue()

Printing event queue 0x7632536c...
RunLoop: 0x40c560
Count: 4 Header: 0x1805010 Head: 0x49faf0 Tail: 0x489d10

EventRef Event Kind           Time       P Cnt Desc
-------- -------------------- ---------- - --- --------------------
  49FAF0 kEventMouseDown       219335.28 H 001 x=879, y=61, button 1
  489530 kEventWindowActivate  219335.46 H 002 0x4350A0 "Untitled 1"
  43A4E0 kEventAppActiveWindo 218971.143 S 002 
  489D10 kEventWindowUpdate   219335.473 L 002 0x4A3C10 "Untitled 1 Properties"
$2 = 0
(gdb) # 0x489D10 is the kEventWindowUpdate event from last command
(gdb) call (void) DebugPrintEvent(0x489D10)
Displaying event 489D10...
   Class           wind
   Kind            1
   When                219335
   Priority        Low
   RetainCount     2
   Queued          Yes
   Info            kEventWindowUpdate, 0x4A3C10 "Untitled 1 Properties"
   Parameters
        param: ----
           type: wind
           size: 4
           data: 004A3C10
                  J<

  Печать меню Listing 52 HIToolbox

(gdb) call (void) DebugPrintMenuList()
Index  MenuRef     ID   Title
----- ---------- ------ -----
    1  0x0041F330 -21629 <Apple>
    2  0x0042EC00     128  QuickTime Player
    3  0x0043C4B0     129  File
    4  0x00445B70     130  Edit
[…]
<hierarchical menus>
           0x0042CF90     140  Open Recent
(gdb) # 0x0042EC00 is the QuickTime Player menu
(gdb) set $menu=0x0042EC00
(gdb) call (void) DebugPrintMenu($menu)
MenuRef: 0x0042EC00
    Title : QuickTime Player
    ID : 128
    Width : 0
    Height : 0
    Enabled : true
    Attributes : CondenseSeparators, ReceivedInit
    Modal level : 0
    Refcount : 3
    Element : 0x004435B0
    Item Count : 12
    Item Icon  Cmd Key   Mark   CmdID E V Text
    ---- ---- -------- -------- ----- - - ----
    0001 0000 0x00 ' ' 0x00 ' '       Y Y About QuickTime Player
    0002 0000 0x00 ' ' 0x00 ' '       N Y -
    0003 0000 0x00 ' ' 0x00 ' '  pref Y Y Preferences
[…]
HIObject
    Ref count : 3
    Event Target : 0x42f040
    Event Handler : 0x436f10
(gdb) call (void) DebugPrintMenuItem($menu, 1)
Menu: 0x0042EC00 Item: 1 Info:
 Text: About QuickTime Player
 Mark: <none>
 Cmd Key: <none>
 Icon: <none>
 Style Normal
 Command ID: 0 (0x00000000)
 Modifiers: 0x00
[…]

  Окно Listing 53 HIToolbox и диалоговая печать

(gdb) call (void) DebugPrintWindowList() 

Window      Class    WID  Vis Hil Level Title                 Group
---------- -------- ---- --- --- ----- --------------------- -----------…
0x004350A0  Document 4ED4  Y   Y      0 Untitled 1            0x76E47A89 …
0x004A3C10  Document 4EED  Y   N      0 Untitled 1 Properties 0x76E47A89 …
(gdb) # 0x004350A0 is the "Untitled 1" window
(gdb) set $window=0x004350A0
(gdb) # 0x004A3C10 is the "Untitled 1 Properties" dialog
(gdb) set $dialogWindow=0x004A3C10
(gdb) call (void) DebugPrintWindow($window)
Window 0x004350A0
    Title : Untitled 1
    Class : Document
    Group : 0x76E47A89 "com.apple.HIToolbox.windowgroups.document"
    Scope : all
    Attributes : Collapse Box, In WindowMenu
    Visible : Yes
    Collapsed : No
    Latent visibility : <none>
    Highlighted : Yes
    Structure region : 1FE80C #0, #0, #106, #352 (#352w x #106h) [non-rect]
[…]
(gdb) call (void) DebugPrintAllWindowGroups()
Window group tree
-------------------------------------------------------------------------…
  1  level    0  group 0x76E0BFE9 "com.apple.hitoolbox.windowgroups.root"
  2  level    0    group 0x76E47A89 "com.apple.HIToolbox.windowgroups.doc…
(gdb) # 0x76E47A89 is the second window group
(gdb) call (void) DebugPrintWindowGroup(0x76E47A89)
WindowGroup 0x76E47A89 "com.apple.HIToolbox.windowgroups.document"
 Attributes: <none>
 Refcount: 1
 Previous group: <none>
 Next group: <none>
 Parent group: 0x76E0BFE9 "com.apple.hitoolbox.windowgroups.root"
[…]
(gdb) set $dialog = (void *) GetDialogFromWindow($dialogWindow)
(gdb) call (void) DebugPrintDialogInfo($dialog)
Dialog: 0x76ED59A1
 Window: 0x004A3C10 "Untitled 1 Properties"
 TextHandle: 0x0059EC7C
 Default Item: 1
 Cancel Item: 0
 Keyboard Focus Item: 0
 RefCon: 0x06054AB5 (101010101)

Перечисление 54  печать управления HIToolbox

(gdb) call (void) DebugPrintControlHierarchy($window)
Dumping info for window 0x4A3C10
Window found. Dumping views...
Root 0x4ba260 , ID ''/0, (-32768,-32768,32767,32767), Embedder, Vis, Act,…
    Control 0x4c24d0 <appl/sbar> ( "" ), ID ''/0, (172,301,226,317), Vis,…
    Control 0x4c6080 <appl/sbar> ( "" ), ID ''/0, (75,301,142,317), Vis, …
    Control 0x4c49c0 <appl/push> ( "Delete" ), ID ''/0, (241,220,261,290)…
    Control 0x4c4790 <appl/push> ( "Edit?" ), ID ''/0, (241,135,261,205),…
    Control 0x4c17c0 <appl/push> ( "Add?" ), ID ''/0, (241,50,261,120), V…
    Control 0x4be1d0 <appl/popb> ( "" ), ID ''/0, (12,176,28,316), Vis, A…
    Control 0x4ba1f0 <appl/popb> ( "" ), ID ''/0, (12,24,28,164), Vis, Ac…
(gdb) # 0x4c24d0 is first scrollbar control
(gdb) call (void) DebugPrintControl(0x4c24d0)
HIScrollBar
    Size : Auto
    Live Tracking : No
Control 0x004C24D0 ""
    Control Kind : 'appl', 'sbar'
    Control ID : '', 0
    Window : 0x004A3C10 "Untitled 1 Properties"
    Parent : 0x004BA260
    Minimum : 0 (0x00000000)
    Maximum : 0 (0x00000000)
    Value : 0 (0x00000000)
[…]
HIObject
    Ref count : 1
    Event Target : 0x4c39a0
    Event Handler : 0x4c3a10

Наконец, можно распечатать отладочную информацию для любого HIObject (окна, меню, средства управления, HIViews, и т.д.) использование HIObjectPrintDebugInfo.

Высвечивание области HIToolbox

Подпрограммы, показанные в Перечислении 55, могут использоваться для высвечивания областей так, чтобы можно было визуализировать их на экране; к сожалению, Вы не видите результаты в этом документе, таким образом, необходимо будет попробовать это сами.

Перечисление 55  подпрограммы высвечивания области HIToolbox

(gdb) call (void) DebugFlashWindowVisRgn($window) (gdb) call (void) DebugFlashWindowUpdateRgn($window)

Можно также использовать HIViewFlashDirtyArea, представленный в Mac OS X 10.5 и задокументированный в HIToolboxDebugging.h.

Отладка события HIToolbox

С появлением Событий Углерода часто трудно понять поток событий через панель инструментов. HIToolbox предлагает два средства отладки, которые могут помочь здесь.

Переменная окружения EventDebug

Путем установки EventDebug переменная окружения к 1, Вы заставляете HIToolbox регистрировать все события, когда они текут через систему. Перечисление 56 показывает пример этого.

  Вывод Listing 56 EventDebug

$ EventDebug=1 /Applications/iTunes.app/Contents/MacOS/iTunes 
Event Posted: Queue: 0x1809c00, Event: kEventAppleEvent, 4949.1, S …
SendEventToEventTarget entered with event kEventTargetHandlerInstalled
    Sending event to target application: kEventTargetHandlerInstalled
        Leaving target application with result -9874
[…]
SendEventToEventTarget entered with event kEventHIObjectInitialize
    Sending event to target 0xb: kEventHIObjectInitialize
        SendEventToEventTarget entered with event kEventControlInitialize
            Sending event to target 0xb: kEventControlInitialize
                Called handler 0x945f072a. Event was handled
                Leaving target 0xb with result 0
[…]

Можно программно включить и отключить трассировку событий с подпрограммой DebugSetEventTraceEnabled.

Трассировка событий

EventDebug переменная окружения производит большой вывод, который может иметь некоторые отрицательные эффекты. В частности это замедляет Вашу программу значительно, и иногда трудно найти информацию, которую Вы ищете среди всего вывода.

Одно решение этой проблемы состоит в том, чтобы включить событие трассировкой событий. Можно сделать это путем вызова DebugTraceEventByName подпрограмма из GDB. Перечисление 57 показывает пример этого, включая прослеживающий только для kEventRawKeyDown событие.

  Трассировка событий перечисления 57

(gdb) call (void) DebugTraceEventByName("kEventRawKeyDown", 1)
(gdb) c
Continuing.
Event Posted: Queue: 0x76309338, Event: kEventRawKeyDown, 221443.183, S
SendEventToEventTarget entered
    Sending Event to 0x415750: kEventRawKeyDown
        SendEventToEventTarget entered
            Sending Event to 0x413050: kEventRawKeyDown
                Called handler 0x928CD05C. Event was NOT handled
                Leaving target 0x413050 with result -9874
        SendEventToEventTarget entered
            Sending Event to 0x42DE30: kEventRawKeyDown
                Leaving target 0x42DE30 with result -9874
            Sending Event to 0x4351F0: kEventRawKeyDown
                Leaving target 0x4351F0 with result -9874
            Sending Event to 0x4126F0: kEventRawKeyDown
                Called handler 0x929597E0. Event was NOT handled
                Called handler 0x927F4F40. Event was NOT handled
                Leaving target 0x4126F0 with result -9874
        Leaving target 0x415750 with result -9874
Event Removed: Queue: 0x76309338, Event: kEventRawKeyDown, 221443.183, S
Event Pulled (C): kEventRawKeyDown, 221443.183, S

Кроме того, запуская в Mac OS X 10.5, Вы видите то, что события прослеживаются путем вызова DebugPrintTracedEvents.

Статистика события HIToolbox

Существует две переменные окружения, вызывающие HIToolbox к статистике события печати. Если Вы устанавливаете EventRate к 1, HIToolbox будет, каждую секунду, распечатывать сводку событий, обработанных в ту секунду. Если Вы устанавливаете HLTBRecordEventStats, Когда Ваше приложение выйдет, HIToolbox распечатает набор статистики об обработке событий; эта функция требует библиотеки отладки.

Другие средства отладки HIToolbox

Если Вы устанавливаете NSQuitAfterLaunch переменная окружения к 1, Ваше приложение выйдет, как только это вводит свой цикл событий. Если Вы хотите измерить время запуска приложения или искать утечки, это полезно. Эта переменная окружения также поддерживается AppKit.

Если Вы устанавливаете HLTBPrintKeyMatchingStatus переменная окружения к 1, HIToolbox распечатает подробную информацию о соответствии пункта меню. Эта функция требует библиотеки отладки.

Если Вы устанавливаете TSMEventTracing переменная окружения к 1, HIToolbox распечатает подробную информацию об обработке событий Text Services Manager (TSM).

Какао и касание какао

Все объекты Какао (все произошло из NSObject) поддержка a description метод, возвращающийся NSString описание объекта. Наиболее удобный способ получить доступ к этому описанию через Описание Печати XCode к команде меню Console. Также, если Вы - наркоман командной строки, можно использовать GDB's print-object (или po если коротко) команда, как проиллюстрировано Перечислением 58.

Перечисление 58  Используя почтовую команду GDB

$ gdb /Applications/TextEdit.app
GNU gdb 6.3.50-20050815 (Apple version gdb-1346) […]
(gdb) fb -[NSCFDictionary copyWithZone:]
Breakpoint 1 at 0x83126e97675259
(gdb) r
Starting program: /Applications/TextEdit.app/Contents/MacOS/TextEdit 
Reading symbols for shared libraries […]
Breakpoint 1, 0x00007fff837aa259 in -[NSCFDictionary copyWithZone:] ()
(gdb) po $rdi
{
    AddExtensionToNewPlainTextFiles = 1;
    AutosaveDelay = 30;
    CheckGrammarWithSpelling = 0;
    CheckSpellingWhileTyping = 1;
    […]
}

Любопытно, debugDescription метод не объявляется ни в каком заголовке. Если Вы хотите реализовать его сами, необходимо сделать так как показано в Перечислении 59.

Перечисление 59  Реализовывая debugDescription

- (NSString *)debugDescription {     ... your code here ... }

Objective C

Для повреждения на исключении Objective C, независимо от того, как это брошено, устанавливает символьную точку останова на objc_exception_throw. Самый простой способ установить такую точку останова с Остановкой XCode на команде меню Objective-C Exceptions.

Если Вы устанавливаете NSObjCMessageLoggingEnabled переменная окружения к «YES», время выполнения Objective C зарегистрирует все диспетчеризированные сообщения Objective C к названному файлу /tmp/msgSends-<pid>.

Если Вы устанавливаете OBJC_HELP переменная окружения (10.4 и позже), время выполнения Objective C распечатает список всех переменных среды отладки, которые это поддерживает. Точный список варьируется от от выпуска к выпуску, таким образом, необходимо установить OBJC_HELP в Вашей определенной системе для наблюдения, что доступно. Таблица 20 перечисляет некоторые выделения.

Таблица 20  Полезные переменные окружения отладки на этапе выполнения Objective C

Переменная

Сводка

OBJC_PRINT_IMAGES

Изображения журнала, загруженные временем выполнения

OBJC_PRINT_LOAD_METHODS

Выполнение журнала +load методов

OBJC_DEBUG_FRAGILE_SUPERCLASSES

Если переменные экземпляра класса перекрывают переменные экземпляра его суперкласса, предупреждает

OBJC_PRINT_EXCEPTIONS (Mac OS X 10.5 и позже)

Зарегистрируйте обработку исключений

OBJC_PRINT_REPLACED_METHODS (Mac OS X 10.5 и позже)

Информация о печати о замененных методах; это особенно полезно при реализации плагинов или приложения, размещающего плагины

Отладка Objective C уровня ассемблера

При отладке кода Какао на уровне ассемблера имейте в виду следующие функции времени выполнения Objective C:

  • Компилятор Objective C добавляет два неявных параметра к каждому методу, первым из которых является указатель на вызываемый объект (self).

  • Второй неявный параметр является селектором метода (_cmd). В Objective C это имеет тип SEL; в GDB можно распечатать это как струну до.

  • Время выполнения Objective C диспетчеризирует методы через семью функции C. Обычно замеченный objc_msgSend, но некоторое использование архитектуры objc_msgSend_stret для методов, который возвращает структуры и некоторое использование архитектуры objc_msgSend_fpret для методов тот возврат значения с плавающей точкой. Существуют также эквивалентные функции для вызова super (objc_msgSendSuper и т.д.).

  • Первое слово любого объекта Objective C ( isa поле), указатель на класс объекта.

Таблица 21 является сводкой того, как получить доступ self и _cmd от GDB, если Вы остановились в первой инструкции метода. Для получения дополнительной информации об этом, посмотрите Некоторый Требуемый блок.

Табличный 21  Доступ сам и _cmd

Архитектура

сам

_cmd

64-разрядный Intel

$rdi

$rsi

32-разрядный Intel

* (интервал*)($esp+4)

* (интервал*)($esp+8)

PowerPC

$r3

$r4

Перечисление 60 показывает пример того, как использовать эту информацию от GDB.

  Время выполнения Objective C перечисления 60 'секреты'

$ gdb /Applications/TextEdit.app
GNU gdb 6.3.50-20050815 (Apple version gdb-1346) […]
(gdb) # Give the runtime a chance to start up.
(gdb) fb NSApplicationMain
Breakpoint 1 at 0x9374bc69df7307
(gdb) r
Starting program: /Applications/TextEdit.app/Contents/MacOS/TextEdit 
Reading symbols for shared libraries […]
Breakpoint 1, 0x00007fff841a0307 in NSApplicationMain ()
(gdb) # Set a breakpoint on -retain.
(gdb) b *'-[NSObject(NSObject) retain]'
Breakpoint 2 at 0x7fff8608a860
(gdb) c
Continuing.

Breakpoint 2, 0x00007fff8608a860 in -[NSObject(NSObject) retain] ()
(gdb) # Hit the breakpoint; dump the first 4 words of the object
(gdb) x/4xg $rdi
0x1001138f0: 0x00007fff7055e6d8  0x0041002f01a00000
0x100113900: 0x0069006c00700070  0x0069007400610063
(gdb) # Now print the selector
(gdb) x/s $rsi
0x7fff848d73d8: "retain"
(gdb) # Want to 'po' object; must disable the breakpoint first
(gdb) dis
(gdb) po $rdi
/Applications/TextEdit.app
(gdb) # Print the 'isa' pointer, which is a Class object.
(gdb) po 0xa02d9740
NSPathStore2

При отладке без символов можно использовать функции со времени выполнения Objective C для помощи усилиям по отладке. Подпрограммы, показанные в Таблице 22, особенно полезны.

Таблица 22  Полезные функции времени выполнения Objective C

Функция

Сводка

id objc_getClass (символ константы *имя);

Получите Объект класса Objective C для данного имени класса

SEL sel_getUid (символ константы *str);

Получите Objective C SEL для данного имени метода

IMP class_getMethodImplementation (Класс cls, имя SEL);

Получите указатель на код, реализующий данный метод в данном классе; доступный на Mac OS X 10.5 и позже

Метод class_getInstanceMethod (Класс, SEL);

Получите Метод Objective C для данного метода экземпляра в данном классе

Перечисление 61 показывает пример отладки -[DocumentController openUntitledDocumentAndDisplay:error:] метод TextEdit, даже при том, что TextEdit не поставляет с символами.

Перечисление 61  Используя время выполнения Objective C для отладки без символов

$ gdb -arch x86_64 /Applications/TextEdit.app
GNU gdb 6.3.50-20050815 (Apple version gdb-1346) […]
(gdb) r
Starting program: /Applications/TextEdit.app/Contents/MacOS/TextEdit 
Reading symbols for shared libraries […]
^C
(gdb) # Try to find the 
(gdb) # -[DocumentController openUntitledDocumentAndDisplay:error:] 
(gdb) # symbol.
(gdb) info func openUntitledDocumentAndDisplay
All functions matching regular expression "openUntitledDocumentAndDisplay":

Non-debugging symbols:
0x00007fff843ac083 -[NSDocumentController openUntitledDocumentAndDisplay:error:]
(gdb) # These are not the droids we're looking for. It turns out that 
(gdb) # TextEdit ships with its symbols stripped, so we'll have to do 
(gdb) # this the hard way.
(gdb) #
(gdb) # Get the Class object for the DocumentController class.
(gdb) set $class=(void *)objc_getClass("DocumentController")
(gdb) # Get the SEL object for the "openUntitledDocumentAndDisplay:error:" method.
(gdb) set $sel=(void *)sel_getUid("openUntitledDocumentAndDisplay:error:")
(gdb) # Get a pointer to the method implementation.
(gdb) call (void*)class_getMethodImplementation($class, $sel)
$1 = (void *) 0x100001966
(gdb) # Confirm that this is sensible. Looks like a method prologue to me.
(gdb) x/4i 0x00009aa5
0x100001966: push   %rbp
0x100001967: mov    %rsp,%rbp
0x10000196a: push   %r12
0x10000196c: push   %rbx
(gdb) # Set a breakpoint on the method.
(gdb) b *0x100001966
Breakpoint 1 at 0x100001966
(gdb) # Resume execution, and then create a new, untitled document.
(gdb) c
Continuing.
[…]
Breakpoint 1, 0x0000000100001966 in ?? ()
(gdb) # We've hit our breakpoint; print the parameters, starting with 
(gdb) # the implicit "self" and "SEL" parameters that are common to all 
(gdb) # methods, followed by the method-specific "display" and 
(gdb) # "error" parameters.
(gdb) po $rdi
<DocumentController: 0x100227a50>
(gdb) x/s $rsi
0x7fff848e4e04: "openUntitledDocumentAndDisplay:error:"
(gdb) p (int)$rdx
$2 = 1
(gdb) x/xg $rcx
0x7fff5fbff108: 0x00000001001238f0

Перечисление 62  Используя class_getInstanceMethod, когда class_getMethodImplementation не доступен

$ # You should only do this on old systems, so we're going to run 
$ # TextEdit as i386 in order to get the old Objective-C runtime.
$ gdb -arch i386 /Applications/TextEdit.app
GNU gdb 6.3.50-20050815 (Apple version gdb-1346) […]
(gdb) r
Starting program: /Applications/TextEdit.app/Contents/MacOS/TextEdit 
Reading symbols for shared libraries […]
^C
Program received signal SIGINT, Interrupt.
0x94af18da in mach_msg_trap ()
(gdb) # These steps are unchanged.
(gdb) set $class=(void *)objc_getClass("DocumentController")
(gdb) set $sel=(void *)sel_getUid("openUntitledDocumentAndDisplay:error:")
(gdb) # Get the Method for that method of that class
(gdb) call (void*)class_getInstanceMethod($class, $sel)
$1 = (void *) 0x11aab0
(gdb) # Dump the Method
(gdb) x/3x 0x11aab0
0x11aab0: 0x913b28c9  0x00015acb  0x00002b64
(gdb) # Print the first word, just to make sure everything is copacetic
(gdb) x/s 0x913b28c9
0x913b28c9: "openUntitledDocumentAndDisplay:error:"
(gdb) # The third word is a pointer to code; confirm that this is sensible
(gdb) x/4i 0x00002b64
0x2b64: push   %ebp
0x2b65: mov    %esp,%ebp
0x2b67: push   %esi
0x2b68: push   %ebx

Можно узнать больше о функциях времени выполнения Objective C и структурах данных путем просмотра заголовков в /usr/include/objc/.

Сборка «мусора»

Если Вы устанавливаете AUTO_USE_GUARDS переменная окружения к YES, собравшее «мусор» средство выделения памяти будет работать как Защищенное Средство выделения Памяти, помещая защитные страницы в конце каждого выделения памяти. Это - отличный способ обнаружить переполнение буфера.

Если Вы устанавливаете AUTO_DISABLE_GENERATIONAL переменная окружения к YES, собравшее «мусор» средство выделения памяти отключит свой коллектор поколений; все наборы будут полными наборами.

Можно использовать переменные окружения от Таблицы 23 для включения различных средств журналирования в собравшем «мусор» средстве выделения памяти. Некоторые из них генерируют большое журналирование.

Таблица 23  Собрала «мусор» средство выделения памяти, регистрирующее переменные окружения

Переменная окружения

Эффект

AUTO_LOG_COLLECTIONS

Журнал, когда происходит набор

AUTO_LOG_REGIONS

Журнал, когда выделяются новые области

AUTO_LOG_WEAK

Зарегистрируйте все манипуляции слабой ссылкой

AUTO_LOG_ALL

Эквивалентный установке всех вышеупомянутых

AUTO_REFERENCE_COUNT_LOGGING

Включает журналирование подсчета ссылок

Собравшее «мусор» средство выделения памяти поддерживает некоторые другие потенциально полезные переменные окружения, как показано в Таблице 24.

Таблица 24  Собрала «мусор» средство выделения памяти другие переменные окружения

Переменная окружения

Эффект

AUTO_COLLECT_EXHAUSTIVE_NOTIFICATION

Если установлено, средство выделения прислушивается к уведомлению (в <notify.h> смысл) указанного имени и, когда уведомлено, инициировало набор

AUTO_DIRTY_ALL_DELETED

Удаленные объекты будут набросаны (подобный MallocScribble)

AUTO_USE_TLC

Отключает поток локальный коллектор (TLC)

Когда запись собрала «мусор», кодируют, Вы иногда сталкиваетесь с проблемами, где объект живет вне своего ожидаемого ресурса. Существует две полезных команды GDB для отладки этого:

  • info gc-roots перечисляет корни, приводящие к указанному адресу

  • info gc-references списки все прямые ссылки к указанному адресу

Можно также получить доступ к этим командам через Корни Печати XCode к Консоли и Печати Referers к пунктам меню Console.

Если у Вас есть двойной код режима (код, поддерживающий обоих собравший «мусор», и сохраните/выпустите модели), можно вынудить его работать в, сохраняют/выпускают режим путем установки OBJC_DISABLE_GC переменная окружения к YES.

Основа

Основа имеет много средств отладки, включенных переменными окружения. Таблица 25 выделяет самые интересные; они все далее документируются в NSDebug.h.

Табличные 25  Переменные окружения от 'NSDebug.h'

Имя

Значение по умолчанию

Действие

NSZombieEnabled

НЕТ

Если установлено в ДА, освобожденные объекты 'зомбированы'; это позволяет Вам быстро отлаживать проблемы, куда Вы отправляете сообщение в уже освобожденный объект; посмотрите Больше Зомби! для подробных данных

NSDeallocateZombies

НЕТ

Если установлено в ДА, память для 'зомбированных' объектов фактически освобождена

NSUnbufferedIO

НЕТ

Если установлено в ДА, Основа будет использовать, освободил буфер I/O для stdout (stderr, освобожден буфер по умолчанию),

Сохраните количества

Можно использовать -retainCount для получения тока сохраняют количество объекта. В то время как это может иногда быть полезным средством отладки, быть очень тщательным при интерпретации результатов. Перечисление 63 показывает один потенциальный источник беспорядка.

  Запутывающее перечисление 63 сохраняет количество

(gdb) set $s=(void *)[NSClassFromString(@"NSString") string]
(gdb) p (int)[$s retainCount]
$4 = 2147483647
(gdb) p/x 2147483647
$5 = 0x7fffffff
(gdb) # The system maintains a set of singleton strings for commonly 
(gdb) # used values, like the empty string. The retain count for these 
(gdb) # strings is a special value indicating that the object can't be 
(gdb) # released.

Другой общий источник беспорядка является механизмом автовыпуска. Если объект был автовыпущен, сохранять количество выше, чем Вы могли бы иначе думать, факт, за который это является компенсацией пулом автовыпуска, выпускающим его в некоторый момент в будущем.

Можно определить, какие объекты находятся в том, что автовыпуск объединяет путем вызова _CFAutoreleasePoolPrintPools распечатать содержание всего автовыпуска объединяет на штабеле пула автовыпуска.

Перечисление 64  , Распечатывающее автовыпуск, объединяет штабель

(gdb) call (void)_CFAutoreleasePoolPrintPools()
- -- ---- -------- Autorelease Pools -------- ---- -- -
==== top of stack ================
  0x327890 (NSCFDictionary)
  0x32cf30 (NSCFNumber)
  […]
==== top of pool, 10 objects ================
  0x306160 (__NSArray0)
  0x127020 (NSEvent)
  0x127f60 (NSEvent)
==== top of pool, 3 objects ================
- -- ---- -------- ----------------- -------- ---- -- -

В более ранних системах можно использовать NSAutoreleasePoolCountForObject функция для определения, сколько раз объект был добавлен к пулу автовыпуска. Для примера см. Перечисление 65.

  Вызов перечисления 65 NSAutoreleasePoolCountForObject

(gdb) # d is an NSDictionary created with -[NSDictionary dictionaryWithObjectsAndKeys:].
(gdb) p d
$1 = (NSDictionary *) 0x12d620
(gdb) po d
{
    test = 12345;
}
(gdb) p (int)[d retainCount]
$2 = 1
(gdb) p (int)NSAutoreleasePoolCountForObject(d)
$3 = 1

Начиная с Mac OS X 10.6, NSAutoreleasePool реализует много зондов DTrace, которые можно использовать для профиля и отладить проблемы автовыпуска. См. Информацию о версии Платформы Основы для подробных данных..

Больше зомби!

Общий тип ошибки, когда программирование с Какао сверхвыпускает объект. Это обычно заставляет Ваше приложение отказывать, но катастрофический отказ происходит после того, как последний подсчет ссылок выпущен (когда Вы пытаетесь передать освобожденный объект), который обычно вполне удаляется из исходной ошибки. NSZombieEnabled Ваш лучший выбор для отладки этого вида проблем; это раскроет любую попытку взаимодействовать с освобожденным объектом.

Самый простой способ включить зомби через Инструменты. Однако можно также включить зомби через переменную окружения. Перечисление 66 показывает тип сообщения, которое Вы будете видеть в этом случае.

Перечисление 66  эффект NSZombie

$ NSZombieEnabled=YES build/Debug/DummyMac.app/Contents/MacOS/DummyMac  […] -[AppDelegate testAction:] […] *** -[CFNumber release]: message sent to deallocated instance 0x3737c0 Trace/BPT trap

Как показано в Перечислении 66, система выполнит команду контрольного останова, если это обнаружит зомби. Если Вы будете работать под GDB, то программа остановится, и можно смотреть на след для наблюдения цепочки вызовов, инициировавших детектор зомби.

NSZombieEnabled также объекты Основы Ядра влияния, а также объекты Objective C. Однако Вы будете только уведомлены при доступе к объекту Основы Ядра зомби от Objective C, не при доступе к нему через CF API.

Другое волшебство основы

Если Вы используете Наблюдение Значения ключа, и Вы хотите знать, кто наблюдает то, что на определенном объекте, можно получить информацию наблюдения для того объекта и распечатать его использование с помощью объектной команды печати GDB. Перечисление 67 показывает пример этого.

  Наблюдатели значения ключа Дисплея перечисления 67

(gdb) # self is some Objective-C object.
(gdb) po self
<ZoneInfoManager: 0x48340d0>
(gdb) # Let's see who's observing what key paths.
(gdb) po [self observationInfo]
<NSKeyValueObservationInfo 0x48702d0> (
<NSKeyValueObservance 0x4825490: Observer: 0x48436e0, \
Key path: zones, Options: <New: NO, Old: NO, Prior: NO> \
Context: 0x0, Property: 0x483a820>
)

Можно установить NSShowNonLocalizedStrings предпочтение к строкам поиска, которые должны были быть локализованы, но не были. После того, как включенный, если Вы запрашиваете, локализованная строка и строка не найдены в строковом файле, система возвратит капитализируемую строку и зарегистрирует сообщение к консоли. Это - отличный способ раскрыть проблемы с устаревшими локализациями.

Эта установка влияние NSLocalizedString, все ее варианты и вся базовая инфраструктура включая CFCopyLocalizedString.

Если Вы устанавливаете NSBundleLogResourceLookUp предпочтение, NSBundle зарегистрирует свои действия, поскольку это ищет ресурсы в пакетах; это средство не доступно до Mac OS X 10.5.

Если Вы устанавливаете NSDOLoggingEnabled переменная окружения к «YES», Основа позволит регистрировать для Распределенных Объектов (NSConnection, NSInvocation, NSDistantObject, и NSConcretePortCoder).

  • Если Вы устанавливаете NSPrintDynamicClassLoads переменная окружения к «YES», Основа зарегистрировала бы сообщение каждый раз, когда это загрузило класс или категорию динамично (т.е. от пакета).

    Это средство не работает в Mac OS X 10.5 или позже; самый близкий эквивалент DYLD_PRINT_LIBRARIES переменная окружения, обсужденная в Динамическом Компоновщике (dyld).

  • Если Вы устанавливаете NSExceptionLoggingEnabled переменная окружения к «YES», Основа зарегистрировала бы все действие исключения (NSException) к stderr.

    Это средство не работает в Mac OS X 10.5 или позже; самый близкий эквивалент OBJC_PRINT_EXCEPTIONS переменная окружения, обсужденная в разделе Objective-C.

Сценарии основы

Можно позволить регистрировать для поддержки сценариев Основы с помощью NSScriptingDebugLogLevel предпочтение. Перечисление 68 показывает пример этого; показанный журнал является результатом выполнения тривиального AppleScript count windows of application "TextEdit".

  Включение перечисления 68 NSScriptingDebugLogLevel

$ /Applications/TextEdit.app/Contents/MacOS/TextEdit -NSScriptingDebugLogLevel 1
[…] Suite NSCoreSuite, apple event code 0x3f3f3f3f
[…] Suite NSTextSuite, apple event code 0x3f3f3f3f
[…] Suite TextEdit, apple event code 0x74786474
[…] Command: NSCoreSuite.Count
    Direct Parameter: (null)
    Receivers: (null)
    Arguments: {
        ObjectClass = 1668770158;
    }
[…] Result: 1

Объекты сценариев основы (вещи как NSAppleEventDescriptor) имейте значимый -description методы, таким образом, Вы вкладываете полезный вывод NSLog и от GDB's print-object команда.

Одним особенно полезным примером вышеупомянутого является NSScriptSuiteRegistry. При отладке определений сценариев Вы видите представление системы определений сценариев своего приложения путем печати описания +[NSScriptSuiteRegistry sharedScriptSuiteRegistry], как проиллюстрировано в Перечислении 69.

  Печать перечисления 69 представление системы Ваших определений сценариев

(gdb) po [NSClassFromString(@"NSScriptSuiteRegistry") sharedScriptSuiteRegistry]
Suite: NSCoreSuite ('????') - uses unnamed arguments
    Name: "Standard Suite", description: "Common classes and commands for most applications."
    Class: NSApplication ('capp'), superclass: AbstractObject
        Implementation class: NSApplication
[…]

Базовые данные

com.apple.CoreData.SQLDebug предпочтение позволяет Вам видеть фактический SQL, отправленный в SQLite. Посмотрите раздел «Debugging Fetching» Базового Руководства по программированию Данных для подробных данных. Кроме того, если Вы устанавливаете com.apple.CoreData.SyntaxColoredLogging предпочтение к 1, журналирование будет иметь элегантную окраску синтаксиса.

com.apple.CoreData.SQLiteDebugSynchronous предпочтение управляет некоторыми аспектами хранилища SQLite. Посмотрите раздел «Configuring a SQLite Store's Save Behavior» Базового Руководства по программированию Данных для подробных данных.

Если Вы устанавливаете com.apple.CoreData.SQLiteIntegrityCheck предпочтение к 1, хранилище SQLite делает дополнительную проверку целостности.

Если Вы устанавливаете com.apple.CoreData.MigrationDebug предпочтение к 1, Базовые Данные зарегистрируют информацию об исключительных случаях, поскольку это перемещает данные.

com.apple.CoreData.ThreadingDebug предпочтение позволяет утверждениям осуществить политику многопоточности Базовых Данных. Это - число, где увеличивающие стоимости включают больше отладки. Значение 3 рекомендуется. Эта функция требует варианта отладки платформы.

AppKit

Если Вы устанавливаете NSQuitAfterLaunch переменная окружения к 1, Ваше приложение выйдет, как только это вводит свой цикл событий. Если Вы хотите измерить время запуска приложения или искать утечки, это полезно. Эта переменная окружения также поддерживается Углеродом.

События AppKit

Если Вы устанавливаете NSTraceEvents предпочтение к ДА, AppKit зарегистрирует информацию обо всех событиях, которые это обрабатывает. Перечисление 70 показывает пример этого.

Перечисление 70  Используя NSTraceEvents

$ /Applications/TextEdit.app/Contents/MacOS/TextEdit -NSTraceEvents YES
2010-02-04 11:08:44.776 TextEdit[29986:903] timeout = 62826929475.223495 se[…]
2010-02-04 11:08:44.797 TextEdit[29986:903] got apple event of class 616576[…]
2010-02-04 11:08:44.840 TextEdit[29986:903] still in loop, timeout = 628269[…]
2010-02-04 11:08:44.841 TextEdit[29986:903] timeout = 62826929475.159660 se[…]
[…]

Представления AppKit

NSView имеет закрытый метод, _subtreeDescription, то, что можно вызвать от GDB для наблюдения довольно распечатанного описания подпредставлений представления.

Если Вы устанавливаете NSShowAllViews предпочтение к ДА, AppKit нарисует основы вокруг каждого из представлений в окне. Рисунок 5 показывает, как стандартное окно TextEdit смотрит с NSShowAllViews включенный.

Рисунок 5  TextEdit с NSShowAllViews включен

Если Вы устанавливаете NSShowAllDrawing предпочтение к ДА, AppKit высветит каждый прямоугольник, который это рисует, во многом как Кварцевая Отладка. Рисунок 6, показанный пример того, что ожидать.

Рисунок 6  NSShowAllDrawing в действии

Можно управлять продолжительностью флэш-памяти путем установки NSShowAllDrawing к числу, интерпретирующемуся как число миллисекунд для высвечивания; значение по умолчанию составляет 100 мс. Можно управлять цветом флэш-памяти путем установки NSShowAllDrawingColor к строке, содержащей три числа с плавающей точкой, разделенные пробелами, представляя красные, зеленые, и синие компоненты цвета. Каждое число должно быть значением от 0,0 до 1,0 представлений интенсивности того компонента. Например, строка «0.0 1.0 1.0» привела бы к чистому циану. Также, если Вы устанавливаете NSShowAllDrawingColor к «CYCLE» AppKit циклически повторится через чистый красный, чистый зеленый, и чистый синий.

Если Вы устанавливаете NSDebugCursorRects предпочтение к ДА, AppKit зарегистрирует информацию о своем курсоре rect обработка.

Если Вы устанавливаете NSDebugFocusRing предпочтение к ДА, AppKit визуально выделит фокусирующие кольца и зарегистрирует информацию об их конструкции.

На Mac OS X 10.6 можно отключить параллельное получение представления путем установки NSEnableConcurrentViewDrawing предпочтение к NO.

Другое волшебство AppKit

NSBindingDebugLogLevel предпочтение, представленное в Mac OS X 10.4, управляет ответом AppKit на обязательные проблемы. Для получения полезных журналов об обязательной проблеме (а не, скажем, неопределенное ключевое исключение) установите это предпочтение в 1. Это полезно при попытке найти неправильно сконфигурированную привязку в большом, большом приложении привязки.

NSDragManagerLogLevel предпочтение является числом, управляющим, сколько журналирование AppKit делает во время операций перетаскивания. Большие значения дают Вам больше журналирования. В настоящее время значение 6 является максимальным действующим значением. Перечисление 71 показывает пример того, как установить это и вид вывода, который Вы получаете при перетаскивании простого текстового выбора из TextEdit.

Перечисление 71  Используя NSDragManagerLogLevel

$ /Applications/TextEdit.app/Contents/MacOS/TextEdit -NSDragManagerLogLevel 6
2010-02-04 11:32:55.956 TextEdit[30160:903] mouseDown location: {11, 360}, […]
2010-02-04 11:32:55.959 TextEdit[30160:903] offset of image lower left rela[…]
2010-02-04 11:32:55.960 TextEdit[30160:903] type public.rtf: data <7b5c7274[…]
[…]

NSAccessibilityDebugLogLevel предпочтение является числом, управляющим, сколько журналирование AppKit делает во время операций доступности. Мы рекомендуем, чтобы сторонние разработчики всегда использовали значение 1.

До Mac OS X 10.4, NSAccessibilityDebugLogLevel имел меньше опций: значение 1 стало входящим в систему, и значение 0 выключило его.

Sync Services

При работе с Sync Services, Syncrospector (в /Developer/Applications/Utilities) неоценимый инструмент.

Sync Services регистрирует информацию о своих действиях к ~/Library/Logs/Sync. Можно радикально увеличить уровень журналирования путем выполнения следующих команд в Терминале.

Перечисление 72  журналирование Enabling Sync Services

$ defaults write -g SyncServicesLogEverything YES $ defaults write com.apple.syncserver SaveSyncServicesDirectory YES

Необходимо выйти из системы, и журнал въезжают задним ходом для настроек для вступления в силу.

Это зарегистрирует большую информацию к ~/Library/Application Support/SyncServices. Поскольку это регистрирует так много данных, необходимо удостовериться, что отключили их, когда Вы сделаны. Можно сделать это со следующими командами.

Перечисление 73  журналирование Disabling Sync Services

defaults delete -g SyncServicesLogEverything defaults delete com.apple.syncserver SaveSyncServicesDirectory rm -rf ~/Library/Application\ Support/SyncServices/Local/ save.isyncplayback

Не забывайте выходить из системы и регистрировать, въезжают задним ходом!

Сети

Самый критический инструмент для отладки сетевого кода является трассировкой пакетов. Технический QA1176 Вопросов и ответов, 'Получение Трассировки пакетов' обсуждает, как получить трассировку пакетов на Mac OS X.

netstat инструмент может вывести на экран богатство информации о состоянии сетевого стека локальной машины; см. его страницу справочника для подробных данных.

Если Вы хотите знать то, что снабжает процесс сокетом, имеет открытый, можно использовать lsof инструмент; см. его страницу справочника для подробных данных.

nc инструмент чрезвычайно полезен для основного сетевого тестирования; см. его страницу справочника для подробных данных.

telnet инструмент может также быть полезен для основного сетевого тестирования; см. его страницу справочника для подробных данных.

При отладке Безопасности Транспортного уровня (TLS, раньше известный как Уровень защищенных сокетов или SSL), проблемы, s_client OpenSSL и s_server подкоманды чрезвычайно полезны.

Демон AirPort (/usr/libexec/airportd) имеет много холодных функций отладки. Для узнавания больше выполните демона от Терминала без любых параметров и считайте получающийся текст справки.



История версии документа


ДатаПримечания
16.11.2010

Обновляет документ для Mac OS X 10.6.

10.01.2007

Исправленный орфографическая ошибка.

25.07.2006

11.04.2006

Добавленный предупреждение о CFZombieLevel. Исправленная ошибка в Перечислении 20.

31.03.2006

Общее обновление для Mac OS X 10.4.x на PowerPC - и основанные на Intel компьютеры. Добавленные новые разделы, покрывающие стандартную библиотеку C++, launchd, lookupd, Дисковую утилиту, Базовую Графику, и время выполнения Objective C.

02.12.2004

Новый документ, описывающий большое количество полезных советов отладки Mac OS X.