2012-04-05 14 views
5

Antecedentes: estoy asignando mis propios contextos de máquina y pilas con la familia de funciones getcontext(3)/makecontext(3)/setcontext(3) (ucontext.h; SUSv2, POSIX.1-2001).¿Cómo determina GDB la parte inferior de la pila?

Cuando uso gdb (versión 6.1.1) para examinar una pila mientras el hilo está en uno de estos contextos que he asignado, parece que gdb no sabe dónde está el final (parte inferior lógica) de la pila es. Por ejemplo, he aquí una pila de x86 FreeBSD:

#0 0x2872d79f in poll() from /lib/libc.so.7 
#1 0x28646e23 in poll() from /lib/libthr.so.3 
#2 0x2869b267 in fdtask (task=0x28a3dc40, v=0x0) at fd.c:58 
#3 0x2869c8dc in taskstart (y=681827392, x=0) at task.c:58 
#4 0x00000000 in ??() 
#5 0x28a3dc40 in ??() 
#6 0x00000000 in ??() 
#7 0x00000000 in ??() 
… 
#65 0x00000000 in ??() 
… 

(Sí, esto se construye encima de Russ Cox' libtask library.)

ejecución de este contexto comienza en la función taskstart, pero parece que el BGF no puede entender que debe dejar de tratar de leer la pila a pesar de que golpea una dirección de retorno de NULL en ese marco.

Mi pregunta es: ¿hay algo que pueda hacer (formateando la pila de alguna manera, o estableciendo un registro, cualquier cosa) para ayudar a GDB a entender dónde está la parte superior de la pila? Gracias.

Edición: Conclusión: parece que una forma en que gdb 6.1.1 detecta el final de la pila es comprobando que el puntero de cuadro almacenado sea NULO; Resolví el problema para mi caso de uso modificando la función x86 y amd64 makecontext(2) para restablecer ebp o rbp a cero al inicializar el nuevo contexto. (En este caso, no me importan otras arquitecturas.) Este problema desaparece con gdb 7.1; presumiblemente gdb 7.1 es capaz de detectar el final de la pila a través de otros medios, como debuginfo.

+1

esto suena como una pregunta que hacer sobre los desarrolladores de GDB lista de correo. –

Respuesta

2

Si GDB está utilizando punteros de marco para desenrollar la pila (método pre-DWARF2) se detiene cuando llega a un puntero de marco nulo, creo. Con DWARF2 las cosas son mucho más complicadas ya que el "puntero de marco" está implícitamente determinado por el puntero de pila combinado con el puntero de entrada y la información de desplazamiento de marco DWARF2 para la instrucción actual, pero esencialmente el efecto es el mismo. No estoy seguro de qué FreeBSD usa en estos días.

+0

Esto es bastante antiguo FreeBSD (~ 7.2, creo). ¡Gracias! –

+0

En cuanto a un desmontaje de 'taskstart', el framepointer se guarda en la entrada. Agregué el código para establecer ebp del contexto creado en cero y las huellas de pila de gdb 6.1.1 se ven correctas. ¡Gracias de nuevo! –

0

La documentación de gdb dice que una forma en que se detiene la enumeración de las tramas de traza inversa es después de la dirección de devolución de main().

Ver ftp://sourceware.org/pub/gdb/snapshots/current/gdb-7.4.50.20120405.tar.bz2 en GDB/doc/gdb.textinfo en línea @cindex backtrace beyond @code{main} function 6251.

+0

Claro, pero esto no es especialmente útil en mi situación porque ninguno de estos contextos comienza en 'main'. –

+0

@ConradMeyer: ¿Qué le parece nombrar la función que llama a 'taskstart' algo así como' main() ',' _main() ', o' __main() '? – wallyk

+0

Nada llama a 'taskstart'. Libtask schedular intercambia contextos de espacio de usuario en el contexto que comienza en 'taskstart'. Supongo que 'taskstart' podría renombrarse a' main' o '_main' o lo que sea, pero eso parece ser un gran kludge. Inicializar el puntero de marco a cero parece suficiente para que gdb6 detecte el final de la pila, y funcionará independientemente del nombre de la función inicial en el contexto. –

Cuestiones relacionadas