Delete old kernel* chapters.
This commit is contained in:
parent
07951ab095
commit
ca1745d9e6
Notes:
svn2git
2020-12-08 03:00:23 +00:00
svn path=/head/; revision=33274
2 changed files with 0 additions and 841 deletions
|
@ -1,625 +0,0 @@
|
|||
<!--
|
||||
The FreeBSD Documentation Project
|
||||
|
||||
The FreeBSD Spanish Documentation Project
|
||||
|
||||
%SOURCE% en_US.ISO8859-1/books/handbook/kerneldebug/chapter.sgml
|
||||
%SRCID% 0.0
|
||||
|
||||
|
||||
$FreeBSD$
|
||||
$FreeBSDes: doc/es_ES.ISO8859-1/books/handbook/kerneldebug/chapter.sgml,v 1.2 2004/10/08 22:14:26 jesusr Exp $
|
||||
-->
|
||||
|
||||
<chapter id="kerneldebug">
|
||||
<title>Depurando el Kernel</title>
|
||||
|
||||
<para><emphasis>Contribución de &a.paul; y &a.joerg;</emphasis></para>
|
||||
|
||||
<sect1>
|
||||
<title>Depuración de un Kernel Crash Dump con <command>kgdb</command></title>
|
||||
|
||||
<para>Aquí se dan instrucciones para hacer funcionar la depuración del
|
||||
kernel sobre un crash dump. En ellos se asume que usted tiene suficiente
|
||||
espacio de swap para un crash dump. Si usted tiene varias particiones
|
||||
de swap y la primera es demasiado pequeña para albergar un dump, puede
|
||||
configurar su kernel para que use un dispositivo alternativo (en la línea
|
||||
<literal>config kernel</literal>=, o puede especificar una alternativa
|
||||
usando el comando &man.dumpon.8;. La mejor manera de usar &man.dumpon.8;
|
||||
es asignar la variable <literal>dumpdev</literal> en
|
||||
<filename>/etc/rc.conf</filename>. Generalmente usted va a querer
|
||||
especificar uno de los dispositivos de swap especificados en
|
||||
<filename>/etc/fstab</filename>. Actualmente no se soportan dumps a
|
||||
dispositivos que no sean de swap, como por ejemplo una unidad de cinta.
|
||||
Configure su kernel usando <command>config -g</command>. Vea <link
|
||||
linkend="kernelconfig">Configuración del Kernel</link> para más detalles
|
||||
sobre la configuración del kernel FreeBSD.</para>
|
||||
|
||||
<para>Use el comando &man.dumpon.8; para decirle al kernel donde hacer
|
||||
el dump (Tenga en cuenta que esto debera hacerse luego de configurar
|
||||
la partición como dispositivo de swap usando &man.swapon.8;). Esto se
|
||||
hace normalmente usando los archivos <filename>/etc/rc.conf</filename>
|
||||
y <filename>/etc/rc</filename>. Como alternativa se puede fijar el
|
||||
dispositivo usando la cláusula <literal>dump</literal> en la línea
|
||||
<literal>config</literal> de su archivo de configuración del kernel.
|
||||
Esta práctica esta en desuso y sólo debería ser usada para obtener
|
||||
un dump de un kernel que falla durante el inicio.</para>
|
||||
|
||||
<note>
|
||||
<para>En adelante, el término <command>kgdb</command> se referirá al
|
||||
<command>gdb</command> corriendo en “kernel debug mode”.
|
||||
Esto puede lograrse ya sea iniciando al <command>gdb</command> con
|
||||
la opción <option>-k</option>, o enlazandolo y arrancandolo con el
|
||||
nombre <command>kgdb</command>. Esto no se hace por default, y
|
||||
la idea está basicamente en desuso ya que a la gente de GNU no le
|
||||
gusta que sus herramientas se comporten distinto cuando se las llama
|
||||
por otro nombre. Esta posibilidad podrá perfectamente ser descontinuada
|
||||
en futuras versiones.</para>
|
||||
</note>
|
||||
|
||||
<para>Una vez que el kernel ha sido compilado haga una copia, digamos
|
||||
<filename>kernel.debug</filename>, y luego corra <command>strip
|
||||
-g</command> sobre el original. Instale el original normalmente. Usted
|
||||
tambien podría instalar el kernel sin hacer el <command>strip</command>,
|
||||
pero los tiempos de busqueda de algunos programas en la tabla de
|
||||
símbolos aumentarán sensiblemente, y dado que el kernel se carga completo
|
||||
en memoria durante el inicio y no puede intercambiarse a disco luego,
|
||||
se desperdiciarán varios megabytes de memoria.</para>
|
||||
|
||||
<para>Si usted esta probando un nuevo kernel, por ejemplo tipeando el
|
||||
nombre del nuevo kernel en el prompt de inicio, pero necesita arrancar
|
||||
otro para tener su sistema funcionando de nuevo, arranquelo solo en modo
|
||||
monousuario usando la opción <option>-s</option> en el prompt de inicio
|
||||
, y luego siga los siguientes pasos:</para>
|
||||
|
||||
<screen>&prompt.root; <userinput>fsck -p</userinput>
|
||||
&prompt.root; <userinput>mount -a -t ufs</userinput> # asi su file system para /var/crash se puede escribir
|
||||
&prompt.root; <userinput>savecore -N /kernel.panicked /var/crash</userinput>
|
||||
&prompt.root; <userinput>exit</userinput> # ...a modo multiusuario</screen>
|
||||
|
||||
<para>Esto instruye a &man.savecore.8; que use otro kernel para la
|
||||
extracción de nombres de símbolo. De otro modo usaria el kernel en uso
|
||||
y probablemente no haga nada ya que los símbolos del kernel y los del
|
||||
dump son diferentes.</para>
|
||||
|
||||
<para>Ahora, luego de un crash dump, vaya a
|
||||
<filename>/sys/compile/WHATEVER</filename> y corra
|
||||
<command>kgdb</command>. desde <command>kgdb</command> haga:
|
||||
|
||||
<screen><userinput>symbol-file kernel.debug</userinput>
|
||||
<userinput>exec-file /var/crash/kernel.0</userinput>
|
||||
<userinput>core-file /var/crash/vmcore.0</userinput></screen>
|
||||
|
||||
y voila, ya puede depurar el crash dump usando las fuentes
|
||||
del kernel como lo hace con cualquier otro programa.</para>
|
||||
|
||||
<para>A continuación se muestra el log de una sesión de
|
||||
<command>kgdb</command> que ilustra el procedimiento. Las líneas
|
||||
fueron numeradas para referencia, y las largas fueron cortadas para
|
||||
mejorar la legibilidad. Mas alla de esto es el registro de un error real
|
||||
tomado durante el desarrollo del driver pcvt de consola.</para>
|
||||
|
||||
<screen> 1:Script started on Fri Dec 30 23:15:22 1994
|
||||
2:&prompt.root; <userinput>cd /sys/compile/URIAH</userinput>
|
||||
3:&prompt.root; <userinput>kgdb kernel /var/crash/vmcore.1</userinput>
|
||||
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:<prompt>(kgdb)</prompt> <userinput>where</userinput>
|
||||
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:<prompt>(kgdb)</prompt> <userinput>up 10</userinput>
|
||||
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:<prompt>(kgdb)</prompt> <userinput>frame frame->tf_ebp frame->tf_eip</userinput>
|
||||
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:<prompt>(kgdb)</prompt> <userinput>list</userinput>
|
||||
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:<prompt>(kgdb)</prompt> <userinput>print tp</userinput>
|
||||
53:Reading in symbols for ../../i386/i386/cons.c...done.
|
||||
54:$1 = (struct tty *) 0x1bae
|
||||
55:<prompt>(kgdb)</prompt> <userinput>print tp->t_line</userinput>
|
||||
56:$2 = 1767990816
|
||||
57:<prompt>(kgdb)</prompt> <userinput>up</userinput>
|
||||
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:<prompt>(kgdb)</prompt> <userinput>up</userinput>
|
||||
62:#2 0xf0132c34 in spec_open ()
|
||||
63:<prompt>(kgdb)</prompt> <userinput>up</userinput>
|
||||
64:#3 0xf012d014 in vn_open ()
|
||||
65:<prompt>(kgdb)</prompt> <userinput>up</userinput>
|
||||
66:#4 0xf012a183 in open ()
|
||||
67:<prompt>(kgdb)</prompt> <userinput>up</userinput>
|
||||
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:<prompt>(kgdb)</prompt> <userinput>up</userinput>
|
||||
75:Initial frame selected; you cannot go up.
|
||||
76:<prompt>(kgdb)</prompt> <userinput>quit</userinput>
|
||||
77:&prompt.root; <userinput>exit</userinput>
|
||||
78:exit
|
||||
79:
|
||||
80:Script done on Fri Dec 30 23:18:04 1994</screen>
|
||||
<para>Comentarios al listado anterior:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>línea 6:</term>
|
||||
|
||||
<listitem>
|
||||
<para>Este es un dump tomado desde el DDB (vea abajo), a partir del
|
||||
comentario del panic “because you said to!”, y un
|
||||
listado de la pila bastante largo; la razón incial para entrar al
|
||||
DDB fue un trap de falta de pagina.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>línea 20:</term>
|
||||
|
||||
<listitem>
|
||||
<para>Esta es la ubicación de la función <function>trap()</function>
|
||||
en el listado de la pila.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>línea 36:</term>
|
||||
|
||||
<listitem>
|
||||
<para>Se fuerza el uso de un nuevo marco de pila; esto ya no es
|
||||
necesario ahora. Actualmente se supone que los marcos de pila apuntan a
|
||||
las ubicaciones correctas, aun en caso de un trap. (No tengo un
|
||||
dump más nuevo a mano <g>, mi kernel no ha hecho un panic
|
||||
desde hace bastante tiempo.) Mirando al código en la línea 403
|
||||
del código fuente, hay una alta probabilidad de que la referencia
|
||||
al puntero “tp” sea erronea, o el acceso al arreglo
|
||||
estuviera fuera de sus límites.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>línea 52:</term>
|
||||
|
||||
<listitem>
|
||||
<para>El puntero se ve sospechoso, pero contiene una dirección
|
||||
válida.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>línea 56:</term>
|
||||
|
||||
<listitem>
|
||||
<para>De todos modos, obviamente apunta a basura, asi que encontramos
|
||||
nuestro error! (Para los que no esten familiarizados con esa pieza
|
||||
de código en particular: <literal>tp->t_line</literal> hace
|
||||
referencia a la disciplina de línea de este dispositivo de consola,
|
||||
el cual debe ser un entero por demás pequeño)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<title>Depurando un crash dump con DDD</title>
|
||||
|
||||
<para>Tambien es posible examinar un crash dump del kernel con un debugger
|
||||
gráfico como <command>ddd</command>. Agregue la opción <option>-k
|
||||
</option> a la línea de comando del <command>ddd</command> que usaría
|
||||
normalmente. Por ejemplo;</para>
|
||||
|
||||
<screen>&prompt.root; <userinput>ddd -k /var/crash/kernel.0 /var/crash/vmcore.0</userinput></screen>
|
||||
|
||||
<para>De esta manera usted debería poder analizar el crash dump usando
|
||||
la interfaz gráfica del <command>ddd</command>.</para>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<title>Analisis Post-mortem de un Dump</title>
|
||||
|
||||
<para>Que sucede si un kernel hace un dump de su memoria que usted
|
||||
no esperaba, y por lo tanto no estaba compilado usando <command>
|
||||
config -g</command>? No todo esta perdido aquí. Do not panic!</para>
|
||||
|
||||
<note>
|
||||
<para>N.del T.: El autor hace un juego con la palabra panic! que
|
||||
prefiero dejar sin traducir.</para>
|
||||
</note>
|
||||
|
||||
<para>Por supuesto, aun necesita habilitar los crash dumps. Vea más arriba
|
||||
las opciones que debe especificar para esto.</para>
|
||||
|
||||
<para>Vaya a su directorio de configuración del kernel
|
||||
(<filename>/usr/src/sys/<replaceable>arq</replaceable>/conf</filename>)
|
||||
y edite su archivo de configuración. Quite las marcas de comentario
|
||||
(o agregue, si no existe) la siguiente línea</para>
|
||||
|
||||
<programlisting>
|
||||
makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols</programlisting>
|
||||
|
||||
<para>Recompile el kernel. Algunos otros archivos seran recompilados,
|
||||
por ejemplo <filename>trap.o</filename>, a causa del cambio de la fecha
|
||||
del archivo Makefile. Con un poco de suerte, la opción <option>-g
|
||||
</option> no cambiará nada del código generado, al final usted tendra
|
||||
un kernel con el mismo código que tiene problemas ahora pero con ciertos
|
||||
símbolos para depuración. Por lo menos usted debería verificar el tamaño
|
||||
anterior y el nuevo con el comando &man.size.1;. Si hay diferencia
|
||||
probablemente sea el momento de darse por vencido.</para>
|
||||
|
||||
<para>Ahora puede examinar el dump como se describió anteriormente. Los
|
||||
símbolos pueden estar incompletos para algunas partes, como se puede ver
|
||||
en el listado de pila del ejemplo anterior donde algunas funciones
|
||||
se muestran sin numeros de línea ni listas de argumentos. Si necesita
|
||||
más símbolos borre los archivos objeto apropiados y repita la sesión de
|
||||
<command>kgdb</command> hasta que haya averiguado lo suficiente.</para>
|
||||
|
||||
<para>No se garantiza que todo esto funcione, pero irá bastante bien la
|
||||
en mayoría de los casos.</para>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<title>Depuración En-línea del Kernel Usando DDB</title>
|
||||
|
||||
<para>Si bien el <command>kgdb</command> provee un muy alto nivel de
|
||||
interfaz de usuario como depurador post-mortem, hay cosas que no puede
|
||||
hacer. Siendo las más importantes poder marcar puntos de interrupción
|
||||
y ejecutar código del kernel paso a paso.</para>
|
||||
|
||||
<para>Si usted necesita hacer una depuración a bajo nivel de su kernel hay
|
||||
disponible un debugger en-línea llamado DDB. Permite poner puntos de
|
||||
interrupción, ejecutar paso a paso las funciones del kernel, examinar y
|
||||
cambiar variables, etc. Sin embargo, no puede acceder al código fuente
|
||||
del kernel y sólo tiene acceso a los símbolos globales y estáticos, no
|
||||
a toda la información de depuración como el <command>kgdb</command>.</para>
|
||||
|
||||
<para>Para configurar su kernel para que incluya el DDB, agregue la opción
|
||||
|
||||
<programlisting>
|
||||
options DDB</programlisting>
|
||||
|
||||
a su archivo de configuración, y recompile (vea <link
|
||||
linkend="kernelconfig">Configuración del Kernel</link> para más
|
||||
detalles sobre como configurar el kernel de FreeBSD.)</para>
|
||||
|
||||
<note>
|
||||
<para>Notese que si usted tiene una versión vieja del boot block,
|
||||
sus símbolos de debugger podrían no ser cargados. Actualize su
|
||||
boot block; los mas recientes cargan los símbolos del DDB
|
||||
automágicamente.</para>
|
||||
</note>
|
||||
|
||||
<para>Una vez que su kernel con DDB esta corriendo, hay varias maneras
|
||||
de entrar al DDB. La primera y más temprana es tipear la opción
|
||||
<option>-d</option> directamente en el prompt de inicio. El kernel
|
||||
se iniciará en modo de depuración e ingresará al DDB antes de cualquier
|
||||
detección de dispositivos. De aquí en adelante usted podrá
|
||||
depurar hasta las funciones probe/attach de los dispositivos.</para>
|
||||
|
||||
<para>El segundo escenario es una combinación de teclas, generalmente
|
||||
Ctrl-Alt-Esc. En el caso de las syscons, esto puede modificarse,
|
||||
algunos mapas de teclado distribuidos lo hacen, por lo que hay que
|
||||
prestar atención. Hay disponible una opción para consolas en puertos
|
||||
serie que permite el uso de la señal BREAK en la línea para entrar al
|
||||
DDB (<literal>options BREAK_TO_DEBUGGER</literal> en el archivo de
|
||||
configuración del kernel). Esto no es el default ya que hay un montón
|
||||
de adaptadores serie dando vueltas que generan condiciones BREAK
|
||||
sin necesidad, por ejemplo cuando se desenchufa el cable.</para>
|
||||
|
||||
<para>La tercera forma es que un panic salte al DDB si el kernel está
|
||||
configurado para usarlo. Por este motivo, no es recomendable configurar
|
||||
un kernel con DDB para una máquina funcionando sin atención.</para>
|
||||
|
||||
<para>Los comandos del DDB se asemejan remotamente a algunos de los
|
||||
del <command>gdb</command>. Lo primero que usted probablemente
|
||||
necesite hacer es poner un punto de interrupción:</para>
|
||||
|
||||
<screen><userinput>b nombre-de-función</userinput>
|
||||
<userinput>b dirección</userinput></screen>
|
||||
|
||||
<para>Por default los números se toman en hexadecimal, pero para
|
||||
distinguirlos de los nombres de símbolo los números hexadecimales
|
||||
que empiezan con las letras <literal>a-f</literal> se deben preceder
|
||||
con <literal>0x</literal> (para los demás números esto es opcional).
|
||||
Tambien se admiten expresiones sencillas, por ejemplo:
|
||||
<literal>nombre-de-función + 0x103</literal>.</para>
|
||||
|
||||
<para>Para que el kernel interrumpido continue ejecutandose, solo
|
||||
tipee:</para>
|
||||
|
||||
<screen><userinput>c</userinput></screen>
|
||||
|
||||
<para>Para ver un listado de la pila, use:</para>
|
||||
|
||||
<screen><userinput>trace</userinput></screen>
|
||||
|
||||
<note>
|
||||
<para>Notese que cuando se entra al DDB con una combinación de teclas
|
||||
el kernel está atendiendo una interrupción, por lo que el listado
|
||||
de la pila podría no serle de mucha utilidad.</para>
|
||||
</note>
|
||||
|
||||
<para>Si quiere quitar un punto de interrupción, use</para>
|
||||
|
||||
|
||||
<screen><userinput>del</userinput>
|
||||
<userinput>del expresión-dirección-de-memoria</userinput></screen>
|
||||
|
||||
<para>La primera forma se aceptará inmediatamente despues de llegar
|
||||
a un punto de interrupción, y borra el punto actual. La segunda
|
||||
puede quitar cualquier punto de interrupción, pero se debe
|
||||
especificar la dirección exacta; esta se puede obtener de:</para>
|
||||
|
||||
<screen><userinput>show b</userinput></screen>
|
||||
|
||||
<para>Para ejecutar el kernel paso a paso, intente:</para>
|
||||
|
||||
<screen><userinput>s</userinput></screen>
|
||||
|
||||
<para>Esto entrará dentro de las funciones, pero puede hacer
|
||||
que DDB las siga hasta llegar a la instrucción de retorno
|
||||
correspondiente usando:</para>
|
||||
|
||||
<screen><userinput>n</userinput></screen>
|
||||
|
||||
<note>
|
||||
<para>Esto es distinto de la instrucción <command>next</command>
|
||||
del <command>gdb</command>; es más parecido a la instrucción
|
||||
<command>finish</command>.</para>
|
||||
</note>
|
||||
|
||||
<para>Para examinar los datos en la memoria use (por ejemplo):
|
||||
|
||||
<screen><userinput>x/wx 0xf0133fe0,40</userinput>
|
||||
<userinput>x/hd db_symtab_space</userinput>
|
||||
<userinput>x/bc termbuf,10</userinput>
|
||||
<userinput>x/s stringbuf</userinput></screen>
|
||||
|
||||
para acceder a palabras/medias palabras/bytes, y para mostrar
|
||||
en hexadecimal/decimal/caracteres/strings. El número luego de la coma
|
||||
es la cantidad de objetos. Para mostrar los siguientes 0x10
|
||||
items, simplemente use:</para>
|
||||
|
||||
<screen><userinput>x ,10</userinput></screen>
|
||||
|
||||
<para>Del mismo modo, use
|
||||
|
||||
<screen><userinput>x/ia foofunc,10</userinput></screen>
|
||||
|
||||
para desensamblar las primeras 0x10 instrucciones de
|
||||
<function>foofunc</function>, y mostrarlas junto con su
|
||||
desplazamiento desde el comienzo de <function>foofunc</function>.</para>
|
||||
|
||||
<para>Para modificar memoria, use el comando write:</para>
|
||||
|
||||
<screen><userinput>w/b termbuf 0xa 0xb 0</userinput>
|
||||
<userinput>w/w 0xf0010030 0 0</userinput></screen>
|
||||
|
||||
<para>El modificador
|
||||
(<literal>b</literal>/<literal>h</literal>/<literal>w</literal>)
|
||||
especifica el tamaño de los datos a ser escritos, la primera expresión
|
||||
a continuación es la dirección donde escribir y el resto es interpretado
|
||||
como datos para escribir en las direcciones de memoria sucesivas.</para>
|
||||
|
||||
<para>Si quiere conocer el valor actual de los registros del
|
||||
procesador, use:</para>
|
||||
|
||||
<screen><userinput>show reg</userinput></screen>
|
||||
|
||||
<para>O, puede mostrar un solo registro usando:
|
||||
|
||||
<screen><userinput>p $eax</userinput></screen>
|
||||
|
||||
y modificarlo haciendo:</para>
|
||||
|
||||
<screen><userinput>set $eax new-value</userinput></screen>
|
||||
|
||||
<para>Si usted quisiera llamar alguna función del kernel desde
|
||||
el DDB, solo debe decir:</para>
|
||||
|
||||
<screen><userinput>call func(arg1, arg2, ...)</userinput></screen>
|
||||
|
||||
<para>El valor devuelto será impreso en la pantalla.</para>
|
||||
|
||||
<para>Para un resumen de los procesos corriendo al estilo &man.ps.1;
|
||||
use:</para>
|
||||
|
||||
<screen><userinput>ps</userinput></screen>
|
||||
|
||||
<para>Usted ya ha examinado la causa de que su kernel falle, y quiere
|
||||
reiniciar su equipo. Recuerde que, dependiendo de lo severo de las
|
||||
fallas que ocurrieron, algunas partes del kernel podrían no funcionar
|
||||
como se espera. Siga una de las siguientes acciones para apagar y
|
||||
reiniciar su equipo:</para>
|
||||
|
||||
<screen><userinput>call diediedie()</userinput></screen>
|
||||
|
||||
<para>Esto causará que su kernel haga un crash dump y reinicie, asi
|
||||
luego podrá analizar el dump a un nivel más alto con el kgdb. Este
|
||||
comando suele tener que acompañarse por otra instrucción <command>
|
||||
continue</command>. Para hacer esto hay un alias:
|
||||
<command>panic</command>.</para>
|
||||
|
||||
<screen><userinput>call boot(0)</userinput></screen>
|
||||
|
||||
<para>La cual podría ser una buena manera de apagar ordenadamente el
|
||||
sistema, hacer un <function>sync()</function> de todos los discos,
|
||||
y finalmente reiniciar. En tanto las interfaces de disco y de
|
||||
filesystem del kernel no esten dañadas, esta podría ser una buena
|
||||
manera de hacer un apagado bastante prolijo.</para>
|
||||
|
||||
<screen><userinput>call cpu_reset()</userinput></screen>
|
||||
|
||||
<para>Es la ultima salida de los desastres y es practicamente lo
|
||||
mismo que presionar el Gran Boton Rojo.</para>
|
||||
|
||||
<para>Si usted necesita un breve sumario de los comandos, tipee:</para>
|
||||
|
||||
<screen><userinput>help</userinput></screen>
|
||||
|
||||
<para>De todos modos, es altamente recomendable tener una copia impresa
|
||||
de la página &man.ddb.4; del manual a mano antes de la sesión de
|
||||
depuración. Recuerde que es bastante difícil leer el manual en línea
|
||||
mientras se está ejecutando el kernel paso a paso.</para>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<title>Depuración En-Línea Usando El GDB remoto</title>
|
||||
|
||||
<para>Esta característica ha sido soportada desde FreeBSD 2.2, y ya está
|
||||
en verdad muy bien pulida.</para>
|
||||
|
||||
<para>El GDB ha soportado <emphasis>depuración remota</emphasis> desde
|
||||
hace mucho tiempo. Esto se hace usando un protocolo muy simple a
|
||||
traves de una línea serie. A diferencia de los otros metodos descriptos
|
||||
anteriormente, hacen falta dos máquinas para hacer esto. Una va a
|
||||
proveer el entorno de depuración, incluyendo todos los archivos fuente,
|
||||
y una copia del ejecutable del kernel con todos los símbolos y la otra
|
||||
será la máquina a depurar que simplemente corre una copia de exactamente
|
||||
el mismo kernel (pero sin los símbolos de depuración).</para>
|
||||
|
||||
<para>Usted debería configurar el kernel en cuestión con <command>config
|
||||
-g</command>, incluir <option>DDB</option> en la configuración, y
|
||||
compilarla como siempre. Esto arrojará un ejecutable enorme, debido a la
|
||||
información de depuración. Copie este kernel a la máquina a depurar,
|
||||
quitele los simbolos con <command>strip -x</command>, e inicielo usando
|
||||
la opción <option>-d</option> en el prompt de inicio. Conecte el primer
|
||||
puerto serie de la máquina a cualquier puerto serie de la máquina que
|
||||
correrá el debugger. Ahora en la máquina que corre el debugger, vaya al
|
||||
directorio de compilación del kernel a depurar, y arranque el gdb:</para>
|
||||
|
||||
<screen>&prompt.user; <userinput>gdb -k kernel</userinput>
|
||||
GDB is free software and you are welcome to distribute copies of it
|
||||
under certain conditions; type "show copying" to see the conditions.
|
||||
There is absolutely no warranty for GDB; type "show warranty" for details.
|
||||
GDB 4.16 (i386-unknown-freebsd),
|
||||
Copyright 1996 Free Software Foundation, Inc...
|
||||
<prompt>(kgdb)</prompt> </screen>
|
||||
|
||||
<para>Inicie la sesión de depuración remota haciendo
|
||||
(asumiendo que se usa el primer puerto serie):</para>
|
||||
|
||||
<screen><prompt>(kgdb)</prompt> <userinput>target remote /dev/cuaa0</userinput></screen>
|
||||
|
||||
<para>Ahora en la máquina a depurar (que entró al DDB justo antes de
|
||||
empezar a detectar los dispositivos), tipee:</para>
|
||||
|
||||
<screen>Debugger("Boot flags requested debugger")
|
||||
Stopped at Debugger+0x35: movb $0, edata+0x51bc
|
||||
<prompt>db></prompt> <userinput>gdb</userinput></screen>
|
||||
|
||||
<para>El DDB responderá diciendo:</para>
|
||||
|
||||
<screen>Next trap will enter GDB remote protocol mode</screen>
|
||||
|
||||
<para>Cada vez que tipee <command>gdb</command>, el modo se alternará
|
||||
entre el GDB remoto y el DDB local. Para forzar un siguiente trap
|
||||
inmediatamente, simplemente tipee <command>s</command> (avanza un paso).
|
||||
la máquina del debugger ahora ganará control sobre el kernel a depurar:
|
||||
</para>
|
||||
|
||||
<screen>Remote debugging using /dev/cuaa0
|
||||
Debugger (msg=0xf01b0383 "Boot flags requested debugger")
|
||||
at ../../i386/i386/db_interface.c:257
|
||||
<prompt>(kgdb)</prompt></screen>
|
||||
|
||||
<para>Esta sesión puede usarse casi como cualquier otra sesión de GDB,
|
||||
incluyendo acceso completo al código fuente, ejecutarlo en modo-gud
|
||||
dentro de una ventana de Emacs (lo cual brinda la posibilidad de
|
||||
mostrar automáticamente el código fuente en otra ventana de Emacs)
|
||||
etc.</para>
|
||||
|
||||
<para>El GDB remoto tambien puede usarse para depurar LKMs. Primero
|
||||
compile el LKM con los simbolos de depuración:</para>
|
||||
|
||||
<screen>&prompt.root; <userinput>cd /usr/src/lkm/linux</userinput>
|
||||
&prompt.root; <userinput>make clean; make COPTS=-g</userinput></screen>
|
||||
|
||||
<para>Luego instale esta versión del módulo en la máquina a depurar,
|
||||
carguelo y use <command>modstat</command> para averiguar donde fue
|
||||
cargado:</para>
|
||||
|
||||
<screen>&prompt.root; <userinput>linux</userinput>
|
||||
&prompt.root; <userinput>modstat</userinput>
|
||||
Type Id Off Loadaddr Size Info Rev Module Name
|
||||
EXEC 0 4 f5109000 001c f510f010 1 linux_mod</screen>
|
||||
|
||||
<para>Tome la dirección de carga (loadaddr) del módulo y sumele
|
||||
0x20 (probablemente para contar el encabezado a.out). Esta es la
|
||||
dirección donde el código del módulo fue reubicado. Use el comando
|
||||
<command>add-symbol-file</command> en el GDB para informarle al
|
||||
debugger acerca del módulo:</para>
|
||||
|
||||
<screen><prompt>(kgdb)</prompt> <userinput>add-symbol-file /usr/src/lkm/linux/linux_mod.o 0xf5109020</userinput>
|
||||
add symbol table from file "/usr/src/lkm/linux/linux_mod.o" at
|
||||
text_addr = 0xf5109020? (y or n) <userinput>y</userinput>
|
||||
<prompt>(kgdb)</prompt></screen>
|
||||
|
||||
<para>Ahora tiene acceso a todos los símbolos en el LKM.</para>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<title>Depurando Un Driver de Consola</title>
|
||||
|
||||
<para>Dado que el DDB necesita un driver de consola sobre el que correr,
|
||||
las cosas son mas complicadas si lo que falla es el propio driver de
|
||||
consola. Usted podría entonces recordar el uso de una consola en puerto serie
|
||||
(ya sea con un sector de inicio modificado, o especificando <option>-h
|
||||
</option> en el prompt <prompt>Boot:</prompt>) y colgar una terminal
|
||||
estándar en su primer puerto serie. El DDB funciona en cualquier
|
||||
driver de consola configurado, por supuesto tambien en una consola de
|
||||
puerto serie.</para>
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
<!--
|
||||
Local Variables:
|
||||
mode: sgml
|
||||
sgml-declaration: "../chapter.decl"
|
||||
sgml-indent-data: t
|
||||
sgml-omittag: nil
|
||||
sgml-always-quote-attributes: t
|
||||
sgml-parent-document: ("../book.sgml" "part" "chapter")
|
||||
End:
|
||||
-->
|
||||
|
|
@ -1,216 +0,0 @@
|
|||
<!--
|
||||
The FreeBSD Documentation Project
|
||||
|
||||
The FreeBSD Spanish Documentation Project
|
||||
|
||||
%SOURCE% en_US.ISO8859-1/books/handbook/kernelopts/chapter.sgml
|
||||
%SRCID% 0.0
|
||||
|
||||
|
||||
$FreeBSD$
|
||||
$FreeBSDes: doc/es_ES.ISO8859-1/books/handbook/kernelopts/chapter.sgml,v 1.2 2004/10/08 22:14:26 jesusr Exp $
|
||||
-->
|
||||
|
||||
<chapter id="kernelopts">
|
||||
<chapterinfo>
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>Jörg</firstname>
|
||||
<surname>Wunsch</surname>
|
||||
<contrib>Contribuido por </contrib>
|
||||
</author>
|
||||
</authorgroup>
|
||||
</chapterinfo>
|
||||
|
||||
<title>Añadiendo Opciones a la Configuración de un Nuevo Kernel</title>
|
||||
|
||||
<note>
|
||||
<para>Es importante que antes de leer este documento, usted este
|
||||
familiarizado con la sección de <link
|
||||
linkend="kernelconfig">configuració del kernel</link>.</para>
|
||||
</note>
|
||||
|
||||
<sect1>
|
||||
<title>¿Qué son las <emphasis>Opciones del Kernel</emphasis>?</title>
|
||||
|
||||
<para>Básicamente el uso de las opciones del kernel se
|
||||
encuentran descritas en la sección de <link
|
||||
linkend="kernelconfig-options">configuración del kernel</link>.
|
||||
También existe una explicación de opciones
|
||||
<quote>históricas</quote> y de <quote>nuevo-estilo</quote>. La
|
||||
meta final es que eventualmente todas las opciones soportadas por el
|
||||
kernel sean del nuevo-estilo, de tal forma que para las personas que
|
||||
acertadamente ejecutan <command>make depend</command> en el directorio
|
||||
de compilación de su kernel, después de ejecutar
|
||||
&man.config.8;, el proceso de compilación detectará
|
||||
automáticamente las opciones modificadas, y sólo
|
||||
recompilará los ficheros donde sea necesario. Eliminando el
|
||||
anterior directorio de compilación en cada ocasión que
|
||||
se ejecute &man.config.8; como es llevado a cabo ahora.</para>
|
||||
|
||||
<para>Básicamente, una opción del kernel no es otra cosa
|
||||
que la definición de un macro del preprocesador C para el
|
||||
proceso de compilación del kernel. Para efecto de hacer que la
|
||||
compilación sea realmente opcional, la parte que corresponde a
|
||||
la fuente del kernel (o bien el fichero kernel<filename>.h</filename>),
|
||||
debe ser escrita teniendo en mente, el uso de
|
||||
las opciones del kernel, por ejemplo, las opciones por omisión
|
||||
pueden modificarse con la opción config. Esto normalmente se
|
||||
lleva a cabo con algo como esto:</para>
|
||||
|
||||
<programlisting>#ifndef ESTA_OPCION
|
||||
#define ESTA_OPCION (algun_valor_por_default)
|
||||
#endif /* ESTA_OPCION */</programlisting>
|
||||
|
||||
<para>De esta forma cuando un administrador indica otro valor en su
|
||||
fichero de configuración, deja sin efecto el valor que se
|
||||
tiene originalmente por default, y lo substituye con este nuevo
|
||||
valor. Claramente el nuevo valor será utilizado como
|
||||
substituto en el código fuente, cuando el preprocesador se
|
||||
ejecute, por lo que debe de tratarse de una expresión
|
||||
válida para el lenguaje C, sin importar el contexto en el que
|
||||
se haya estado usando el valor por default.</para>
|
||||
|
||||
<para>También es posible crear opciones de menor valor, que
|
||||
simplemente habilitan o deshabilitan una parte particular del
|
||||
código, al encerrarlo en él</para>
|
||||
|
||||
<programlisting>#ifdef ESTA_OPCION
|
||||
|
||||
[su código aqui]
|
||||
|
||||
#endif</programlisting>
|
||||
|
||||
<para>Simplemente al incluir <literal>ESTA_OPCION</literal> en su
|
||||
fichero de configuración (con o sin valor alguno), activará
|
||||
la parte del código que haya ingresado.</para>
|
||||
|
||||
<para>Para la gente que este familiarizada con el lenguaje C, inmediatamente
|
||||
podrá darse cuenta de que todo pudiera ser tratado como una
|
||||
<quote>opción de configuración</quote>, donde cuando menos
|
||||
se tiene una simple referencia del tipo <literal>#ifdef</literal>...
|
||||
Por otro lado, es poco probable que alguien especifique</para>
|
||||
|
||||
<programlisting>options aunno,nodefinida</programlisting>
|
||||
|
||||
<para>en su fichero de configuración, y que posteriormente
|
||||
se pregunten por que fallo la compilación del kernel.</para>
|
||||
|
||||
<para>Es claro que, el uso de nombres arbitrarios para las opciones,
|
||||
hacen muy difícil el poder rastrear su uso en el código
|
||||
del kernel. Lo anterior es el razonamiento detrás del esquema
|
||||
de opciones de <emphasis>nuevo-estilo</emphasis>, donde cada opción
|
||||
se localiza en un fichero <filename>.h</filename> diferente dentro del
|
||||
directorio de compilación del kernel, los cuales por
|
||||
convicción son llamados
|
||||
<filename>opt_<replaceable>foo</replaceable>.h</filename>. De esta
|
||||
manera se pueden crear las dependencias dispuestas por Makefile, y el
|
||||
comando <command>make</command> puede determinar que debe ser
|
||||
recompilado, cuando una opción ha cambiado.</para>
|
||||
|
||||
<para>Aun con esto los mecanismos del estilo-viejo, tienen una ventaja
|
||||
para las opciones locales o quizás para las opciones de
|
||||
experimentación, que cuentan con un periodo de vida corto:
|
||||
en virtud de que es fácil añadir un nuevo
|
||||
<literal>#ifdef</literal> al código fuente del kernel, lo cual
|
||||
ya lo ha hecho una opción de configuración del kernel. En
|
||||
este caso, al utilizar esta opción, el administrador, es
|
||||
responsable por completo, al tener conocimiento de las implicaciones
|
||||
que tiene usarla (y probablemente el forzar la recompilación de
|
||||
ciertas partes del kernel). Una vez que la transición de
|
||||
todas las opciones soportadas por el kernel ha finalizado, &man.config.8;
|
||||
advertirá cuando una opción no soportada aparezca en el
|
||||
fichero de configuración, y no procederá a incluirlo
|
||||
en el fichero Makefile del kernel.</para>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<title>Ahora, ¿Qué Debo Hacer?</title>
|
||||
|
||||
<para>Lo primero es, editar el fichero <filename>sys/conf/options</filename>
|
||||
(o bien <filename>sys/<replaceable><arch></replaceable>/conf/options.
|
||||
<replaceable><arch></replaceable></filename>, por ejemplo;
|
||||
<filename>/sys/i386/conf/options.i386</filename>), y seleccionar un
|
||||
fichero <filename>opt_<replaceable>foo</replaceable>.h</filename> que
|
||||
mejor describa la nueva opción, para su inclusión.</para>
|
||||
|
||||
<para>Si ya existiese alguno, que se acerce al propósito de la
|
||||
nueva opción, debe elegir ese. Por ejemplo, opciones que
|
||||
modifiquen el comportamiento global del subsistema SCSI, pueden
|
||||
incluirse en <filename>opt_scsi.h</filename>. Por default, con el simple
|
||||
hecho de mencionar una opción en el fichero apropiado, digamos
|
||||
<literal>FOO</literal>, implica que el valor correspondiente a esta
|
||||
opción se localiza en el fichero correspondiente
|
||||
<filename>opt_foo.h</filename>. Por otro lado, esto puede modificarse
|
||||
al especificar el nombre de otro fichero.</para>
|
||||
|
||||
<para>Si el fichero
|
||||
<filename>opt_<replaceable>foo</replaceable>.h</filename> para la
|
||||
nueva opción no existiera, invente un nuevo nombre. Creelo de
|
||||
manera que sea intuitivo, con significado, y comente la nueva
|
||||
sección en el fichero
|
||||
<filename>options[<replaceable>.<arch></replaceable>]</filename>.
|
||||
En la ejecución de &man.config.8;, este automágicamente
|
||||
reconocerá los cambios, y creará ese fichero, la
|
||||
próxima vez que se ejecute. La mayoría de las opciones
|
||||
deberán incluirse como encabezados por si mismos..</para>
|
||||
|
||||
<para>El hecho de incluir muchas opciones, dentro de un solo fichero
|
||||
<filename>opt_<replaceable>foo</replaceable>.h</filename>,
|
||||
tendrá como resultado la creación de un buen numero de
|
||||
ficheros del kernel, durante la compilación, cuando sólo
|
||||
se haya realizado un cambio en alguna de las opciones del fichero de
|
||||
configuración del kernel, por esta
|
||||
razón es conveniente conservar cada opción en su
|
||||
propio fichero <filename>opt_</filename>.</para>
|
||||
|
||||
<para>Finalmente, averigue las dependencias que existen para la
|
||||
nueva opción. A menos que la nueva opción sea de
|
||||
nueva creación, y no exista en ninguna parte, la siguiente
|
||||
alternativa es su amiga, para efecto de encontrar dependencias:</para>
|
||||
|
||||
<screen>&prompt.user;
|
||||
<userinput>find /usr/src/sys -type f | xargs fgrep NUEVA_OPCION</userinput>
|
||||
</screen>
|
||||
|
||||
<para>El comando anterior dará como resultado un listado de
|
||||
ficheros que tienen dependecia, dirijase a todos esos ficheros y
|
||||
añada lo siguiente, en la parte <emphasis>superior</emphasis>
|
||||
(como encabezado), antes de todo lo que se refiere a
|
||||
<literal>#include <xxx.h></literal>.</para>
|
||||
|
||||
<programlisting>#include "opt_foo.h"</programlisting>
|
||||
|
||||
<para>El seguir este orden es de suma importancia, en virtud de que las
|
||||
opciones pueden modificar el comportamiento, por omisión, de los
|
||||
ficheros normales del tipo <quote>#include</quote>
|
||||
(N de T: librerís de encabezado), si
|
||||
estos son del tipo:</para>
|
||||
|
||||
<programlisting> #ifndef NUEVA_OPCION #define NUEVA_OPCION (algo)
|
||||
#endif</programlisting>
|
||||
|
||||
<para>El añadir una opción que substituye algún
|
||||
encabezado, en ficheros del sistema (por ejemplo; un fichero que se
|
||||
localiza en <filename>/usr/include/sys/</filename>) da como resultado
|
||||
casi siempre un error. El fichero <filename>opt_<replaceable>foo
|
||||
</replaceable>.h</filename> no puede ser incluido en esos ficheros,
|
||||
en virtud de que generaran un conflicto más serio, con sus
|
||||
propios encabezados, pero si no son incluidos, al momento de que se
|
||||
deseen utilizar, se puede obtener un valor inconsistente para esta
|
||||
opción. Si, existen antecedentes de esto en este momento,
|
||||
pero eso no lo hace más correcto.</para>
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
<!--
|
||||
Local Variables:
|
||||
mode: sgml
|
||||
sgml-declaration: "../chapter.decl"
|
||||
sgml-indent-data: t
|
||||
sgml-omittag: nil
|
||||
sgml-always-quote-attributes: t
|
||||
sgml-parent-document: ("../book.sgml" "part" "chapter")
|
||||
End:
|
||||
-->
|
||||
|
Loading…
Reference in a new issue