📦 محمل الشفرات: تشريح elf/mod.rs (ELF64 Loader)
تخيل أنك استلمت صندوقاً مقفلاً. لتفتحه، تحتاج إلى قراءة الدليل الملصق عليه لتفهم كيفية تركيب ما بداخله. ملف الـ ELF هو الصيغة القياسية للبرامج في Linux وفي نظام QOS. وهذا الملف هو الذي يقرأ الدليل!
1. قراءة كلمة السر (Magic Bytes)
كل برنامج أصيل يبدأ بـ 4 بايتات سحرية. إذا لم تكن موجودة، نرفض الملف فوراً.
rust
const ELF_MAGIC: [u8; 4] = [0x7F, b'E', b'L', b'F'];
if data[0..4] != ELF_MAGIC {
return Err("ELF: bad magic"); // هذا ليس ملفاً تنفيذياً!
}2. استخراج القطع (Segments Extraction)
البرنامج ليس قطعة واحدة مصمتة. هناك:
- الكود (Text): مسموح بتنفيذه، ممنوع التعديل عليه (أماناً من الفيروسات).
- البيانات (Data): مسموح بالتعديل عليها.
- المتغيرات الفارغة (BSS): غير موجودة في الملف أصلاً، مجرد طلب لمساحة فارغة.
النواة تقرأ رؤوس البرنامج (Program Headers) وتبحث فقط عن القطع التي من نوع PT_LOAD (أي التي يجب تحميلها للذاكرة):
rust
if phdr.p_type != PT_LOAD { continue; } // تجاهل التفاصيل غير الضرورية للتشغيل
info.segments[info.segment_count] = LoadSegment {
vaddr: phdr.p_vaddr, // أين يجب وضعها في الذاكرة؟
file_size: phdr.p_filesz, // كم حجمها في الملف؟
mem_size: phdr.p_memsz, // الخدعة (BSS): كم يجب أن تحجز لها فعلياً؟
writable: phdr.p_flags & PF_W != 0, // هل هي قابلة للكتابة؟
// ...
};3. لماذا الـ mem_size أكبر من file_size؟ (The BSS Trick)
إذا صمم المبرمج مصفوفة فارغة حجمها 1 جيجابايت [0u8; 1_000_000_000]. هل من المنطقي أن يكون حجم ملف الـ EXE النهائي 1 جيجابايت أصفار؟ طبعاً لا! الملف يكون صغيراً جداً (file_size = 0)، ولكنه يطلب من النواة أن تخصص له مساحة ضخمة من الـ RAM عند تشغيله (mem_size = 1GB). النواة الذكية تفهم ذلك وتملأ الباقي أصفاراً مجاناً!