查找数据段的地址范围

作为编程练习,我在C中编写了一个标记 – 清除垃圾收集器。我希望扫描数据段(全局等)以获得指定内存的指针,但我不知道如何获取该段的地址。 我怎么能这样做?

linux(和其他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; } 

这些符号来自哪里 : 符号etext,edata和end定义在哪里?

如果您正在使用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中运行,演示如何使用Windows API:

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

如果您对DbgHelp库的其他用途感兴趣, 此页面可能会有所帮助。

您可以在此处阅读PE图像格式,以便详细了解它。 一旦理解了PE格式,您就可以使用上面的代码,甚至可以修改它以满足您的需求。

  • PE格式

PE内部对等:Win32可移植可执行文件格式之旅

深入研究Win32可移植可执行文件格式,第1部分

深入研究Win32可移植可执行文件格式,第2部分

  • Windows API和结构

IMAGE_SECTION_HEADER结构

ImageNtHeader函数

IMAGE_NT_HEADERS结构

我认为这会在很大程度上帮助你,其余你可以自己研究:-)

顺便说一下,你也可以看到这个post,因为所有这些都与此有关:

场景:DLL中的全局变量,由multithreading应用程序使用

由于您可能必须使您的垃圾收集器成为程序运行的环境,因此您可以直接从elf文件中获取它。

为Win32加载可执行文件来自的文件并解析PE头。 我不知道其他操作系统。 请记住,如果您的程序包含多个文件(例如DLL),则可能有多个数据段。

对于iOS,您可以使用此解决方案 。 它显示了如何查找文本段范围,但您可以轻松更改它以查找您喜欢的任何段。