17

Als Programmierübung schreibe ich einen Mark-and-Sweep-Speicherbereiniger in C. Ich möchte das Datensegment (Globals usw.) nach Zeigern auf zugewiesenen Speicher durchsuchen, aber Ich weiß nicht, wie ich die Reichweite der Adressen dieses Segments ermitteln kann. Wie könnte ich das tun?Ermitteln des Adressbereichs des Datensegments

+4

Ich würde sagen, es ist Betriebssystem abhängig. – ruslik

+0

Ich stimme zu, aber gibt es eine Möglichkeit, dies in das Programm zu bekommen, wie bei einem Systemanruf? – Nick

+0

Wie können wir das beantworten, wenn Sie uns nicht sagen, was das System ist? – Puppy

Antwort

19

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

Wo diese Symbole kommen aus: Where are the symbols etext ,edata and end defined?

+0

brk() und sbrk() sind allgegenwärtig, aber nicht POSIX, von Entwurf. Das liegt daran, dass die Argumente implementiert sind. Überprüfen Sie Ihre Manpage für Details. –

+0

Da diese also das Ende jedes der drei Segmente darstellen, würden wir, um das Datensegment zu durchsuchen, von & etext nach & edata suchen, richtig? – Nick

+0

Wie skaliert das auf ein gemeinsames Objekt? Wenn ich ein So lade, hat es auch ein Daten- und ein BSS-Segment. Dieses Symbol wird in diesem Fall nicht funktionieren. Oder sie? Kannst du mich aufklären? – deadalnix

0

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

1

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

21

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

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

ImageSectionInfo definieren als,

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

This page kann hilfreich, wenn Sie an weiteren Verwendungen der DbgHelp-Bibliothek interessiert sind.

Sie können das PE-Bildformat hier lesen, um es im Detail zu wissen. Sobald Sie das PE-Format verstanden haben, können Sie mit dem obigen Code arbeiten und ihn sogar an Ihre Bedürfnisse anpassen.

  • PE Format

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

  • Windows-API und Strukturen

IMAGE_SECTION_HEADER Structure

ImageNtHeader Function

IMAGE_NT_HEADERS Structure

ich denke, das Sie zu großen Teil dazu beitragen würde, und der Rest kann man sich die Forschung :-)

By the way, können Sie auch sehen Dieser Thread, wie alle diese sind irgendwie damit zusammenhängen:

Scenario: Global variables in DLL which is used by Multi-threaded Application

0

Für iOS können Sie this solution verwenden. Es zeigt, wie man den Textsegmentbereich findet, aber Sie können es leicht ändern, um irgendein Segment zu finden, das Sie mögen.

Verwandte Themen