2010-07-07 10 views
5

Estoy luchando por convertir un C-programa vinculado con ld, de la cadena de herramientas gnu para que se compile como un proyecto visual-studio (2005). El programa pone .data-symbols en diferentes segmentos y durante una fase de inicialización copia datos entre segmentos. Los punteros al inicio y al final de los segmentos se definen en la secuencia de comandos ld linker.¿Cómo hacer referencia al inicio de un segmento definido por el usuario en un proyecto de Visual Studio?

entiendo cómo localizar las variables en los diferentes, definidos por el usuario segmentos, pero que no he sido capaz de encontrar la manera de definir las constantes de engarce como _start_of_my_segment o si hay algo similar a un guión enlazador en Visual Estudio.

Mi objetivo es ser capaz de compilar el programa con, prefferably no hay modificaciones en el código fuente que se refiere a los símbolos enlazador definidos, pero con mi propio diseño personalizado de los datos en el proyecto de Visual Studio .

A continuación se muestra algunos ejemplos de código C que ilustra lo que me gustaría hacer y una (reducidos al mínimo, posiblemente sintaxis incorrecta) versión del script maquillaje utilizado cuando se enlaza con gcc/ld.

¡Cualquier sugerencia sería muy apreciada!

#pragma data_seg("MY_DATA_FOO") 
#pragma data_seg("MY_DATA_BAR") 
#pragma comment(linker, "/section:MY_DATA_BAR,R") 

__declspec(allocate("MY_DATA_FOO")) int foo1; 
__declspec(allocate("MY_DATA_FOO")) int foo2; 

__declspec(allocate("MY_DATA_BAR")) int bar1 = 1; 
__declspec(allocate("MY_DATA_BAR")) int bar2 = 2; 

#pragma data_seg() 
void test() { 
    foo1 = bar1; 
    foo2 = bar2; 

    // i would rather do this as 
    //extern unsigned int __start_of_MY_DATA_FOO; 
    //extern unsigned int __start_of_MY_DATA_BAR; 
    //extern unsigned int __size_of_MY_DATA_BAR; 
    //memcpy(__start_of_MY_DATA_FOO, _start_of_MY_DATA_BAR, _size_of_MY_DATA_BAR); 
} 

Pseudo enlace-script (lo que sería el equivalente para Visual Studio

MEMORY 
{ 
    foo: org=0x1000, len=0x100 
    bar: org=0x2000, len=0x100 
} 

SECTIONS 
{ 
    GROUP: 
    { 
     MY_DATA_FOO : {} 
     __start_of_MY_DATA_FOO = ADDR(MY_DATA_FOO); 
     __end_of_MY_DATA_FOO = .; 
     __size_of_MY_DATA_FOO = SIZEOF(MY_DATA_FOO); 
    } > foo 

    GROUP: 
    { 
     MY_DATA_BAR : {} 
     __start_of_MY_DATA_BAR = ADDR(MY_DATA_BAR); 
     __end_of_MY_DATA_BAR = .; 
     __size_of_MY_DATA_BAR = SIZEOF(MY_DATA_BAR); 
    } > bar 
} 
+0

Esto es realmente algo que no se debe hacer. Seguramente hay formas portátiles de escribir el mismo programa. Parece que alguien pensó que era inteligente engañando con componentes internos de cadena de construcción de bajo nivel en lugar de usar C correctamente ... Está un paso por encima de suponer que puede acceder a variables locales desde una función llamada en su llamador después de que regrese ... –

+0

@ R .: Raras pero ocasionalmente decentes razones para usar este patrón. Lo he usado para agregar verificaciones de depuración. En versiones de lanzamiento, mis objetos son independientes y no se conocen entre sí. Pero para la depuración, lo hacen. La forma "legal C/C++" es un registro central para rastrear esto, hecho solo para la depuración, en realidad es mucho más mantenimiento para más de 200 cosas que este enfoque (este enfoque es automático). Por otro lado, la importabilidad es un costo diferente que esto trae. – VoidStar

Respuesta

0

Crear segmentos adicionales (que se colocan en la memoria por orden alfabético):

#pragma data_seg("MY_DATA_FOO__a") 
#pragma data_seg("MY_DATA_FOO__z") 
#pragma data_seg("MY_DATA_FOO__m") 

__declspec(allocate("MY_DATA_FOO__a")) int fooFirst; 
__declspec(allocate("MY_DATA_FOO__z")) int fooLast; 
__declspec(allocate("MY_DATA_FOO__m")) int foo1; 
__declspec(allocate("MY_DATA_FOO__m")) int foo2; 

luego copiar todo lo que entre & fooFirst y & fooLast.

+0

Gracias por la sugerencia. Sin embargo, cuando lo intento, la dirección de fooFirst NO es menor que fooLast, y el & foo1 es mayor que & fooLast. También parece haber algo de relleno para alinear los segmentos a incluso 0x1000 bloques. Esto podría ser ajustable mediante algunos ajustes de compilador y enlazador. ¿Alguna pista sobre qué configuración usaste? – ara

+0

¡Gracias de nuevo! Encontré un ejemplo del truco que sugieres en el documento para #pragma init_seg (aquí http://msdn.microsoft.com/en-us/library/7977wcck.aspx). Dice "Los nombres de las secciones deben tener 8 caracteres o menos.Las secciones con el mismo nombre antes de $ se combinan en una sección. El orden en que se combinan se determina ordenando los caracteres después de $. " Y, cuando cambié los nombres de las secciones a" MY_DATA_FOO $ a "etc. terminaron correctamente ordenados. Sin embargo, el tamaño de cada sección sigue siendo cero -padded hasta aproximadamente 0x100 bytes lo que hace difícil saber el final "apropiado" del segmento. – ara

+0

Aquí hay un ejemplo de fuentes ATL: sección #pragma ("ATL $ __ a", lectura, compartida) sección #pragma ("ATL $ __ z", leído, compartido) #pragma section ("ATL $ __ m", leído, compartido) Pruebe la sección en lugar de data_seg. –

3

el relleno puede ser removido por segmentos que se fusionan

por ejemplo

#pragma data_seg(".foo_begin") 
#pragma data_seg(".foo_data") 
#pragma data_seg(".foo_end") 

#pragma comment(linker, "/merge:.foo_begin=.foo") 
#pragma comment(linker, "/merge:.foo_data=.foo") 
#pragma comment(linker, "/merge:.foo_end=.foo") 

__declspec(allocate(".foo_begin")) int foo_begin_marker; 
__declspec(allocate(".foo_end")) int foo_end_marker; 

__declspec(allocate(".foo_data")) int foo_data; 
+1

¡Gracias! Sin embargo, todavía obtengo un relleno de 0x100 bytes entre las variables (¿no?). Sin el comando merge, el relleno tiene 0x1000 bytes y los segmentos terminan en el orden incorrecto, por lo que el comando merge tiene algún efecto y parece igualmente útil que el otro enfoque (usando $ en los nombres de sección). – ara

Cuestiones relacionadas