| |
Текст предоставили Paul Richards <paul@FreeBSD.org>
и
Jörg Wunsch <joerg@FreeBSD.org>
Вот некоторые указания по работе с отладкой ядра с аварийными дампами памяти. Как правило, вам нужно будет задать одно из устройств подкачки, перечисленных в файле /etc/fstab. Сброс образов памяти на устройства, не являющиеся устройствами подкачки, например, ленты, в данный момент не поддерживаются.
Note: Используйте команду dumpon(8) для указания ядру места, где нужно сохранять аварийные дампы. После настройки по команде swapon(8) раздела подкачки должна быть вызвана программа dumpon. Обычно это выполняется заданием переменной dumpdev в файле rc.conf(5). Если задана эта переменная, то после сбоя при первой многопользовательской перезагрузке будет автоматически запущена программа savecore(8). Она сохранит аварийный дамп ядра в каталог, заданный в переменной dumpdir файла rc.conf. По умолчанию каталогом для аварийных дампов является /var/crash.
Либо вы можете задать устройство для сброса образа памяти явно через параметр dump в строке config конфигурационного файла вашего ядра. Такой способ использовать не рекомендуется и он должен использоваться, только если вы хотите получать аварийные образы памяти ядра, которое аварийно завершает свою работу при загрузке.
Note: Далее термин gdb означает отладчик gdb, запущенный в ``режиме отладки ядра''. Переход в этот режим достигается запуском gdb с параметром -k. В режиме отладки ядра gdb изменяет своё приглашение на (kgdb).
Tip: Если вы используете FreeBSD версии 3 или более раннюю, вы должны выполнить усечение отладочного ядра командой strip, а не устанавливать большое отладочное ядро:
# cp kernel kernel.debug # strip -g kernelЭтот шаг не так уж и необходим, но рекомендуем. (Во FreeBSD 4 и более поздних релизах этот шаг выполняется автоматически в конце процесса построения ядра make.) Когда ядро усечено, автоматически или при помощи команд выше, вы можете установить его обычным образом, набрав make install.
Заметьте, что в старых версиях FreeBSD (до 3.1, не включая этот релиз), используется ядра в формате a.out, поэтому их таблицы символов должны располагаться постоянно в памяти. С большой таблицей символов в не усеченном отладочном ядре это излишняя трата. Последние релизы FreeBSD используют ядра в формате ELF, где это не является проблемой.
Если вы тестируете новое ядро, скажем, набирая имя нового ядра в приглашении загрузчика, но вам нужно загружать и работать с другим ядром, чтобы снова вернуться к нормальному функционированию, загружайте его только в однопользовательском режиме при помощи флага -s, указываемого при загрузке, а затем выполните такие шаги:
# fsck -p # mount -a -t ufs # so your filesystem for /var/crash is writable # savecore -N /kernel.panicked /var/crash # exit # ...to multi-user
Эта последовательность указывает программе savecore(8) на использование другого ядра для извлечения символических имен. Иначе она будет использовать ядро, работающее в данный момент и, скорее всего, ничего не сделает, потому что аварийный образ памяти и символы ядра будут отличаться.
А теперь, после сброса аварийного дампа, перейдите в каталог /sys/compile/WHATEVER и запустите команду gdb -k. Из программы gdb сделайте вот что:
symbol-file kernel.debug exec-file /var/crash/kernel.0 core-file /var/crash/vmcore.0и вуаля - вы можете отлаживать аварийный дамп, используя исходные тексты ядра точно также, как вы это делаете с любой другой программой.
Вот журнал команд сеанса работы gdb, иллюстрирующий эту процедуру. Длинные строки были разорваны для улучшения читабельности и для удобства строки были пронумерованы. Все остальное является трассировкой ошибки, реально возникнувшей во время работы над драйвером консоли pcvt.
1:Script started on Fri Dec 30 23:15:22 1994 2:# cd /sys/compile/URIAH 3:# gdb -k kernel /var/crash/vmcore.1 4:Reading symbol data from /usr/src/sys/compile/URIAH/kernel ...done. 5:IdlePTD 1f3000 6:panic: because you said to! 7:current pcb at 1e3f70 8:Reading in symbols for ../../i386/i386/machdep.c...done. 9:(kgdb) where 10:#0 boot (arghowto=256) (../../i386/i386/machdep.c line 767) 11:#1 0xf0115159 in panic () 12:#2 0xf01955bd in diediedie () (../../i386/i386/machdep.c line 698) 13:#3 0xf010185e in db_fncall () 14:#4 0xf0101586 in db_command (-266509132, -266509516, -267381073) 15:#5 0xf0101711 in db_command_loop () 16:#6 0xf01040a0 in db_trap () 17:#7 0xf0192976 in kdb_trap (12, 0, -272630436, -266743723) 18:#8 0xf019d2eb in trap_fatal (...) 19:#9 0xf019ce60 in trap_pfault (...) 20:#10 0xf019cb2f in trap (...) 21:#11 0xf01932a1 in exception:calltrap () 22:#12 0xf0191503 in cnopen (...) 23:#13 0xf0132c34 in spec_open () 24:#14 0xf012d014 in vn_open () 25:#15 0xf012a183 in open () 26:#16 0xf019d4eb in syscall (...) 27:(kgdb) up 10 28:Reading in symbols for ../../i386/i386/trap.c...done. 29:#10 0xf019cb2f in trap (frame={tf_es = -260440048, tf_ds = 16, tf_\ 30:edi = 3072, tf_esi = -266445372, tf_ebp = -272630356, tf_isp = -27\ 31:2630396, tf_ebx = -266427884, tf_edx = 12, tf_ecx = -266427884, tf\ 32:_eax = 64772224, tf_trapno = 12, tf_err = -272695296, tf_eip = -26\ 33:6672343, tf_cs = -266469368, tf_eflags = 66066, tf_esp = 3072, tf_\ 34:ss = -266427884}) (../../i386/i386/trap.c line 283) 35:283 (void) trap_pfault(&frame, FALSE); 36:(kgdb) frame frame->tf_ebp frame->tf_eip 37:Reading in symbols for ../../i386/isa/pcvt/pcvt_drv.c...done. 38:#0 0xf01ae729 in pcopen (dev=3072, flag=3, mode=8192, p=(struct p\ 39:roc *) 0xf07c0c00) (../../i386/isa/pcvt/pcvt_drv.c line 403) 40:403 return ((*linesw[tp->t_line].l_open)(dev, tp)); 41:(kgdb) list 42:398 43:399 tp->t_state |= TS_CARR_ON; 44:400 tp->t_cflag |= CLOCAL; /* cannot be a modem (:-) */ 45:401 46:402 #if PCVT_NETBSD || (PCVT_FREEBSD >= 200) 47:403 return ((*linesw[tp->t_line].l_open)(dev, tp)); 48:404 #else 49:405 return ((*linesw[tp->t_line].l_open)(dev, tp, flag)); 50:406 #endif /* PCVT_NETBSD || (PCVT_FREEBSD >= 200) */ 51:407 } 52:(kgdb) print tp 53:Reading in symbols for ../../i386/i386/cons.c...done. 54:$1 = (struct tty *) 0x1bae 55:(kgdb) print tp->t_line 56:$2 = 1767990816 57:(kgdb) up 58:#1 0xf0191503 in cnopen (dev=0x00000000, flag=3, mode=8192, p=(st\ 59:ruct proc *) 0xf07c0c00) (../../i386/i386/cons.c line 126) 60: return ((*cdevsw[major(dev)].d_open)(dev, flag, mode, p)); 61:(kgdb) up 62:#2 0xf0132c34 in spec_open () 63:(kgdb) up 64:#3 0xf012d014 in vn_open () 65:(kgdb) up 66:#4 0xf012a183 in open () 67:(kgdb) up 68:#5 0xf019d4eb in syscall (frame={tf_es = 39, tf_ds = 39, tf_edi =\ 69: 2158592, tf_esi = 0, tf_ebp = -272638436, tf_isp = -272629788, tf\ 70:_ebx = 7086, tf_edx = 1, tf_ecx = 0, tf_eax = 5, tf_trapno = 582, \ 71:tf_err = 582, tf_eip = 75749, tf_cs = 31, tf_eflags = 582, tf_esp \ 72:= -272638456, tf_ss = 39}) (../../i386/i386/trap.c line 673) 73:673 error = (*callp->sy_call)(p, args, rval); 74:(kgdb) up 75:Initial frame selected; you cannot go up. 76:(kgdb) quit 77:# exit 78:exit 79: 80:Script done on Fri Dec 30 23:18:04 1994
Комментарии к вышеприведенному журналу:
Это дамп, взятый при помощи DDB (смотри ниже), поэтому комментарий к аварийному останову имеет именно вид ``because you said to!'' и трассировка стека глубока; однако изначальной причиной перехода в DDB была аварийная остановка при возникновению ошибки страницы памяти.
Это местонахождение функции trap()
в трассировке
стека.
Принудительное использование новой границы стека; теперь это не нужно. Предполагается, что границы стека указывают на правильное расположение, даже в случае аварийного останова. Глядя на строку исходного кода 403, можно сказать, что весьма вероятно, что либо виноват доступ по указателю ``tp'', либо был выход за границы массива.
Похоже, что виноват указатель, но он является допустимым адресом.
Однако, очевидно, что он указывает на мусор, так что мы нашли нашу ошибку! (Для тех, кто не знаком с этой частью кода: tp->t_line служит для хранения режима канала консольного устройства, и это должно быть достаточно маленькое целое число.)
Этот, и другие документы, могут быть скачаны с ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.
По вопросам связанными с FreeBSD, прочитайте документацию прежде чем писать в <questions@FreeBSD.org>.
По вопросам связанным с этой документацией, пишите <doc@FreeBSD.org>.
По вопросам связанным с русским переводом документации, пишите <frdp@FreeBSD.org.ua>.
Закладки на сайте Проследить за страницей |
Created 1996-2024 by Maxim Chirkov Добавить, Поддержать, Вебмастеру |