اگر زمان طولانی کامپایل پروژههای بزرگ C++ یا Rust شما را کلافه کرده است، ابزاری که قرار است این گلوگاه را از بین ببرد، حالا امنتر و پایدارتر شده است. mold در نسخه ۳.۰.۰ با یک چرخش بنیادین، تمام کدهای خود را از C++ به Rust منتقل کرد تا سرعت خیرهکننده خود را با ایمنی حافظه ترکیب کند. این تغییر استراتژیک با هدف حذف آسیبپذیریهای مربوط به ایمنی حافظه صورت گرفته است، در حالی که سرعت فوقالعادهای که ویژگی اصلی این ابزار است، کاملاً حفظ شده است. همانطور که در یادداشتهای انتشار نسخه ۲.۴۲.۱ ذکر شده، آن نسخه آخرین انتشار مبتنی بر C++ بود و نسخه ۳.۰.۰ نخستین نسخه بازنویسیشده با Rust است.
برای درک اهمیت این خبر، ابتدا باید بدانیم لینکر (Linker) — شبیه به یک تکهدوز حرفهای که قطعات مختلف پارچه را به هم میدوزد تا یک لباس کامل شود — آخرین مرحله از فرآیند ساخت نرمافزار است که فایلهای شیء (Object Files) را به یک فایل اجرایی واحد تبدیل میکند. در حالی که GNU ld استاندارد صنعت است، اما در پروژههای مقیاسبزرگ C++ یا Rust بهشدت کند عمل میکند و اغلب به یک گلوگاه تبدیل میشود. mold برای حل این مشکل طراحی شد و اکنون انتقال به Rust یک حرکت استراتژیک است تا این ابزار به اندازه کافی پایدار شود که به عنوان پیشفرض سیستم در توزیعهای لینوکس قرار گیرد. هدف سری ۳.x این است که شکافهای سازگاری باقیمانده با GNU ld، بهویژه در پشتیبانی از اسکریپتهای لینکر، کاملاً پر شود.
به نقل از مستندات رسمی در گیتهاب، نسخه C++ ابزار mold در مواجهه با فایلهای ورودی خراب، به دلیل خواندن حافظه خارج از محدوده (out-of-bounds memory reads)، دچار خطاهای Segmentation Fault میشد. در mold 3.0، تمام این عملیاتها اکنون دارای بررسی محدوده (bounds-checked) هستند. بهجای یک کرش ناگهانی و خاموش یا ایجاد یک آسیبپذیری امنیتی، لینکر اکنون در نقطه دسترسی اشتباه، یک «Panic» کنترلشده را فعال میکند.
تیم توسعه برای اطمینان از اینکه عملکرد ابزار با نسخه ۲.۴۲.۱ برابری میکند، تمام بستههای Gentoo را با نسخه جدید ساختند و مجموعهای جامع از تستها را روی تمامی معماریهای مورد پشتیبانی اجرا کردند تا مطمئن شوند هیچ پسرفت (Regression) در بازنویسی رخ نداده است. آنها خروجی لینکر را در طیف گستردهای از حجمهای کاری واقعی و ترکیبات مختلف گزینهها مقایسه کردند تا تأیید کنند mold 3.0 یک جایگزین مستقیم (Drop-in replacement) برای نسخه ۲.۴۲.۱ است؛ به این معنا که همان گزینههای خط فرمان را میپذیرد و از همان معماریهای هدف پشتیبانی میکند.
ساختار سیستم ساخت (Build System) نیز بهطور کامل تغییر کرده است. این پروژه CMake را کنار گذاشته و اکنون از Cargo — مدیر بستههای زبان Rust — استفاده میکند. متغیر CMake با نام MOLD_TARGETS اکنون با ویژگیهای (Features) Cargo جایگزین شده است و مجموعه تستها بهجای ctest با دستور cargo test اجرا میشوند.
جزئیات فنی تغییرات زیرساختی عبارتند از:
- نیازمندیها: کاربران اکنون به Rust 1.95 یا نسخههای جدیدتر و یک کامپایلر استاندارد C نیاز دارند. اسکریپت
install-build-deps.shباinstall-test-deps.shجایگزین شده که فقط برای اجرای تستها مورد نیاز است. - فرآیند ساخت: ابزار با دستور
cargo build --releaseساخته شده و از طریق اسکریپتinstall-mold.shنصب میشود. این اسکریپت نصب، متغیرهایPREFIXوDESTDIRرا میپذیرد. - وابستگیها: mold دیگر به oneTBB وابسته نیست. این ابزار همچنان mimalloc 3.5.3 را بهصورت استاتیک لینک میکند، هرچند کاربران میتوانند با پرچم
--features system-allocatorاز تخصیصکننده سیستم استفاده کنند. همچنین در صورت موجود بودن، zlib سیستم را لینک میکند و شامل zstd و BLAKE3 است؛ کاربران میتوانند برای لینک کردن zstd سیستم، مقدارZSTD_SYS_USE_PKG_CONFIG=1را تنظیم کنند. - مدیریت کتابخانهها: اگر کتابخانهها خارج از پیشفرض (مثلاً در
/usr/lib64) نصب شده باشند، کاربران باید متغیر محیطیMOLD_LIBDIRرا تنظیم کنند تاmold -runبتواند Wrapper را پیدا کند.
طبق گزارش گیتهاب، یکی از اولویتهای سری ۳.x، پر کردن شکافهای سازگاری با GNU ld است. در این نسخه، چندین باگ بحرانی رفع شده است:
- پایداری: رفع کرشها هنگام ساخت فایلهای اجرایی با لینک استاتیک که از اسکریپتهای نسخه یا
--default-symverاستفاده میکردند. همچنین کرشها یا خروجیهای خراب در حالتی که فایل خروجی همزمان فایل ورودی بود (مانندmold -r -o foo.o foo.o bar.o) برطرف شد. - مدیریت نمادها: نمادهای رایج با نام یکسان اما اندازههای متفاوت، اکنون بزرگترین اندازه و سختگیرانهترین تراز (Alignment) را میپذیرند که دقیقاً مشابه رفتار GNU ld و lld است. علاوه بر این، گزینه
--gc-sectionsدیگر توابعی را که توسط--initو--finiارائه شدهاند، حذف نمیکند. - بهبودهای ICF: گزینه
--icf=safeدیگر توابع صادر شده از کتابخانههای مشترک (Shared Libraries) را ادغام (Fold) نمیکند و--icf=allهنگام استفاده با--emit-relocsدیگر باعث کرش نمیشود. - خروجیهای قطعی: تیم توسعه چندین مورد از خروجیهای غیرقطعی (Non-deterministic) را که بر
--dependency-file،--repro، جابهجاییهای پویا (Dynamic Relocations) و دستور-rبا گروههای COMDAT همنام اثر میگذاشت، حل کرد. - تجزیه خط فرمان: گزینههایی که با یک خط تیره شروع میشوند، اکنون دقیقاً مشابه GNU ld خوانده میشوند. برای مثال،
-entry=mainدیگر بهاشتباه به صورت-e ntry=mainتفسیر نمیشود. - گزارش خطا: خطاهای مربوط به جابهجاییهای PC-relative که در خروجیهای مستقل از موقعیت (Position-independent) قابل استفاده نیستند، اکنون علت و راه حل را توضیح میدهند. همچنین برای مواردی مانند
--defsymکه نمادی در کتابخانه مشترک را مستعار میکند یا مقداری بیش از ۶۴ بیت دارد، بهجای تولید خروجی خراب، خطاهای جدیدی صادر میشود.
در بخش معماریهای غیر x86 نیز پیشرفتهای چشمگیری رخ داده است. برای AArch64، PPC32 و ARM32، آدرسهای پرش در range extension thunks اصلاح شدند؛ مشکلی که پیش از این باعث شکست در کامپایل برنامههای عظیم مانند Chromium در حالت دیباگ ARM64 میشد.
جزئیات تکمیلی معماریها:
- AArch64: پشتیبانی از انواع جابهجاییهای بیشتر، از جمله
R_AARCH64_TSTBR14وR_AARCH64_GOT_LD_PREL19اضافه شد. - ARM32: پشتیبانی از
R_ARM_ALU_PC_G0وR_ARM_THM_PC12اضافه شد و خروجی-rبرای ARM با Endian بزرگ اصلاح گردید. همچنین در کنار i386، دستور-rدیگر دستورالعملهای مربوط به برخی جابهجاییهای Branch و TLS را خراب نمیکند. - RISC-V و LoongArch: مشکلات ادغام توابع هنگام کوچک شدن آنها توسط Relaxation رفع شد و جابهجاییهای
R_RISCV_64وR_LARCH_64در اشیاء ۳۲ بیتی اصلاح شدند. RISC-V همچنین اصلاحاتی برای TLSDESC با Clang 18 و پرچمEF_RISCV_TSOدریافت کرد. - LoongArch: پشتیبانی از TLSDESC در مدل کد extreme اضافه شد و جابهجاییهای
*64_PC_HI12اصلاح شدند. - PPC32 و m68k: اگر GOT برای آفستهای ۱۶ بیتی مورد استفاده در کدهای
-fpicبیش از حد بزرگ باشد، اکنون بهجای حذف خاموش، بهصورت خطا گزارش میشود. - PPC64: فراخوانیهای IFUNC در فایلهای اجرایی با لینک استاتیک و ارجاعات
@gotدر اسمبلیهای دستنویس اصلاح شدند. mold اکنون خانواده توابع_savegpr0_*را برای PPC64V1 سنتز میکند. - SH4 و SPARC64: کرشهای SH4 هنگام فراخوانی توابعی که ساختارها را از طریق PLT برمیگردانند، رفع شد. SPARC64 نیز اصلاحاتی برای
R_SPARC_WDISP16وR_SPARC_OLO10در خروجی-rدریافت کرد.
در زمینه مدیریت منابع، در یک تغییر کلیدی، mold 3.0 دیگر در لحظه شروع، ۸ گیگابایت فضای آدرس مجازی رزرو نمیکند. این تغییر اجازه میدهد لینکر تحت محدودیتهای سختگیرانه ulimit -v بهدرستی کار کند و آن را برای محیطهای CI/CD محدود، کاربردیتر میکند. علاوه بر این، MOLD_JOBS اکنون حتی اگر XDG_RUNTIME_DIR یک رشته خالی باشد، بهدرستی عمل میکند.
سایر پاکسازیها شامل حذف نمادهای بیمعنی مانند __start_EHDR، __stop_EHDR، __start_PHDR و __stop_PHDR است. همچنین فایلهای ایجاد شده توسط --separate-debug-file دیگر شامل بخش .gnu_debuglink نمیشوند.
این بازنویسی، فرضیات قدیمی درباره ابزارهای سیستمی با کارایی بالا را به چالش میکشد. mold ثابت کرد که ایمنی حافظه لزوماً به قیمت کاهش سرعت اجرا تمام نمیشود. این پروژه همچنان توسط حامیان در GitHub Sponsors و OpenCollective و سازمانهایی مانند SAP، Mercedes-Benz Group و Cybozu, Inc. حمایت میشود.
گام بعدی شما
- اگر از نسخه ۲.۴۲.۱ استفاده میکنید، همین امروز به نسخه ۳.۰.۰ بهروزرسانی کنید تا از پایداری بیشتر و سازگاری بهبودیافته با GNU ld بهرهمند شوید.
- در محیطهای CI/CD خود، محدودیتهای حافظه مجازی را تست کنید تا اثر حذف رزرو ۸ گیگابایتی را مشاهده کنید.
- برای پروژههای ARM64، سازگاری جدید در لینک کردن برنامههای حجیم را بررسی کنید.
منتظر تلاشهای ادغام در آینده باشید، زیرا توزیعهای بزرگ لینوکس شروع به تست mold به عنوان جایگزین پیشفرض برای لینکر قدیمی GNU کردهاند.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.




گفتگو