سؤال

كتمرين للبرمجة ، أكتب جامع القمامة ماركًا في C. أرغب في مسح قطاع البيانات (Globals ، وما إلى ذلك) للتأثيرات على الذاكرة المخصصة ، لكنني لا أعرف كيفية الحصول على مجموعة من عناوين هذا الجزء. كيف أستطيع فعل هذا؟

هل كانت مفيدة؟

المحلول

حدود النص (رمز البرنامج) وبيانات 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++;
}

تحديد الصور AS ،

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

Peering داخل PE: جولة في تنسيق ملف Win32 المحمول القابل للتنفيذ

نظرة متعمقة على تنسيق الملف القابل للتنفيذ WIN32 ، الجزء 1

نظرة متعمقة على تنسيق ملفات قابلة للتنفيذ WIN32 ، الجزء 2

  • Windows API والهياكل

Image_section_header الهيكل

وظيفة الخيال

هيكل Image_nt_headers

أعتقد أن هذا سيساعدك إلى حد كبير ، والباقي يمكنك البحث بنفسك :-)

بالمناسبة ، يمكنك أيضًا رؤية هذا الموضوع ، لأن كل هذا يرتبط بطريقة ما بهذا:

السيناريو: المتغيرات العالمية في DLL التي تستخدمها التطبيق متعدد الخيوط

نظرًا لأنه من المحتمل أن تضطر إلى جعل جامع القمامة الخاص بك البيئة التي يعمل فيها البرنامج ، يمكنك الحصول عليها من ملف ELF مباشرة.

قم بتحميل الملف الذي جاءه القابل للتنفيذ من رؤوس PE وتحليله ، لـ Win32. ليس لدي أي فكرة عن أنظمة أخرى. تذكر أنه إذا كان برنامجك يتكون من ملفات متعددة (مثل DLLs) ، فقد يكون لديك عدة قطاعات بيانات.

لنظام التشغيل iOS يمكنك استخدامه هذا الحل. يوضح كيفية العثور على نطاق شريحة النص ولكن يمكنك تغييره بسهولة للعثور على أي شريحة تريدها.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top