17

В качестве упражнения для программирования я пишу сборщик мусора маркировки и прокрутки в C. Я хочу отсканировать сегмент данных (глобалы и т. Д.) Для указателей на выделенную память, но Я не знаю, как получить диапазон адресов этого сегмента. Как я могу это сделать?Поиск диапазона адресов в сегменте данных

+4

Я бы сказал, что это зависит от ОС. – ruslik 2010-11-29 23:05:55

+0

Согласен, но есть ли способ получить это внутри программы, например, с помощью системного вызова? – Nick 2010-11-29 23:17:26

ответ

19

Границы для текста (программный код) и данные для Linux (и других Unixes):

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

Где эти символы приходят из: Where are the symbols etext ,edata and end defined?

0

Загрузите файл, из которого пришел исполняемый файл, и проанализируйте заголовки PE для Win32. Я понятия не имею о других ОС. Помните, что если ваша программа состоит из нескольких файлов (например, DLL), у вас может быть несколько сегментов данных.

1

Поскольку вам, вероятно, придется сделать ваш сборщик мусора средой, в которой работает программа, вы можете получить ее непосредственно из файла эльфа.

21

Если вы работаете в Windows, то есть это Windows API, который поможет вам.

//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, как,

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

Вот полный, минимальный WIN32 консольная программа, вы можете запустить в Visual Studio, который демонстрирует использование API 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 может быть полезными, если вы заинтересованы в дополнительном использовании библиотеки DbgHelp.

Здесь вы можете прочитать формат изображения PE, чтобы узнать его подробно. После того, как вы поймете формат PE, вы сможете работать с указанным выше кодом и можете даже модифицировать его в соответствии с вашими потребностями.

  • PE Формат

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 и структуры

IMAGE_SECTION_HEADER Structure

ImageNtHeader Function

IMAGE_NT_HEADERS Structure

Я думаю, что это поможет вам в значительной степени, а все остальное вы можете исследовать себя :-)

Кстати, вы также можете увидеть эта нить, так как все они как-то связаны с этим:

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

0

Для iOS вы можете использовать this solution. Он показывает, как найти диапазон сегмента текста, но вы можете легко изменить его, чтобы найти любой сегмент, который вам нравится.