2011-10-11 14 views
5

He escrito varios programas y descubrí que cuando se compila en 64 bits, el segmento de mapeo de memoria (donde se guardan por ejemplo los objetos compartidos y la memoria compartida) siempre ubicado en algún lugar alrededor de 7f9aca84a000-7fff88400000 pero nunca exactamente igual.ELF64/x86_64 y la dirección de inicio del segmento de mapeo de memoria (para objetos compartidos)

Me gustaría saber si hay una dirección de inicio fijo para este segmento de memoria en la arquitectura x86_64 (ELF64) o cuál es el rango máximo y mínimo para este segmento?

He aquí por qué hago esta pregunta. Estamos migrando un sistema de Tru64 UNIX a Linux. Este sistema utilizó una asignación de memoria fija compleja de la memoria compartida IPC Sys V, y está utilizando una lista encadenada para ir de una estructura a otra dentro de este segmento. Con el tamaño y la complejidad de esta pieza de código, y el tiempo limitado que tenemos a mano, estamos tratando de encontrar una forma robusta de arreglar el inicio de la memoria compartida (utilizando efectivamente shmat con una dirección específica en la que adjuntar el segmento) Con 64 bits, el espacio de direcciones virtuales es tan grande (direcciones efectivamente posibles de 48 bits) que elegir una dirección fija "segura" es mucho más fácil y menos riesgoso que en 32 bits.

Respuesta

4

El diseño de asignación de memoria x86-64 se define en arch/x86/mm/mmap.c. Como puede ver, hay dos estrategias utilizadas: de arriba hacia abajo y de abajo hacia arriba.

La asignación descendente es la predeterminada. Comienza a 128 MB por debajo de la extensión máxima de la pila (según lo define la pila rlimit), ajustado por un desplazamiento aleatorio, y luego asigna mapeos posteriores hacia abajo en memoria desde allí.

Asignación ascendente es la reserva. Se usa si:

  • El stack rlimit es ilimitado;
  • El proceso tiene el conjunto de personalidad ADDR_COMPAT_LAYOUT; o
  • El vm.legacy_va_layout sysctl no es cero.

En la asignación ascendente, a las regiones asignadas se les asignan direcciones progresivamente más altas, comenzando en TASK_SIZE/3, ajustadas mediante un desplazamiento aleatorio. TASK_SIZE en x86-64 es 0x800000000000, por lo que las asignaciones ascendentes comenzarán alrededor de 0x2AAAAAAAAAAA.

Sugeriría un agujero adecuado para sus asignaciones fijas que debería estar bien bajo cualquiera de las estrategias de asignación es alrededor de 2 * TASK_SIZE/3 - Yo usaría 0x500000000000.

+0

Gracias por tal idea. Voy a mirar alrededor de toda la información que me indicaste. – Huygens

+0

así que no podemos dar nuestra propia dirección de inicio? – sdkie

3

No tengo una respuesta directa para usted (¡aún!), Pero puedo decir que he tenido éxito mapeando la memoria bien fuera de los rangos de memoria superiores. Por ejemplo:

#include <stdio.h> 
#include <sys/mman.h> 
#include <stdint.h> 

#define ADDRESS 0x700000000 

int main(int argc, char *argv[]) { 
    uint64_t *map = mmap((void *)ADDRESS, 4096, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 

    map[0] = 64; 

    printf("Value: %lu\n", map[0]); 

    munmap(map, 4096); 

    return 0; 
} 

Me temo que no tengo tiempo para mirar a través de la fuente del núcleo en el momento, pero que sin duda va a echar un vistazo más tarde. Siempre me he preguntado cuál fue la respuesta a esta pregunta. . .

+0

Gracias por la información, se utiliza una técnica similar en el código con System V IPC, establecemos una dirección especial al llamar a shmat. Consulte el extracto de la página man: si shmaddr no es NULL y SHM_RND está especificado en shmflg, la conexión se produce en la dirección igual a shmaddr redondeada al múltiplo más cercano de SHMLBA. De lo contrario, shmaddr debe ser una dirección alineada con la página en la que se produce la conexión. – Huygens

+0

La dificultad es determinar una dirección adecuada, como la que usted propone: 0x700000000. Y nos gustaría poder justificar claramente nuestra elección. – Huygens

4

¿Hay una dirección de inicio fija para mmaped segmentos?

No. Linux admite ASLR (aleatoriedad de diseño de espacio de direcciones), lo que significa que las direcciones en los programas tienen algún elemento de aleatoriedad. Esto es para hacer que algunos exploits tengan menos probabilidades de tener éxito. Además, probablemente algunos parches kernel implementen diferentes estrategias ASLR (lo hacen para x86 regular), piensen en PaX, exec-shield, ...

Entonces, si quiere usar una dirección fija, puede salirse con la suya usando MAP_FIXED , como se recomienda @Ethereal.

Cuestiones relacionadas