2010-09-27 7 views
8

Estoy escribiendo un código que almacena algunas estructuras de datos en una sección binaria con un nombre especial. Estas son todas instancias de la misma estructura que están dispersas en muchos archivos C y no están dentro del alcance de la otra. Al colocarlos todos en la sección nombrada, puedo iterar sobre todos ellos.¿Cómo obtener un puntero a una sección binaria en MSVC?

En GCC, utilizo _ atributo _ ((sección (...)), además de algunos indicadores extern con nombres especiales que se llenan en mágicamente por el enlazador Aquí está un ejemplo trivial:.

#include <stdio.h> 

extern int __start___mysection[]; 
extern int __stop___mysection[]; 

static int x __attribute__((section("__mysection"))) = 4; 
static int y __attribute__((section("__mysection"))) = 10; 
static int z __attribute__((section("__mysection"))) = 22; 

#define SECTION_SIZE(sect) \ 
    ((size_t)((__stop_##sect - __start_##sect))) 

int main(void) 
{ 
    size_t sz = SECTION_SIZE(__mysection); 
    int i; 

    printf("Section size is %u\n", sz); 

    for (i=0; i < sz; i++) { 
     printf("%d\n", __start___mysection[i]); 
    } 

    return 0; 
} 

Estoy intentando averiguar cómo hacer esto en MSVC, pero estoy dibujando un espacio en blanco. Veo en la documentación del compilador que puedo declarar la sección usando __pragma (sección (...)) y declaro que los datos están en ese sección con __declspec (asignar (...)) pero no puedo ver cómo puedo obtener un puntero al inicio y al final de la sección en tiempo de ejecución.

He visto algunos ejemplos en la web relacionados con hacer _ atributo _ ((constructor)) en MSVC, pero parece una piratería específica de CRT y no una forma general de obtener un puntero al principio/final de un sección. ¿Alguien tiene alguna idea?

+0

¿Puedo preguntar por qué quieres controlar la nomenclatura de la sección binaria en primer lugar? – Reinderien

+0

Es para un marco de instrumentación de alto rendimiento. Imagine una invocación printf (formato, args ...), donde todas las cadenas de formato se almacenan en la sección binaria, y lo único que se registra son los argumentos más un valor de búsqueda. La sustitución de argumentos tiene lugar en el postprocesamiento. –

+0

Un mejor ejemplo de esto es un programa que le permite agregar módulos volviendo a vincular en lugar de recompilar (y posiblemente regenerar algún código). Si puede tratar toda la sección como una matriz de alguna estructura, puede iterar sobre ella y realizar alguna acción en/para cada entrada, como llamar a 'cur_entry [i] -> init (& cur_entry)'. También puede utilizar conocimientos especiales sobre patrones de uso de memoria para optimizar la localización y la ubicación del caché haciendo esto. No suele estar relacionado con Windows (que yo sepa) pero esto también puede ser necesario para los procesadores de arquitectura de Harvard. – nategoose

Respuesta

4

También hay una forma de hacerlo sin utilizar un archivo de ensamblaje.

#pragma section(".init$a") 
#pragma section(".init$u") 
#pragma section(".init$z") 

__declspec(allocate(".init$a")) int InitSectionStart = 0; 
__declspec(allocate(".init$z")) int InitSectionEnd = 0; 

__declspec(allocate(".init$u")) int token1 = 0xdeadbeef; 
__declspec(allocate(".init$u")) int token2 = 0xdeadc0de; 

La primera línea de 3 define los segmentos. Estos definen las secciones y toman el lugar del archivo de ensamblaje. A diferencia de data_seg pragma, la sección pragma solo crea la sección. Las líneas __declspec (allocate()) le dicen al compilador que coloque el elemento en ese segmento.

Desde la página de microsoft: El orden aquí es importante. 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 $.

Otro punto importante para recordar es que las secciones se completan 0 a 256 bytes. Los punteros START y END NO serán directamente antes y después, como era de esperar.

Si la configuración de la tabla sea punteros a funciones u otros valores NULL ninguno, debe ser fácil saltarse las entradas NULL antes y después de la tabla, debido a la sección de relleno

Ver this msdn page para más detalles

3

En primer lugar, usted tendrá que crear un ASM-archivo que contiene todas las secciones de su interés (por ej, section.asm.):

.686 
.model flat 

PUBLIC C __InitSectionStart 
PUBLIC C __InitSectionEnd 

INIT$A SEGMENT DWORD PUBLIC FLAT alias(".init$a") 
     __InitSectionStart EQU $ 
INIT$A ENDS 

INIT$Z SEGMENT DWORD PUBLIC FLAT alias(".init$z") 
     __InitSectionEnd EQU $ 
INIT$Z ENDS 

END 

A continuación, en el código que puede utilizar lo siguiente:

#pragma data_seg(".init$u") 
int token1 = 0xdeadbeef; 
int token2 = 0xdeadc0de; 
#pragma data_seg() 

Esto da una MAP-archivo de este tipo:

Start   Length  Name     Class 
0003:00000000 00000000H .init$a     DATA 
0003:00000000 00000008H .init$u     DATA 
0003:00000008 00000000H .init$z     DATA 

    Address   Publics by Value    Rva+Base  Lib:Object 
0003:00000000  [email protected]@3HA    10005000  dllmain.obj 
0003:00000000  ___InitSectionStart  10005000  section.obj 
0003:00000004  [email protected]@3HA    10005004  dllmain.obj 
0003:00000008  ___InitSectionEnd   10005008  section.obj 

lo tanto, como se puede ver, la sección con el nam e .init$u se coloca entre .init$a y .init$z y esto le da la capacidad de obtener el puntero al comienzo de los datos a través del símbolo __InitSectionStart y al final de los datos a través del símbolo __InitSectionEnd.

0

Estaba experimentando aquí un poco y traté de implementar la versión sin un archivo de ensamblaje, sin embargo estaba luchando con el número aleatorio de bytes de relleno entre las secciones, lo que hace que sea casi imposible encontrar el comienzo de la sección .init $ u parte si el contenido no es solo punteros u otros elementos simples que se pueden verificar para NULL o algún otro patrón conocido. Si se inserta el relleno parece correlacionarse con el uso de la opción de depuración Zi. Cuando se da, se inserta relleno, sin, todas las secciones aparecen exactamente en la forma en que a uno le gustaría tenerlas.

Cuestiones relacionadas