Pregunta

Imagine que desea escribir un programa que pone a prueba las funciones en un archivo DLL de C ++. Usted debe permitir al usuario seleccionar un archivo DLL (suponemos que estamos hablando de C ++ DLL). Él debe ser capaz de obtener una lista de todas las funciones exportadas por la DLL. A continuación, el usuario debe ser capaz de seleccionar un nombre de función de la lista, de forma manual de entrada de una lista de argumentos (los argumentos son todos los tipos básicos, como int, doble, bool o arrays char (por ejemplo, cadenas de tipo c)) y intento de ejecutar la función seleccionada con los argumentos especificados. A él le gustaría saber si la función se ejecuta con los argumentos especificados, o hacer que hacer que se caiga (porque no coinciden con la firma por ejemplo).

El problema principal es que C ++, al ser un lenguaje fuertemente tipado, requiere conocer el número y tipo de los argumentos a favor de una llamada de función en tiempo de compilación time.And en mi caso, simplemente no se que estos argumentos son , hasta que el usuario los selecciona en tiempo de ejecución.

La única solución que se me ocurrió, era utilizar el montaje de empujar manualmente los argumentos en la pila de llamadas.

Sin embargo, he llegado a comprender que si quiero echar a perder con el montaje, que será mejor que hacer absolutamente seguro de que sé lo que se llama a convención las funciones de la DLL utilizando.

Así que (por fin :) aquí está mi pregunta: ¿Se puede deducir la convención de llamada programmaticaly? Dependency Walker no me va a ayudar, y no tengo ni idea de cómo leer manualmente formato PE.

¿Fue útil?

Solución

La respuesta es tal vez .

Si los nombres de las funciones son C decoradas ++, entonces se puede determinar el número de argumentos y tipos de la decoración de nombres, esta es su mejor de los casos, y bastante probable si MSVC se utiliza para escribir el código en el primer lugar.

Si las funciones exportadas están llamando stdcall convención (el valor predeterminado para la API de Windows), puede determinar el número de bytes para ser empujado, pero no los tipos de los argumentos.

La mala noticia es que para C convención de llamada, no hay ninguna manera de decir mirando a los nombres de símbolos. Usted tendría que tener acceso al código fuente o la información de depuración.

http://en.wikipedia.org/wiki/X86_calling_conventions

El nombre que una función se da como una exportación no es requerida Para tener alguna relación con el nombre que el enlazador ve, pero la mayoría de las veces, el nombre exportado y el nombre del símbolo que la enlazador ve son los mismos.

Otros consejos

No se ha especificado si estamos hablando de 32 bits o 64 bits aquí, y las dificultades planteadas por usted y los otros carteles se aplican principalmente a código de 32 bits. En Windows de 64 bits, no hay esencialmente sólo una convención de llamada (está en también en el artículo de Wikipedia ligado por John Knoeller), lo que significa que hacer conocer la convención de llamada (por supuesto, con la excepción de nadie cocinar su propia).

Además, con los 64 bits de Microsoft convención de llamada, sin saber el número de parámetros de la función que se ha llamado no le impide llamar a ella, proporcionando tantos parámetros como desee / el usuario desea. Esto se debe a que como una persona que llama a un lado espacio de pila y limpiarlo después. -. Por supuesto, no proporcionar la derecha [número de] parámetros todavía puede tener la función llamada hacer cosas tontas, porque usted está proporcionando una entrada no válida, pero eso es otra historia

El código compilado no se limita a decir: 'Aquí esta función es una fastcall, y esto de aquí es stdcall' por desgracia.

Ni siquiera desensambladores modernos como la AIF tratan de deducir los tipos de llamada por defecto (que podría haber un plugin o una opción en algún lugar idk).

Básicamente, si usted es un ser humano cn vistazo a las primeras instrucciones y decirle a un 90% del tiempo. Si son pop y empuje, su stdcall, si sus parametros pasando a través de los registros (especialmente ECX) entonces su cdecl. Fastcall también utiliza los registros, pero hace algo especial .. No sé de la parte superior de la cabeza. Sin embargo, toda esta información es inútil porque su programa, obviamente, no va a ser un ser humano.

Si usted está haciendo las pruebas, no lo hace usted al menos tiene los archivos de cabecera ?? Esta es una manera muy difícil de pelar un gato ..

Si desea saber qué convención de llamada utiliza una función de C ++, su mejor esperanza es estudiar

  1. El encabezado que declara que la función y
  2. La documentación para el compilador que compila el archivo DLL en particular.

Pero todo esto suena como un poco de un desastre, la verdad. ¿Por qué su amigo quiere ser capaz de hacer esto, y por qué no puede obtener la información que necesita mediante el análisis de un encabezado que declara las funciones pertinentes?

Esta página describe la forma en VC ++ 6 codifica parámetro y la información convención de llamada en un nombre de símbolo: http://www.bottledlight.com/docs/mangle.html

Sospecho que las versiones posteriores de VC ++ serán compatibles pero no he confirmado esto.

También hay algunas herramientas que automatizan este que acompañan el compilador: http: //msdn.microsoft.com/en-us/library/5x49w699.aspx

El nombre mangling sólo se aplica para funciones de C ++; si una función es 'extern 'C'', entonces esto no funcionará.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top