ماخ-أو
Mach-O ( كائن Mach ) هو تنسيق ملفات للملفات التنفيذية ، ورمز الكائن ، والمكتبات المشتركة ، والتعليمات البرمجية المحملة ديناميكيًا، وملفات تفريغ الذاكرة الأساسية . وقد تم تطويره ليحل محل تنسيق a.out .
يستخدم نظام التشغيل Mach-O في بعض الأنظمة المبنية على نواة Mach . ومن أمثلة هذه الأنظمة NeXTSTEP و macOS و iOS التي تستخدم هذا التنسيق للملفات التنفيذية الأصلية والمكتبات والتعليمات البرمجية الكائنية.
تخطيط الملف
يتكون كل ملف Mach-O من رأس Mach-O واحد، يليه سلسلة من أوامر التحميل، ثم مقطع واحد أو أكثر، يحتوي كل منها على ما بين 0 و255 قسمًا. يستخدم Mach-O تنسيق إعادة التوجيه REL للتعامل مع مراجع الرموز. عند البحث عن الرموز، يستخدم Mach-O مساحة أسماء ثنائية المستوى تُشفّر كل رمز في زوج "اسم الكائن/اسم الرمز"، والذي يتم البحث عنه خطيًا، أولًا باسم الكائن ثم باسم الرمز. [ 2 ]
استُخدمت البنية الأساسية - وهي قائمة من "أوامر التحميل" ذات الطول المتغير التي تشير إلى صفحات البيانات في أماكن أخرى من الملف [ 3 ] - أيضًا في تنسيق الملف التنفيذي لبرنامج Accent . وقد استند تنسيق ملف Accent بدوره إلى فكرة من لغة Spice Lisp .
تُكتب جميع القيم متعددة البايتات في جميع هياكل البيانات بترتيب البايتات الخاص بالجهاز المضيف الذي تم إنتاج الكود من أجله. [ 4 ]
رأس الصفحة
| إزاحة | بايت | وصف |
|---|---|---|
| 0 | 4 | الرقم السحري |
| 4 | 4 | نوع وحدة المعالجة المركزية |
| 8 | 4 | نوع وحدة المعالجة المركزية |
| 12 | 4 | نوع الملف |
| 16 | 4 | عدد أوامر التحميل |
| 20 | 4 | حجم أوامر التحميل |
| 24 | 4 | الأعلام |
| 28 | 4 | محجوز (64 بت فقط) |
الرقم السحري للتعليمات البرمجية ذات 32 بت هو 0xfeedface بينما الرقم السحري للبنى ذات 64 بت هو 0xfeedfacf .
القيمة المحجوزة موجودة فقط في ملفات Mach-O ذات 64 بت. وهي محجوزة للاستخدام المستقبلي أو لتوسيع رأس الملف ذي 64 بت.
يشير نوع وحدة المعالجة المركزية إلى بنية مجموعة التعليمات المستخدمة في البرنامج. إذا كان الملف مخصصًا لإصدار 64 بت من بنية مجموعة التعليمات، فإن قيمة نوع وحدة المعالجة المركزية تكون مُفعّلة عند البت 0x01000000 . أما إذا كان الملف مخصصًا لإصدار 64 بت من بنية مجموعة التعليمات ولكن بمؤشرات 32 بت، فإن قيمة نوع وحدة المعالجة المركزية تكون مُفعّلة عند البت 0x02000000 .
قيم نوع وحدة المعالجة المركزية هي كما يلي: [ 6 ] [ 7 ]
| قيمة | نوع وحدة المعالجة المركزية |
|---|---|
| 0x00000001 | فاكس |
| 0x00000002 | مرح |
| 0x00000004 | NS32032 |
| 0x00000005 | NS32332 |
| 0x00000006 | MC680x0 |
| 0x00000007 | x86 |
| 0x00000008 | نظام MIPS |
| 0x00000009 | NS32352 |
| 0x0000000B | HP-PA |
| 0x0000000C | ذراع |
| 0x0000000D | MC88000 |
| 0x0000000E | سبارك |
| 0x0000000F | i860 (big-endian) |
| 0x00000010 | i860 (little-endian) أو ربما DEC Alpha [ 8 ] |
| 0x00000011 | RS/6000 |
| 0x00000012 | باور بي سي / إم سي 98000 |
| 0x00000018 | RISC-V |
لكل نوع من أنواع المعالجات المركزية مجموعة من قيم النوع الفرعي، تشير إلى طراز معين من هذا النوع من المعالجات المركزية الذي صُمم الكود من أجله. قد تدعم الطرازات الأحدث من نوع معين من المعالجات المركزية تعليمات أو ميزات أخرى غير مدعومة في الطرازات الأقدم، لذا قد يحتوي الكود المُجمَّع أو المكتوب لطراز أحدث على تعليمات غير صالحة في طراز أقدم، مما يتسبب في حدوث خطأ أو فشل في العمل بشكل صحيح عند تشغيله على طراز أقدم. أما الكود المُصمم لطراز أقدم فسيعمل على الطرازات الأحدث دون مشاكل.
إذا كان نوع وحدة المعالجة المركزية ARM، فإن الأنواع الفرعية هي كما يلي: [ 6 ]
| قيمة | إصدار وحدة المعالجة المركزية |
|---|---|
| 0x00000000 | جميع معالجات ARM |
| 0x00000001 | مُحسَّن للعمل مع معالج ARM-A500 ARCH أو أحدث. |
| 0x00000002 | مُحسَّن للعمل مع معالج ARM-A500 أو أحدث. |
| 0x00000003 | مُحسَّن للعمل مع معالج ARM-A440 أو أحدث. |
| 0x00000004 | مُحسَّن للعمل مع معالج ARM-M4 أو أحدث. |
| 0x00000005 | مُحسَّن للعمل مع معالجات ARM-V4T أو أحدث. |
| 0x00000006 | مُحسَّن للعمل مع معالجات ARM-V6 أو أحدث. |
| 0x00000007 | مُحسَّن للعمل مع معالج ARM-V5TEJ أو أحدث. |
| 0x00000008 | مُحسَّن للعمل مع معالجات ARM-XSCALE أو أحدث. |
| 0x00000009 | مُحسَّن للعمل مع معالجات ARM-V7 أو أحدث. |
| 0x0000000A | مُحسَّن للعمل مع معالج ARM-V7F (Cortex A9) أو أحدث. |
| 0x0000000B | مُحسَّن للعمل مع معالج ARM-V7S (Swift) أو أحدث. |
| 0x0000000C | مُحسَّن للعمل مع معالج ARM-V7K (Kirkwood40) أو أحدث. |
| 0x0000000D | مُحسَّن للعمل مع معالجات ARM-V8 أو أحدث. |
| 0x0000000E | مُحسَّن للعمل مع معالجات ARM-V6M أو أحدث. |
| 0x0000000F | مُحسَّن للعمل مع معالجات ARM-V7M أو أحدث. |
| 0x00000010 | مُحسَّن للعمل مع معالج ARM-V7EM أو أحدث. |
إذا كان نوع وحدة المعالجة المركزية x86 فإن الأنواع الفرعية هي كما يلي: [ 6 ]
| قيمة | إصدار وحدة المعالجة المركزية |
|---|---|
| 0x00000003 | جميع معالجات x86. |
| 0x00000004 | مُحسَّن لأجهزة 486 أو أحدث. |
| 0x00000084 | مُحسَّن للعمل مع معالجات 486SX أو أحدث. |
| 0x00000056 | مُحسَّن للمعالجات Pentium M5 أو أحدث. |
| 0x00000067 | مُحسَّن للعمل مع معالجات سيليرون أو أحدث. |
| 0x00000077 | مُحسَّن للهواتف المحمولة المزودة بمعالجات سيليرون. |
| 0x00000008 | مُحسَّن للعمل مع معالجات بنتيوم 3 أو أحدث. |
| 0x00000018 | مُحسَّن للعمل مع معالجات Pentium 3-M أو أحدث. |
| 0x00000028 | مُحسَّن للعمل مع معالجات Pentium 3-XEON أو أحدث. |
| 0x0000000A | مُحسَّن للمعالجات Pentium-4 أو أحدث. |
| 0x0000000B | مُحسَّن للعمل مع معالجات إيتانيوم أو أحدث. |
| 0x0000001B | مُحسَّن للعمل مع معالجات Itanium-2 أو أحدث. |
| 0x0000000C | مُحسَّن للعمل مع معالجات XEON أو أحدث. |
| 0x0000001C | مُحسَّن للعمل مع معالج XEON-MP أو أحدث. |
يلي قيمة النوع الفرعي قيمة نوع الملف.
| قيمة | وصف |
|---|---|
| 0x00000001 | ملف كائن قابل للنقل. |
| 0x00000002 | طلب ملف تنفيذي مُقسّم إلى صفحات. |
| 0x00000003 | تم إصلاح ملف المكتبة المشتركة للجهاز الظاهري. |
| 0x00000004 | ملف أساسي. |
| 0x00000005 | ملف تنفيذي مُحمّل مسبقًا. |
| 0x00000006 | ملف مكتبة مشتركة مرتبط ديناميكيًا. |
| 0x00000007 | محرر الروابط الديناميكية. |
| 0x00000008 | ملف حزمة مرتبط ديناميكيًا. |
| 0x00000009 | ملف مكتبة مشترك للربط الثابت فقط، بدون محتويات أقسام. |
| 0x0000000A | ملف مصاحب يحتوي على أقسام تصحيح الأخطاء فقط. |
| 0x0000000B | x86_64 kexts. |
| 0x0000000C | ملف يتكون من برامج Mach-O أخرى لتشغيلها في نفس مساحة المستخدم التي تشترك في ملف واحد مرتبط. |
بعد قيمة نوع الملف، يكون عدد أوامر التحميل وإجمالي عدد البايتات التي تأتي بعد رأس Mach-O، ثم علامة 32 بت مع الإعدادات الممكنة التالية.
| العلم في وضعية الانعطاف الأيسر | العلم بالصيغة الثنائية | وصف |
|---|---|---|
| 1<<0 | 0000_0000_0000_0000_0000_0000_0001 | لا يحتوي ملف الكائن على أي مراجع غير معرفة. |
| 1<<1 | 0000_0000_0000_0000_0000_0000_0010 | ملف الكائن هو ناتج عن ربط تزايدي بملف أساسي ولا يمكن تعديله مرة أخرى. |
| 1<<2 | 0000_0000_0000_0000_0000_0000_0100 | يُعد ملف الكائن مدخلاً للرابط الديناميكي ولا يمكن تعديله بشكل ثابت مرة أخرى. |
| 1<<3 | 0000_0000_0000_0000_0000_0000_1000 | يتم ربط المراجع غير المعرفة لملف الكائن بواسطة الرابط الديناميكي عند تحميله. |
| 1<<4 | 0000_0000_0000_0000_0000_0000_0001_0000 | يحتوي الملف على مراجع غير معرفة ديناميكية مرتبطة مسبقًا. |
| 1<<5 | 0000_0000_0000_0000_0000_0010_0000 | يحتوي الملف على أجزاء للقراءة فقط وأجزاء للقراءة والكتابة مقسمة. |
| 1<<6 | 0000_0000_0000_0000_0000_0100_0000 | يتم تشغيل روتين تهيئة المكتبة المشتركة بشكل كسول عن طريق التقاط أخطاء الذاكرة في أجزائها القابلة للكتابة (قديم). |
| 1<<7 | 0000_0000_0000_0000_0000_1000_0000 | تستخدم الصورة روابط مساحة اسم ثنائية المستوى. |
| 1<<8 | 0000_0000_0000_0000_0000_0001_0000_0000 | يجبر الملف التنفيذي جميع الصور على استخدام روابط مساحة الاسم المسطحة. |
| 1<<9 | 0000_0000_0000_0000_0010_0000_0000 | تضمن هذه المظلة عدم وجود تعريفات متعددة للرموز في صورها الفرعية، لذا يمكن دائمًا استخدام تلميحات مساحة الاسم ذات المستويين. |
| 1<<10 | 0000_0000_0000_0000_0100_0000_0000 | لا تقم بإخطار وكيل الربط المسبق بشأن هذا الملف التنفيذي. |
| 1<<11 | 0000_0000_0000_0000_0000_1000_0000_0000 | الملف الثنائي غير مرتبط مسبقًا، ولكن يمكن إعادة ربطه مسبقًا. يُستخدم فقط عندما لا يتم تعيين MH_PREBOUND. |
| 1<<12 | 0000_0000_0000_0000_0001_0000_0000_0000 | يشير هذا إلى أن هذا الملف الثنائي يرتبط بجميع وحدات مساحة الاسم ذات المستويين للمكتبات التابعة له. |
| 1<<13 | 0000_0000_0000_0000_0010_0000_0000_0000 | من الآمن تقسيم الأقسام إلى أقسام فرعية باستخدام الرموز لإزالة التعليمات البرمجية غير المستخدمة. |
| 1<<14 | 0000_0000_0000_0000_0100_0000_0000_0000 | تم توحيد الصيغة الثنائية من خلال عملية إلغاء الربط المسبق. |
| 1<<15 | 0000_0000_0000_0000_1000_0000_0000_0000 | تحتوي الصورة المرتبطة الأخيرة على رموز ضعيفة خارجية. |
| 1<<16 | 0000_0000_0000_0001_0000_0000_0000_0000 | تستخدم الصورة المرتبطة الأخيرة رموزًا ضعيفة. |
| 1<<17 | 0000_0000_0000_0010_0000_0000_0000_0000 | عند ضبط هذه البتة، سيتم منح جميع المكدسات في المهمة امتياز تنفيذ المكدس. |
| 1<<18 | 0000_0000_0000_0100_0000_0000_0000_0000 | عند ضبط هذه البتة، يعلن الملف الثنائي أنه آمن للاستخدام في العمليات ذات المعرف الفريد (uid) صفر. |
| 1<<19 | 0000_0000_0000_1000_0000_0000_0000_0000 | عندما يتم ضبط هذه البتة، يعلن الملف الثنائي أنه آمن للاستخدام في العمليات عندما تكون قيمة UGID صحيحة. |
| 1<<20 | 0000_0000_0001_0000_0000_0000_0000_0000 | عندما يتم تعيين هذا البت على مكتبة ديناميكية، فإن الرابط الثابت لا يحتاج إلى فحص المكتبات الديناميكية التابعة لمعرفة ما إذا كان يتم إعادة تصدير أي منها. |
| 1<<21 | 0000_0000_0010_0000_0000_0000_0000_0000 | عند ضبط هذا البت، سيقوم نظام التشغيل بتحميل الملف التنفيذي الرئيسي في عنوان عشوائي. |
| 1<<22 | 0000_0000_0100_0000_0000_0000_0000_0000 | للاستخدام فقط مع المكتبات الديناميكية. عند الربط مع مكتبة ديناميكية تم ضبط هذه البتة عليها، لن يقوم الرابط الثابت تلقائيًا بإنشاء أمر تحميل إلى المكتبة الديناميكية إذا لم تتم الإشارة إلى أي رموز من المكتبة الديناميكية. |
| 1<<23 | 0000_0000_1000_0000_0000_0000_0000_0000 | يحتوي على قسم من النوع S_THREAD_LOCAL_VARIABLES. |
| 1<<24 | 0000_0001_0000_0000_0000_0000_0000_0000 | عند ضبط هذا البت، سيقوم نظام التشغيل بتشغيل الملف التنفيذي الرئيسي مع كومة غير قابلة للتنفيذ حتى على الأنظمة الأساسية (مثل i386) التي لا تتطلب ذلك. |
| 1<<25 | 0000_0010_0000_0000_0000_0000_0000_0000 | تم ربط الكود لاستخدامه في أحد التطبيقات. |
| 1<<26 | 0000_0100_0000_0000_0000_0000_0000_0000 | لا تتضمن الرموز الخارجية المدرجة في جدول رموز nlist جميع الرموز المدرجة في معلومات dyld. |
| 1<<27 | 0000_1000_0000_0000_0000_0000_0000_0000 | السماح لأوامر التحميل LC_MIN_VERSION_MACOS و LC_BUILD_VERSION مع منصات macOS و macCatalyst و iOSSimulator و tvOSSimulator و watchOSSimulator. |
| 1<<31 | 1000_0000_0000_0000_0000_0000_0000 | يُستخدم هذا الخيار فقط مع مكتبات dylib. عند ضبط هذا الخيار، تصبح مكتبة dylib جزءًا من ذاكرة التخزين المؤقت المشتركة لـ dyld، بدلاً من أن تكون منفصلة في نظام الملفات. |
| 7<<28 | الأرقام التي تحمل علامة "x" ليس لها استخدام، وهي محجوزة للاستخدام المستقبلي. |
يمكن ضبط عدة أرقام ثنائية على واحد في العلامات لتحديد أي معلومات أو إعدادات تنطبق على النظام الثنائي.
الآن تُقرأ أوامر التحميل كما لو أن المرء قد وصل إلى نهاية رأس Mach-O.
ملفات ثنائية متعددة البنية
يمكن دمج ملفات Mach-O المتعددة في ملف ثنائي متعدد البنى . يسمح هذا لملف ثنائي واحد باحتواء تعليمات برمجية تدعم بنى مجموعات تعليمات متعددة، على سبيل المثال لأجيال وأنواع مختلفة من أجهزة Apple، بما في ذلك بنى معالجات مختلفة [ 9 ] مثل ARM64 و x86-64 . [ 10 ]
جميع الحقول في الترويسة العامة هي من نوع big-endian. [ 4 ]
يكون رأس الملف العام بالشكل التالي: [ 11 ]
| إزاحة | بايت | وصف |
|---|---|---|
| 0 | 4 | الرقم السحري |
| 4 | 4 | عدد الثنائيات |
الرقم السحري في ملف ثنائي متعدد البنية هو 0xcafebabe بترتيب البايتات الكبير، لذا فإن أول أربعة بايتات من الرأس ستكون دائمًا 0xca 0xfe 0xba 0xbe ، بهذا الترتيب.
عدد الملفات الثنائية هو عدد الإدخالات التي تلي العنوان.
يتبع العنوان سلسلة من الإدخالات بالشكل التالي: [ 12 ]
| إزاحة | بايت | وصف |
|---|---|---|
| 0 | 4 | نوع وحدة المعالجة المركزية |
| 4 | 4 | نوع وحدة المعالجة المركزية |
| 8 | 4 | إزاحة الملف |
| 12 | 4 | مقاس |
| 16 | 4 | محاذاة المقطع (قوة العدد 2) |
يتبع تسلسل المدخلات تسلسل من صور Mach-O. يشير كل مدخل إلى صورة Mach-O.
يجب أن يكون نوع وحدة المعالجة المركزية ونوعها الفرعي لإدخال ما هو نفسه نوع وحدة المعالجة المركزية ونوعها الفرعي لصورة Mach-O التي يشير إليها الإدخال.
يمثل موضع الملف وحجمه موضع بداية صورة Mach-O في الملف، وحجم صورة Mach-O التي يشير إليها الإدخال.
يمثل محاذاة القسم اللوغاريتم الثنائي لمحاذاة البايتات في الملف المطلوب لصورة Mach-O التي يشير إليها الإدخال؛ على سبيل المثال، تعني القيمة 14 أن الصورة يجب أن تكون محاذية على حد 2^ 14 بايت، أي حد 16384 بايت. هذا ضروري للأدوات التي تُعدّل الملف الثنائي متعدد البنية، لكي تحافظ على محاذاة الصورة بشكل صحيح.
أوامر التحميل
تُقرأ أوامر التحميل مباشرة بعد رأس Mach-O.
يُحدد رأس Mach-O عدد أوامر التحميل الموجودة بعد رأس Mach-O وحجمها بالبايتات حتى نهاية أوامر التحميل. ويُستخدم حجم أوامر التحميل كفحص للتكرار.
عندما تتم قراءة أمر التحميل الأخير ولا يتطابق عدد البايتات لأوامر التحميل، أو إذا تجاوزنا عدد البايتات لأوامر التحميل قبل الوصول إلى أمر التحميل الأخير، فقد يكون الملف تالفًا.
كل أمر تحميل عبارة عن سلسلة من الإدخالات بالشكل التالي: [ 13 ]
| إزاحة | بايت | وصف |
|---|---|---|
| 0 | 4 | نوع الأمر |
| 4 | 4 | حجم القيادة |
يُحدد نوع أمر التحميل المعلمات المُستخدمة فيه. إذا بدأ أمر التحميل بتفعيل البت 0x80000000 ، فهذا يعني أن هذا الأمر ضروري لتحميل أو تشغيل الملف التنفيذي. يسمح هذا لمُحملات Mach-O القديمة بتجاوز الأوامر غير المفهومة لها والتي لا تُعد ضرورية لتحميل التطبيق.
أمر تحميل المقطع
تستخدم ملفات Mach-O الثنائية التي تستخدم نوع أمر التحميل 0x00000001 الإصدار 32 بت من أمر تحميل المقطع، [ 14 ] بينما يتم استخدام 0x00000019 لتحديد الإصدار 64 بت من أمر تحميل المقطع. [ 15 ]
يختلف أمر تحميل المقطع باختلاف حجم رأس Mach-O، سواء كان 32 بت أو 64 بت. ويعود ذلك إلى أن بنية المعالج 64 بت تستخدم عناوين 64 بت، بينما تستخدم بنية المعالج 32 بت عناوين 32 بت.
تُضاف جميع عناوين ذاكرة الوصول العشوائي الافتراضية إلى عنوان أساسي للحفاظ على تباعد التطبيقات. يحتوي كل قسم في أمر تحميل المقطع على إزاحة قائمة إعادة التوطين التي تحدد الإزاحات في القسم التي يجب تعديلها بناءً على العنوان الأساسي للتطبيق. لا داعي لإعادة التوطين إذا كان من الممكن وضع التطبيق في مواقع عناوين ذاكرة الوصول العشوائي المحددة له، مثل العنوان الأساسي صفر.
| الإزاحة (32 بت) | بايت (32 بت) | الإزاحة (64 بت) | بايت (64 بت) | وصف |
|---|---|---|---|---|
| 0 | 4 | 0 | 4 | 0x00000001 (نوع الأمر 32 بت) 0x00000019 (نوع الأمر 64 بت) |
| 4 | 4 | 4 | 4 | حجم القيادة |
| 8 | 16 | 8 | 16 | اسم المقطع |
| 24 | 4 | 24 | 8 | عنوان |
| 28 | 4 | 32 | 8 | حجم العنوان |
| 32 | 4 | 40 | 8 | إزاحة الملف |
| 36 | 4 | 48 | 8 | الحجم (بايت من إزاحة الملف) |
| 40 | 4 | 56 | 4 | أقصى حماية للذاكرة الافتراضية |
| 44 | 4 | 60 | 4 | الحماية الأولية للذاكرة الافتراضية |
| 48 | 4 | 64 | 4 | عدد الأقسام |
| 52 | 4 | 68 | 4 | Flag32 |
لا يمكن أن يتجاوز اسم المقطع 16 حرفًا نصيًا بالبايت. الأحرف غير المستخدمة قيمتها 0x00 .
يحتوي أمر المقطع على عنوان كتابة القسم في مساحة العناوين الافتراضية بالإضافة إلى عنوان التطبيق الأساسي. ويُحدد حجم العنوان (عدد البايتات المراد كتابتها في موقع العنوان).
بعد معلومات العنوان، يتم تحديد موضع إزاحة الملف، ثم يتم تحديد موقع بيانات المقطع في ملف Mach-O الثنائي، وعدد البايتات المراد قراءتها من الملف.
عندما يكون حجم العنوان أكبر من عدد البايتات المراد قراءتها من الملف، يتم تعيين باقي البايتات في مساحة ذاكرة الوصول العشوائي إلى 0x00 .
يوجد جزء يُسمى `<input>` __PAGEZERO، وله إزاحة ملف صفرية وحجم صفري في الملف. وله عنوان ذاكرة افتراضية وحجم مُحددان. كما أن أذونات الوصول إليه مُعيّنة على الصفر، مما يعني أنه لا يمكن استخدامه إطلاقًا (أي وصول إلى هذا الجزء سيؤدي إلى خطأ في الصفحة). الغرض من هذا الجزء هو اكتشاف مؤشرات NULL غير الصالحة (التي قيمتها صفر). في بيئات 32 بت، يكون الحجم الافتراضي لهذا الجزء 4 كيلوبايت، بينما في بيئات 64 بت يكون 4 جيجابايت (يكتشف هذا مؤشرات NULL غير الصالحة ذات 32 بت والتي قد تكون قد اقتُطعت أثناء عملية إسناد ذهاب وإياب عبر عدد صحيح 32 بت). يمكن ضبط حجم هذا الجزء من خلال -pagezero_sizeعلامة المُصرّف/الرابط.
عند وضع مقطع في مساحة العناوين الافتراضية، يُمنح أذونات الوصول إلى وحدة المعالجة المركزية المحددة بقيمة حماية الذاكرة الافتراضية الأولية. يمكن تغيير أذونات الوصول إلى منطقة معينة من مساحة العناوين الافتراضية بواسطة تطبيق أو مكتبة برمجية من خلال استدعاءات لوظائف مثل mprotect() ؛ وتحدّ حماية الذاكرة الافتراضية القصوى من الأذونات الممنوحة للوصول إلى المقطع.
| بت الإذن في النظام الثنائي | وصف |
|---|---|
| 00000000000000000000000000000001 | يسمح هذا القسم لوحدة المعالجة المركزية بقراءة البيانات من هذا القسم (إعداد القراءة). |
| 0000000000000000000000000000010 | يسمح هذا القسم لوحدة المعالجة المركزية بكتابة البيانات إلى هذا القسم (إعداد الكتابة). |
| 0000000000000000000000000000100 | يسمح هذا القسم لوحدة المعالجة المركزية بتنفيذ التعليمات البرمجية في هذا القسم (إعداد التنفيذ). |
| xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx000 | الأرقام التي تحمل علامة "x" ليس لها استخدام، وهي محجوزة للاستخدام المستقبلي. |
ثم بعد إعدادات حماية عنوان وحدة المعالجة المركزية، يأتي عدد الأقسام الموجودة داخل هذا الجزء والتي تتم قراءتها بعد إعدادات علامة الأجزاء.
إعدادات علامة القطاع هي كالتالي:
| Flag32 في النظام الثنائي | وصف |
|---|---|
| 00000000000000000000000000000001 | محتويات الملف لهذا الجزء مخصصة للجزء العلوي من مساحة الجهاز الظاهري، أما الجزء السفلي فهو مملوء بالأصفار (للمكدسات في ملفات الذاكرة الأساسية). |
| 0000000000000000000000000000010 | هذا الجزء هو الجهاز الظاهري الذي يتم تخصيصه بواسطة مكتبة أجهزة ظاهرية ثابتة، وذلك للتحقق من التداخل في محرر الروابط. |
| 0000000000000000000000000000100 | لا يحتوي هذا الجزء على أي شيء تم نقله بداخله ولا شيء تم نقله إليه، أي أنه يمكن استبداله بأمان دون نقل. |
| 0000000000000000000000000001000 | هذا الجزء محمي. إذا بدأ الجزء عند الإزاحة 0، فإن الصفحة الأولى منه غير محمية. أما باقي صفحات الجزء فهي محمية. |
| 0000000000000000000000000010000 | يتم جعل هذا الجزء للقراءة فقط بعد تطبيق عمليات النقل إذا لزم الأمر. |
| xxxxxxxxxxxxxxxxxxxxxxxxxxx00000 | الأرقام التي تحمل علامة "x" ليس لها استخدام، وهي محجوزة للاستخدام المستقبلي. |
عدد الأقسام في المقطع هو مجموعة من المدخلات التي تُقرأ على النحو التالي:
| الإزاحة (32 بت) | بايت (32 بت) | الإزاحة (64 بت) | بايت (64 بت) | وصف |
|---|---|---|---|---|
| 0 | 16 | 0 | 16 | اسم القسم |
| 16 | 16 | 16 | 16 | اسم المقطع |
| 32 | 4 | 32 | 8 | عنوان القسم |
| 36 | 4 | 40 | 8 | حجم القسم |
| 40 | 4 | 48 | 4 | إزاحة ملف القسم |
| 44 | 4 | 52 | 4 | تنسيق |
| 48 | 4 | 56 | 4 | إزاحة ملف عمليات النقل |
| 52 | 4 | 60 | 4 | عدد عمليات النقل |
| 56 | 4 | 64 | 4 | العلم/النوع |
| 60 | 4 | 68 | 4 | محجوز 1 |
| 64 | 4 | 72 | 4 | محجوز ٢ |
| غير متوفر | غير متوفر | 76 | 4 | محجوز 3 (64 بت فقط) |
يجب أن يتطابق اسم مقطع القسم مع اسم أمر التحميل الخاص به. تشير إدخالات الأقسام إلى البيانات الموجودة في المقطع. ويشير كل قسم إلى إدخالات إعادة التوجيه لتعديل العناوين في القسم إذا تمت إضافة عنوان التطبيق الأساسي إلى أي قيمة غير الصفر.
ينطبق حجم القسم على كل من حجم القسم في موقع عنوانه وحجمه في الملف في موقع الإزاحة الخاص به.
تُقرأ قيمة قسم Flag/Type على النحو التالي:
| العلم بالصيغة الثنائية | وصف |
|---|---|
| 10000000000000000000000000000000xxxxxxxx | يحتوي هذا القسم على تعليمات الآلة الحقيقية فقط |
| 01000000000000000000000000000000xxxxxxxx | يحتوي هذا القسم على رموز مدمجة لا ينبغي أن تكون موجودة في جدول محتويات ranlib |
| 001000000000000000000000000000000xxxxxxxx | يُسمح بإزالة الرموز الثابتة في هذا القسم في الملفات التي تحمل علامة MH_DYLDLINK. |
| 000100000000000000000000000000000xxxxxxxx | لا يوجد اتصال لاسلكي |
| 00001000000000000000000000000000xxxxxxxx | تكون الكتل نشطة إذا كانت تشير إلى كتل نشطة |
| 000001000000000000000000000000000xxxxxxxx | يُستخدم مع نماذج التعليمات البرمجية i386 المكتوبة بواسطة dyld |
| 000000100000000000000000000000000xxxxxxxx | قسم تصحيح الأخطاء |
| 0000000000000000000010000000000xxxxxxxx | يحتوي هذا القسم على بعض تعليمات الآلة |
| 0000000000000000000001000000000xxxxxxxx | يحتوي القسم على مدخلات نقل خارجية |
| 0000000000000000000000100000000xxxxxxxx | يحتوي القسم على إدخالات النقل المحلي |
أي من الإعدادات التي تنطبق على القسم لها قيمة ثنائية مضبوطة على واحد. آخر ثمانية أرقام ثنائية هي قيمة نوع القسم.
| العلم بالصيغة الثنائية | وصف |
|---|---|
| xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx00000110 | قسم يحتوي فقط على مؤشرات الرموز غير الكسولة |
| xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx00000111 | قسم يحتوي فقط على مؤشرات الرموز الكسولة |
| xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx00001000 | قسم يحتوي على رموز مختصرة فقط |
| xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx00001100 | قسم التعبئة الصفرية عند الطلب (والذي يمكن أن يكون حجمه أكبر من 4 جيجابايت) |
| xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx00010000 | قسم يحتوي فقط على مؤشرات الرموز الكسولة إلى مكتبات dylibs المحملة بشكل كسول |
يقوم مُحمِّل Mach-O بتسجيل أقسام مؤشر الرمز وأقسام رمز الجذع. ويتم استخدامها بالتسلسل بواسطة جدول الرموز غير المباشر لتحميل استدعاءات الأساليب.
يُخزَّن حجم كل جزء من الرمز في القيمة reserved2. كل مؤشر عبارة عن موقع عنوان 32 بت في Mach-O ذي 32 بت، وموقع عنوان 64 بت في Mach-O ذي 64 بت. عند الوصول إلى نهاية القسم، ننتقل إلى القسم التالي أثناء قراءة جدول الرموز غير المباشر.
رقم الجزء وأرقام الأقسام
يتم تحديد مواقع الأجزاء والأقسام حسب رقم الجزء ورقم القسم في أقسام معلومات تحرير الروابط المضغوطة وغير المضغوطة.
قيمة المقطع 3 تعني الإزاحة لبيانات أمر تحميل المقطع الرابع في ملف Mach-O بدءًا من الصفر لأعلى (0،1،2،3 = المقطع الرابع).
تُرقّم الأقسام أيضًا بدءًا من القسم 1. يُستخدم الرقم صفر في جدول الرموز للرموز غير المُعرّفة في أي قسم (غير مُعرّفة). مثل طريقة أو بيانات موجودة ضمن قسم آخر من جدول رموز الملفات الثنائية.
المقطع الذي يحتوي على سبعة أقسام يعني أن القسم الأخير هو القسم الثامن. وإذا كان أمر تحميل المقطع التالي يحتوي على ثلاثة أقسام، فسيتم تسميتها بالأقسام 9 و10 و11. القسم رقم 10 يعني المقطع الثاني، القسم 2.
لن يكون من الممكن قراءة جدول الرموز ومعلومات الربط بشكل صحيح إذا لم نقم بتخزين ترتيب قراءة الأقسام وموضع عنوانها/إزاحة الملف.
يمكن للمرء بسهولة استخدام إزاحة الملف دون استخدام عناوين ذاكرة الوصول العشوائي وعمليات النقل لإنشاء قارئ رموز وقراءة أقسام تحرير الارتباط وحتى تعيين استدعاءات الأساليب أو تصميم برنامج تفكيك.
إذا كنت تقوم ببناء برنامج تحميل Mach-O، فأنت تريد تفريغ الأقسام إلى عناوين RAM المحددة بالإضافة إلى عنوان أساسي للحفاظ على تباعد التطبيقات حتى لا تكتب فوق بعضها البعض.
يمكن إعادة تسمية أسماء المقاطع وأسماء الأقسام إلى أي شيء تريده، ولن تكون هناك أي مشاكل في تحديد موقع الأقسام المناسبة بواسطة رقم القسم أو رقم المقطع طالما أنك لا تغير ترتيب أوامر المقاطع.
مكتبات الربط
تتشابه مكتبات الربط مع أي ملف ثنائي آخر من نوع Mach-O، باستثناء عدم وجود أمر يحدد نقطة الدخول الرئيسية التي يبدأ عندها البرنامج.
توجد ثلاثة أوامر تحميل لتحميل ملف مكتبة الارتباط.
نوع أمر التحميل 0x0000000C مخصص لمسار الملف الكامل للمكتبة المشتركة المرتبطة ديناميكيًا.
تُستخدم أوامر التحميل من النوع 0x0000000D للمواقع المشتركة المرتبطة ديناميكيًا من المسار الحالي للتطبيق.
يُستخدم أمر التحميل من النوع 0x00000018 لمكتبة مشتركة مرتبطة ديناميكيًا يُسمح بفقدانها. توجد أسماء الرموز في مكتبات ارتباط أخرى، ويتم استخدامها في حال فقدان المكتبة، مما يعني استيراد جميع الرموز استيرادًا ضعيفًا.
يُقرأ أمر مكتبة الربط على النحو التالي:
| إزاحة | بايت | وصف |
|---|---|---|
| 0 | 4 | 0x0000000C (نوع الأمر) 0x0000000D (نوع الأمر) 0x00000018 (نوع الأمر) |
| 4 | 4 | حجم القيادة |
| 8 | 4 | إزاحة السلسلة (دائماً إزاحة 24) |
| 12 | 4 | ختم التاريخ والوقت |
| 16 | 4 | الإصدار الحالي |
| 20 | 4 | إصدار متوافق |
| 24 | حجم الأمر - 24 | سلسلة مسار الملف |
يبدأ اسم مسار الملف من إزاحة السلسلة النصية، وهي دائمًا 24. عدد البايتات لكل حرف نصي هو عدد البايتات المتبقية في حجم الأمر. تُحدد نهاية مسار ملف المكتبة بالحرف 0x00 . تُستخدم قيم 0x00 المتبقية كحشو، إن وُجد.
أرقام ترتيب مكتبة الروابط
يتم تحديد موقع المكتبة حسب الرقم الترتيبي في أقسام معلومات تحرير الروابط المضغوطة وغير المضغوطة.
تُرقّم مكتبات الربط من الترتيب 1 فصاعدًا. تُستخدم القيمة الترتيبية صفر في جدول الرموز لتحديد أن الرمز غير موجود كرمز خارجي في ملف ثنائي آخر من نوع Mach-O.
لن تواجه معلومات تعديل الرابط أي مشكلة في تحديد موقع المكتبة المناسبة للقراءة حسب الرقم الترتيبي طالما لم يتم تغيير ترتيب إدخال أوامر مكتبة الرابط.
ينبغي تجنب استخدام أمر ربط المكتبة 0x00000018 لأسباب تتعلق بالأداء، لأنه في حالة فقدان المكتبة، يجب إجراء بحث من خلال جميع مكتبات الربط المحملة.
__LINKEDITجدول الرموز
تحتوي ملفات تطبيق Mach-O ومكتبات الربط على أمر جدول الرموز.
يُقرأ الأمر على النحو التالي:
| إزاحة | بايت | وصف |
|---|---|---|
| 0 | 4 | 0x00000002 (نوع الأمر) |
| 4 | 4 | حجم الأمر (دائماً 24) |
| 8 | 4 | الرموز (إزاحة الملف بالنسبة لرأس Mach-O) |
| 12 | 4 | عدد الرموز |
| 16 | 4 | جدول السلاسل النصية (إزاحة الملف بالنسبة إلى رأس Mach-O) |
| 20 | 4 | حجم جدول السلاسل |
إزاحة ملف الرموز هي المسافة النسبية من بداية رأس Mach-O إلى بداية إدخالات الرموز في الملف. ويشير عدد إدخالات الرموز إلى نهاية جدول الرموز.
يحتوي كل رمز على إزاحة اسم يجب ألا تتجاوز حجم جدول السلاسل النصية. تُضاف إزاحة اسم كل رمز إلى إزاحة ملف جدول السلاسل النصية، والتي بدورها تكون نسبية إلى بداية رأس Mach-O. وينتهي كل اسم رمز بقيمة بايت 0x00 .
يستخدم عنوان الرمز عنوانًا من 32 بت لملفات Mach-O ذات 32 بت وعنوانًا من 64 بت لملفات Mach-O ذات 64 بت.
تُقرأ كل خانة رمزية على النحو التالي:
| الإزاحة (32 بت) | بايت (32 بت) | الإزاحة (64 بت) | بايت (64 بت) | وصف |
|---|---|---|---|---|
| 0 | 4 | 0 | 4 | إزاحة الاسم |
| 4 | 1 | 4 | 1 | نوع الرمز |
| 5 | 1 | 5 | 1 | القسم رقم 0 إلى 255 |
| 6 | 2 | 6 | 2 | معلومات البيانات (الرقم التسلسلي للمكتبة) |
| 8 | 4 | 8 | 8 | عنوان الرمز |
تُضاف قيمة اسم الرمز إلى قيمة جدول السلاسل النصية. ويُقرأ آخر بايت من النص على أنه 0x00 .
تحتوي قيمة نوع الرمز على عدة أقسام قابلة للتعديل في النظام الثنائي. يُقرأ نوع الرمز كما يلي:
| الأرقام الثنائية | وصف |
|---|---|
| ???xxxxx | رموز تصحيح الأخطاء المحلية |
| xxxx???x | نوع عنوان الرمز |
| xxx?xxx? | علامات ضبط رؤية الرموز |
تُستخدم الأرقام التي تحمل علامة الاستفهام (؟) للغرض المحدد؛ أما الأرقام التي تحمل علامة x فتُستخدم لأغراض أخرى.
الأرقام الثنائية الثلاثة الأولى هي رموز تُحدد مواقع أسماء الدوال بالنسبة لتعليمات لغة الآلة المُجمّعة، وأرقام الأسطر بحسب موقع العنوان. تُتيح لنا هذه المعلومات توليد أرقام أسطر لموقع تعطل البرنامج. رموز تصحيح الأخطاء المحلية مفيدة فقط عند تصميم التطبيق، وليست ضرورية لتشغيله.
| القيمة الثنائية | وصف |
|---|---|
| xxxx000x | الرمز غير مُعرَّف |
| xxxx001x | رمز مطلق |
| xxxx101x | الرمز غير المباشر |
| xxxx110x | الرمز المحدد مسبقًا غير معرف |
| xxxx111x | الرمز المحدد في رقم القسم |
إعدادات العلم التالية:
| القيمة الثنائية | وصف |
|---|---|
| xxx1xxx0 | رموز خاصة |
| xxx0xxx1 | رمز خارجي |
الرموز الخارجية هي رموز لها عنوان محدد في مكتبة الربط، ويمكن نسخها إلى رمز غير محدد في تطبيق Mach-O. يُضاف موقع العنوان إلى عنوان مكتبة الربط الأساسي.
يتم تجاهل الرمز الخاص حتى لو كان مطابقًا لاسم رمز غير مُعرَّف. ولا يمكن تعيين رمز خاص ورمز خارجي إلى رمز غير مُعرَّف إلا إذا كانا في الملف نفسه.
بعد نوع الرمز، يأتي رقم القسم الذي يوجد فيه الرمز. رقم القسم هو قيمة بايت (من 0 إلى 255). يمكنك إضافة أقسام أكثر من 255 باستخدام أوامر تحميل المقاطع، ولكن أرقام الأقسام ستكون حينها خارج نطاق قيمة البايت المستخدمة في إدخالات الرمز.
يشير رقم القسم صفر إلى أن الرمز غير موجود في أي قسم من أقسام التطبيق، وأن موقع عنوان الرمز هو صفر، وبالتالي فهو مُعيّن على أنه غير مُعرّف. يجب العثور على اسم رمز خارجي مطابق في مكتبة الارتباط التي تحتوي على عنوان الرمز.
يحتوي حقل معلومات البيانات على رقم تسلسل مكتبة الارتباط التي يمكن العثور فيها على الرمز الخارجي مع اسم الرمز المطابق. وينقسم حقل بت معلومات البيانات على النحو التالي:
| الأرقام الثنائية | وصف |
|---|---|
| ؟؟؟؟؟؟؟؟xxxxxxxx | رقم المكتبة الترتيبي من 0 إلى 255 |
| xxxxxxxx????xxxx | خيارات علامة التحميل الديناميكي |
| xxxxxxxxxxxx???? | خيار نوع العنوان |
يُعيّن رقم المكتبة الترتيبي إلى الصفر إذا كان الرمز رمزًا خارجيًا، أو موجودًا في الملف الحالي. أما الرموز غير المعرّفة فقط، فتستخدم قسم معلومات البيانات لتحديد رقم المكتبة الترتيبي وخيارات الرابط.
خيارات علامة التحميل الديناميكي هي كما يلي:
| الأرقام الثنائية | وصف |
|---|---|
| xxxxxxxx0001xxxx | يجب تعيينها لأي رمز محدد يتم الرجوع إليه بواسطة المحمل الديناميكي. |
| xxxxxxxx0010xxxx | يستخدمه الرابط الديناميكي في وقت التشغيل. |
| xxxxxxxx0100xxxx | إذا لم يتمكن الرابط الديناميكي من العثور على تعريف لهذا الرمز، فإنه يضبط عنوان هذا الرمز على 0. |
| xxxxxxxx1000xxxx | إذا وجد الرابط الثابت أو الرابط الديناميكي تعريفًا آخر لهذا الرمز، فسيتم تجاهل التعريف. |
يمكن اختيار أي من الخيارات الأربعة المتاحة.
فيما يلي قيم خيارات نوع العنوان:
| الأرقام الثنائية | وصف |
|---|---|
| xxxxxxxxxxxx0000 | استدعاء دالة المؤشر غير المحملة بشكل كسول |
| xxxxxxxxxxxx0001 | استدعاء دالة المؤشر للتحميل الكسول |
| xxxxxxxxxxxx0010 | استدعاء الأسلوب المحدد في هذه المكتبة/البرنامج |
| xxxxxxxxxxxx0011 | تم تعريف استدعاء الأسلوب الخاص في هذه المكتبة/البرنامج |
| xxxxxxxxxxxx0100 | استدعاء دالة مؤشر خاصة غير محملة بشكل كسول |
| xxxxxxxxxxxx0101 | استدعاء دالة مؤشر خاصة محملة بشكل كسول |
لا يمكن تعيين سوى قيمة واحدة لنوع العنوان. المؤشر هو قيمة يقرأها كود الآلة للبرنامج لاستدعاء دالة من ملف ثنائي آخر. تعني كلمة "خاص" أنه لا يُسمح للبرامج الأخرى بقراءة أو استدعاء الدالة/الأساليب باستثناء الملف الثنائي نفسه. أما كلمة "كسول" فتعني أن المؤشر ينتقل إلى dyld_stub_binder الذي يبحث عن الرمز ثم يستدعي الدالة، ثم يستبدل موقع dyld_stub_binder بموقع الرمز. أي استدعاءات أخرى تتم من كود الآلة في الملف الثنائي ستنتقل الآن إلى عنوان الرمز ولن تستدعي dyld_stub_binder.
تنظيم جدول الرموز
تُخزَّن جميع إدخالات جدول الرموز بالترتيب حسب النوع. أول الرموز التي تُقرأ هي رموز تصحيح الأخطاء المحلية إن وُجدت، ثم الرموز الخاصة، ثم الرموز الخارجية، وأخيرًا الرموز غير المُعرَّفة التي ترتبط بجدول رموز ثنائي آخر يحتوي على عنوان الرمز الخارجي في ملف ثنائي آخر من نوع Mach-O.
يوجد أمر تحميل معلومات جدول الرموز 0x0000000B دائمًا إذا كان هناك قسم لجدول الرموز في ملف Mach-O الثنائي. يُخبر هذا الأمر الرابط بعدد الرموز المحلية، والرموز الخاصة، والرموز الخارجية، والرموز غير المُعرَّفة. كما يُحدد رقم الرمز الذي تبدأ منه. تُستخدم معلومات جدول الرموز قبل قراءة مدخلات الرموز بواسطة الرابط الديناميكي، حيث تُخبره بمكان بدء قراءة الرموز لتحميل الرموز غير المُعرَّفة، ومكان بدء البحث عن الرموز الخارجية المطابقة دون الحاجة إلى قراءة جميع مدخلات الرموز.
يجب عدم تغيير ترتيب الرموز في قسم الرموز، حيث يتم ترقيم كل رمز من الصفر فصاعدًا. يستخدم أمر معلومات جدول الرموز أرقام الرموز لتحديد ترتيب تحميل الرموز غير المعرّفة في أقسام المؤشرات والوحدات الفرعية. سيؤدي تغيير الترتيب إلى استدعاء الدالة الخاطئة أثناء تنفيذ كود الآلة.
__LINKEDITمعلومات جدول الرموز
يستخدم الرابط الديناميكي أمر معلومات جدول الرموز لمعرفة مكان قراءة إدخالات جدول الرموز تحت أمر جدول الرموز 0x00000002 ، من أجل البحث السريع عن الرموز غير المعرفة والرموز الخارجية أثناء الربط.
يُقرأ الأمر على النحو التالي:
| إزاحة | بايت | وصف |
|---|---|---|
| 0 | 4 | 0x0000000B (نوع الأمر) |
| 4 | 4 | حجم الأمر (دائماً 80) |
| 8 | 4 | فهرس الرموز المحلية |
| 12 | 4 | عدد الرموز المحلية |
| 16 | 4 | فهرس الرموز الخارجية |
| 20 | 4 | عدد الرموز الخارجية |
| 24 | 4 | فهرس الرموز غير المعرفة |
| 28 | 4 | عدد الرموز غير المعرفة |
| 32 | 4 | إزاحة جدول المحتوى |
| 36 | 4 | عدد إدخالات جدول المحتويات |
| 40 | 4 | إزاحة جدول الوحدات النمطية |
| 44 | 4 | عدد إدخالات جدول الوحدة النمطية |
| 48 | 4 | إزاحة إلى جدول الرموز المرجعي |
| 52 | 4 | عدد إدخالات جدول الرموز المرجعية |
| 56 | 4 | إزاحة جدول الرموز غير المباشرة |
| 60 | 4 | إدخالات جدول الرموز غير المباشرة |
| 64 | 4 | إزاحة النقل الخارجي |
| 68 | 4 | عدد عمليات النقل الخارجية |
| 72 | 4 | تعويض النقل المحلي |
| 76 | 4 | عدد عمليات النقل المحلية |
يتم ضرب فهرس الرمز في 12 لـ Mach-O 32 بت، أو 16 لـ Mach-O 64 بت بالإضافة إلى إزاحة إدخالات جدول الرموز للعثور على الإزاحة لقراءة إدخالات الرموز بواسطة فهرس رقم الرمز.
يكون فهرس الرمز المحلي صفرًا لأنه يقع في بداية إدخالات الرموز. تُستخدم الرموز المحلية لمعلومات تصحيح الأخطاء.
عدد الرموز المحلية هو عدد الرموز الموجودة بعد فهرس الرمز.
يتم تكرار نفس الخاصيتين للرموز الخارجية والرموز غير المعرفة من أجل قراءة سريعة لإدخالات جدول الرموز.
توجد فجوة صغيرة في الفهرس/الحجم بين الرموز المحلية والرموز الخارجية في حالة وجود رموز خاصة.
أي إزاحات ملفات تساوي صفرًا تكون غير مستخدمة.
جدول غير مباشر
يقوم مُحمِّل Mach-O بتسجيل أقسام مؤشر الرموز وأقسام الرموز الفرعية أثناء أوامر تحميل المقاطع. ويستخدمها جدول الرموز غير المباشر بالتتابع لتحميل استدعاءات الدوال. وبمجرد الوصول إلى نهاية القسم، ننتقل إلى القسم التالي.
يحدد إزاحة جدول الرموز غير المباشر مجموعة من القيم ذات 32 بت (4 بايت) والتي تستخدم كمؤشر لرقم الرمز.
إن ترتيب أرقام فهرس الرموز هو الترتيب الذي نكتب به عنوان كل رمز واحداً تلو الآخر في أقسام المؤشر والجذع.
يحتوي قسم رمز الجذع على تعليمات لغة الآلة مع تعليمات قفز إلى عنوان الرمز غير المباشر لاستدعاء دالة/طريقة من ملف ثنائي آخر من نوع Mach-O. يعتمد حجم كل تعليمة قفز على نوع المعالج، ويُخزَّن في القيمة reserved2 ضمن القسم section32/64 من أمر تحميل المقطع.
تُمثل أقسام المؤشر قيم عناوين 32 بت (4 بايت) للملفات الثنائية Mach-O ذات 32 بت، وقيم عناوين 64 بت (8 بايت) للملفات الثنائية Mach-O ذات 64 بت. يقرأ رمز الآلة هذه المؤشرات، وتُستخدم القيمة المقروءة كموقع لاستدعاء الدالة/الطريقة بدلاً من أن تحتوي على تعليمات رمز الآلة.
إن رقم فهرس الرمز 0x40000000 بت مضبوطة هو طريقة مطلقة، مما يعني أن المؤشر يحدد العنوان الدقيق للطريقة.
إن رمز رقم الفهرس 0x80000000 بت مضبوطة هو طريقة محلية، مما يعني أن المؤشر نفسه موجود في الطريقة وأنه لا يوجد اسم للطريقة (طريقة محلية).
إذا كنت تقوم بتصميم برنامج تفكيك، يمكنك بسهولة ربط اسم الرمز فقط بعنوان الإزاحة لكل جذع ومؤشر لإظهار استدعاء الطريقة أو الدالة التي تحدث دون البحث عن موقع عنوان الرمز غير المحدد في ملفات Mach-O الأخرى.
__LINKEDITطاولة مضغوطة
إذا كان أمر تحرير جدول الروابط المضغوطة موجودًا، فلن تكون هناك حاجة إلى الرموز غير المعرّفة/الخارجية في جدول الرموز. كما لن يكون هناك حاجة إلى جدول الرموز غير المباشر وموقع أقسام الروابط الفرعية والمؤشرات.
لا يزال جدول الرموز غير المباشر موجودًا في حالة إنشاء ملفات Mach-O متوافقة مع الإصدارات السابقة والتي يتم تحميلها على إصدارات نظام التشغيل الأحدث والأقدم.
| إزاحة | بايت | وصف |
|---|---|---|
| 0 | 4 | 0x00000022 (نوع الأمر) |
| 4 | 4 | حجم الأمر (دائماً 48 بايت) |
| 8 | 4 | إعادة ضبط إزاحة الملف |
| 12 | 4 | حجم إعادة التأسيس |
| 16 | 4 | إزاحة ملف الربط |
| 20 | 4 | حجم الغلاف |
| 24 | 4 | إزاحة ملف الربط الضعيف |
| 28 | 4 | حجم التجليد الضعيف |
| 32 | 4 | إزاحة ملف الربط الكسول |
| 36 | 4 | حجم التجليد الكسول |
| 40 | 4 | إزاحة ملف التصدير |
| 44 | 4 | حجم التصدير |
أي إزاحات ملفات تساوي صفرًا هي أقسام غير مستخدمة.
معلومات الربط
تتم قراءة أقسام الربط، والربط الضعيف، والربط الكسول باستخدام نفس تنسيق رمز العملية.
في الأصل، كان جدول الرموز يحدد نوع العنوان في حقل معلومات البيانات في جدول الرموز على أنه كسول أو ضعيف أو غير كسول.
يعني الربط الضعيف أنه إذا تم تحديد المكتبة المراد البحث فيها بواسطة رقم المكتبة الترتيبي، ولم يكن اسم الرمز المحدد موجودًا ولكنه موجود في ملف Mach-O مختلف تم تحميله مسبقًا، فسيتم استخدام موقع الرمز من ملف Mach-O الآخر.
تعني كلمة "Lazy" أن العنوان الذي يُكتب موجود في dyld_stub_binder، والذي يبحث عن الرمز ثم يستدعي الدالة، ثم يستبدل موقع dyld_stub_binder بموقع الرمز. أي استدعاءات أخرى تتم من كود الآلة في الملف الثنائي ستنتقل الآن إلى عنوان الرمز ولن تستدعي dyld_stub_binder.
لا يقوم قسم الربط البسيط بأي عمليات تحميل أو عنونة معقدة. يجب أن يكون الرمز موجودًا في ترتيب مكتبة المجموعة.
تحدد قيمة البايت 0x1X رقم ترتيب مكتبة الارتباط. أما الرقم الست عشري X فهو رقم ترتيب المكتبة من 0 إلى 15.
تقوم قيمة البايت التي تتراوح من 0x20 إلى 0x2F بتعيين الرقم الترتيبي لمكتبة الارتباط إلى القيمة التي تتم قراءتها بعد رمز العملية.
تسلسل البايت 0x20 0x84 0x01 يحدد الرقم الترتيبي 132.
يتم ترميز القيمة العددية بعد رمز العملية كرقم LEB128 . تُجمع آخر 7 أرقام ثنائية لتكوين رقم أكبر، بشرط أن يكون الرقم الثنائي الأخير مساويًا للواحد. يتيح لنا هذا ترميز قيم عددية ذات أطوال متغيرة.
تحدد قيمة البايت 0x4X اسم الرمز. ويحدد الرقم الست عشري المسمى X إعداد العلامة.
يشير الإعداد 8 إلى أن الدالة مستوردة بشكل ضعيف. ويشير الإعداد 1 إلى أن الدالة مستوردة بشكل غير ضعيف.
يُحدد تسلسل البايتات 0x48 0x45 0x78 0x61 0x6D 0x70 0x6C 0x65 0x00 اسم الرمز Example. بايت الحرف النصي الأخير هو 0x00 . وهو مُستورد بشكل ضعيف، أي يُمكن استبداله إذا وُجد رمز آخر قابل للتصدير يحمل نفس الاسم.
تحدد قيمة البايت 0x7X الموقع الحالي. يشير الرقم السداسي العشري المُشار إليه بـ X إلى المقطع المُختار من 0 إلى 15. بعد رمز العملية، يُضاف الإزاحة كرقم LEB128 إلى إزاحة المقطع.
يقوم تسلسل البايت 0x72 0x8C 0x01 بتعيين الموقع إلى عنوان أمر تحميل الجزء الثالث ويضيف 140 إلى العنوان.
يربط رمز العملية من 0x90 إلى 0x9F موقع المجموعة الحالي باسم رمز المجموعة وترتيب المكتبة. يزيد موقع المجموعة الحالي بمقدار 4 بايتات لملف Mach-O ثنائي 32 بت، أو يزيد عنوان المجموعة بمقدار 8 بايتات لملف Mach-O ثنائي 64 بت.
تسلسل البايتات 0x11 0x72 0x8C 0x01 0x48 0x45 0x78 0x61 0x6D 0x70 0x6C 0x65 0x00 0x90 0x48 0x45 0x78 0x61 0x6D 0x70 0x6C 0x65 0x32 0x00 0x90
يُعيّن هذا الأمر ترتيب مكتبة الارتباط رقم 1. ثم يُعيّن الموقع إلى رقم المقطع 2، ويُضيف 140 إلى الموقع الحالي. يبحث عن رمز باسم Example في ترتيب المكتبة المُحدد. يكتب رمز العملية 0x90 عنوان الرمز ويزيد العنوان المُعيّن حاليًا. بعد ذلك، يُعيّن رمز العملية اسم الرمز التالي للبحث عن رمز باسم Example2. يكتب رمز العملية 0x90 عنوان الرمز ويزيد العنوان المُعيّن حاليًا.
يؤدي التنسيق الجديد إلى إزالة الحقول المتكررة في جدول الرموز ويجعل جدول الرموز غير المباشر قديمًا.
نقطة الدخول الرئيسية للتطبيق
يتم استخدام أمر التحميل الذي يبدأ بالنوع 0x00000028 لتحديد موقع العنوان الذي يبدأ التطبيق عنده.
| إزاحة | بايت | وصف |
|---|---|---|
| 0 | 4 | 0x00000028 (نوع الأمر) |
| 4 | 4 | حجم الأمر (دائماً 24 بايت) |
| 8 | 8 | موقع العنوان |
| 16 | 8 | حجم ذاكرة المكدس |
إذا لم تكن هناك حاجة لنقل أجزاء/أقسام البرنامج لتشغيله، فإن نقطة الدخول الرئيسية هي موقع العنوان المحدد. هذا ينطبق فقط في حال إضافة عناوين أجزاء التطبيق إلى عنوان أساسي للتطبيق يساوي صفرًا، وعدم حاجة الأقسام إلى أي عمليات نقل.
نقطة الدخول الرئيسية في مُحمِّل Mach-O هي عنوان البرنامج الأساسي بالإضافة إلى موقع العنوان. هذا هو العنوان الذي يُضبط عليه المعالج لبدء تنفيذ تعليمات لغة الآلة.
وقد حل هذا محل أمر التحميل القديم 0x00000005 الذي كان يختلف باختلاف نوع وحدة المعالجة المركزية لأنه كان يخزن الحالة التي يجب أن تكون عليها جميع السجلات قبل بدء البرنامج.
رقم تعريف التطبيق الفريد (UUID)
يتم استخدام أمر التحميل الذي يبدأ بالنوع 0x0000001B لتحديد المعرف الفريد عالميًا (UUID) للتطبيق.
| إزاحة | بايت | وصف |
|---|---|---|
| 0 | 4 | 0x0000001B (نوع الأمر) |
| 4 | 4 | حجم الأمر (دائماً 24 بايت) |
| 8 | 16 | معرّف فريد عالمي (UUID) ذو 128 بت |
يحتوي UUID على رقم عشوائي فريد مكون من 128 بت عند تجميع التطبيق والذي يمكن استخدامه لتحديد ملف التطبيق على الإنترنت أو في متاجر التطبيقات.
الحد الأدنى لإصدار نظام التشغيل
يتم استخدام أمر التحميل الذي يبدأ بالنوع 0x00000032 لتحديد الحد الأدنى من معلومات إصدار نظام التشغيل.
| إزاحة | بايت | وصف |
|---|---|---|
| 0 | 4 | 0x00000032 (نوع الأمر) |
| 4 | 4 | حجم القيادة |
| 8 | 4 | نوع المنصة |
| 12 | 4 | الحد الأدنى لإصدار نظام التشغيل |
| 16 | 4 | إصدار SDK |
| 20 | 4 | عدد الأدوات المستخدمة |
أنواع المنصات التي يُفترض أن يعمل عليها الملف الثنائي هي كما يلي:
| قيمة | منصة |
|---|---|
| 0x00000001 | نظام التشغيل macOS |
| 0x00000002 | نظام التشغيل iOS |
| 0x00000003 | tvOS |
| 0x00000004 | أرشيف |
| 0x00000005 | bridgeOS |
| 0x00000006 | ماك كاتاليست |
| 0x00000007 | محاكي نظام التشغيل iOS |
| 0x00000008 | محاكي tvOS |
| 0x00000009 | محاكي نظام التشغيل أندرويد |
| 0x0000000A | DriverKit |
| 0x0000000B | نظام التشغيل VisionOS |
| 0x0000000C | محاكي نظام التشغيل VisionOS |
تُقرأ قيمة الإصدار 32 بت كقيمة 16 بت وقيمتين 8 بت. على سبيل المثال، قيمة الإصدار 32 بت 0x000D0200 تُقسّم إلى: 0x000D (القيمة 13)، ثم 8 بتات التالية 0x02 (القيمة 2)، ثم 8 بتات الأخيرة 0x00 (القيمة صفر)، مما يُعطي رقم الإصدار 13.2.0v. تُقرأ قيمة إصدار SDK بنفس الطريقة.
عدد الأدوات اللازمة لإنشاء الملف الثنائي هو مجموعة من المدخلات التي تُقرأ على النحو التالي:
| إزاحة | بايت | وصف |
|---|---|---|
| 0 | 4 | نوع الأداة |
| 4 | 4 | إصدار الأداة |
قيم أنواع الأدوات هي كما يلي:
| قيمة | نوع الأداة المستخدمة |
|---|---|
| 0x00000001 | CLANG |
| 0x00000002 | سويفت |
| 0x00000003 | إل دي |
يُقرأ رقم الإصدار بنفس طريقة قراءة إصدار نظام التشغيل وإصدار SDK.
مع إطلاق نظام التشغيل Mac OS X 10.6، طرأت تعديلات جوهرية على ملف Mach-O، مما يجعل الملفات الثنائية المُجمّعة على جهاز يعمل بنظام 10.6 أو أحدث قابلة للتنفيذ (افتراضيًا) فقط على أجهزة تعمل بنظام Mac OS X 10.6 أو أحدث. ويعود هذا الاختلاف إلى أوامر التحميل التي لا يفهمها الرابط الديناميكي في الإصدارات السابقة من Mac OS X. ومن التغييرات المهمة الأخرى في تنسيق Mach-O تغيير طريقة __LINKEDITعمل جداول Link Edit (الموجودة في القسم). في الإصدار 10.6، تُضغط هذه الجداول الجديدة بإزالة البيانات غير المستخدمة وغير الضرورية؛ إلا أن نظام Mac OS X 10.5 والإصدارات الأقدم لا تستطيع قراءة تنسيق جدول Link Edit الجديد هذا. ولإنشاء ملفات تنفيذية متوافقة مع الإصدارات السابقة، يمكن استخدام علامة الرابط "-mmacosx-version-min=".
تطبيقات أخرى
محللات ومحررات لغة Mach-O
ليس من النادر أن يعمل باحثو الأمن وغيرهم مع ملفات Mach-O من مصادر أخرى غير أجهزة Mac. وتنتشر البرامج التي تتيح تحليل أو حتى تعديل بنية بيانات Mach-O (كصيغة ملف).
بالنسبة للغة البرمجة روبي ، توفر مكتبة ruby-macho [ 16 ] تطبيقًا لمحلل ومحرر ثنائي Mach-O.
عدائي ماخ-أو
نظريًا، يُمكن تشغيل برنامج بصيغة Mach-O، بواسطة كود قادر على تحميل صور Mach-O في الذاكرة، على أنظمة تشغيل أخرى غير النظام الذي صُمم البرنامج لأجله، طالما وُجدت صورة ثنائية لـ Mach-O تُطابق نوع المعالج في الحاسوب المُستخدم. تحتوي معظم الحواسيب المكتبية والمحمولة على معالجات x86 ، ما يعني أن Mach-O بملف ثنائي x86 سيتمكن من التشغيل بمجرد تحميل الأجزاء في الذاكرة. أما إذا كانت Mach-O تحتوي على ملفات ثنائية ARM فقط ، مثل برامج أجهزة iPhone أو iPad، فلا يُمكن تشغيلها إلا على حاسوب مزود بنواة ARM متوافقة (ليس بالضرورة نواة Apple Silicon )؛ وإلا، فسيتعين استخدام أداة محاكاة مثل QEMU، حيث سيتعين تحويل تعليمات ARM إلى تعليمات x86 مُكافئة باستخدام أدوات محاكاة المعالج مثل QEMU.
تتمثل إحدى المشكلات العملية في تحميل وتنفيذ برنامج Mach-O مباشرةً في ظهور "رموز غير مُعرَّفة": فالملفات الثنائية لا تعمل بمعزل عن غيرها، بل تستدعي دوالًا/أساليب (رموزًا) من ملفات Mach-O الثنائية (المكتبات) لكي تعمل؛ ويؤدي عدم العثور على رمز إلى ظهور هذا الخطأ. تفترض ملفات Mach-O الخاصة بأنظمة iPhone (iOS) وmacOS وwatchOS وtvOS وجود مجموعة مكتبات مختلفة، مما يُسبب عدم توافق ناتج عن هذه المشكلة. يجب أن تكون هذه المكتبات موجودة على الجهاز الذي يُحاول تشغيل البرنامج، أو أن يستبدلها مُحمِّل Mach-O باستخدام دوال التكييف الخاصة به أو الدوال الموجودة في أنظمة التشغيل المُضيفة. كما يجب أن تُوفر إجراءات المكتبة المُستدعاة نفس واجهة التطبيق الثنائية التي تُوفرها إجراءات نظام التشغيل المُخصصة للبرنامج الثنائي، أو يجب توفير إجراء تكييف.
- أُضيفت خاصية دعم لغة Mach-O إلى بعض إصدارات نظام NetBSD كجزء من تطبيق التوافق الثنائي، مما سمح بتشغيل بعض الملفات الثنائية لنظام Mac OS 10.3. [ 17 ] [ 18 ]
- بالنسبة لنظام لينكس، قام شينيتشيرو هاماجي بكتابة برنامج تحميل Mach-O قادر على تحميل الملفات الثنائية لنظام 10.6. [ 19 ] وكحلٍّ أكثر شمولاً يعتمد على برنامج التحميل هذا، يهدف مشروع دارلينج إلى توفير بيئة متكاملة تسمح بتشغيل تطبيقات macOS على نظام لينكس.
انظر أيضًا إلى قسم "المشاريع المشتقة من نظام التشغيل داروين" ، والذي يتضمن بعض الجهود الأخرى لتحقيق التوافق الثنائي بين نظامي macOS وiOS. حتى الجهود التي استندت مباشرةً إلى نواة داروين نفسها تطلبت إضافة أكواد لاستبدال المكتبات والمكونات الأخرى التي لم تُصدرها شركة آبل كمصدر مفتوح.
انظر أيضاً
مراجع
- ↑ مواضيع برمجة Mach-O (ملف PDF) . أبل. 28 نوفمبر 2006.
- ↑ "مرجع تنسيق ملف Mach-O لنظام التشغيل OS X ABI" . شركة أبل. 4 فبراير 2009. مؤرشف من الأصل في 4 سبتمبر 2014.
- ↑ أفاديس تيفانيان الابن؛ ريتشارد ف. رشيد؛ مايكل و. يونغ؛ ديفيد ب. غولوب؛ ماري ر. طومسون؛ ويليام بولوسكي؛ ريتشارد سانزي (يونيو 1987). "واجهة يونكس للذاكرة المشتركة وملفات الذاكرة المُرتبطة في نظام ماخ" . وقائع مؤتمر يوسينكس الصيفي . فينيكس، أريزونا، الولايات المتحدة الأمريكية: جمعية يوسينكس. الصفحات 53-67 .
- 1 2 "أنواع البيانات" . مرجع تنسيق ملفات Mach-O لنظام التشغيل OS X ABI . شركة آبل. 4 فبراير 2009 [2003]. مؤرشف من الأصل في 11 سبتمبر 2014. تم الاطلاع عليه في 15 مارس 2023 .
- ↑ xnu/EXTERNAL_HEADERS/mach-o/loader.h في main - apple-oss-distributions/xnu على GitHub
- 1 2 3 cctools/include/mach/machine-cctools.h في main - apple-oss-distributions/cctools على GitHub
- ↑ llvm-project/llvm/include/llvm/BinaryFormat/MachO.h في main - llvm-project/llvm على GitHub
- ↑ xnu/osfmk/mach/machine.h في main - apple-oss-distributions/xnu على GitHub
- ↑ "الملفات الثنائية الشاملة وملفات PowerPC الثنائية 32 بت/64 بت" . مرجع تنسيق ملفات Mach-O لنظام التشغيل OS X ABI . شركة آبل، 4 فبراير 2009 [2003]. مؤرشف من الأصل في 4 سبتمبر 2014.
- ↑ "بناء ملف تنفيذي شامل لنظام macOS" . مطورو Apple .
- ↑ "fat_header" . مرجع تنسيق ملفات Mach-O لنظام التشغيل OS X ABI . شركة Apple Inc. ، 4 فبراير 2009 [2003]. مؤرشف من الأصل في 4 سبتمبر 2014.
- ↑ "fat_arch" . مرجع تنسيق ملفات Mach-O لنظام التشغيل OS X ABI . شركة آبل، 4 فبراير 2009 [2003]. مؤرشف من الأصل في 4 سبتمبر 2014.
- ↑ "هياكل بيانات أمر التحميل" . مرجع تنسيق ملفات Mach-O لنظام التشغيل OS X ABI . شركة آبل، 4 فبراير 2009 [2003]. مؤرشف من الأصل في 11 سبتمبر 2014. تم الاطلاع عليه في 15 مارس 2023 .
- ↑ "segment_command" . مرجع تنسيق ملف Mach-O لنظام التشغيل OS X ABI . شركة آبل، 4 فبراير 2009 [2003]. مؤرشف من الأصل في 11 سبتمبر 2014. تم الاطلاع عليه في 15 مارس 2023 .
- ↑ "segment_command_64" . مرجع تنسيق ملفات Mach-O لنظام التشغيل OS X ABI . شركة آبل، 4 فبراير 2009 [2003]. مؤرشف من الأصل في 11 سبتمبر 2014. تم الاطلاع عليه في 15 مارس 2023 .
- ↑ ويليام وودروف (15 نوفمبر 2021)، مكتبة روبي خالصة لتحليل ملفات Mach-O.
- ↑ إيمانويل دريفوس (20 يونيو 2006). " التوافق الثنائي بين Mach وDarwin لأنظمة NetBSD/powerpc وNetBSD/i386" . تم الاطلاع عليه في 18 أكتوبر 2013 .
- ↑ إيمانويل دريفوس (سبتمبر 2004)، التوافق الثنائي لنظام التشغيل Mac OS X على NetBSD: التحديات والتنفيذ (PDF)
- ↑ شينيتشيرو هاماجي، مُحمِّل Mach-O لنظام لينكس - لقد كتبته...
فهرس
روابط خارجية
- مرجع تنسيق ملف Mach-O لنظام التشغيل OS X ABI في Wayback Machine (تمت أرشفته في 4 سبتمبر 2014) (شركة أبل).
- دليل تنسيقات الملفات لنظامي التشغيل داروين وماك أو إس
- ملفات كائنات Mach (وثائق NEXTSTEP)
- مرجع مكتبة Mach-O الديناميكية
- حيل ربط وتحميل Mach-O
- MachOView
- JDasm (أداة تفكيك متعددة المنصات، لأنظمة macOS و iOS و Windows PE و ELF، وأداة تحليل تنسيقات الملفات)
- تنسيقات الملفات القابلة للتنفيذ
- تطوير نظام التشغيل macOS
- التالي
- ماخ (نواة)
