Encontrar el rango de direcciones del segmento de datos

Como ejercicio de progtwigció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?

Los límites para texto (código de progtwig) y datos para Linux (y otros unixes):

#include  #include  /* 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; } 

De dónde provienen esos símbolos: ¿dónde se definen los símbolos etext, edata y end?

Si estás trabajando en Windows, entonces hay una API de Windows que te puede ayudar.

 //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 progtwig de consola WIN32 completo y mínimo que puede ejecutar en Visual Studio que demuestra el uso de la API de Windows:

 #include  #include  #include  #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) } 

Esta página puede ser útil si está interesado en usos adicionales de la biblioteca DbgHelp.

Puede leer el formato de imagen PE aquí, 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.

  • Formato PE

Peering dentro del PE: un recorrido por el formato de archivo ejecutable portátil Win32

Una mirada profunda al formato de archivo ejecutable portátil Win32, parte 1

Una mirada a fondo en el formato de archivo ejecutable portátil Win32, Parte 2

  • API y estructuras de Windows

IMAGE_SECTION_HEADER Estructura

Función ImageNtHeader

IMAGE_NT_HEADERS Estructura

Creo que esto te ayudará en gran medida, y el rest puedes investigarte a ti mismo 🙂

Por cierto, también puedes ver este hilo, ya que todos estos están de alguna manera relacionados con esto:

Escenario: variables globales en DLL que utiliza la aplicación de subprocesos múltiples

Dado que probablemente deba hacer de su recolector de basura el entorno en el que se ejecuta el progtwig, puede obtenerlo directamente del archivo elf.

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 progtwig consta de varios archivos (por ejemplo, DLL) puede tener múltiples segmentos de datos.

Para iOS puedes usar esta solución . Muestra cómo encontrar el rango del segmento de texto, pero puede cambiarlo fácilmente para encontrar el segmento que desee.