Волшебство отладки Mac OS X
Mac OS X содержит много 'секретных' средств отладки, включая переменные окружения, предпочтения, подпрограммы, вызываемые от GDB, и т.д. Этот technotes описывает эти средства. Если Вы разрабатываете для Mac OS X, необходимо просмотреть этот список, чтобы видеть, пропускаете ли Вы что-то, что сделает Вашу жизнь проще.
Введение
Все системы Apple включают средства отладки, добавленные командами инженеров Apple, чтобы помочь разработать и отладить определенные подсистемы. Многие из этих средств остаются в выпущенном системном программном обеспечении, и можно использовать их для отладки кода. Этот technote описывает некоторые более широко полезные. В случаях, где средство отладки документируется в другое место, существует краткий обзор средства и ссылки к существующей документации.
Многие подробные данные, покрытые этим technote, варьируются от платформы до платформы и выпуска к выпуску. Также, можно встретиться с незначительными изменениями между платформами, и в более старых или более новых системах. Известные значительные изменения вызываются в тексте.
Этот technote был записан в отношении Mac OS X 10.6.
Этот technote покрытия усовершенствовал отладку методов. Если Вы просто начинаете, необходимо консультироваться со следующим материалом:
GDB является основным средством отладки системы. Для полного описания GDB посмотрите Отладку с GDB.
XCode является интегрированной средой разработки (IDE) Apple. Это включает сложный графический отладчик, реализованный как обертка вокруг GDB. Для получения дополнительной информации о XCode, посмотрите раздел «Tools & Languages» Ссылочной Библиотеки разработчика Apple.
Этот technote не покрывает отладку производительности. При попытке отладить проблему производительности, лучшее место для запуска является Началом работы с документом Производительности.
Основы
Более поздние разделы этого technote описывают средства отладки подробно. Многие из этих средств используют подобные методы, чтобы включить и отключить средство и видеть его вывод. В этом разделе описываются эти общие методы.
Включение средств отладки
Некоторые средства отладки включены по умолчанию. Однако большинство средств должно быть включено с помощью одного из методов, описанных в следующих разделах.
Переменные окружения
Во многих случаях можно включить средство отладки путем установки определенной переменной окружения. Можно сделать это использование исполнимого инспектора в XCode. Рисунок 1 показывает пример этого.


Кроме того, существуют многочисленный другие способы установить переменную окружения. Первое включает запуск Вашего приложения от Терминала и указания переменной окружения на командной строке. Перечисление 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 показывает, как это сделано.


Можно также сделать это путем выполнения программы из командной строки и предоставления предпочтения в параметрах. Перечисление 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, когда Вы остановились в первой инструкции функции.
Что | Синтаксис 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.
Что | Синтаксис GDB |
|---|---|
обратный адрес | * (интервал *) $esp |
первый параметр | * (интервал*)($esp+4) |
второй параметр | * (интервал*)($esp+8) |
... и т.д. |
|
После вводной части подпрограммы можно получить доступ к параметрам относительно указателя кадра (зарегистрируйте EBP). Таблица 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, когда Вы остановились в первой инструкции функции.
Что | Синтаксис 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.
Размер | C тип | Модуль GDB | Мнемосхема |
|---|---|---|---|
1 байт | символ | b | байт |
2 байта | короткий | h | полуслово |
4 байта | интервал | w | слово |
8 байтов | долго или долго долго | g | гигант |
Это особенно важно в следующих случаях:
При отладке 64-разрядной программы много количеств (например, все указатели, включая обратный адрес подпрограммы) составят 64 бита. Размер модуля GDB по умолчанию ('w') только покажет Вам 32 бита. Необходимо будет указать 'g' для наблюдения всех 64 битов.
При отладке в системе с прямым порядком байтов (т.е. все кроме основанных на PowerPC компьютеров Macintosh), Вы получаете запутывающие результаты при указании неправильного размера модуля. Перечисление 16 показывает пример этого. Вторые и третьи параметры
CFStringCreateWithCharactersукажите массив символов Unicode. Каждый элемент является aUniChar, который является 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 перечисляет некоторые более полезные.
Переменная | Сводка |
|---|---|
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 перечисляет некоторые более полезные переменные.
Переменная | Сводка |
|---|---|
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] | Статистика производительности запуска печати |
Примечания:
Доступный на 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 перечисляет некоторые лучшие.
Инструмент | Документация | Сводка |
|---|---|---|
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] |
Примечания:
Доступный в Mac OS X 10.5 и позже.
ktraceиkdumpне доступны в Mac OS X 10.5 и позже; использоватьdtraceилиdtrussвместо этого.Доступный в 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 Вы видите, что «Использование … суффикс при загрузке платформ», раскрывающихся, было установлено «отладить».

Точное поведение библиотеки отладки варьируется от платформы до платформы. Большинство библиотек отладки включает:
если источник для платформы включен в Дарвина, полные отладочные символы — Это особенно полезно.
дополнительные утверждения — Они могут помочь точно определить программные ошибки с Вашей стороны.
дополнительные средства отладки — Много средств отладки, описанных позже в этом документе, только доступны в библиотеке отладки.
Включение всего одной библиотеки отладки
При некоторых обстоятельствах Вы могли бы хотеть включить всего одну библиотеку отладки. Например, скажем, Вы отлаживаете проблему события 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 обеспечивает удобный способ сделать это:
В панели Accounts Установок системы щелкните по Login Options. Если текст отображается серым, необходимо сначала разблокировать панель путем щелчка по значку блокировки.
Измените настройки «Display login window as» к «Имени и паролю».
Выйти из системы.
В окне входа в систему введите»> консоль» как Ваше имя пользователя и нажмите кнопку Log In;
loginwindowвыйдет и Вы столкнетесь со стеклянным интерфейсом TTY, выводящим на экран подсказку «Входа в систему» (Вы, возможно, должны нажать Return, чтобы заставить подсказку быть выведенной на экран).Войдите в систему с помощью стандартного имени пользователя и пароля.
Когда Вы сделаны, работая на этом уровне, просто выходите от своей оболочки (использующий exit команда), и Вы возвратитесь к стандартному окну входа в систему.
DTrace
DTrace является всесторонним динамическим средством трассировки, начатым с Mac OS X 10.5. DTrace был первоначально разработан Sun Microsystems (теперь Oracle) для их операционной системы Соляриса, но был интегрирован в Mac OS X Apple. В то время как полное объяснение DTrace выходит за рамки этого документа, этот раздел покрывает некоторые выделения.
Самая важная вещь понять состоит в том, что DTrace не только для отладки производительности. В то время как это было первоначально разработано для поддержки отладки производительности, и это очень сильно в той области, это может также использоваться для других типов отладки. Например, иногда полезно знать, какие процессы открывают то, что файлы и DTrace могут сказать Вам настолько легко.
DTrace является также основой многих средств отладки на Mac OS X, включая:
dtruss — Это упрощает видеть что системные вызовы, сделанные процессом.
Инструменты — Многие встроенные инструменты фактически реализованы с точки зрения DTrace.
многочисленные другие инструменты — Видят находящиеся в DTrace Инструменты для списка инструментов на основе DTrace.
Хорошее место для запуска с DTrace является страницей Oracle BigAdmin для DTrace. Также существует много сценариев DTrace, встроенных к Mac OS X (некоторые описаны в следующем разделе), и можно просто смотреть на источник для тех сценариев. Наконец, инструменты имеет хороший UI для создания пользовательских Инструментов на основе сценария DTrace.
Не торопитесь для изучения DTrace; это окупится в конечном счете!
Находящиеся в DTrace инструменты
Следующие таблицы приводят некоторые находящиеся в DTrace инструменты, встроенные к Mac OS X. Следует иметь в виду, что, в то время как эти сценарии не могли бы сделать точно, что Вы хотите, можно скопировать источник сценария и настроить его для лучше удовлетворения потребностям.
Инструмент | Документация | Сводка |
|---|---|---|
execsnoop | страница руководства | Трассировки обрабатывают выполнение |
newproc.d | страница руководства | Показывает новые процессы, поскольку они создаются |
pidpersec.d | страница руководства | Показывает, что процесс создает количество в секунду |
setuids.d | страница руководства | Показывает изменения setuid, как они происходят |
Инструмент | Документация | Сводка |
|---|---|---|
dtruss | страница руководства | Трассировки обрабатывают системные вызовы |
errinfo | страница руководства | Отказы системного вызова трассировок |
lastwords | страница руководства | Показывает последние системные вызовы, сделанные процессом |
procsystime | страница руководства | Показывает времена выполнения системного вызова |
syscallbypid.d | страница руководства | Показывает системные вызовы процессом ID |
syscallbyproc.d | страница руководства | Показывает системные вызовы именем процесса |
syscallbysysc.d | страница руководства | Показывает количества системного вызова |
topsyscall | страница руководства | Каждую секунду, показывает наиболее распространенные системные вызовы |
topsysproc | страница руководства | Каждую секунду, показывает процессы, делающие большинство системных вызовов |
Инструмент | Документация | Сводка |
|---|---|---|
kill.d | страница руководства | Показывает сигналы, когда они отправляются |
sigdist.d | страница руководства | Показывает сигналы процессом |
Инструмент | Документация | Сводка |
|---|---|---|
creatbyproc.d | страница руководства | Показывает, что файлы, создаваемые с, создают |
fddist | страница руководства | Показывает распределение использования дескриптора файла |
filebyproc.d | страница руководства | Файлы трассировок открылись процессом |
opensnoop | страница руководства | Показывает открываемые файлы |
pathopens.d | страница руководства | Показывает открытые количества путем |
rwbypid.d | страница руководства | Показывает чтение и вызовы записи процессом |
rwbytype.d | страница руководства | Показывает чтение и вызовы записи типом vnode |
rwsnoop | страница руководства | Показывает чтение и вызовы записи, как они происходят |
Инструмент | Документация | Сводка |
|---|---|---|
httpdstat.d | страница руководства | Показывает статистику соединений Apache |
weblatency.d | страница руководства | Показывает статистику задержки Запроса HTTP |
Инструмент | Документация | Сводка |
|---|---|---|
bitesize.d | страница руководства | Показывает диску размер I/O процессом |
diskhits | страница руководства | Показывает доступ к файлу смещением |
hotspot.d | страница руководства | Показывает использование диска расположением |
iofile.d | страница руководства | Показывает времена ожидания I/O файлом |
iofileb.d | страница руководства | Показывает размеры передачи файлом |
iopattern | страница руководства | Показывает образцы доступа к диску |
iopending | страница руководства | Показывает число незаконченных дисковых передач |
iosnoop | страница руководства | Показывает доступы к диску, как они происходят |
iotop | страница руководства | Показывает диску I/O для каждого процесса |
seeksize.d | страница руководства | Показывает поиск на диске процессом |
Инструмент | Документация | Сводка |
|---|---|---|
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 перечисляет тех, которые наиболее относятся к отладке.
Команда | Сводка |
|---|---|
список | Выводит на экран список загруженных заданий или подробную информацию об определенном задании |
предел | Устанавливает пределы ресурса 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 перечисляет свойства, которые являются самыми полезными для отладки.
Свойство | Сводка |
|---|---|
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 отладка со следующими шагами:
Создайте
DebugиTraceсвойства в локальной машине/config/lookupdКаталог NetInfo.Измените конфигурацию системного журнала так, чтобы отладочная информация NetInfo (
netinfo.debug) отправляется в файл журнала NetInfo (/var/log/netinfo.log).Отправьте a
SIGHUPсигнал кsyslogdзаставить его распознавать предыдущее изменение.Отправьте 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).

Базовая основа
Платформа 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.
Бит | Действие |
|---|---|
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 углерода включает богатство средств для Вашего удобства отладки:
Существует вариант отладки библиотеки HIToolbox, распечатывающей сообщения отладки, когда это встречается с ошибками.
Существуют многочисленные подпрограммы HIToolbox, которые можно вызвать из GDB для печати информации об объектах 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 перечисляет некоторые выделения.
Переменная | Сводка |
|---|---|
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, если Вы остановились в первой инструкции метода. Для получения дополнительной информации об этом, посмотрите Некоторый Требуемый блок.
Архитектура | сам | _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, особенно полезны.
Функция | Сводка |
|---|---|
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 для включения различных средств журналирования в собравшем «мусор» средстве выделения памяти. Некоторые из них генерируют большое журналирование.
Переменная окружения | Эффект |
|---|---|
AUTO_LOG_COLLECTIONS | Журнал, когда происходит набор |
AUTO_LOG_REGIONS | Журнал, когда выделяются новые области |
AUTO_LOG_WEAK | Зарегистрируйте все манипуляции слабой ссылкой |
AUTO_LOG_ALL | Эквивалентный установке всех вышеупомянутых |
AUTO_REFERENCE_COUNT_LOGGING | Включает журналирование подсчета ссылок |
Собравшее «мусор» средство выделения памяти поддерживает некоторые другие потенциально полезные переменные окружения, как показано в Таблице 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.
Имя | Значение по умолчанию | Действие |
|---|---|---|
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 включенный.

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

Можно управлять продолжительностью флэш-памяти путем установки 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. |