
نواة هجينة تجمع بين Mach وFreeBSD وIOKit لنظامي macOS وiOS. تقدم خدمات نظام التشغيل الأساسية، إطار عمل السائق، وتطبيق سياسات الأمان على x86_64 وARM64.
نواة XNU هي جزء من نظام تشغيل Darwin المستخدم في أنظمة تشغيل macOS و iOS. XNU هو اختصار لعبارة X is Not Unix. XNU هي نواة هجينة تجمع بين نواة Mach التي طورتها جامعة Carnegie Mellon مع مكونات من FreeBSD وواجهة برمجة تطبيقات C++ لكتابة برامج التشغيل تسمى IOKit. تعمل XNU على x86_64 و ARM64 لكل من التكوينات أحادية المعالج ومتعددة المعالجات.
config - تكوينات لواجهات برمجة التطبيقات المصدرة للبنية الأساسية والمنصة المدعومة.SETUP - مجموعة أساسية من الأدوات المستخدمة لتكوين النواة، وإدارة الإصدارات، وإدارة رموز kext.EXTERNAL_HEADERS - ملفات الرأس المستمدة من مشاريع أخرى لتجنب دورات التبعية أثناء البناء. يجب مزامنة هذه الملفات بانتظام عند تحديث المصدر.libkern - كود مكتبة IOKit بلغة C++ للتعامل مع برامج التشغيل وملحقات النواة (kexts).libsa - كود تمهيد النواة لبدء التشغيل.libsyscall - واجهة مكتبة استدعاءات النظام لبرامج مساحة المستخدم.libkdd - مصدر مكتبة المستخدم لتحليل بيانات النواة مثل البيانات المجزأة للنواة.makedefs - قواعد وتعريفات المستوى الأعلى لبناء النواة.osfmk - الأنظمة الفرعية القائمة على نواة Mach.pexpert - كود خاص بالمنصة مثل معالجة المقاطعات، الذريات، إلخ.security - واجهات سياسة فحص الوصول الإلزامي والتنفيذ المرتبط بها.bsd - كود الأنظمة الفرعية لـ BSD.tools - مجموعة من الأدوات لاختبار وتصحيح وتحليل أداء النواة.DEVELOPMENTيمكن لنظام make الخاص بـ xnu بناء نواة بناءً على متغيرات KERNEL_CONFIGS و ARCH_CONFIGS كوسائط.
إليك الصيغة:```text
make SDKROOT= ARCH_CONFIGS= KERNEL_CONFIGS=
Where:
* `<sdkroot>`: المسار إلى macOS SDK على القرص. (الافتراضي `/`)
* `<variant>`: يمكن أن يكون `debug`، `development`، `release`، `profile` ويقوم بتكوين أعلام الترجمة والتأكيدات عبر كود النواة.
* `<arch>`: يمكن أن يكون بنية صالحة للبناء من أجلها. (مثال: `X86_64`)
لبناء نواة لنفس بنية نظام التشغيل الجاري، اكتب فقط```text
make SDKROOT=macosx.internal
بالإضافة إلى ذلك، هناك دعم لتكوين البنى من خلال ARCH_CONFIGS وتكوينات النواة باستخدام KERNEL_CONFIGS.```text
make SDKROOT=macosx.internal ARCH_CONFIGS=X86_64 KERNEL_CONFIGS=DEVELOPMENT
make SDKROOT=macosx.internal ARCH_CONFIGS=X86_64 KERNEL_CONFIGS="RELEASE DEVELOPMENT DEBUG"
> ملاحظة: يتم تعيين البنية افتراضيًا على بنية جهاز البناء، ويتم تعيين تكوين kernel الافتراضي للبناء من أجل `DEVELOPMENT`.
سيؤدي هذا أيضًا إلى إنشاء صورة قابلة للإقلاع، و kernel.[config]، وملف ثنائي للنواة مع الرموز، kernel.[config].unstripped.
لتثبيت kernel في DSTROOT، استخدم الهدف `install_kernels`:```text
make install_kernels DSTROOT=/tmp/xnu-dst
للحصول على تجربة تصحيح أخطاء النواة أكثر إرضاءً، مع الوصول إلى جميع المتغيرات والوسائط المحلية، ولكن دون جميع الفحوصات الإضافية لنواة DEBUG، أضف شيئًا مثل ما يلي إلى أمر make الخاص بك:```text CFLAGS_DEVELOPMENTARM64="-O0 -g -DKERNEL_STACK_MULTIPLIER=2" CXXFLAGS_DEVELOPMENTARM64="-O0 -g -DKERNEL_STACK_MULTIPLIER=2"
تذكر استبدال `DEVELOPMENT` و `ARM64` بالبناء والمنصة المناسبين.
> الخيارات الإضافية: يمكنك تمرير خيارات إضافية لمجمع C من سطر الأوامر باستخدام إعداد البناء `EXTRA_CFLAGS`. يتم إلحاق هذه الخيارات بقاعدة `CFLAGS`، والقيمة الافتراضية للإعداد هي سلسلة فارغة.
>
> يتيح لك هذا الإعداد، على سبيل المثال، تشغيل كود التصحيح بشكل انتقائي المحمي بواسطة ماكرو المعالج المسبق. مثال الاستخدام...
>
> ```text
> make SDKROOT=macosx.internal PRODUCT_CONFIGS=j314s
> EXTRA_CFLAGS='-DKERNEL_STACK_MULTIPLIER=2'
> ```
* لبناء مع تكوين نواة RELEASE
```text
make KERNEL_CONFIGS=RELEASE SDKROOT=/path/to/SDK
```
### بناء ثنائي نواة FAT
حدد البنى في بيئتك أو عند تشغيل أمر make.```text
make ARCH_CONFIGS="X86_64" exporthdrs all
يمكن لنظام بناء XNU اختياريا إخراج مخرجات بناء ملونة. لتمكين ذلك، يمكنك إما
تعيين متغير البيئة XNU_LOGCOLORS إلى y، أو يمكنك تمرير LOGCOLORS=y لأمر make.
يتم اشتقاق إصدار xnu من SDK أو KDK عن طريق قراءة CFBundleVersion
من ملف System/Library/Extensions/System.kext/Info.plist الخاص بهما.
يمكن تخصيص ذلك عن طريق تعيين المتغير RC_DARWIN_KERNEL_VERSION في
البيئة أو في سطر أمر make.
انظر doc/building/xnu_version.md لمزيد من التفاصيل.
بشكل افتراضي، يتم إنشاء مستودع معلومات تصحيح DWARF أثناء مرحلة التثبيت؛ وهو "حزمة" تحمل اسم kernel.development.<variant>.dSYM لتحديد تنسيق معلومات تصحيح STABS الأقدم (حيث تكون معلومات التصحيح مضمنة في صورة kernel.development.unstripped)، قم بتعيين متغير البيئة BUILD_STABS.```sh export BUILD_STABS=1 make
## بناء ذواكر النواة (KernelCaches)
لاختبار نواة xnu، تحتاج إلى بناء ذاكرة نواة (kernelcache) تربط الإضافات (kexts) والنواة معًا في صورة واحدة قابلة للإقلاع.
لبناء ذاكرة نواة، يمكنك استخدام الآليات التالية:
* استخدام التوليد التلقائي لذاكرة النواة مع `kextd`.
يقوم البرنامج الخفي `kextd` بمراقبة التغييرات في دليل `/System/Library/Extensions`.
لذا يمكنك إعداد نواة جديدة كالتالي:
```text
cp BUILD/obj/DEVELOPMENT/X86_64/kernel.development /System/Library/Kernels/
touch /System/Library/Extensions
ps -e | grep kextd
```
* استدعاء `kextcache` يدويًا لبناء ذاكرة نواة جديدة.
```text
kextcache -q -z -a x86_64 -l -n -c /var/tmp/kernelcache.test -K /var/tmp/kernel.test /System/Library/Extensions
```
## إقلاع ذاكرة نواة على جهاز مستهدف
يدعم كل من النواة التطويرية و iBoot تكوين وسائط الإقلاع (boot arguments) بحيث يمكننا الإقلاع بأمان إلى نواة اختبارية، وإذا حدث خطأ، نعود بأمان إلى ذاكرة النواة المستخدمة سابقًا.
فيما يلي خطوات تحقيق هذا الإعداد:
1. إنشاء ذاكرة نواة باستخدام أمر kextcache باسم `/kernelcache.test`
2. نسخ تكوينات الإقلاع الحالية إلى ملف بديل
```sh
cp /Library/Preferences/SystemConfiguration/com.apple.Boot.plist /next_boot.plist
```
3. تحديث ذاكرة النواة ووسائط الإقلاع لإعدادك
```sh
plutil -insert "Kernel Cache" -string "kernelcache.test" /next_boot.plist
plutil -replace "Kernel Flags" -string "debug=0x144 -v kernelsuffix=test " /next_boot.plist
```
4. نسخ التكوين الجديد إلى `/Library/Preferences/SystemConfiguration/`
```sh
cp /next_boot.plist /Library/Preferences/SystemConfiguration/boot.plist
```
5. بارك (bless) الحجم بالتكوينات الجديدة.
```text
sudo -n bless --mount / --setBoot --nextonly --options "config=boot"
```
العلامة `--nextonly` تحدد استخدام تكوينات `boot.plist` فقط لمرة إقلاع واحدة.
لذا إذا حدث ذعر في النواة، يمكنك بسهولة إعادة التشغيل والتعافي إلى النواة الأصلية.
## إنشاء علامات (tags) وقاعدة cscope
أعد بيئة البناء ومن الدليل العلوي، قم بتشغيل:
make tags # سيبني هذا ctags و etags على وحدة تخزين حساسة لحالة الأحرف، و ctags فقط على غير حساسة
make TAGS # سيبني هذا etags
make cscope # سيبني هذا قاعدة بيانات cscope
## تثبيت ملفات الرؤوس الجديدة من XNU
تقوم XNU بتثبيت ملفات الرؤوس في المواقع التالية -
a. $(DSTROOT)/System/Library/Frameworks/Kernel.framework/Headers
b. $(DSTROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders
c. $(DSTROOT)/usr/include/
d. $(DSTROOT)/usr/local/include/
e. $(DSTROOT)/System/DriverKit/usr/include/
f. $(DSTROOT)/System/Library/Frameworks/IOKit.framework/Headers
g. $(DSTROOT)/System/Library/Frameworks/IOKit.framework/PrivateHeaders
h. $(DSTROOT)/System/Library/Frameworks/System.framework/PrivateHeaders
`Kernel.framework` يُستخدم بواسطة إضافات النواة.
`System.framework` و `/usr/include` و `/usr/local/include` تُستخدم بواسطة تطبيقات مستوى المستخدم.
`IOKit.framework` يُستخدم بواسطة عملاء IOKit في مساحة المستخدم.
`/System/DriverKit/usr/include` يُستخدم بواسطة برامج تشغيل مساحة المستخدم.
ملفات الرؤوس في `PrivateHeaders` الخاصة بالإطارات متاحة فقط لـ **التطوير الداخلي لـ Apple**.
يجب أن يحتوي الدليل الذي يحتوي على ملف الرأس على ملف Makefile ينشئ قائمة الملفات التي يجب تثبيتها في مواقع مختلفة.
إذا كنت تضيف أول ملف رأس في دليل، فستحتاج إلى إنشاء Makefile مشابه لـ `xnu/bsd/sys/Makefile`.
أضف ملف الرأس الخاص بك إلى قائمة الملفات الصحيحة اعتمادًا على المكان الذي تريد تثبيته فيه. المواقع الافتراضية التي يتم تثبيت ملفات الرؤوس منها من كل قائمة ملفات هي -
a. `DATAFILES`: لجعل ملف الرأس متاحًا في مستوى المستخدم -
`$(DSTROOT)/usr/include`
`$(DSTROOT)/System/Library/Frameworks/System.framework/PrivateHeaders`
b. `DRIVERKIT_DATAFILES`: لجعل ملف الرأس متاحًا لبرامج تشغيل DriverKit في مساحة المستخدم -
`$(DSTROOT)/System/DriverKit/usr/include`
c. `PRIVATE_DATAFILES`: لجعل ملف الرأس متاحًا لـ Apple داخليًا في
مستوى المستخدم -
`$(DSTROOT)/System/Library/Frameworks/System.framework/PrivateHeaders`
d. `EMBEDDED_PRIVATE_DATAFILES`: لجعل ملف الرأس متاحًا في مستوى المستخدم
لـ macOS كـ `EXTRA_DATAFILES`، ولكن Apple داخليًا في مستوى المستخدم
لأنظمة التشغيل المضمنة كـ `EXTRA_PRIVATE_DATAFILES` -
`$(DSTROOT)/usr/include` (`EXTRA_DATAFILES`)
`$(DSTROOT)/usr/local/include` (`EXTRA_PRIVATE_DATAFILES`)
e. `KERNELFILES`: لجعل ملف الرأس متاحًا في مستوى النواة -
`$(DSTROOT)/System/Library/Frameworks/Kernel.framework/Headers`
`$(DSTROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders`
f. `PRIVATE_KERNELFILES`: لجعل ملف الرأس متاحًا لـ Apple داخليًا
لإضافات النواة -
`$(DSTROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders`
g. `MODULEMAPFILES`: لجعل ملف خريطة الوحدة متاحًا في مستوى المستخدم -
`$(DSTROOT)/usr/include`
h. `PRIVATE_MODULEMAPFILES`: لجعل ملف خريطة الوحدة متاحًا لـ Apple
داخليًا في مستوى المستخدم -
`$(DSTROOT)/usr/local/include`
i. `LIBCXX_DATAFILES`: لجعل ملف الرأس متاحًا لعملاء libcxx داخل النواة:
`$(DSTROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders/kernel_sdkroot`
j. `EXCLAVEKIT_DATAFILES`: لجعل ملف الرأس متاحًا لـ Apple داخليًا
لـ ExclaveKit SDK -
`$(DSTROOT)/System/ExclaveKit/usr/include`
k. `EXCLAVECORE_DATAFILES`: لجعل ملف الرأس متاحًا لـ Apple داخليًا
لـ ExclaveCore SDK -
`$(DSTROOT)/System/ExclaveCore/usr/include`
يقوم ملف Makefile بدمج قوائم الملفات المذكورة أعلاه في قوائم تثبيت مختلفة يستخدمها نظام البناء لتثبيت ملفات الرؤوس. هناك نوعان من قوائم التثبيت: المعتمدة على الآلة والمستقلة عن الآلة.
يُشار إلى هذه القوائم بوجود `MD` و `MI` في إعداد البناء، على التوالي. إذا كان رأسك خاصًا بمعمارية معينة، فيجب عليك استخدام قائمة تثبيت معتمدة على الآلة (مثل `INSTALL_MD_LIST`). إذا كان يجب تثبيت رأسك لجميع المعماريات، فيجب عليك استخدام قائمة تثبيت مستقلة عن الآلة (مثل `INSTALL_MI_LIST`).
إذا كانت قائمة التثبيت التي تهمك غير موجودة، فأنشئها عن طريق إضافة قوائم الملفات المناسبة. قوائم التثبيت الافتراضية، وقوائم الملفات الأعضاء فيها ومواقعها الافتراضية موصوفة أدناه -
a. `INSTALL_MI_LIST`، `INSTALL_MODULEMAP_MI_LIST`: تثبيت ملفات الرؤوس وخرائط الوحدة
إلى موقع متاح للجميع في مستوى المستخدم.
المواقع -
$(DSTROOT)/usr/include
التعريف -
INSTALL_MI_LIST = ${DATAFILES}
INSTALL_MODULEMAP_MI_LIST = ${MODULEMAPFILES}
b. `INSTALL_DRIVERKIT_MI_LIST`: تثبيت ملف الرأس إلى موقع
متاح لبرامج تشغيل DriverKit في مساحة المستخدم.
المواقع -
$(DSTROOT)/System/DriverKit/usr/include
التعريف -
INSTALL_DRIVERKIT_MI_LIST = ${DRIVERKIT_DATAFILES}
c. `INSTALL_MI_LCL_LIST`، `INSTALL_MODULEMAP_MI_LCL_LIST`: تثبيت ملفات الرؤوس وخرائط الوحدة
إلى موقع متاح لـ Apple داخليًا في مستوى المستخدم.
المواقع -
$(DSTROOT)/usr/local/include
التعريف -
INSTALL_MI_LCL_LIST =
INSTALL_MODULEMAP_MI_LCL_LIST = ${PRIVATE_MODULEMAPFILES}
d. `INSTALL_IF_MI_LIST`: تثبيت ملف الرأس إلى موقع متاح
للجميع لعملاء IOKit في مساحة المستخدم.
المواقع -
$(DSTROOT)/System/Library/Frameworks/IOKit.framework/Headers
التعريف -
INSTALL_IF_MI_LIST = ${DATAFILES}
e. `INSTALL_IF_MI_LCL_LIST`: تثبيت ملف الرأس إلى موقع
متاح لـ Apple داخليًا لعملاء IOKit في مساحة المستخدم.
المواقع -
$(DSTROOT)/System/Library/Frameworks/IOKit.framework/PrivateHeaders
التعريف -
INSTALL_IF_MI_LCL_LIST = ${DATAFILES} ${PRIVATE_DATAFILES}
f. `INSTALL_SF_MI_LCL_LIST`: تثبيت ملف الرأس إلى موقع متاح
لـ Apple داخليًا في مستوى المستخدم.
المواقع -
$(DSTROOT)/System/Library/Frameworks/System.framework/PrivateHeaders
التعريف -
INSTALL_SF_MI_LCL_LIST = ${DATAFILES} ${PRIVATE_DATAFILES}
g. `INSTALL_KF_MI_LIST`: تثبيت ملف الرأس إلى موقع متاح
للجميع لإضافات النواة.
المواقع -
$(DSTROOT)/System/Library/Frameworks/Kernel.framework/Headers
التعريف -
INSTALL_KF_MI_LIST = ${KERNELFILES}
h. `INSTALL_KF_MI_LCL_LIST`: تثبيت ملف الرأس إلى موقع
متاح لـ Apple داخليًا لإضافات النواة.
المواقع -
$(DSTROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders
التعريف -
INSTALL_KF_MI_LCL_LIST = ${KERNELFILES} ${PRIVATE_KERNELFILES}
i. `EXPORT_MI_LIST`: تصدير ملف الرأس إلى جميع أجزاء xnu (bsd/, osfmk/, إلخ)
للترجمة فقط. لا يقوم بتثبيت أي شيء في SDK.
التعريف -
EXPORT_MI_LIST = ${KERNELFILES} ${PRIVATE_KERNELFILES}
j. `INSTALL_KF_LIBCXX_MI_LIST`: تثبيت ملف الرأس لدعم libc++ داخل النواة.
المواقع -
$(DSTROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders/kernel_sdkroot
التعريف -
INSTALL_KF_LIBCXX_MI_LIST = ${LIBCXX_DATAFILES}
k. `INSTALL_EXCLAVEKIT_MI_LIST`: تثبيت ملف الرأس إلى موقع
متاح لـ Apple داخليًا لـ ExclaveKit.
المواقع -
$(DSTROOT)/System/ExclaveKit/usr/include
التعريف -
INSTALL_EXCLAVEKIT_MI_LIST = ${EXCLAVEKIT_DATAFILES}
l. `INSTALL_EXCLAVECORE_MI_LIST`: تثبيت ملف الرأس إلى موقع
متاح لـ Apple داخليًا لـ ExclaveCore.
المواقع -
$(DSTROOT)/System/ExclaveCore/usr/include
التعريف -
INSTALL_EXCLAVECORE_MI_LIST = ${EXCLAVECORE_DATAFILES}
إذا كنت تريد تثبيت ملف الرأس في دليل فرعي من المسارات
الموصوفة في (1)، حدد اسم الدليل باستخدام متغيرين
`INSTALL_MI_DIR` و `EXPORT_MI_DIR` على النحو التالي -```text
INSTALL_MI_DIR = dirname
EXPORT_MI_DIR = dirname
إذا كنت تريد تثبيت ملف خريطة الوحدة في دليل فرعي، فحدد اسم الدليل
باستخدام المتغير INSTALL_MODULEMAP_MI_DIR كما يلي -```text
INSTALL_MODULEMAP_MI_DIR = dirname
يمكن لملف رأس واحد أن يوجد في مواقع مختلفة باستخدام الخطوات المذكورة أعلاه. ومع ذلك، قد لا يكون من المرغوب فيه جعل كل الكود الموجود في ملف الرأس متاحًا في جميع المواقع. على سبيل المثال، تريد تصدير دالة فقط إلى مستوى النواة وليس إلى مستوى المستخدم.
يمكنك استخدام توجيهات المعالج المسبق للغة C (`#ifdef`, `#endif`, `#ifndef`) للتحكم في النص الذي يتم إنشاؤه قبل تثبيت ملف رأس. تتضمن النواة فقط الكود إذا كان الماكرو الشرطي `TRUE` وتستبعد الكود الخاص بالشروط `FALSE` من ملف الرأس.
بعض الماكروات المحددة مسبقًا وأوصافها هي -
1. `PRIVATE` : إذا تم تعريفه، تعتبر التعريفات المضمنة واجهات خاصة بالنظام. تكون مرئية داخل xnu ومكشوفة في رؤوس المستخدم/النواة المثبتة ضمن أقسام "PrivateHeaders" الخاصة بـ AppleInternal في إطاري System وKernel.
2. `KERNEL_PRIVATE` : إذا تم تعريفه، يكون الكود المضمن متاحًا لجميع نواة xnu وملحقات النواة الداخلية لـ Apple ويتم حذفه من رؤوس المستخدم.
3. `BSD_KERNEL_PRIVATE` : إذا تم تعريفه، يكون الكود المضمن مرئيًا حصريًا داخل وحدة xnu/bsd.
4. `MACH_KERNEL_PRIVATE`: إذا تم تعريفه، يكون الكود المضمن مرئيًا حصريًا داخل وحدة xnu/osfmk.
5. `XNU_KERNEL_PRIVATE`: إذا تم تعريفه، يكون الكود المضمن مرئيًا حصريًا داخل xnu.
6. `KERNEL` : إذا تم تعريفه، يكون الكود المضمن متاحًا داخل xnu وملحقات النواة ولا يكون مرئيًا في ملفات رأس مستوى المستخدم. فقط ملفات الرأس المثبتة في المسارات التالية ستحتوي على الكود -
```text
$(DSTROOT)/System/Library/Frameworks/Kernel.framework/Headers
$(DSTROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders
```
7. `DRIVERKIT`: إذا تم تعريفه، يكون الكود المضمن مرئيًا حصريًا في رؤوس SDK الخاصة بـ DriverKit المستخدمة بواسطة برامج تشغيل فضاء المستخدم.
8. `EXCLAVEKIT`: إذا تم تعريفه، يكون الكود المضمن مرئيًا حصريًا في رؤوس SDK الخاصة بـ ExclaveKit.
9. `EXCLAVECORE`: إذا تم تعريفه، يكون الكود المضمن مرئيًا حصريًا في رؤوس SDK الخاصة بـ ExclaveCore.
10. `MODULES_SUPPORTED` إذا تم تعريفه، يكون الكود المضمن مرئيًا حصريًا في المواقع التي تدعم الوحدات/Swift (أي ليس إطاري System أو Kernel).
## اصطلاح تسمية ملفات رأس VM
تتبع رؤوس VM اصطلاحات التسمية التالية:
* تحتوي رؤوس `*_internal.h` على مكونات نظام VM الفرعي للاستخدام فقط من قبل كود VM.
* تحتوي رؤوس `*_xnu.h` على مكونات نظام VM الفرعي للاستخدام فقط من قبل كود xnu الآخر.
* تحتوي رؤوس `*.h` على مكونات نظام VM الفرعي التي يتم تصديرها إلى kexts.
* يحتوي رأس `vm_iokit.h` على مكونات نظام VM الفرعي التي يتم تصديرها إلى نظام iokit الفرعي.
* يحتوي رأس `vm_ubc.h` على مكونات نظام VM الفرعي التي يتم تصديرها إلى نظام ubc الفرعي.
## اصطلاح تسمية ملفات خريطة الوحدة
في الحالة البسيطة، يمكن تمثيل دليل فرعي من `usr/include` أو `usr/local/include` بوحدة مستقلة. حيثما ينطبق ذلك، قم بتعيين `INSTALL_MODULEMAP_MI_DIR` إلى `INSTALL_MI_DIR` وقم بتثبيت ملف `module.modulemap` هناك. يتم استخدام `module.modulemap` حتى للوحدات الخاصة في `usr/local/include`؛ لا يتم استخدام `module.private.modulemap`. تحذير: للبقاء في الحالة البسيطة، يجب أن يكون اسم الوحدة مطابقًا تمامًا لاسم الدليل. إذا كان ذلك غير ممكن، فستحتاج إلى تطبيق الطريقة التالية.
يساهم `xnu` في الوحدات المعرفة في CoreOSModuleMaps عن طريق تثبيت ملفات خريطة وحدة مصدرها من `usr/include/module.modulemap` و `usr/local/include/module.modulemap`. اصطلاح التسمية لملفات خريطة الوحدة الخاصة بـ `xnu` هو كما يلي.
أ. من الناحية المثالية، يغطي ملف خريطة الوحدة دليلاً كاملاً. سيتم تسمية ملف خريطة وحدة يغطي `usr/include/a/b/c` باسم `a_b_c.modulemap`. بينما `usr/local/include/a/b/c` سيكون `a_b_c_private.modulemap`.
ب. بعض الرؤوس خاصة وتتطلب وحدة خاصة بها. في هذه الحالة، سيتم تسمية ملف خريطة الوحدة باسم الوحدة التي يعرفها. سيتم تسمية ملف خريطة وحدة يعرف الوحدة `One.Two.Three` باسم `one_two_three.modulemap`.
## الترجمة الشرطية
يوفر `xnu` الآليات التالية لترجمة الكود بشكل شرطي:
1. *خصائص وحدة المعالجة المركزية* إذا كان الكود الذي تقوم بتأمينه له خصائص محددة ستختلف فقط بناءً على بنية وحدة المعالجة المركزية المستهدفة، فاستخدم هذا الخيار. يُفضل التحقق من ميزات البنية (مثل `__LP64__`, `__LITTLE_ENDIAN__`, إلخ).
2. *الميزات الجديدة* إذا كان الكود الذي تقوم بتأمينه، عند تجميعه معًا، ينفذ ميزة، فيجب عليك تعريف ميزة جديدة في `config/MASTER` واستخدام رمز `CONFIG` المعالج المسبق الناتج (على سبيل المثال لميزة باسم `config_virtual_memory`، تحقق من `#if CONFIG_VIRTUAL_MEMORY`). تضمن هذه الممارسة إمكانية نقل الميزات الحالية إلى منصات أخرى بمجرد تغيير مفتاح الميزة.
3. *الميزات الحالية* يمكنك استخدام الميزات الحالية إذا كان الكود الخاص بك مرتبطًا بها بشدة (على سبيل المثال استخدم `SECURE_KERNEL` إذا كان الكود الخاص بك ينفذ وظائف جديدة ذات صلة حصرية بالنواة الموثوقة ويحدث تعريف/فهم ما يعنيه أن تكون نواة موثوقة).
يوصى بتجنب الترجمة بناءً على المنصة المستهدفة. لا يعرّف `xnu` ماكروات المنصة من `TargetConditionals.h` (`TARGET_OS_OSX`, `TARGET_OS_IOS`, إلخ).
## تصحيح أخطاء XNU
بشكل افتراضي، يتم إعادة تشغيل النواة في حالة حدوث ذعر. يمكن تجاوز هذا السلوك باستخدام وسيط الإقلاع `debug` -- `debug=0x14e` سيؤدي إلى انتظار الذعر لمصحح الأخطاء للاتصال. لإقلاع نواة بحيث يمكن تصحيح أخطائها بواسطة جهاز متصل، قم بتجاوز وسيط الإقلاع `kdp_match_name` باستخدام واجهة `ifconfig` المناسبة. يتم دعم تصحيح الأخطاء عبر Ethernet و Thunderbolt والتسلسلي، اعتمادًا على الأجهزة.
استخدم LLDB لتصحيح أخطاء النواة:```text
xcrun -sdk macosx lldb <path-to-unstripped-kernel>
(lldb) gdb-remote [<host-ip>:]<port>
معلومات تصحيح الأخطاء الخاصة بالنواة (dSYM) تأتي مع مجموعة من وحدات الماكرو لدعم تصحيح أخطاء النواة. لتحميل هذه الوحدات تلقائيًا عند الاتصال بالنواة، أضف ما يلي إلى ~/.lldbinit:```text
settings set target.load-script-from-symbol-file true
`tools/lldbmacros` يحتوي على المصدر لهذه الأوامر.
انظر إلى ملف README في هذا الدليل لمعرفة استخدامها، أو استخدم تعليمات LLDB المضمنة مع:```text
(lldb) help showcurrentstacks