ABIDIFF(1) Libabigail ABIDIFF(1)

abidiff - مقایسه واسط‌های باینری کاربردی (ABI) فایل‌های ELF

دستور abidiff واسط‌های باینری کاربردی (ABI) دو کتابخانه مشترک با فرمت ELF http://en.wikipedia.org/wiki/Executable_and_Linkable_Format را با یکدیگر مقایسه می‌کند. این ابزار گزارش معناداری حاوی توصیف تفاوت‌های میان دو ABI تولید می‌کند.

این ابزار همچنین می‌تواند نمایش‌های متنی ABI دو فایل باینری ELF (تولیدشده توسط abidw) یا یک فایل باینری ELF را در برابر نمایش متنی یک فایل باینری ELF دیگر مقایسه کند.

جهت ارائه یک گزارش جامع از تغییرات ABI میان دو کتابخانه مشترک ورودی که شامل تغییرات مربوط به زیرنوع‌های توابع و متغیرها باشد، abidiff به‌طور پیش‌فرض از اطلاعات اشکال‌زدایی با فرمت DWARF http://www.dwarfstd.org (در صورت وجود) استفاده می‌کند؛ در غیر این صورت، واسط‌ها را با استفاده از اطلاعات اشکال‌زدایی در فرمت‌های CTF https://raw.githubusercontent.com/wiki/oracle/binutils-gdb/files/ctf-spec.pdf یا BTF https://docs.kernel.org/bpf/btf.html (در صورت وجود) مقایسه می‌کند. در نهایت، اگر هیچ اطلاعات اشکال‌زدایی در این فرمت‌ها یافت نشود، فقط نمادهای ELF http://en.wikipedia.org/wiki/Executable_and_Linkable_Format را در نظر می‌گیرد و اضافه یا حذف شدن آن‌ها را گزارش می‌کند.

این ابزار از کتابخانه libabigail برای تحلیل باینری و همچنین اطلاعات اشکال‌زدایی وابسته به آن استفاده می‌کند. در ادامه نحوه عملکرد کلی آن شرح داده شده است.

هنگامی که دستور اجرا می‌شود، فایل باینری و اطلاعات اشکال‌زدایی وابسته به آن خوانده و تحلیل می‌شوند. برای این منظور، libabigail به‌طور پیش‌فرض توضیحات مربوط به انواعی را تحلیل می‌کند که از طریق واسط‌های (توابع و متغیرها) قابل مشاهده در بیرون از واحد ترجمه (Translation Unit) خود در دسترس هستند. پس از اتمام این تحلیل، یک پیکره واسط باینری کاربردی (ABI Corpus) با در نظر گرفتن زیرمجموعه‌ای از انواع در دسترس از واسط‌های مرتبط با نمادهای ELF http://en.wikipedia.org/wiki/Executable_and_Linkable_Format که توسط فایل باینری تعریف و صادر (Export) شده‌اند ساخته می‌شود. این پیکره نهایی ABI همان چیزی است که libabigail آن را به عنوان نماینده ABI باینری تحلیل‌شده در نظر می‌گیرد.

سپس libabigail قابلیت تولید نمایش‌های متنی از پیکره‌های ABI، مقایسه آن‌ها، تحلیل تغییراتشان و گزارش‌دهی درباره آن‌ها را دارد.

abidiff [گزینه‌ها] <first-shared-library> <second-shared-library>

ابزار abidiff دو فایل پیش‌فرض مشخصات مهارسازی (Suppression) <#suppr-spec-label> را بارگذاری کرده، محتوای آن‌ها را ادغام می‌کند و برای فیلتر کردن گزارش‌های تغییرات ABI که ممکن است از نظر کاربران مثبت کاذب تلقی شوند، به کار می‌گیرد.

  • فایل سراسری پیش‌فرض مشخصات مهارسازی سیستم

    مسیر آن توسط متغیر محیطی اختیاری LIBABIGAIL_DEFAULT_SYSTEM_SUPPRESSION_FILE تعیین می‌شود. اگر این متغیر محیطی تنظیم نشده باشد، abidiff تلاش می‌کند فایل مهارسازی $libdir/libabigail/libabigail-default.abignore را بارگذاری کند. اگر این فایل موجود نباشد، هیچ فایل مشخصات مهارسازی سراسری سیستمی بارگذاری نمی‌شود.

  • فایل پیش‌فرض مشخصات مهارسازی کاربر

    مسیر آن توسط متغیر محیطی اختیاری LIBABIGAIL_DEFAULT_USER_SUPPRESSION_FILE تعیین می‌شود. اگر این متغیر محیطی تنظیم نشده باشد، abidiff تلاش می‌کند فایل مهارسازی $HOME/.abignore را بارگذاری کند. اگر این فایل موجود نباشد، هیچ مشخصات مهارسازی کاربری پیش‌فرضی بارگذاری نمی‌شود.

  • --add-binaries1 <bin1,bin2,bin3,..>

    برای هر یک از فایل‌های باینری جداشده با کاما که به عنوان آرگومان به این گزینه داده می‌شود، در صورتی که فایل باینری در پوشه مشخص‌شده توسط گزینه --added-binaries-dir1 پیدا شود، abidiff پیکره ABI آن باینری را بارگذاری کرده و به مجموعه‌ای از پیکره‌ها (موسوم به گروه پیکره ABI) که شامل اولین آرگومان abidiff است اضافه می‌کند.

    سپس آن گروه پیکره ABI با دومین گروه پیکره داده‌شده به عنوان آرگومان به abidiff مقایسه می‌شود.

  • --add-binaries2 <bin1,bin2,bin3,..>

    برای هر یک از فایل‌های باینری جداشده با کاما که به عنوان آرگومان به این گزینه داده می‌شود، در صورتی که فایل باینری در پوشه مشخص‌شده توسط گزینه --added-binaries-dir2 پیدا شود، abidiff پیکره ABI آن باینری را بارگذاری کرده و به مجموعه‌ای از پیکره‌ها (موسوم به گروه پیکره ABI) که شامل دومین آرگومان abidiff است اضافه می‌کند.

    سپس آن گروه پیکره ABI با اولین گروه پیکره داده‌شده به عنوان آرگومان به abidiff مقایسه می‌شود.

  • --added-binaries-dir1 | --abd1 <added-binaries-directory-1>

    این گزینه همراه با گزینه‌های --add-binaries1، --follow-dependencies و --list-dependencies به کار می‌رود. فایل‌های باینری ارجاع‌شده توسط این گزینه‌ها، در صورت یافت شدن در پوشه added-binaries-directory-1، به عنوان پیکره ABI بارگذاری شده و به اولین گروه پیکره ABI مورد استفاده در مقایسه افزوده می‌شوند.

  • --added-binaries-dir2 | --abd2 <added-binaries-directory-2>

    این گزینه همراه با گزینه‌های --add-binaries2، --follow-dependencies و --list-dependencies به کار می‌رود. فایل‌های باینری ارجاع‌شده توسط این گزینه‌ها، در صورت یافت شدن در پوشه added-binaries-directory-2، به عنوان پیکره ABI بارگذاری شده و به دومین گروه پیکره ABI مورد استفاده در مقایسه افزوده می‌شوند.

  • --added-fns

    در گزارش حاصل از تفاوت‌های میان first-shared-library و second-shared-library، فقط توابع با تعریف سراسری را که به second-shared-library اضافه شده‌اند نمایش می‌دهد.

  • --added-vars

    در گزارش حاصل از تفاوت‌های میان first-shared-library و second-shared-library، فقط متغیرهای سراسری را که به second-shared-library اضافه (تعریف) شده‌اند نمایش می‌دهد.

  • --allow-non-exported-interfaces

    هنگام بررسی اطلاعات اشکال‌زدایی همراه با یک باینری، این ابزار توضیحات انواعی را که توسط واسط‌های (توابع و متغیرها) قابل مشاهده در بیرون از واحد ترجمه خود در دسترس هستند تحلیل می‌کند. پس از انجام این تحلیل، یک پیکره ABI تنها با در نظر گرفتن زیرمجموعه‌ای از انواع در دسترس از واسط‌های مرتبط با نمادهای ELF http://en.wikipedia.org/wiki/Executable_and_Linkable_Format که توسط فایل باینری تعریف و صادر شده‌اند ساخته می‌شود. این همان پیکره‌های نهایی ABI است که توسط این ابزار مقایسه می‌شوند.

    اما اشکال این رویکرد در آن است که تحلیل تمام واسط‌های قابل مشاهده از بیرون واحد ترجمه می‌تواند حجم بسیار زیادی از داده تولید کند، به‌ویژه زمانی که آن باینری‌ها برنامه‌های کاربردی باشند (در مقایسه با کتابخانه‌های مشترک). یک نمونه از این برنامه‌ها، هسته لینوکس https://kernel.org است. تحلیل چنین پیکره‌های عظیمی از ABI می‌تواند به‌شدت کند باشد.

    با این حال، در حضور یک باینری با «اندازه متوسط»، می‌توان با استفاده از این گزینه به libabigail اجازه داد تمام واسط‌های قابل مشاهده از بیرون واحد ترجمه را تحلیل کند.

    توجه داشته باشید که این گزینه به‌طور پیش‌فرض فعال است، مگر اینکه در حال تحلیل هسته لینوکس https://kernel.org باشیم.

  • --btf

    هنگام مقایسه باینری‌ها، اطلاعات ABI را از اطلاعات اشکال‌زدایی BTF https://docs.kernel.org/bpf/btf.html (در صورت وجود) استخراج می‌کند.

  • --changed-fns

    در گزارش حاصل از تفاوت‌های میان first-shared-library و second-shared-library، فقط تغییرات در زیرنوع‌های توابع سراسری تعریف‌شده در first-shared-library را نمایش می‌دهد.

  • --changed-vars

    در گزارش حاصل از تفاوت‌های میان first-shared-library و second-shared-library، فقط تغییرات در زیرنوع‌های متغیرهای سراسری تعریف‌شده در first-shared-library را نمایش می‌دهد.

  • --ctf

    هنگام مقایسه باینری‌ها، اطلاعات ABI را از اطلاعات اشکال‌زدایی CTF https://raw.githubusercontent.com/wiki/oracle/binutils-gdb/files/ctf-spec.pdf (در صورت وجود) استخراج می‌کند.

  • --debug-info-dir1 | --d1 <di-path1>

    برای مواردی که اطلاعات اشکال‌زدایی first-shared-library در یک فایل جداگانه قرار دارد، به abidiff می‌گوید که آن فایل اطلاعات اشکال‌زدایی مجزا را در کجا پیدا کند.

    توجه داشته باشید که di-path باید به پوشه ریشه‌ای اشاره کند که اطلاعات اشکال‌زدایی به صورت درختی در زیر آن مرتب شده است. در سیستم‌های مبتنی بر Red Hat، این پوشه معمولاً <root>/usr/lib/debug است.

    این گزینه را می‌توان چندین بار با پوشه‌های ریشه مختلف مشخص کرد. در این حالت، abidiff برای یافتن اطلاعات اشکال‌زدایی مجزای first-shared-library به‌طور بالقوه تمام آن پوشه‌های ریشه را جستجو می‌کند.

    همچنین توجه داشته باشید که این گزینه برای اطلاعات اشکال‌زدایی مجزایی که توسط مدیر بسته سیستم شما نصب شده‌اند اجباری نیست، زیرا در آن صورت abidiff می‌داند که آن را کجا پیدا کند.

  • --debug-info-dir2 | --d2 <di-path2>

    مانند --debug-info-dir1، این گزینه به abidiff می‌گوید که فایل اطلاعات اشکال‌زدایی مجزا را برای فایل second-shared-library در کجا پیدا کند.

    این گزینه را می‌توان چندین بار با پوشه‌های ریشه مختلف ارائه کرد. در این حالت، abidiff به دنبال اطلاعات اشکال‌زدایی مجزای second-shared-library در تمام آن پوشه‌های ریشه خواهد گشت.

  • --debug-self-comparison

    در این حالت، هنگام مقایسه یک باینری با خودش در شرایط خاص، برای انواعی که یکسان‌سازی نوع (Type Canonicalization) روی آن‌ها ناموفق بوده است، پیام‌های خطا صادر می‌شود.

    هنگام مقایسه یک باینری با خودش، انواع متعارف (Canonical Types) باینری دوم باید (تا حد ممکن) با انواع متعارف باینری اول برابر باشند. اگر در این حالت مغایرتی تشخیص داده شود، یک سیگنال توقف (Abort) ارسال شده و فرآیند متوقف می‌گردد. این گزینه باید هنگام اجرای ابزار در یک دیباگر، برای مقاصد عیب‌یابی مورد استفاده قرار گیرد.

    این یک گزینه اختیاری برای اشکال‌زدایی و بررسی سلامت است. برای فعال‌سازی آن، بسته libabigail باید با گزینه پیکربندی --enable-debug-self-comparison کامپایل شود.

  • --debug-tc

    در این حالت، فرآیند یکسان‌سازی نوع (Type Canonicalization) تحت نظارت و بررسی دقیق قرار می‌گیرد. اساساً در طول یکسان‌سازی نوع، هر مقایسه نوع دو بار انجام می‌شود: یک بار در حالت ساختاری (مقایسه عضوبه‌عضو تمام زیرنوع‌ها) و یک بار با استفاده از مقایسه متعارف (Canonical). هر دو مقایسه باید نتیجه یکسانی داشته باشند. در غیر این صورت، یک سیگنال توقف (Abort) ارسال می‌شود و می‌توان فرآیند را اشکال‌زدایی کرد تا مشخص شود چرا دو نوع مقایسه نتایج متفاوتی داده‌اند.

    این یک گزینه اختیاری برای اشکال‌زدایی و بررسی سلامت است. برای فعال‌سازی آن، بسته libabigail باید با گزینه پیکربندی --enable-debug-type-canonicalization کامپایل شود.

  • --deleted-fns

    در گزارش حاصل از تفاوت‌های میان first-shared-library و second-shared-library، فقط توابع با تعریف سراسری را که از first-shared-library حذف شده‌اند نمایش می‌دهد.

  • --deleted-vars

    در گزارش حاصل از تفاوت‌های میان first-shared-library و second-shared-library، فقط متغیرهای با تعریف سراسری را که از first-shared-library حذف شده‌اند نمایش می‌دهد.

  • --drop <regex>

    هنگام خواندن فایل‌های ورودی ELF شامل first-shared-library و second-shared-library، توابع و متغیرهای دارای تعریف سراسری که نام آن‌ها با عبارت باقاعده regex مطابقت دارد را نادیده می‌گیرد (حذف می‌کند). در نتیجه، هیچ تغییری شامل این توابع یا متغیرها در گزارش تفاوت صادر نخواهد شد.

  • --drop-fn <regex>

    هنگام خواندن فایل‌های ورودی ELF شامل first-shared-library و second-shared-library، توابع دارای تعریف سراسری که نام آن‌ها با عبارت باقاعده regex مطابقت دارد را نادیده می‌گیرد. در نتیجه، هیچ تغییری شامل این توابع در گزارش تفاوت صادر نخواهد شد.

  • --drop-var <regex>

    هنگام خواندن فایل‌های ورودی ELF شامل first-shared-library و second-shared-library، متغیرهای دارای تعریف سراسری که با عبارت باقاعده regex مطابقت دارند را نادیده می‌گیرد.

  • --drop-private-types

    این گزینه همراه با گزینه‌های --headers-dir1، header-file1، header-file2 و --headers-dir2 به کار می‌رود. با فعال بودن این گزینه، انواعی که در هدرها تعریف نشده‌اند به‌طور کامل از نمایش درونی ساخته‌شده توسط Libabigail برای نمایش ABI حذف می‌شوند. بنابراین، نیازی به فیلتر کردن آن‌ها از گزارش نهایی تغییرات ABI نیست زیرا اصلاً در نمایش درونی Libabigail وجود نخواهند داشت.

    اما بدون این گزینه، آن انواع خصوصی در نمایش درونی نگهداری شده و بعداً از گزارش فیلتر می‌شوند.

    بنابراین این گزینه به‌طور بالقوه مصرف حافظه Libabigail را کاهش می‌دهد. کاربرد اصلی آن بهینه‌سازی مصرف حافظه ابزار روی باینری‌هایی با تعداد زیادی انواع تعریف‌شده و صادرشده عمومی است.

  • --dump-diff-tree
پس از گزارش تفاوت، یک نمایش متنی از درخت گره‌های تفاوت (Diff Nodes Tree) را که توسط موتور مقایسه برای نمایش توابع و متغیرهای تغییریافته استفاده شده است در خروجی خطا (stderr) صادر می‌کند. این نمایش برای مقاصد اشکال‌زدایی است. توجه داشته باشید که این درخت تفاوت فقط به توابع و متغیرهایی مربوط می‌شود که دارای تغییراتی در زیرنوع‌های خود هستند. توابع و متغیرهای اضافه‌شده یا حذف‌شده هیچ درخت گره تفاوتی وابسته به خود ندارند.
  • --exported-interfaces-only

    به‌طور پیش‌فرض، هنگام بررسی اطلاعات اشکال‌زدایی همراه با یک باینری، این ابزار توضیحات انواعی را تحلیل می‌کند که توسط واسط‌های (توابع و متغیرها) قابل مشاهده در بیرون از واحد ترجمه خود در دسترس هستند. پس از انجام آن تحلیل، یک پیکره ABI تنها با در نظر گرفتن زیرمجموعه‌ای از انواع در دسترس از واسط‌های مرتبط با نمادهای ELF http://en.wikipedia.org/wiki/Executable_and_Linkable_Format که توسط فایل باینری تعریف و صادر شده‌اند ساخته می‌شود. این همان پیکره‌های نهایی ABI است که توسط این ابزار مقایسه می‌شوند.

    اما مشکل این رویکرد آن است که تحلیل تمام واسط‌های قابل مشاهده از خارج واحد ترجمه می‌تواند داده‌های بسیار زیادی تولید کند، به‌ویژه زمانی که آن باینری‌ها برنامه‌های کاربردی باشند (در مقایسه با کتابخانه‌های مشترک). یک نمونه از این برنامه‌ها هسته لینوکس https://kernel.org است. تحلیل چنین پیکره‌های عظیمی از ABI می‌تواند به‌شدت کند باشد.

    برای کاهش این مشکل عملکردی، این گزینه به libabigail امکان می‌دهد فقط انواعی را تحلیل کند که از طریق واسط‌های مرتبط با نمادهای تعریف‌شده و صادرشده ELF http://en.wikipedia.org/wiki/Executable_and_Linkable_Format در دسترس هستند.

    توجه داشته باشید که این گزینه هنگام تحلیل هسته لینوکس https://kernel.org به‌طور پیش‌فرض فعال است؛ در غیر این صورت، به‌طور پیش‌فرض غیرفعال است.

  • --fail-no-debug-info

    اگر هیچ اطلاعات اشکال‌زدایی یافت نشود، این گزینه موجب شکست اجرای برنامه (خروج با خطا) می‌شود. در غیر این صورت، بدون این گزینه، برنامه تلاش می‌کند ویژگی‌های باینری‌ها را که به اطلاعات اشکال‌زدایی وابسته نیستند (مانند ویژگی‌های خالص ELF) مقایسه کند.

  • --follow-dependencies | --fdeps

    برای هر وابستگی آرگومان اول abidiff، اگر در پوشه مشخص‌شده با گزینه --added-binaries-dir1 یافت شود، یک پیکره ABI از آن وابستگی ایجاد کرده و به مجموعه‌ای از پیکره‌ها (موسوم به گروه پیکره ABI) که شامل اولین آرگومان abidiff است اضافه می‌کند.

    به‌همین ترتیب، برای هر وابستگی آرگومان دوم abidiff، اگر در پوشه مشخص‌شده با گزینه --added-binaries-dir2 یافت شود، یک پیکره ABI از آن وابستگی ایجاد کرده و به گروه پیکره ABI که شامل دومین آرگومان abidiff است اضافه می‌کند.

    سپس این دو گروه پیکره ABI در برابر یکدیگر مقایسه می‌شوند.

    به عبارت دیگر، این گزینه باعث می‌شود abidiff مجموعه ورودی اول و وابستگی‌های آن را در برابر مجموعه ورودی دوم و وابستگی‌های آن مقایسه کند.

  • --harmless

    در گزارش تفاوت، فقط تغییرات بی‌ضرر (Harmless) <#harmlesschangeconcept-label> را نمایش می‌دهد. به‌طور پیش‌فرض، تغییرات بی‌ضرر از گزارش تفاوت فیلتر می‌شوند تا شلوغی متن به حداقل برسد و شانس تشخیص مشکلات واقعی ABI افزایش یابد.

  • --headers-dir1 | --hd1 <headers-directory-path-1>

    مشخص می‌کند که فایل‌های هدر عمومی اولین کتابخانه مشترک (یا به‌طور کلی باینری) که ابزار باید مد نظر قرار دهد در کجا قرار دارند. بدین ترتیب ابزار تغییرات ABI مربوط به انواعی را که در هدرهای عمومی تعریف نشده‌اند فیلتر خواهد کرد.

    توجه داشته باشید که می‌توان چندین پوشه هدر عمومی را برای اولین کتابخانه مشترک مشخص کرد. در این صورت، گزینه --headers-dir1 باید چندین بار در خط فرمان درج شود، همانند مثال زیر:

$ abidiff --headers-dir1 /some/path       \
          --headers-dir1 /some/other/path \
          binary-version-1 binary-version-2
•
--headers-dir2 | --hd2 <headers-directory-path-2>

مشخص می‌کند که فایل‌های هدر عمومی دومین کتابخانه مشترک که ابزار باید مد نظر قرار دهد در کجا قرار دارند. بدین ترتیب ابزار تغییرات ABI مربوط به انواعی را که در هدرهای عمومی تعریف نشده‌اند فیلتر خواهد کرد.

توجه داشته باشید که می‌توان چندین پوشه هدر عمومی را برای دومین کتابخانه مشترک مشخص کرد. در این صورت گزینه --headers-dir2 باید چندین بار درج شود، مانند مثال زیر:

$ abidiff --headers-dir2 /some/path       \
          --headers-dir2 /some/other/path \
          binary-version-1 binary-version-2
  • --header-file1 | --hf1 <header-file-path-1>

    مشخص می‌کند که یک هدر عمومی از اولین کتابخانه مشترک که ابزار باید مد نظر قرار دهد در کجا قرار دارد. بدین ترتیب ابزار تغییرات ABI انواعی را که در هدرهای عمومی تعریف نشده‌اند فیلتر خواهد کرد.

  • --header-file2 | --hf2 <header-file-path-2>

    مشخص می‌کند که یک هدر عمومی از دومین کتابخانه مشترک که ابزار باید مد نظر قرار دهد در کجا قرار دارد. بدین ترتیب ابزار تغییرات ABI انواعی را که در هدرهای عمومی تعریف نشده‌اند فیلتر خواهد کرد.

  • --help | -h

    نمایش یک راهنمای کوتاه درباره دستور و خروج.

  • --ignore-soname

    چشم‌پوشی از تفاوت‌های موجود در SONAME هنگام انجام مقایسه.

  • --impacted-interfaces

    هنگام نمایش تغییرات برگ (Leaf changes)، این گزینه به abidiff دستور می‌دهد فهرست واسط‌های تحت تأثیر قرار گرفته را نشان دهد. بنابراین این گزینه باید در کنار گزینه --leaf-changes-only استفاده شود، در غیر این صورت نادیده گرفته می‌شود.

  • --keep <regex>

    هنگام خواندن فایل‌های ورودی ELF شامل first-shared-library و second-shared-library، توابع و متغیرهای دارای تعریف سراسری را که نامشان با عبارت باقاعده regex مطابقت دارد نگه می‌دارد. تمام توابع و متغیرهای دیگر کنار گذاشته می‌شوند و در گزارش تفاوت نهایی ظاهر نخواهند شد.

  • --keep-fn <regex>

    هنگام خواندن فایل‌های ورودی ELF شامل first-shared-library و second-shared-library، توابع دارای تعریف سراسری را که نامشان با عبارت باقاعده regex مطابقت دارد نگه می‌دارد. سایر توابع کنار گذاشته می‌شوند و در گزارش تفاوت نهایی ظاهر نخواهند شد.

  • --keep-var <regex>

    هنگام خواندن فایل‌های ورودی ELF شامل first-shared-library و second-shared-library، متغیرهای دارای تعریف سراسری را که نامشان با عبارت باقاعده regex مطابقت دارد نگه می‌دارد. سایر متغیرها کنار گذاشته می‌شوند و در گزارش تفاوت نهایی ظاهر نخواهند شد.

  • --kmi-whitelist | -w <path-to-whitelist>

    هنگام تحلیل یک فایل باینری هسته لینوکس، این گزینه به فهرست سفید نام نمادهای ELF توابع و متغیرهایی اشاره می‌کند که ABI آن‌ها باید مد نظر قرار گیرد. به این فهرست سفید، «فهرست سفید واسط ماژول هسته» (Kernel Module Interface white list یا KMI) گفته می‌شود. علت این نام‌گذاری این است که برای هسته، ما از واژه ABI استفاده نمی‌کنیم؛ بلکه درباره واسط میان هسته و ماژول‌های آن صحبت می‌کنیم؛ از این رو اصطلاح KMI به جای ABI به کار می‌رود.

    هر تابع یا متغیر دیگری که نماد ELF آن در این فهرست سفید موجود نباشد، توسط این ابزار در نظر گرفته نخواهد شد.

    اگر این گزینه مشخص نشود -- یعنی هیچ فهرست سفیدی ارائه نشود -- کل KMI، یعنی مجموعه تمام توابع و متغیرهای سراسری تعریف‌شده و صادرشده به صورت عمومی توسط باینری‌های هسته لینوکس، مد نظر قرار خواهد گرفت.

  • --leaf-changes-only|-l فقط تغییرات برگ را نشان می‌دهد و گزارش تحلیل اثرگذاری را نمایش نمی‌دهد. این گزینه متضمن گزینه --redundant است.

    خروجی معمول abidiff هنگام مقایسه دو باینری شبیه به این است:

$ abidiff libtest-v0.so libtest-v1.so
Functions changes summary: 0 Removed, 1 Changed, 0 Added function
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
1 function with some indirect sub-type change:
  [C]'function void fn(C&)' at test-v1.cc:13:1 has some indirect sub-type changes:
    parameter 1 of type 'C&' has sub-type changes:
      in referenced type 'struct C' at test-v1.cc:7:1:
        type size hasn't changed
        1 data member change:
         type of 'leaf* C::m0' changed:
           in pointed to type 'struct leaf' at test-v1.cc:1:1:
             type size changed from 32 to 64 bits
             1 data member insertion:
               'char leaf::m1', at offset 32 (in bits) at test-v1.cc:4:1
$

بنابراین در این مثال، گزارش اطلاعاتی را درباره چگونگی دسترسی به تغییر درج عضو داده "struct leaf" از تابع "void fn(C&)" ارائه می‌دهد. به عبارت دیگر، گزارش نه تنها تغییر عضو داده روی "struct leaf" را نشان می‌دهد، بلکه تأثیر آن تغییر بر روی تابع "void fn(C&)" را نیز نمایش می‌دهد.

در اصطلاح abidiff، به تغییر روی "struct leaf" تغییر برگ (Leaf Change) گفته می‌شود. بنابراین گزینه‌های --leaf-changes-only --impacted-interfaces فقط تغییر برگ را نمایش می‌دهند. خروجی به این صورت خواهد بود:

$ abidiff -l libtest-v0.so libtest-v1.so
'struct leaf' changed:
  type size changed from 32 to 64 bits
  1 data member insertion:
    'char leaf::m1', at offset 32 (in bits) at test-v1.cc:4:1
  one impacted interface:
    function void fn(C&)
$

توجه کنید که گزارش با نمایش فهرستی از واسط‌های تحت تأثیر تغییر برگ به پایان می‌رسد.

حال اگر مایل به مشاهده آن فهرست از واسط‌های تحت تأثیر نیستید، می‌توانید به سادگی از گزینه --impacted-interface استفاده نکنید. در هر صورت، توضیحات بیشتر درباره این گزینه در ادامه آمده است.

  • --list-dependencies | --ldeps

    این گزینه تمام وابستگی‌های آرگومان‌های ورودی abidiff را که در پوشه‌های مشخص‌شده توسط گزینه‌های --added-binaries-dir1 و --added-binaries-dir2 یافت می‌شوند، فهرست می‌کند.

  • --no-added-syms

    در گزارش حاصل از تفاوت‌های میان first-shared-library و second-shared-library، توابع یا متغیرهای اضافه‌شده را نمایش نمی‌دهد. نمادهای ELF توابع یا متغیرهای اضافه‌شده را نیز نمایش نمی‌دهد. تمام انواع دیگر تغییرات نمایش داده می‌شوند مگر اینکه صریحاً توسط سایر گزینه‌ها در خط فرمان منع شده باشند.

  • --no-assume-odr-for-cplusplus

    هنگام تحلیل یک باینری تولیدشده از کد C++ با استفاده از اطلاعات اشکال‌زدایی DWARF http://www.dwarfstd.org، کتابخانه libabigail قاعده یک تعریف (One Definition Rule یا ODR) https://en.wikipedia.org/wiki/One_Definition_Rule را برای افزایش سرعت تحلیل فرض می‌گیرد. در این حالت، هنگامی که چند نوع دارای نام یکسان در باینری باشند، فرض می‌شود که همگی برابر هستند.

    این گزینه آن فرض را غیرفعال کرده و به libabigail دستور می‌دهد تا انواع را واقعاً با یکدیگر مقایسه کند تا برابری آن‌ها مشخص گردد.

  • --no-architecture

    هنگام مقایسه واسط‌های کاربردی باینری (ABI)، معماری سیستم را مد نظر قرار نمی‌دهد.

  • --no-change-categorization | -x

    این گزینه دسته‌بندی تغییرات به تغییرات بی‌ضرر (Harmless) و زیان‌آور (Harmful) را غیرفعال می‌کند. توجه داشته باشید که این دسته‌بندی پیش‌نیاز فیلتر کردن تغییرات است؛ بنابراین این گزینه آن فیلترسازی را نیز غیرفعال می‌سازد. هدف از این گزینه، افزایش سرعت اجرای برنامه در مواردی است که گراف تغییرات بسیار بزرگ بوده و کاربر صرفاً علاقه‌مند به بررسی تغییرات گره‌های برگ بدون توجه به تأثیر بالقوه آن‌ها بر واسط‌ها باشد. در چنین حالتی، این گزینه معمولاً در کنار گزینه --leaf-changes-only استفاده می‌شود.

  • --no-corpus-path

    ویژگی مسیر (path attribute) را برای پیکره ABI صادر نمی‌کند.

  • --no-default-suppression

    فایل‌های پیش‌فرض مشخصات مهارسازی (Suppression) را بارگذاری نمی‌کند.

  • --no-harmful

    در گزارش تفاوت، تغییرات زیان‌آور (Harmful) <#harmfulchangeconcept-label> را نمایش نمی‌دهد. به‌طور پیش‌فرض، فقط تغییرات زیان‌آور در گزارش تفاوت نمایش داده می‌شوند.

  • --no-leverage-dwarf-factorization

    هنگام تحلیل باینری‌ای که اطلاعات اشکال‌زدایی DWARF http://www.dwarfstd.org آن توسط ابزار DWZ https://sourceware.org/dwz پردازش شده است، فرض بر این است که اطلاعات نوع از قبل فاکتورگیری شده‌اند. این زمینه توسط libabigail برای انجام برخی بهینه‌سازی‌های سرعتی به کار گرفته می‌شود.

    این گزینه آن بهینه‌سازی‌ها را غیرفعال می‌سازد.

  • --no-linkage-name

    در گزارش خروجی، نام‌های پیوند (Linkage Names) توابع یا متغیرهای اضافه‌شده، حذف‌شده یا تغییریافته را نمایش نمی‌دهد.

  • --no-linux-kernel-mode

    بدون این گزینه، اگر abidiff تشخیص دهد که باینری‌های مورد بررسی باینری‌های هسته لینوکس هستند (یا vmlinux یا ماژول‌ها)، فقط توابع و متغیرهایی را در نظر می‌گیرد که نمادهای ELF آن‌ها در بخش‌های __ksymtab و __ksymtab_gpl فهرست شده باشند.

    با این گزینه، abidiff باینری را به عنوان یک باینری ELF غیرویژه در نظر می‌گیرد و بنابراین توابع و متغیرهایی را که بر اساس مفهوم ELF تعریف و صادر شده‌اند بررسی می‌کند.

  • --no-redundant

    در گزارش تفاوت، تغییرات تکراری (Redundant) را نمایش نمی‌دهد. یک تغییر تکراری تغییری است که در جای دیگری از گزارش نمایش داده شده است. این گزینه به‌طور پیش‌فرض فعال است.

  • --no-show-locs
اطلاعات مربوط به اینکه نوع مورد نظر در کجای second shared library تغییر یافته است را نمایش نمی‌دهد.
  • --no-show-relative-offset-changes

    بدون این گزینه، هنگامی که آفست یک عضو داده تغییر می‌کند، گزارش تغییرات علاوه بر ذکر آفست قدیم و جدید، مشخص می‌کند که عضو داده به چه میزان (چند بیت) تغییر کرده است. با این گزینه، این تفاوت بیتی نسبی نمایش داده نمی‌شود.

  • --no-unreferenced-symbols

    در گزارش خروجی، اطلاعات تغییرات مربوط به نمادهای توابع و متغیرهایی را که توسط هیچ اطلاعات اشکال‌زدایی ارجاع داده نشده‌اند نمایش نمی‌دهد. توجه داشته باشید که برای این نمادهای ارجاع‌نشده، اطلاعات تغییرات نمایش‌داده‌شده صرفاً شامل نمادهای اضافه‌شده یا حذف‌شده است.

  • --non-reachable-types|-t

    تحلیل و صدور گزارش‌های تغییرات را برای تمام انواع باینری، شامل انواعی که از طریق توابع و متغیرهای سراسری در دسترس نیستند، انجام می‌دهد.

    این گزینه ممکن است منجر به افت شدید عملکرد شود زیرا تعداد انواع تحلیل‌شده می‌تواند بسیار زیاد باشد. با این حال، اگر همراه با گزینه‌های --headers-dir{1,2} و/یا header-file{1,2} استفاده شود، انواع غیرقابل‌دسترس اضافی تحلیل‌شده به انواعی که در فایل‌های هدر عمومی تعریف شده‌اند محدود می‌شوند و در نتیجه افت عملکرد در حد قابل قبولی باقی می‌ماند.

    همچنین، استفاده از این گزینه در کنار مشخصات مهارسازی (با استفاده از گزینه --suppressions) می‌تواند به کنترل تعداد انواع تحلیل‌شده (و افت احتمالی کارایی) کمک کند.

    توجه داشته باشید که بدون این گزینه، فقط انواعی که از توابع و متغیرهای سراسری در دسترس هستند تحلیل می‌شوند؛ بنابراین ابزار تغییرات را فقط روی این انواع در دسترس تشخیص داده و گزارش می‌کند.

  • --redundant

    در گزارش تفاوت، تغییرات تکراری را نمایش می‌دهد. یک تغییر تکراری، تغییری است که در جای دیگری از گزارش نیز نمایش داده شده است.

  • --show-bits

    نمایش اندازه‌ها و آفست‌ها بر حسب بیت، نه بایت. این گزینه به‌طور پیش‌فرض فعال است.

  • --show-bytes

    نمایش اندازه‌ها و آفست‌ها بر حسب بایت، نه بیت. به‌طور پیش‌فرض، اندازه‌ها و آفست‌ها بر حسب بیت نمایش داده می‌شوند.

  • --show-dec

    نمایش اندازه‌ها و آفست‌ها در مبنای ده‌دهی (Decimal). این گزینه به‌طور پیش‌فرض فعال است.

  • --show-hex

    نمایش اندازه‌ها و آفست‌ها در مبنای شانزده‌شانزدهی (Hexadecimal).

  • --stat

    به جای نمایش تفاوت‌های تفصیلی ABI میان first-shared-library و second-shared-library، صرفاً برخی آمارهای خلاصه درباره این تفاوت‌ها را نمایش می‌دهد.

  • --stats

    صدور آمار درباره موارد گوناگون درونی برنامه.

  • --suppressions | --suppr <path-to-suppressions>

    استفاده از یک فایل مشخصات مهارسازی <#suppr-spec-label> واقع در path-to-suppressions. توجه داشته باشید که این گزینه می‌تواند چندین بار در خط فرمان درج شود. در این صورت، تمام فایل‌های مشخصات مهارسازی ارائه‌شده مد نظر قرار خواهند گرفت.

    لطفاً توجه داشته باشید که به‌طور پیش‌فرض، در صورت عدم ارائه این گزینه، فایل‌های پیش‌فرض مشخصات مهارسازی بارگذاری می‌شوند.

  • --symtabs

    فقط جدول‌های نمادهای first-shared-library و second-shared-library را نمایش می‌دهد.

  • --verbose

    صدور گزارش‌های پرجزئیات (Verbose) درباره روند انجام کارهای گوناگون درونی.

  • --version | -v

    نمایش نسخه برنامه و خروج.

کد خروج دستور abidiff در صورتی که ABI باینری‌های مورد مقایسه یکسان باشند برابر با 0 است، و در صورتی که تفاوت داشته باشند یا ابزار با خطایی مواجه شود، عددی غیر صفر خواهد بود.

در حالت دوم، کد خروج یک فیلد بیتی ۸ بیتی است که در آن هر بیت دارای معنای ویژه‌ای است.

بیت اول با مقدار عددی 1 و به نام ABIDIFF_ERROR، بیانگر رخ دادن یک خطا است.

بیت دوم با مقدار عددی 2 و به نام ABIDIFF_USAGE_ERROR، بیانگر وجود خطا در نحوه فراخوانی ابزار توسط کاربر است. این بیت برای نمونه زمانی فعال می‌شود که کاربر ابزار را با یک گزینه خط فرمان ناشناخته، یا تعداد یا آرگومان‌های اشتباه فراخوانی کرده باشد. اگر این بیت تنظیم شود، بیت ABIDIFF_ERROR نیز باید تنظیم شده باشد.

بیت سوم با مقدار عددی 4 و به نام ABIDIFF_ABI_CHANGE، بیانگر تفاوت در ABI باینری‌های مورد مقایسه است.

بیت چهارم با مقدار عددی 8 و به نام ABIDIFF_ABI_INCOMPATIBLE_CHANGE، به این معنی است که ABI باینری‌های مورد مقایسه به صورتی ناسازگار دچار تفاوت شده‌اند. اگر این بیت تنظیم شود، بیت ABIDIFF_ABI_CHANGE نیز باید حتماً تنظیم شده باشد. اگر بیت ABIDIFF_ABI_CHANGE تنظیم شود اما بیت ABIDIFF_INCOMPATIBLE_CHANGE تنظیم نشده باشد، به این معناست که واسط‌های باینری کاربردی مقایسه‌شده ممکن است سازگار یا ناسازگار باشند. در چنین حالتی، یک بازبین انسانی باید تغییرات ABI را بررسی کند تا درباره سازگار یا ناسازگار بودن آن‌ها تصمیم بگیرد.

توجه داشته باشید که در حال حاضر، تنها انواع خاصی از تغییرات ABI منجر به فعال شدن فلگ ABIDIFF_ABI_INCOMPATIBLE_CHANGE می‌شوند. این تغییرات ABI عبارتند از:

  • حذف نماد یک تابع یا متغیر که قبلاً تعریف و صادر (Export) شده بوده است.
  • تغییر اندیس یکی از اعضای جدول توابع مجازی (vtable) برای برنامه‌ها و کتابخانه‌های زبان C++.

با گذشت زمان، هرگاه الگوهای تغییر بیشتری شناسایی شوند که همواره به معنای تغییر ناسازگار در ABI باشند، کد برنامه تطبیق داده خواهد شد تا آن موارد را شناسایی کرده و مقدار ABIDIFF_ABI_INCOMPATIBLE_CHANGE را متناسب با آن‌ها تنظیم کند. بنابراین، اگر با چنین الگوهایی روبرو شدید، لطفاً به ما اطلاع دهید.

بیت‌های باقی‌مانده در حال حاضر مورد استفاده قرار نمی‌گیرند.

1.
تشخیص تغییر در زیرنوع یک تابع:
$ cat -n test-v0.cc
         1      // Compile this with:
         2      //   g++ -g -Wall -shared -o libtest-v0.so test-v0.cc
         3
         4      struct S0
         5      {
         6        int m0;
         7      };
         8
         9      void
        10      foo(S0* /*parameter_name*/)
        11      {
        12        // do something with parameter_name.
        13      }
$
$ cat -n test-v1.cc
         1      // Compile this with:
         2      //   g++ -g -Wall -shared -o libtest-v1.so test-v1.cc
         3
         4      struct type_base
         5      {
         6        int inserted;
         7      };
         8
         9      struct S0 : public type_base
        10      {
        11        int m0;
        12      };
        13
        14      void
        15      foo(S0* /*parameter_name*/)
        16      {
        17        // do something with parameter_name.
        18      }
$
$ g++ -g -Wall -shared -o libtest-v0.so test-v0.cc
$ g++ -g -Wall -shared -o libtest-v1.so test-v1.cc
$
$ abidiff libtest-v0.so libtest-v1.so; echo "exit code: $?"
Functions changes summary: 0 Removed, 1 Changed, 0 Added function
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
1 function with some indirect sub-type change:
  [C]'function void foo(S0*)' has some indirect sub-type changes:
        parameter 0 of type 'S0*' has sub-type changes:
          in pointed to type 'struct S0':
            size changed from 32 to 64 bits
            1 base class insertion:
              struct type_base
            1 data member change:
             'int S0::m0' offset changed from 0 to 32
exit code: 4
$

توجه کنید که کد خروج 4 است؛ به این معنی که بیت سوم ABIDIFF_ABI_CHANGE با مقدار عددی 4 روی 1 تنظیم شده است. این بدان معناست که ابزار تغییرات ABI را به عنوان زیان‌آور (Harmful) <#harmfulchangeconcept-label> دسته‌بندی کرده و بنابراین نیازمند بازبینی کاربر است.

2.
تشخیص یک تغییر ناسازگار در ABI در نوع یک تابع:
$ cat -n test-v0.cc
     1  // Compile this with:
     2  //   g++ -g -Wall -shared -o libtest-v0.so test-v0.cc
     3
     4  struct S0
     5  {
     6    int m0;
     7  };
     8
     9  S0
    10  foo()
    11  {
    12    S0 s = {};
    13    return s;
    14  }
$
$ cat -n test-v1.cc
     1  // Compile this with:
     2  //   g++ -g -Wall -shared -o libtest-v1.so test-v1.cc
     3
     4  struct type_base
     5  {
     6    int inserted;
     7  };
     8
     9  struct S0 : public type_base
    10  {
    11    int m0;
    12  };
    13
    14  S0
    15  foo()
    16  {
    17    S0 s = {};
    18    return s;
    19  }
$
$ g++ -g -Wall -shared -o libtest-v0.so test-v0.cc
$ g++ -g -Wall -shared -o libtest-v1.so test-v1.cc
$
$ abidiff libtest-v0.so libtest-v1.so; echo "exit code: $?"
Functions changes summary: 0 Removed, 1 Changed, 0 Added function
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
1 function with incompatible sub-type changes:
  [C] 'function S0 foo(void)' at test-v0.cc:10:1 has some sub-type changes:
    return type changed:
      type size changed from 32 to 64 (in bits)
      1 base class insertion:
        struct type_base at test-v1.cc:4:1
      1 data member change:
        'int m0' offset changed from 0 to 32 (in bits) (by +32 bits)
exit code: 12
$

توجه کنید که کد خروج 12 است؛ به این معنی که هر دو بیت سوم ABIDIFF_ABI_CHANGE با مقدار 4 و بیت چهارم ABIDIFF_ABI_INCOMPATIBLE_CHANGE با مقدار 8 روی 1 تنظیم شده‌اند. این بدان معناست که ابزار تغییرات ABI را به عنوان ناسازگار <#incompatiblechangeconcept-label> دسته‌بندی کرده است. این یک شکست در ABI (یا ABI break) محسوب می‌شود.

3.
تشخیص تغییر دیگری در یک زیرنوع از یک تابع:
$ cat -n test-v0.cc
         1      // Compile this with:
         2      //   g++ -g -Wall -shared -o libtest-v0.so test-v0.cc
         3
         4      struct S0
         5      {
         6        int m0;
         7      };
         8
         9      void
        10      foo(S0& /*parameter_name*/)
        11      {
        12        // do something with parameter_name.
        13      }
$
$ cat -n test-v1.cc
         1      // Compile this with:
         2      //   g++ -g -Wall -shared -o libtest-v1.so test-v1.cc
         3
         4      struct S0
         5      {
         6        char inserted_member;
         7        int m0;
         8      };
         9
        10      void
        11      foo(S0& /*parameter_name*/)
        12      {
        13        // do something with parameter_name.
        14      }
$
$ g++ -g -Wall -shared -o libtest-v0.so test-v0.cc
$ g++ -g -Wall -shared -o libtest-v1.so test-v1.cc
$
$ abidiff libtest-v0.so libtest-v1.so; echo "exit code: $?"
Functions changes summary: 0 Removed, 1 Changed, 0 Added function
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
1 function with some indirect sub-type change:
  [C]'function void foo(S0&)' has some indirect sub-type changes:
        parameter 0 of type 'S0&' has sub-type changes:
          in referenced type 'struct S0':
            size changed from 32 to 64 bits
            1 data member insertion:
              'char S0::inserted_member', at offset 0 (in bits)
            1 data member change:
             'int S0::m0' offset changed from 0 to 32
exit code: 4
$
4.
تشخیص حذف یا اضافه شدن توابع به یک کتابخانه:
$ cat -n test-v0.cc
         1      // Compile this with:
         2      //   g++ -g -Wall -shared -o libtest-v0.so test-v0.cc
         3
         4      struct S0
         5      {
         6        int m0;
         7      };
         8
         9      void
        10      foo(S0& /*parameter_name*/)
        11      {
        12        // do something with parameter_name.
        13      }
$
$ cat -n test-v1.cc
         1      // Compile this with:
         2      //   g++ -g -Wall -shared -o libtest-v1.so test-v1.cc
         3
         4      struct S0
         5      {
         6        char inserted_member;
         7        int m0;
         8      };
         9
        10      void
        11      bar(S0& /*parameter_name*/)
        12      {
        13        // do something with parameter_name.
        14      }
$
$ g++ -g -Wall -shared -o libtest-v0.so test-v0.cc
$ g++ -g -Wall -shared -o libtest-v1.so test-v1.cc
$
$ abidiff libtest-v0.so libtest-v1.so; echo "exit code: $?"
Functions changes summary: 1 Removed, 0 Changed, 1 Added functions
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
1 Removed function:
  'function void foo(S0&)'    {_Z3fooR2S0}
1 Added function:
  'function void bar(S0&)'    {_Z3barR2S0}
exit code: 12
$
5.
مقایسه دو مجموعه باینری که در خط فرمان ارسال می‌شوند:
$ abidiff --add-binaries1=file2-v1              \
          --add-binaries2=file2-v2,file2-v1     \
          --added-binaries-dir1 dir1            \
          --added-binaries-dir2 dir2            \
          file1-v1 file1-v2

توجه داشته باشید که فایل‌های file2-v1 و file2-v2 باید در dir1 و dir2 یا در دایرکتوری جاری یافت شوند.

6.
مقایسه دو کتابخانه و وابستگی‌های آن‌ها:
$ abidiff --follow-dependencies                      \
          --added-binaries-dir1 /some/where          \
          --added-binaries-dir2 /some/where/else     \
          foo bar

این دستور مجموعه باینری‌های تشکیل‌شده توسط foo و وابستگی‌های آن را در برابر مجموعه باینری‌های تشکیل‌شده توسط bar و وابستگی‌های آن مقایسه می‌کند.

Dodji Seketeli

2014-2025, Red Hat, Inc.

1 مه 2026