visual tools mod_wsgi microsoft for error descargar compiler c++ windows visual-c++ portable-executable

tools - microsoft visual c++ 9 python



Construcciones deterministas en Windows (4)

¿Hay alguna forma de forzar al compilador a usar rutas relativas, o engañarlo para que piense que el camino no es lo que es?

Tienes dos formas de hacer esto:

  1. Utilice el comando subst.exe y asigne una letra de unidad a la carpeta de compilación (esto puede no ser confiable).
  2. Si subst.exe no funciona, cree acciones para cada una de sus carpetas de compilación y use el comando "net use". Este seguramente debería funcionar.

En cualquier caso, vas a mapear y reutilizar la misma letra de unidad para una carpeta antes de comenzar una compilación en particular, de modo que la ruta parezca idéntica al compilador.

El objetivo final es comparar 2 binarios construidos de exactamente la misma fuente en el mismo entorno y poder decir que efectivamente son equivalentes funcionalmente.

Una aplicación para esto sería enfocar el tiempo de QA en cosas que realmente se cambiaron entre lanzamientos, así como el monitoreo de cambios en general.

MSVC en tándem con formato PE, naturalmente, hace que esto sea muy difícil de hacer.

Hasta ahora he encontrado y neutralizado esas cosas:

  • Marca de tiempo PE y suma de comprobación
  • Entrada de directorio de firma digital
  • Marca de tiempo de la sección del depurador
  • Firma PDB, edad y ruta del archivo
  • Marca de tiempo de recursos
  • Todas las versiones de archivo / producto en el recurso VS_VERSION_INFO
  • Sección de firma digital

Analizo PE, encuentro desplazamientos y tamaños para todas esas cosas e ignoro los rangos de bytes al comparar binarios. Funciona como el encanto (bueno, para las pocas pruebas que he ejecutado). Puedo decir que el ejecutable firmado con la versión 1.0.2.0 creada en Win Server 2008 es igual a uno sin firmar, de la versión 10.6.6.6, compilado en mi Win XP box, siempre que la versión del compilador y todas las fuentes y encabezados sean iguales. Esto parece funcionar para VC 7.1 - 9.0. (Para compilaciones de versiones)

Con una advertencia.

Los caminos absolutos para ambas construcciones deben ser iguales deben tener la misma longitud.

cl.exe convierte rutas relativas a rutas absolutas, y las coloca en objetos junto con indicadores de compilación, etc. Esto tiene efectos desproporcionados en todo el binario. Un cambio de carácter en la ruta dará como resultado que un byte cambie aquí y allá varias veces en toda la sección .text (independientemente de cuántos objetos haya vinculados, sospecho). Cambiar la longitud de la ruta da como resultado muchas más diferencias. Ambos en archivos obj y en binario vinculado.

Siente que la ruta del archivo con indicadores de compilación se usa como un tipo de hash, que lo convierte en binario vinculado o incluso afecta al orden de colocación de las partes no relacionadas del código compilado.

Así que aquí está la pregunta de 3 partes (resumida como "¿ahora qué?"):

  • ¿Debería abandonar todo el proyecto e irme a casa porque lo que estoy tratando de hacer rompe las leyes de la física y la política corporativa de la EM?

  • Suponiendo que manejo el problema de la ruta absoluta (a nivel de política o al encontrar una bandera de compilador mágico), ¿hay otras cosas que debería tener en cuenta? (cosas como __TIME__ significan código modificado, así que no me importa que no se ignoren)

  • ¿Hay alguna forma de forzar al compilador a usar rutas relativas, o engañarlo para que piense que el camino no es lo que es?

La razón del último es el sistema de archivos de Windows, que es muy molesto. Nunca se sabe cuando se borran varias gigas de fuentes y objetos y los metadatos svn fallarán debido a un bloqueo de archivos deshonestos. Al menos la creación de una nueva raíz siempre tiene éxito mientras queda espacio. Ejecutar múltiples compilaciones a la vez también es un problema. Ejecutar un montón de máquinas virtuales, mientras que una solución, es bastante pesada.

Me pregunto si hay una manera de configurar un sistema de archivos virtual para un proceso y sus hijos, de modo que varios árboles de proceso vean diferentes directorios "C: / build", privados para ellos solamente, todos al mismo tiempo ... Una luz virtualización de alto calibre ...

ACTUALIZACIÓN: recientemente abrimos la herramienta en GitHub . Ver la sección Comparar en la documentación.


Estandarizar las rutas de compilación

Una solución simple sería estandarizar en sus rutas de construcción, por lo que siempre son de la forma, por ejemplo:

c:/buildXXXX

Luego, cuando compara, digamos, build0434 con build0398 , simplemente preprocesa el binario para cambiar todas las ocurrencias de build0434 a build0398 . Elija un patrón que sepa que es poco probable que se muestre en su fuente / datos reales, excepto en aquellas cadenas que el compilador / vinculador integra en el PE.

Entonces puedes hacer tu análisis de diferencia normal. Al usar los mismos nombres de ruta de longitud, no desplazará ningún dato y causará falsos positivos.

Utilidad Dumpbin

Otro consejo es usar dumpbin.exe (se envía con MSVC). Use dumpbin / all para volcar todos los detalles de un binario en un volcado de texto / hex. Esto puede hacer que sea más obvio ver qué / dónde está cambiando.

Por ejemplo:

dumpbin /all program1.exe > program1.txt dumpbin /all program2.exe > program2.txt windiff program1.txt program2.txt

O use su herramienta favorita de diferenciación de texto, en lugar de Windiff.

Utilidad Bindiff

Puede encontrar útil la herramienta bindiff.exe de Microsoft, que se puede obtener aquí:

Herramientas de soporte de Windows XP Service Pack 2

Tiene una opción / v para indicarle que ignore ciertos campos binarios, tales como marcas de tiempo, sumas de comprobación, etc.

"BinDiff usa una rutina de comparación especial para archivos ejecutables de Win32 que enmascara varios campos de marca de tiempo de compilación en ambos archivos al realizar la comparación. Esto permite que dos archivos ejecutables se marquen como" Casi idénticos "cuando los archivos son verdaderamente idénticos, excepto el tiempo en que fueron construidos ".

Sin embargo, parece que ya está haciendo un superconjunto de lo que hace bindiff.exe.


¿Has intentado desmontar el ejecutable y comparar el desmontaje? Eso debería eliminar muchos de los detalles molestos que mencionas, y hacer que quitar los demás sea mucho más fácil.


Lo resolví en cierta medida.

Actualmente tenemos un sistema de compilación que asegura que todas las compilaciones nuevas estén en la ruta de longitud constante (compilaciones / 001, compilaciones / 002, etc.), evitando así los cambios en el diseño de PE. Después de compilar, una herramienta compara binarios antiguos y nuevos ignorando los campos PE relevantes y otras ubicaciones con cambios superficiales conocidos. También ejecuta algunas heurísticas simples para detectar cambios dinámicos ignorables. Aquí hay una lista completa de cosas para ignorar:

  • Marca de tiempo PE y suma de comprobación
  • Entrada de directorio de firma digital
  • Tabla de tiempos de exportación
  • Marca de tiempo de la sección del depurador
  • Firma PDB, edad y ruta del archivo
  • Marca de tiempo de recursos
  • Todas las versiones de archivo / producto en el recurso VS_VERSION_INFO
  • Sección de firma digital
  • MIDL vanity stub para bibliotecas de tipos incrustados (contiene cadena de marca de tiempo)
  • __FILE__, __DATE__ y __TIME__ macros cuando se usan como cadenas literales (puede ser un carácter ancho o angosto)

De vez en cuando, el vinculador haría algunas secciones PE más grandes sin tirar nada fuera de alineación. Parece que mueve el límite de la sección dentro del relleno, de todos modos hay ceros, pero debido a eso obtendré binarios con una diferencia de 1 byte.

ACTUALIZACIÓN: recientemente abrimos la herramienta en GitHub . Ver la sección Comparar en la documentación.