Pregunta

Como un ejercicio de programación, estoy escribiendo un recolector de basura de marcaje y barrido en C. Deseo explorar el segmento de datos (variables globales, etc.) para los punteros a memoria asignada, pero no sé cómo llegar el rango de las direcciones de este segmento. ¿Cómo podría hacer esto?

¿Fue útil?

Solución

Los límites de 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 esos símbolos provienen de: Dónde están los símbolos eText, edata y al final define?

Otros consejos

Si está trabajando en Windows, entonces hay API de Windows que le ayudaría.

//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 una mínima programa completo, 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)
}

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

Puede leer el formato de imagen PE aquí, para saber en detalles. Una vez que entienda el formato PE, podrás trabajar con el código anterior, e incluso puede modificarlo para satisfacer sus necesidades.

  • Formato PE

asomándose al PE: Una gira por el portátil de formato de archivo ejecutable Win32

Una mirada en profundidad en el Win32 ejecutable portable Formato de archivo, Parte 1

Una mirada en profundidad en el Win32 ejecutable portable Formato de archivo, Parte 2

  • Windows API y Estructuras

Estructura IMAGE_SECTION_HEADER

ImageNtHeader Función

IMAGE_NT_HEADERS Estructura

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, ya que todos estos están relacionados de alguna manera a esto:

Escenario: Las variables globales en DLL que es utilizado por aplicación multi-hilo

Dado que es probable que tenga que hacer su recolector de basura del entorno en el que se ejecuta el programa, puede conseguirlo a partir del archivo ELF directamente.

Cargar el archivo ejecutable que el vino y analizar los encabezados PE, para Win32. No tengo ni idea acerca de otros sistemas operativos. Recuerde que si su programa se compone de varios archivos (por ejemplo DLL) que puede tener múltiples segmentos de datos.

Para iOS puede utilizar esta solución . Se muestra cómo encontrar el rango segmento de texto pero se puede cambiar fácilmente para encontrar cualquier segmento te gusta.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top