Como ejercicio de programación, estoy escribiendo un recolector de basura con marca y barrido en C. Deseo escanear el segmento de datos (globales, etc.) para los punteros a la memoria asignada, pero No sé cómo obtener el rango de las direcciones de este segmento. ¿Cómo podría hacer esto?Encontrar el rango de direcciones del segmento de datos
Respuesta
Los límites para el texto (código de programa) y los datos para Linux (y otros sistemas Unix):
#include <stdio.h>
#include <stdlib.h>
/* these are in no header file, and on some
systems they have a _ prepended
These symbols have to be typed to keep the compiler happy
Also check out brk() and sbrk() for information
about heap */
extern char etext, edata, end;
int
main(int argc, char **argv)
{
printf("First address beyond:\n");
printf(" program text segment(etext) %10p\n", &etext);
printf(" initialized data segment(edata) %10p\n", &edata);
printf(" uninitialized data segment (end) %10p\n", &end);
return EXIT_SUCCESS;
}
Cuando estos símbolos provienen de: Where are the symbols etext ,edata and end defined?
brk() y sbrk() son omnipresentes, pero no POSIX, por diseño. Eso es porque los argumentos son implementación definida. Verifique su página de hombre para detalles. –
Entonces, dado que representan el final de cada uno de los tres segmentos, para buscar a través del segmento de datos buscaríamos desde & etext a & edata, ¿verdad? – Nick
¿Cómo se escala eso al objeto compartido? Si cargo uno, también tiene un segmento de datos y bss. Este símbolo no funcionará en ese caso. ¿O ellos? ¿Puedes iluminarme? – deadalnix
Cargue el archivo del que proviene el ejecutable y analice los encabezados PE, para Win32. No tengo idea sobre otros sistemas operativos. Recuerde que si su programa consta de varios archivos (por ejemplo, archivos DLL), puede tener múltiples segmentos de datos.
Dado que probablemente deba hacer de su recolector de basura el entorno en el que se ejecuta el programa, puede obtenerlo directamente desde el archivo elf.
Si está trabajando en Windows, entonces hay son API de Windows que te ayudarían.
//store the base address the loaded Module
dllImageBase = (char*)hModule; //suppose hModule is the handle to the loaded Module (.exe or .dll)
//get the address of NT Header
IMAGE_NT_HEADERS *pNtHdr = ImageNtHeader(hModule);
//after Nt headers comes the table of section, so get the addess of section table
IMAGE_SECTION_HEADER *pSectionHdr = (IMAGE_SECTION_HEADER *) (pNtHdr + 1);
ImageSectionInfo *pSectionInfo = NULL;
//iterate through the list of all sections, and check the section name in the if conditon. etc
for (int i = 0 ; i < pNtHdr->FileHeader.NumberOfSections ; i++)
{
char *name = (char*) pSectionHdr->Name;
if (memcmp(name, ".data", 5) == 0)
{
pSectionInfo = new ImageSectionInfo(".data");
pSectionInfo->SectionAddress = dllImageBase + pSectionHdr->VirtualAddress;
**//range of the data segment - something you're looking for**
pSectionInfo->SectionSize = pSectionHdr->Misc.VirtualSize;
break;
}
pSectionHdr++;
}
Definir ImageSectionInfo como,
struct ImageSectionInfo
{
char SectionName[IMAGE_SIZEOF_SHORT_NAME];//the macro is defined WinNT.h
char *SectionAddress;
int SectionSize;
ImageSectionInfo(const char* name)
{
strcpy(SectioName, name);
}
};
Aquí hay un programa completo, mínimo de consola Win32 puede ejecutar en Visual Studio que muestra el uso de la API de Windows:
#include <stdio.h>
#include <Windows.h>
#include <DbgHelp.h>
#pragma comment(lib, "dbghelp.lib")
void print_PE_section_info(HANDLE hModule) // hModule is the handle to a loaded Module (.exe or .dll)
{
// get the location of the module's IMAGE_NT_HEADERS structure
IMAGE_NT_HEADERS *pNtHdr = ImageNtHeader(hModule);
// section table immediately follows the IMAGE_NT_HEADERS
IMAGE_SECTION_HEADER *pSectionHdr = (IMAGE_SECTION_HEADER *)(pNtHdr + 1);
const char* imageBase = (const char*)hModule;
char scnName[sizeof(pSectionHdr->Name) + 1];
scnName[sizeof(scnName) - 1] = '\0'; // enforce nul-termination for scn names that are the whole length of pSectionHdr->Name[]
for (int scn = 0; scn < pNtHdr->FileHeader.NumberOfSections; ++scn)
{
// Note: pSectionHdr->Name[] is 8 bytes long. If the scn name is 8 bytes long, ->Name[] will
// not be nul-terminated. For this reason, copy it to a local buffer that's nul-terminated
// to be sure we only print the real scn name, and no extra garbage beyond it.
strncpy(scnName, (const char*)pSectionHdr->Name, sizeof(pSectionHdr->Name));
printf(" Section %3d: %p...%p %-10s (%u bytes)\n",
scn,
imageBase + pSectionHdr->VirtualAddress,
imageBase + pSectionHdr->VirtualAddress + pSectionHdr->Misc.VirtualSize - 1,
scnName,
pSectionHdr->Misc.VirtualSize);
++pSectionHdr;
}
}
// For demo purpopses, create an extra constant data section whose name is exactly 8 bytes long (the max)
#pragma const_seg(".t_const") // begin allocating const data in a new section whose name is 8 bytes long (the max)
const char const_string1[] = "This string is allocated in a special const data segment named \".t_const\".";
#pragma const_seg() // resume allocating const data in the normal .rdata section
int main(int argc, const char* argv[])
{
print_PE_section_info(GetModuleHandle(NULL)); // print section info for "this process's .exe file" (NULL)
}
This page puede ser útil si está interesado en usos adicionales de la biblioteca DbgHelp.
Aquí puede leer el formato de imagen PE, para conocerlo en detalle. Una vez que comprenda el formato PE, podrá trabajar con el código anterior e incluso modificarlo para satisfacer sus necesidades.
- PE Formato
Peering Inside the PE: A Tour of the Win32 Portable Executable File Format
An In-Depth Look into the Win32 Portable Executable File Format, Part 1
An In-Depth Look into the Win32 Portable Executable File Format, Part 2
- API de Windows y Estructuras
IMAGE_SECTION_HEADER Structure
creo que esto le ayudaría a gran medida, y el resto se puede investigar a sí mismo :-)
Por cierto, también se puede ver este hilo, como todos estos están de alguna manera relacionados con esto:
Scenario: Global variables in DLL which is used by Multi-threaded Application
Para iOS puede usar this solution. Muestra cómo encontrar el rango del segmento de texto, pero puede cambiarlo fácilmente para encontrar el segmento que desee.
- 1. ¿Cómo comparar el rango de direcciones IP en C#?
- 2. Rango de direcciones de una biblioteca cargada dinámicamente en Windows
- 3. Azure SQL Server Firewall Rango de direcciones IP
- 4. C#: Enumerar direcciones IP en un rango
- 5. Encontrar un rango de CoffeeScript
- 6. búsqueda de mysql para el segmento del nombre de tabla
- 7. Ensamblaje: utilizando el Registro de segmento de datos (DS)
- 8. Encontrar la frecuencia del rango de números en Mathematica
- 9. Cómo encontrar el rango con nombre de una celda - VSTO
- 10. Encontrar el LCM de un rango de números
- 11. Cambiar el color del control de segmento seleccionado
- 12. redirigida un rango de direcciones IP que utilizan RewriteCond
- 13. ¿Cómo puedo generar un rango de direcciones IP en Perl?
- 14. Punteros dentro del segmento de memoria compartida
- 15. Intersección del segmento de línea y línea
- 16. ELF64/x86_64 y la dirección de inicio del segmento de mapeo de memoria (para objetos compartidos)
- 17. errores Catching: datos JPEG corrupto: final prematuro del segmento de datos
- 18. datos y propagación perezoso en el árbol segmento
- 19. montón vs segmento de datos vs asignación de pila
- 20. Rangos de direcciones IPv6
- 21. cuán rápido es el segmento de python
- 22. ios: cómo encontrar el rango visible de texto en UITextView?
- 23. Detectando el segmento interceptado de un UISegmentedControl
- 24. Cómo convertir CIDR a la red y el rango de direcciones IP en C#?
- 25. ¿Existe un diseño común de la base de datos de direcciones para todas las direcciones del mundo?
- 26. dígitos del segmento en una imagen - Matlab
- 27. encontrar direcciones duplicadas en la base de datos, ¿evita que los usuarios las ingresen temprano?
- 28. configuración del segmento predeterminado en UISegmentedControl
- 29. PHPExcel tipo de datos establecido en el rango de celdas
- 30. ¿Qué pasaría si se cambia el registro del segmento CS?
Yo diría que depende del sistema operativo. – ruslik
Estoy de acuerdo, pero ¿hay alguna forma de obtener esto dentro del programa, como con una llamada al sistema? – Nick
¿Cómo podemos responder eso si no nos dice qué es el sistema? – Puppy