Вопрос

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

Это было полезно?

Решение

Границы для текста (программный код) и данные для 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;
}

Откуда эти символы берутся: Где определены символы 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, которая демонстрирует использование 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)
}

Эта страница Может быть полезным, если вы заинтересованы в дополнительном использовании библиотеки DBGHELP.

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

  • Формат PE

Встановка внутри PE: экскурсия по портативному формату исполняемого файла Win32

Углубленный взгляд на портативный формат исполняемого файла Win32, часть 1

Глубокая внешность в формате исполняемого файла Win32 портативный файл Win32, часть 2

  • Windows API и структуры

Image_Section_Header Структура

Функция ImagentHeader

Image_nt_Headers Структура

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

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

Сценарий: глобальные переменные в DLL, используемые многопоточным приложением

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top