Frage

Als Programmierübung, ich bin ein Mark-and-Sweep Garbage Collector in C. Ich wünsche Schreiben des Datensegments (Globals, etc.) scannen für Zeiger auf reservierten Speicher, aber ich weiß nicht, wie zu bekommen der Bereich der Adressen dieses Segments. Wie könnte ich das tun?

War es hilfreich?

Lösung

Die Grenzen für Text (Programmcode) und Daten für Linux (und andere Unix-Varianten):

#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;
}

Sind diese Symbole kommen aus: Wo sind die Symbole eText, edata und Ende definiert?

Andere Tipps

Wenn Sie unter Windows arbeiten, dann gibt es Windows-API, die Ihnen helfen würde.

//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++;
}

definieren ImageSectionInfo wie,

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); 
       }
};

Hier ist ein komplettes, minimal WIN32 Konsole Programm, das Sie in Visual Studio ausführen können, die die Verwendung des Windows-API demonstriert:

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

Diese Seite kann hilfreich sein, wenn Sie daran interessiert sind in zusätzlichen Verwendungen der DbgHelp Bibliothek.

Sie können das PE-Bildformat lesen Sie hier, es im Detail zu kennen. Sobald Sie das PE-Format verstehen, werden Sie mit dem obigen Code zu arbeiten können und es sogar ändern können Ihren Bedarf zu erfüllen.

  • PE-Format

Peering Im Inneren des PE: Eine Besichtigung des Win32 Portable Executable File Format

Eine eingehende Blick in die Win32 Portable Executable Datei-Format, Teil 1

Eine eingehende Blick in die Win32 Portable Executable Datei-Format, Teil 2

  • Windows-API und Strukturen

IMAGE_SECTION_HEADER Struktur

ImageNtHeader Funktion

IMAGE_NT_HEADERS Struktur

ich denke, das Sie zu großem Teil dazu beitragen würde, und der Rest können Sie sich selbst erforschen: -)

Durch die Art und Weise, können Sie auch diesen Thread sehen, wie alle diese irgendwie zu diesem Zusammenhang sind:

Szenario: Globale Variablen in DLL, die von Multi-threaded-Anwendung

verwendet wird,

Da Sie wahrscheinlich Ihre Garbage Collector machen müssen die Umgebung, in der das Programm ausgeführt wird, können Sie es von der Elf-Datei direkt erhalten.

Laden Sie die Datei, dass die ausführbare Datei herkommt und die PE-Header analysieren, für Win32. Ich habe keine Ahnung von auf anderen Betriebssystemen. Denken Sie daran, dass, wenn Ihr Programm besteht aus mehreren Dateien (z DLLs) mehrere Datensegmente haben.

scroll top