2009-03-05 13 views
6

Actualmente estoy trasladando un proyecto con unos pocos cientos de archivos de código y dependencias a varias bibliotecas de terceros a Mac Os. Finalmente llegué al punto en que el programa se compila sin advertencias ni errores, pero parece que no ejecuta mi propia función principal.¿Cómo encuentro la función principal (...) de mi programa?

En su lugar, parece ejecutar alguna otra función principal que parece pertenecer a un tercero. Esta función escribe algunos datos de aspecto de diagnóstico para la consola y sale después:

(gdb) continue 
Current language: auto; currently c++ 
// 
// This is an automatically generated file. 
// Do not edit. 
// 

const unsigned short expTable[] = 
{ 
    0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 
... 
    0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 
}; 

Debugger stopped. 
Program exited with status value:0. 

no puedo utilizar el depurador para averiguar dónde reside esta función principal, ya que, mientras que el seguimiento de la pila parece válido, el BGF no lo hace muéstrame el número de línea y el nombre de archivo correctos para cada entrada de pila (Ver this unsolved question para más detalles).

La búsqueda tardó varios minutos en completarse, pero no devolvió ningún resultado.

Mi proyecto está utilizando SDL entre otras bibliotecas, pero soy galardonado con SDL_Main() y los problemas subyacentes y he construido mi proyecto sobre una plantilla de proyecto SDL que funciona perfectamente bien. Así que estoy bastante seguro de que mi propia función principal es válida.

¿Tiene alguna idea de lo que podría estar yendo mal? Actualmente no tengo ideas sobre cómo encontrar y eliminar la función principal deshonesta.

Gracias,

Adrian

EDIT: Como acabo de descubrir, he cometido un error al buscar los archivos de archivos con la cadena "Este es un generan automáticamente". Acabo de encontrar varias docenas de archivos con la misma cadena, todos ellos pertenecientes a FreeImage, una de las bibliotecas de terceros que estoy usando. Entonces, el problema parece estar relacionado con FreeImage, pero aún no estoy seguro de cómo proceder, ya que he compilado Freeimage como una biblioteca con el archivo MacOs adjunto e incluido solo la biblioteca. Intentaré reconstruir una versión más nueva de FreeImage y la veré si eso solucionó mi problema.

+0

Supongo que su flujo es algo así como: gdb foo
b principal
r
¿correcto? – Hasturkun

+0

Normalmente ejecuto gdb a través de XCode, pero traté de usar gdb directamente como describió y obtuve los mismos resultados. –

Respuesta

8

¿Podría ser un inicializador para un objeto estático que falla antes de llamar a su main()?

+0

es decir, el constructor de un objeto global (para los no iniciados). +1 –

+0

Muy bien posible, pero con algunos cientos de archivos de código, ¿cómo puedo saberlo? –

+0

Ejecútelo en el depurador. Pon un punto de quiebre en terminate(). Vea de dónde se llama a terminación. –

1

¿Has intentado ejecutar tu ejecutable a través del nm? Es posible que pueda darle algunas pistas. No creo que sea posible vincular un programa con más de una función visible a nivel mundial llamada main(), no estoy seguro de cómo se logra eso.

+0

Acabo de hacer. Solo hay una función principal definida. También noté que nm localiza la función principal en una dirección diferente a gdb. Puede ser la dirección correcta, pero no estoy seguro de cómo verificarla. –

2

No estoy seguro de cómo encontrar el otro, pero puede especificar su propio punto de entrada explícitamente y hacer que el otro no se use. Puede usar la opción del enlazador GNU ld -e para establecer su punto de entrada.

entrada -e

--entry = entrada

Uso de entrada como el símbolo explícito para el comienzo de la ejecución de su programa de , más que el punto de entrada por defecto. Si no hay una entrada denominada sym- bol, el enlazador tratará de analizar la entrada como un número, y la usará como la dirección de entrada (el número se interpretará en la base 10; puede usar un 0x inicial para la base 16 , o un 0 líder para la base 8).

Para futuros lectores, si tiene este problema en Windows. La opción del vinculador equivalente es /ENTRY.

1

Mire a través de los archivos de encabezado que incluye y vea si no hay una definición que reasigne main a otra cosa. Este es un viejo truco para asegurar que se llame primero a la función principal de una biblioteca para hacer algo de configuración. Generalmente, eventualmente llamará a su función principal al referirse al valor redefinido.

+0

Sé que SDL hace esto (eso es lo que quiero decir con SDL_Main(), y parece que FreeImage también lo hace. Intentaré encontrar algo como esto en las fuentes de FreeImage. –

1

Un truco rápido:

readelf -s -w my_bin_file > temp.txt 

temp.txt abierta, búsqueda de principal (con FUNC en una columna) Ir arriba hasta encontrar la primera columna ARCHIVO - este es el archivo con el ligado principal.

editar: Esto solo funciona en los sabores y amigos de GNU Unix. OS X usa el formato Mach-O, no ELF.

+0

Esto se ve genial, pero yo soy usando MacOS X y yo no pudimos encontrar ninguna fuente readelf. Supongo que readelf por lo general viene preinstalado en las distribuciones de Linux? –

+0

Sí, viene con distribuciones de Linux. No tengo acceso a una Mac en este momento. Probablemente pueda instalarlo con fink. –

+0

con puerto mac, un puerto de búsqueda readelf no devuelve nada – claf

0

Sé que en C, puede tener un punto de entrada diferente llamado antes de la función principal, eso podría ser una idea. El código generalmente se ve así:

void __attribute__ ((constructor)) my_main(void); 

Tal vez pueda buscar algo así en su código.

En C, también hay diferentes formas de capturar la función principal y llamarla después de la principal "real". Algunas bibliotecas de hilos tienen este tipo de ataques para "preparar" el entorno, el programador y cosas así.

Esto no es realmente útil, pero esto puede explicar por qué su principal no se llama en absoluto.

Espero que esto ayude!

3

¿Tiene varias principales en el binario? Intente usar nm en él. (que no debería ser posible, ya que ld no va a enlazar con duplicados, pero ir a las librerías dinámicas y buscar allí _main)

nm a.out | grep -5 _main 

Esto debería dar 5 líneas antes y después de cualquier _main encontrado en el binaria a.out

Si tiene varios, ver los símbolos que rodean en busca de pistas que las partes que están en ...

el siguiente paso puede ser la de hacer lo mismo en cada lib dinámica que se utiliza. Para obtener una lista de las bibliotecas dinámicas utilizadas utilizan otool

otool -L a.out 
0

Otra nota.

WxWidgets hará también definir sus propias main

De here

Al igual que en todos los programas que debe haber una función "principal". En wxWidgets main se implementa utilizando esta macro, que crea una instancia de aplicación e inicia el programa.

IMPLEMENT_APP(MyApp)

0

Parece que puede tener un archivo llamado b44ExpLogTable.cpp compilado en el binario o algún thirdpart biblioteca. Parece que ese pequeño programa es para generar una tabla exp(), pero de alguna manera ha llegado a ser importados en su proyecto (s)

Ver this y esto a su FreeImage sources

0

Generar un archivo de mapa. La mayoría de los programas en realidad no comienzan en main. Un archivo de mapa de GCC debe indicarle la dirección de __start o __executable_start, que debería poder entrar y examinar para ver qué está causando que su programa salga.

+0

Desafortunadamente, esto no funciona si el depurador no funciona ... –

+0

Creo que quiere decir que agrega "-map my_map_file" al comando de enlace final. Si se utiliza "C++" o similar, puede usar "-Xlinker -map -Xlinker my_map_file" – epatel

+0

Incluso si no puede usar GDB (que puede, simplemente no se alinea con su fuente) ... siempre que Quiero ver qué hay en tu ejecutable generas un archivo de mapa. Siempre que quiera ver lo que está sucediendo, interrumpe la entrada del programa y el paso. Incluso si tiene que hacerlo en el montaje. –

Cuestiones relacionadas