العثور على نطاق العنوان لقطاع البيانات
-
29-09-2019 - |
سؤال
كتمرين للبرمجة ، أكتب جامع القمامة ماركًا في 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 والهياكل
أعتقد أن هذا سيساعدك إلى حد كبير ، والباقي يمكنك البحث بنفسك :-)
بالمناسبة ، يمكنك أيضًا رؤية هذا الموضوع ، لأن كل هذا يرتبط بطريقة ما بهذا:
السيناريو: المتغيرات العالمية في DLL التي تستخدمها التطبيق متعدد الخيوط
نظرًا لأنه من المحتمل أن تضطر إلى جعل جامع القمامة الخاص بك البيئة التي يعمل فيها البرنامج ، يمكنك الحصول عليها من ملف ELF مباشرة.
قم بتحميل الملف الذي جاءه القابل للتنفيذ من رؤوس PE وتحليله ، لـ Win32. ليس لدي أي فكرة عن أنظمة أخرى. تذكر أنه إذا كان برنامجك يتكون من ملفات متعددة (مثل DLLs) ، فقد يكون لديك عدة قطاعات بيانات.
لنظام التشغيل iOS يمكنك استخدامه هذا الحل. يوضح كيفية العثور على نطاق شريحة النص ولكن يمكنك تغييره بسهولة للعثور على أي شريحة تريدها.