| LLVM-DEBUGINFO-ANALYZER(1) | LLVM | LLVM-DEBUGINFO-ANALYZER(1) |
نام (NAME)
llvm-debuginfo-analyzer - چاپ نمایشی منطقی از اطلاعات اشکالزدایی سطح پایین.
- خلاصه دستور (SYNOPSIS)
- توضیحات (DESCRIPTION)
- گزینهها (OPTIONS)
- عمومی (GENERAL)
- مشخصهها (ATTRIBUTES)
- چاپ (PRINT)
- خروجی (OUTPUT)
- گزارش (REPORT)
- گزینش (SELECTION)
- عناصر (ELEMENTS)
- خطوط (LINES)
- حوزهها (SCOPES)
- نمادها (SYMBOLS)
- نوعها (TYPES)
- مقایسه (COMPARE)
- هشدار (WARNING)
- داخلی (INTERNAL)
- •
- مثالها (EXAMPLES)
- •
- مورد آزمون ۱ - گزینههای عمومی
- •
- حالت چاپ
- جزئیات پایه
- انتخاب عناصر منطقی
- •
- حالت مقایسه
- نمای منطقی
- عناصر منطقی
- •
- مورد آزمون ۲ - دستورالعملهای اسمبلی
- CodeView - Clang (Windows)
- CodeView - MSVC (Windows)
- DWARF - Clang (Linux)
- DWARF - GCC (Linux)
- •
- مورد آزمون ۳ - حوزه واژگانی نادرست برای TYPEDEF
- CodeView - Clang (Windows)
- CodeView - MSVC (Windows)
- DWARF - Clang (Linux)
- DWARF - GCC (Linux)
- •
- مورد آزمون ۴ - شمارشهای تودرتوی مفقود
- CodeView - Clang (Windows)
- CodeView - MSVC (Windows)
- DWARF - Clang (Linux)
- DWARF - GCC (Linux)
- •
- مورد آزمون ۵ - حوزه واژگانی نادرست برای متغیر
- CODEVIEW - Clang (Windows)
- CODEVIEW - MSVC (Windows)
- DWARF - Clang (Linux)
- DWARF - GCC (Linux)
- مورد آزمون ۶ - نمای منطقی کامل
- پشتیبانی از WEBASSEMBLY
- چاپ جزئیات پایه
- گزینش عناصر منطقی
- حالت مقایسه
- نمای منطقی
- عناصر منطقی
- وضعیت خروج (EXIT STATUS)
- محدودیتها و مشکلات شناختهشده
- همچنین
ببینید (SEE ALSO)
llvm-debuginfo-analyzer [options] [filename ...]
توضیحات (DESCRIPTION)
llvm-debuginfo-analyzer بخشهای debug و text را در فایلهای شیء دودویی (binary object files) تجزیه کرده و محتوای آنها را در یک نمای منطقی (logical view) چاپ میکند؛ این نما بازنمایی خوانایی برای انسان است که تطابق نزدیکی با ساختار کد منبع اصلی کاربر دارد. قالبهای فایل شیء پشتیبانیشده شامل ELF، Mach-O، WebAssembly، PDB و COFF هستند.
نمای منطقی پیچیدگیهای مربوط به نمایشهای گوناگون سطح پایین اطلاعات اشکالزداییِ تعبیهشده در فایل شیء را انتزاع میکند. llvm-debuginfo-analyzer صرفنظر از چگونگی قالببندی اطلاعات اشکالزدایی، یک نمای استاندارد و متعارف (canonical) از آن تولید میکند. با فرض اینکه اطلاعات اشکالزدایی بهدرستی بیانگر همان کد منبع اصلی باشند، بدون در نظر گرفتن قالب فایل شیء، همان نمای منطقی یکسان مشاهده خواهد شد.
نمای منطقی شامل عناصر منطقی زیر است: type، scope، symbol و line که عناصر پایهای نرمافزار مورد استفاده در زبان برنامهنویسی C/C++ هستند. هر عنصر منطقی دارای مجموعهای از ویژگیها (attributes) است، مانند types، classes، functions، variables، parameters و غیره. گزینهٔ --attribute میتواند برای مشخص کردن ویژگیهایی به کار رود که هنگام چاپ یک عنصر منطقی باید لحاظ شوند. یک عنصر منطقی ممکن است دارای یک kind باشد که انواع خاصی از عناصر را توصیف میکند؛ به عنوان مثال، یک scope میتواند دارای نوعِ (kind) function، class یا namespace باشد.
llvm-debuginfo-analyzer بهطور پیشفرض چیدمان از پیشتعریفشدهای از عناصر و ویژگیهای منطقی را چاپ میکند. از گزینههای خط فرمان میتوان برای کنترل عناصر چاپشده (--print)، استفاده از یک چیدمان مشخص (--report) و مطابقت با یک الگوی معین (--select، --select-offsets) استفاده کرد. همچنین خروجی را میتوان با استفاده از (--select-lines، --select-scopes، --select-symbols، --select-types) به عناصر منطقی مشخصشده محدود نمود.
llvm-debuginfo-analyzer همچنین میتواند مجموعهای از نماهای منطقی را با یکدیگر مقایسه کند (--compare) تا تفاوتها را بیابد و خطاهای نحوی احتمالی در اطلاعات اشکالزدایی (--warning) را در هر فایل شیء شناسایی کند.
گزینهها (OPTIONS)
گزینههای llvm-debuginfo-analyzer به چند دسته تقسیم میشوند که هر یک برای هدف خاصی طراحی شدهاند:
- GENERAL - گزینههای استاندارد LLVM برای نمایش راهنما، نگارش و غیره.
- ATTRIBUTES - توصیف چگونگی گنجاندن جزئیات مختلف هنگام چاپ یک عنصر.
- PRINT - مشخص کردن اینکه کدام عناصر هنگام چاپ نما لحاظ شوند.
- OUTPUT - توصیف قالبهای پشتیبانیشده هنگام چاپ نما.
- REPORT - توصیف چیدمانهای قالب برای چاپ نما.
- SELECTION - امکان استفاده از معیارها یا شرایط خاص برای انتخاب عناصر جهت چاپ.
- COMPARE - مقایسهٔ نماهای منطقی و چاپ عناصر ناموجود یا اضافهشده.
- WARNING - چاپ هشدارهای شناساییشده در حین ایجاد نما.
- INTERNAL - تحلیل داخلی نمای منطقی.
GENERAL
این بخش گزینههای استاندارد راهنما را شرح میدهد که برای نمایش نحوهٔ استفاده، نگارش، فایلهای پاسخ (response files) و غیره به کار میروند.
- -h, --help
- نمایش راهنما و نحوهٔ استفاده از این دستور. (--help-hidden برای موارد بیشتر).
- --help-list
- نمایش راهنما و نحوهٔ استفاده از این دستور بدون گروهبندی گزینهها در دستهها (--help-list-hidden برای موارد بیشتر).
- --help-hidden
- نمایش تمام گزینههای موجود.
- --print-all-options
- چاپ مقادیر تمام گزینهها پس از تجزیهٔ خط فرمان.
- --print-options
- چاپ گزینههای غیرپیشفرض پس از تجزیهٔ خط فرمان.
- --version
- نمایش نگارش ابزار.
- @<FILE>
- خواندن گزینههای خط فرمان از <FILE>.
اگر هیچ فایل ورودی مشخص نشود، llvm-debuginfo-analyzer بهطور پیشفرض a.out را میخواند و در صورتی که فایل ورودی پیدا نشود، خطایی بازمیگرداند.
اگر از - به عنوان فایل ورودی استفاده شود، llvm-debuginfo-analyzer ورودی را از جریان ورودی استاندارد خود میخواند..SS "مشخصهها (ATTRIBUTES)"
گزینههای زیر مشخصههای ارائهشده برای عناصر چاپشده را فعال میکنند. این مشخصهها بر اساس نوع دادهای که افزوده میشود به دستههایی تقسیم میشوند، مانند: آفستهای داخلی در فایل باینری، توصیفکنندههای مکان، نامهای ثبات، نام فایلهای منبع کاربر، تبدیلات اضافی عنصر، نام زنجیره ابزار، قالب فایل باینری، و غیره.
- --attribute=<value[,value,...]>
- که در آن value یکی از گزینههای موجود در فهرستهای زیر است.
=all: شامل تمام مشخصههای زیر. =extended: افزودن مشخصههای سطح پایین (low-level). =standard: افزودن مشخصههای استاندارد سطح بالا (high-level).
مشخصههای زیر رایجترین اطلاعات را برای یک عنصر منطقی توصیف میکنند. آنها به شناسایی سطح حوزه لغوی (lexical scope level)، میزان دید عنصر در میان ماژولها (سراسری، محلی)، نام زنجیره ابزار و زبان منبعی که فایل باینری را تولید کرده است کمک میکنند.
=global: عنصری که در چندین Compile Unit به آن ارجاع شده است. =format: نام قالب فایل شیء (object file). =language: نام زبان منبع (source language). =level: سطح حوزه لغوی (File=0, Compile Unit=1). =local: عنصری که فقط در همان Compile Unit به آن ارجاع شده است. =producer: نام شناسایی زنجیره ابزار (toolchain).
مشخصههای زیر نام فایلها و دایرکتوریها را از کد منبع کاربر توصیف میکنند، جایی که عناصر در آن اعلان یا تعریف شدهاند؛ همچنین توابعی با دید عمومی در میان ماژولها. این گزینهها امکان نگاشت عناصر به مکانشان در کد کاربر را برای اهداف ارجاع متقابل (cross reference) فراهم میکنند.
=directories: دایرکتوریهای ارجاعدادهشده در اطلاعات اشکالزدایی. =filename: نام فایلی که عنصر در آن تعریف شده است. =files: فایلهای ارجاعدادهشده در اطلاعات اشکالزدایی. =pathname: نام مسیری که شیء در آن تعریف شده است. =publics: نام توابعی که عمومی (public) هستند.
مشخصههای زیر تبدیلات اضافی سورس عنصر منطقی را توصیف میکنند، بهمنظور نمایش انواع توکار (int، bool، و غیره)؛ پارامترها و آرگومانهای استفادهشده هنگام نمونهسازی الگو (template instantiation)؛ سلسلهمراتب نام والد؛ اطلاعات ابعاد آرایهها؛ عناصر تولیدشده توسط کامپایلر؛ اندازه انواع و انواع زیرین مرتبط با نامهای مستعار انواع (type aliases).
=argument: پارامترهای الگو جایگزینشده با آرگومانهای آن. =base: انواع پایه (int, bool, etc.). =generated: عناصر تولیدشده توسط کامپایلر. =encoded: آرگومانهای الگو که در نام الگو کدگذاری شدهاند. =qualified: نوع عنصر که نام والدین را در نام خود شامل میشود. =reference: ارجاعات به اعلان و تعریف عنصر. =size: اندازهها برای انواع مرکب و پایه. =subrange: اطلاعات کدگذاری زیردامنه (subrange) برای آرایهها. =typename: پارامترهای الگو (template). =underlying: نوع زیرین برای تعریف نوعها (type definitions).
مشخصههای زیر اطلاعات مکان اشکالزدایی (debug location) را برای یک نماد یا حوزه توصیف میکنند. این مشخصهها شامل درصد پوشش نماد و هرگونه شکاف (gap) درون چیدمان مکان، و محدودههای تعیینکننده بخشهای کد متصل به یک تابع هستند. هنگامی که از توصیفکنندهها استفاده شود، ثباتهای پردازنده مقصد نمایش داده میشوند.
=coverage: درصد پوشش مکان نماد. =gaps: مکانهای اشکالزدایی ناموجود (شکافها). =location: مکان اشکالزدایی نماد. =range: محدودههای مکان اشکالزدایی. =register: نامهای ثباتهای پردازنده.
مشخصههای زیر با جزئیات سطح پایین مرتبط هستند، از قبیل: آفستها در فایل باینری؛ متمایزکنندهها (discriminators) افزوده شده به خطوط توابع درونخطی (inlined) برای تفکیک نمونههای خاص؛ ثباتهای ماشین حالت خطوط اشکالزدایی؛ عناصر دور ریختهشده توسط کامپایلر (درونخطیسازی) یا بهینهسازیهای پیونددهنده (حذف کدهای مرده یا dead-stripping)؛ واحدهای کامپایل سیستمی تولیدشده توسط زنجیره ابزار MS در PDBها.
=discarded: عناصر دور ریختهشده توسط پیونددهنده (linker). =discriminator: متمایزکنندهها برای نمونههای توابع درونخطی (inlined). =inserted: ارجاعات انتزاعی درونخطی تولیدشده. =linkage: نام پیوند (linkage) در فایل شیء. =offset: آفست اطلاعات اشکالزدایی. =qualifier: توصیفکنندههای خط (Newstatement, BasicBlock, etc). =zero: شماره خطهای صفر.
مشخصه زیر اطلاعات خاص مربوط به قالب فایل PE/COFF را توصیف میکند. این مشخصه شامل انواع زمان اجرای MS است.
=system: نمایش عناصر سیستمی MS مربوط به PDBها.
مشخصههای بالا در دستههای standard و extended گروهبندی شدهاند که میتوان آنها را فعال کرد.
گروه standard شامل مشخصههایی است که اطلاعات کافی برای توصیف یک عنصر منطقی اضافه میکنند و میتوانند موقعیتهای عادی را در هنگام کار با اطلاعات اشکالزدایی پوشش دهند.
=base =coverage =directories =discriminator =filename =files =format =language =level =producer =publics =range =reference =zero
گروه extended شامل مشخصههایی است که نیازمند دانش عمیقتری درباره اطلاعات اشکالزدایی هستند. این مشخصهها زمانی کاربرد دارند که سطح پایینتر و دقیقتری از جزئیات مورد نیاز باشد.
=argument =discarded =encoded =gaps =generated =global =inserted =linkage =local =location =offset =operation =pathname =qualified =qualifier =register =size =subrange =system =typename
گزینههای زیر عنصرهایی را که باید چاپ شوند توصیف میکنند. چیدمان مورد استفاده توسط --report مشخص میشود. در چیدمان درختی، تمام عنصرها حوزههای لغوی دربرگیرنده خود را چاپ میکنند، حتی زمانی که بهطور صریح مشخص نشده باشند.
- --print=<value[,value,...]>
- که در آن value یکی از گزینههای فهرستهای زیر است.
=all: تمام ویژگیهای زیر را شامل میشود.
گزینههای زیر عنصرهای درخواستی را چاپ میکنند؛ در صورت تعیین هرگونه شرایط انتخاب (--select)، تنها عنصرهایی که با آنها مطابقت داشته باشند چاپ خواهند شد. مقدار elements روشی مناسب برای مشخص کردن همزمان دستورالعملها، خطوط، حوزهها، نمادها و انواع است.
=elements: دستورالعملها، خطوط، حوزهها، نمادها و انواع. =instructions: دستورالعملهای اسمبلی برای بخشهای کد. =lines: خطوط مبدأ ارجاع دادهشده در اطلاعات اشکالزدایی. =scopes: بلوکهای لغوی (تابع، کلاس، فضای نام و غیره). =symbols: نمادها (متغیر، عضو، پارامتر و غیره). =types: انواع (اشارهگر، ارجاع، نام مستعار نوع و غیره).
گزینههای زیر اطلاعات جمعآوریشده در حین ایجاد عنصرها را چاپ میکنند، از قبیل: سهم حوزهها در اطلاعات اشکالزدایی؛ خلاصه عنصرهای ایجادشده، چاپشده یا تطبیقیافته (--select)؛ هشدارهای تولیدشده در حین ایجاد نما.
=sizes: سهم حوزهها در اطلاعات اشکالزدایی. =summary: خلاصه عنصرهای تخصیصیافته، انتخابشده یا چاپشده. =warnings: هشدارهای شناساییشده.
نکته: گزینه --print=sizes مختص ELF است.
خروجی (OUTPUT)
گزینههای زیر نحوه کنترل خروجی تولیدشده هنگام چاپ عنصرهای منطقی را توصیف میکنند.
- --output-file=<path>
- تغییر مسیر خروجی به فایلی که با <path> مشخص میشود، که در آن - نشاندهنده جریان خروجی استاندارد است.
دستور llvm-debuginfo-analyzer دارای مفهوم «نمای تفکیکشده» (split view) است. هنگام تغییر مسیر خروجی از یک قالب باینری پیچیده، خروجی به فایلهای مجزا تقسیم میشود که هر کدام شامل خروجی نمای منطقی برای یک واحد ترجمه (compilation unit) مجزا است.
- --output-folder=<name>
- پوشهای برای نوشتن یک فایل به ازای هر واحد ترجمه، در صورتی که --output=split مشخص شده باشد.
- --output-level=<level>
- تنها عنصرهایی را چاپ میکند که تا مقدار سطح لغوی (lexical level) مشخصشده باشند. فایل ورودی در سطح لغوی صفر و یک واحد ترجمه در سطح لغوی یک قرار دارد.
- --output=<value[,value,...]>
- که در آن value یکی از گزینههای فهرستهای زیر است.
=all: تمام خروجیهای زیر را شامل میشود.
=json: استفاده از JSON به عنوان قالب خروجی (پیادهسازی نشده است). =split: تفکیک خروجی بر اساس واحدهای ترجمه (Compile Units). =text: استفاده از خروجی متنی با فرم آزاد.
- --output-sort=<key>
- کلید اصلی هنگام مرتبسازی عنصرها در خروجی (پیشفرض: line). مرتبسازی بر اساس نوع عنصر منطقی، مستلزم آشنایی با گزینههای انتخاب نوع عنصر (--select-lines، --select-scopes، --select-symbols، --select-types) است، زیرا آن گزینهها انواع مختلف عنصرهای منطقی را توصیف میکنند.
=none: خروجی بدون مرتبسازی (همانگونه که از ورودی خوانده شده است). =id: مرتبسازی بر اساس شناسه یکتای عنصر. =kind: مرتبسازی بر اساس نوع عنصر. =line: مرتبسازی بر اساس شماره خط عنصر. =name: مرتبسازی بر اساس نام عنصر. =offset: مرتبسازی بر اساس آفست عنصر.
بسته به وظیفهای که اجرا میشود (print، compare، select)، چندین طرحبندی برای نمایش عناصر به شکلی مناسبتر پشتیبانی میشوند تا درک خروجی آسانتر گردد.
- --report=<value[,value,...]>
- بهطوریکه value یکی از گزینههای فهرست زیر باشد.
=all: شامل تمام گزارشهای زیر.
=children: عناصر و فرزندان در قالب درختی نمایش داده میشوند. =list: عناصر در قالب جدولی نمایش داده میشوند. =parents: عناصر و والدین در قالب درختی نمایش داده میشوند. =view: عناصر، والدین و فرزندان در قالب درختی نمایش داده میشوند.
طرحبندی list عناصر منطقی را در قالبی جدولی و بدون هیچگونه رابطهٔ والد-فرزندی نمایش میدهد. این روش هنگام مقایسهٔ نماهای منطقی، میتواند روش ارجح برای نمایش عناصری باشد که با شرایط خاصی مطابقت دارند، و پیدا کردن تفاوتها را آسانتر میکند.
طرحبندیهای children، parents و view عناصر را در یک قالب درختی نمایش میدهند؛ بهطوریکه حوزهها (scopes) گرههای آن، و انواع (types)، نمادها (symbols)، خطوط (lines) و سایر حوزهها فرزندان آنها را تشکیل میدهند. این طرحبندی، رابطهٔ حوزهٔ واژگانی (lexical scoping) میان عناصر را نشان میدهد که در آن فایل باینری ریشهٔ درخت (سطح 0) و هر واحد ترجمه (compilation unit) یک فرزند (سطح 1) است.
طرحبندی children شامل عناصری است که با هر یک از معیارهای تعیینشده (--select) یا (--compare) مطابقت دارند، به همراه فرزندان آنها.
طرحبندی parents شامل عناصری است که با هر یک از معیارهای تعیینشده (--select) یا (--compare) مطابقت دارند، به همراه والدین آنها.
طرحبندی ترکیبی view شامل عناصری است که با هر یک از معیارهای تعیینشده (--select) یا (--compare) مطابقت دارند، به همراه والدین و فرزندان آنها.
نکات:
- 1.
- هنگامی که یک معیار گزینش (--select) بدون مشخص کردن گزینهٔ گزارش تعیین شود، طرحبندی list انتخاب میشود.
- 2.
- حالت مقایسه همواره از طرحبندی view استفاده میکند.
گزینش (SELECTION)
هنگام چاپ یک عنصر، دادههای گوناگونی را میتوان لحاظ کرد و این اطلاعات (--attribute) از دادههای مستقیماً مرتبط با فایل باینری (افست) گرفته تا جزئیات سطح بالا مانند پوشش، سطح حوزهٔ واژگانی و مکان را در بر میگیرد. با توجه به اینکه خروجی چاپشده ممکن است به اندازهٔ قابلتوجهی برسد، چندین گزینهٔ گزینش، امکان چاپ عناصری مشخص را فراهم میکنند.
تطبیق الگو میتواند به حروف کوچک و بزرگ حساس نباشد (--select-nocase) و برای استفاده از عبارات باقاعده گسترش یابد (--select-regex).
عناصر (ELEMENTS)
گزینههای زیر امکان چاپ عناصری را فراهم میکنند که با <pattern>، مقدار <value> افست یا یک <condition> عنصر دادهشده مطابقت دارند.
- --select=<pattern>
- چاپ تمام عناصری که نام یا شماره خط آنها با <pattern> دادهشده مطابقت دارد.
- --select-offsets=<value[,value,...]>
- چاپ تمام عناصری که افست آنها با مقادیر دادهشده مطابقت دارد. گزینهٔ --attribute را ببینید.
- --select-elements=<condition[,condition,...]>
- چاپ تمام عناصری که <condition> دادهشده را برآورده میکنند؛ بهطوریکه condition یکی از گزینههای فهرست زیر باشد.
=discarded: عناصر کنار گذاشتهشده توسط پیونددهنده (linker). =global: عنصری که در چندین واحد ترجمه به آن ارجاع داده شده است. =optimized: ارجاعات انتزاعی درونخطیشدهٔ بهینهسازیشده.
- --select-nocase
- هنگام استفاده از --select، تطبیق الگو به حروف بزرگ و کوچک حساس نیست.
- --select-regex
- هنگام گزینش با گزینهٔ --select، با هر رشتهٔ <pattern> به عنوان یک عبارت باقاعده رفتار میکند. اگر --select-nocase مشخص شده باشد، عبارت باقاعده به حروف بزرگ و کوچک حساس نخواهد بود.
اگر معیار <pattern> بیش از حد عمومی باشد، میتوان گزینهٔ دقیقتری را برای هدف قرار دادن دستهبندی خاصی از عناصر تعیین کرد: خطوط (--select-lines)، حوزهها (--select-scopes)، نمادها (--select-symbols) و انواع (--select-types).
این گزینهها نیازمند آگاهی از قالب اطلاعات اشکالزدایی (DWARF، CodeView) هستند، زیرا kind دادهشده، نوع بسیار خاصی از عناصر را توصیف میکند..SS "سطرها (LINES)"
گزینههای زیر امکان چاپ سطرهایی را فراهم میکنند که با <kind> دادهشده مطابقت دارند. معیار ارائهشده، ثباتهای ماشین حالت debug line را توصیف میکند.
- --select-lines=<kind[,kind,...]>
- بهطوری که kind یکی از گزینههای فهرست زیر باشد.
=AlwaysStepInto: یک پرش همیشگی به درون (always step into) را علامتگذاری میکند. =BasicBlock: یک بلوک پایهای (basic block) جدید را علامتگذاری میکند. =Discriminator: سطری که دارای یک تفکیککننده (discriminator) است. =EndSequence: پایان توالی سطرها را علامتگذاری میکند. =EpilogueBegin: آغاز بخش پایانی (epilogue) تابع را علامتگذاری میکند. =LineAssembler: سطرهایی که متناظر با متن دیساسمبلی هستند. =LineDebug: سطرهایی که متناظر با سطرهای اشکالزدایی (debug lines) هستند. =NeverStepInto: یک عدم پرش به درون (never step into) را علامتگذاری میکند. =NewStatement: یک عبارت (statement) جدید را علامتگذاری میکند. =PrologueEnd: پایان بخش آغازین (prologue) تابع را علامتگذاری میکند.
حوزهها (SCOPES)
گزینههای زیر امکان چاپ حوزههایی را فراهم میکنند که با <kind> دادهشده مطابقت دارند.
- --select-scopes=<kind[,kind,...]>
- بهطوری که kind یکی از گزینههای فهرست زیر باشد.
=Aggregate: یک کلاس، ساختار یا اجتماع (union). =Array: یک آرایه. =Block: یک بلوک عمومی (بلوک واژگانی یا بلوک استثنا). =CallSite: یک محل فراخوانی (call site). =CatchBlock: یک بلوک استثنا (catch block). =Class: یک کلاس. =CompileUnit: یک واحد کامپایل (compile unit). =EntryPoint: یک نقطهٔ ورود زیرروال (subroutine). =Enumeration: یک شمارش (enumeration). =Function: یک تابع. =FunctionType: یک اشارهگر تابع (function pointer). =InlinedFunction: یک تابع درونخطی (inlined function). =Label: یک برچسب (label). =LexicalBlock: یک بلوک واژگانی (lexical block). =Module: یک ماژول. =Namespace: یک فضای نام (namespace). =Root: عنصری که نمایانگر حوزهٔ اصلی (main scope) است. =Structure: یک ساختار (structure). =Subprogram: یک زیربرنامه (subprogram). =Template: یک تعریف الگو (template). =TemplateAlias: یک نام مستعار الگو (template alias). =TemplatePack: یک بسته الگو (template pack). =TryBlock: یک بلوک استثنای try. =Union: یک اجتماع (union).
نمادها (SYMBOLS)
گزینههای زیر امکان چاپ نمادهایی را فراهم میکنند که با <kind> دادهشده مطابقت دارند.
- --select-symbols=<kind[,kind,...]>
- بهطوری که kind یکی از گزینههای فهرست زیر باشد.
=CallSiteParameter: یک پارامتر محل فراخوانی (call site). =Constant: یک نماد ثابت (constant). =Inheritance: یک کلاس پایه (base class). =Member: یک کلاس عضو (member class). =Parameter: یک پارامتر برای تابع. =Unspecified: پارامترهای نامشخص برای تابع. =Variable: یک متغیر.
گزینههای زیر امکان چاپ نوعهایی را فراهم میکنند که با <kind> مشخصشده مطابقت دارند.
- --select-types=<kind[,kind,...]>
- به طوری که kind یکی از گزینههای فهرست زیر باشد:
=Base: نوع پایه (عدد صحیح، بولی و غیره). =Const: مشخصگر ثابت (const). =Enumerator: مقدار شمارشی (Enumerator). =Import: اعلان واردسازی (import). =ImportDeclaration: اعلان واردسازی. =ImportModule: ماژول واردسازی. =Pointer: نوع اشارهگر. =PointerMember: اشارهگر به تابع عضو. =Reference: نوع مرجع. =Restrict: مشخصگر restrict. =RvalueReference: مرجع مقدار راست (R-value reference). =Subrange: زیربازه آرایه. =TemplateParam: پارامتر الگو. =TemplateTemplateParam: پارامتر الگوی الگو. =TemplateTypeParam: پارامتر نوع الگو. =TemplateValueParam: پارامتر مقدار الگو. =Typedef: تعریف نوع (typedef). =Unspecified: نوع مشخصنشده. =Volatile: مشخصگر فرار (volatile).
مقایسه (COMPARE)
هنگام کار با اطلاعات اشکالزدایی (debug information)، موقعیتهایی وجود دارد که چاپ صرف عناصر، رویکرد مناسبی نیست. این حالت زمانی رخ میدهد که بررسی تأثیرات ناشی از نسخههای مختلف یک زنجیرهابزار یکسان، یا اثر بهینهسازیهای خاص کامپایلر مد نظر باشد.
در چنین مواردی، به دنبال آن هستیم که ببینیم چه عناصری افزوده یا حذف شدهاند. با توجه به قالب پیچیده اطلاعات اشکالزدایی، استفاده از یک ابزار diff معمولی برای یافتن این عناصر بسیار دشوار و هنگام کار با قالبهای اشکالزدایی متفاوت، حتی ناممکن است.
ابزار llvm-debuginfo-analyzer از مقایسه منطقی عناصر پشتیبانی میکند که امکان یافتن تفاوتهای معنایی بین نماهای منطقیِ تولیدشده توسط نسخههای مختلف زنجیرهابزار یا حتی قالبهای اطلاعات اشکالزدایی گوناگون را فراهم میسازد.
هنگام مقایسه نماهای منطقیِ ایجادشده از قالبهای اشکالزدایی متفاوت، دقت مقایسه به این بستگی دارد که اطلاعات اشکالزدایی تا چه اندازه کد کاربر را دقیق بازنمایی میکنند. به عنوان مثال، یک نمای منطقی ایجادشده از یک فایل باینری با اطلاعات اشکالزدایی DWARF ممکن است شامل دادههای دقیقتری نسبت به یک نمای منطقی ایجادشده از یک فایل باینری با اطلاعات اشکالزدایی CodeView باشد.
گزینههای زیر عناصر مورد مقایسه را شرح میدهند.
- --compare=<value[,value,...]>
- به طوری که value یکی از گزینههای فهرست زیر باشد:
=all: شامل تمام عناصر زیر.
=lines: شامل خطها. =scopes: شامل حوزهها. =symbols: شامل نمادها. =types: شامل انواع.
ابزار llvm-debuginfo-analyzer نخستین فایل باینری در خط فرمان را به عنوان reference (مرجع) و فایل دوم را به عنوان target (هدف) در نظر میگیرد. برای دستیابی به گزارشی توصیفیتر، مقایسه دو بار انجام میشود. نماهای مرجع و هدف جابهجا میشوند تا آن دسته از عناصر missing (مفقود) از نمای هدف و عناصر added (افزودهشده) به نمای مرجع مشخص شوند.
برای چگونگی شرح گزارشهای مقایسه، گزینههای --report را ببینید..SS "هشدار (WARNING)"
هنگام خواندن فایلهای شیء ورودی، llvm-debuginfo-analyzer میتواند مشکلاتی را در اطلاعات اشکالزدایی خام شناسایی کند. ممکن است این موارد برای هدفِ چاپ یک نمای منطقی مهلک تلقی نشوند، اما میتوانند نشانهای از کیفیت بوده و بهطور بالقوه مشکلاتی را در اطلاعات اشکالزدایی تولیدشده آشکار سازند.
گزینههای زیر هشدارهایی را شرح میدهند که در صورت درخواست توسط --print، برای چاپ بعدی ثبت میشوند.
- --warning=<value[,value,...]>
- که در آن value یکی از گزینههای فهرست زیر است.
=all: شامل تمام هشدارهای زیر.
گزینههای زیر اطلاعات بیشتری را در طول ایجاد نمای منطقی جمعآوری میکنند، از جمله مقادیر نامعتبر پوشش و مکانها برای نمادها؛ محدودههای نامعتبر کد؛ و خطوطی که صفر هستند.
=coverages: مقادیر نامعتبر پوشش نماد. =lines: خطوط اشکالزدایی با مقدار صفر. =locations: مکانهای نامعتبر نماد. =ranges: محدودههای نامعتبر کد.
داخلی (INTERNAL)
llvm-debuginfo-analyzer از این گزینههای پیشرفته در هر دو ساخت release و debug پشتیبانی میکند.
- --internal=<value[,value,...]>
- که در آن value یکی از گزینههای فهرست زیر است.
=all: شامل تمام گزینههای زیر.
گزینههای زیر امکان بررسی یکپارچگی نمای منطقی را فراهم میکنند؛ برچسبهای اشکالزدایی که پردازش شده یا پیادهسازی نشدهاند را جمعآوری میکنند؛ شماره خط عنصر منطقی را نادیده میگیرند تا مقایسه نمای منطقی هنگام استفاده از ابزارهای مقایسه خارجی آسانتر شود؛ و گزینههای خط فرمانی را که برای فراخوانی llvm-debuginfo-analyzer استفاده شدهاند، چاپ میکنند.
=id: چاپ شناسه یکتای عنصر. =cmdline: چاپ خط فرمان. =integrity: بررسی یکپارچگی عناصر. =none: نادیده گرفتن شماره خط عنصر. =tag: برچسبهای اطلاعات اشکالزدایی.
نکته: برای قالب ELF، برچسبهای جمعآوریشده نشاندهنده برچسبهای اشکالزدایی هستند که پردازش نشدهاند. برای قالب PE/COFF، آنها نشاندهنده برچسبهایی هستند که پردازش شدهاند.
این بخش شامل چند فایل باینری واقعی است تا نحوه استفاده از llvm-debuginfo-analyzer را برای چاپ یک نمای منطقی و تشخیص مشکلات احتمالی اطلاعات اشکالزدایی نشان دهد.
مورد آزمون ۱ - گزینههای عمومی (TEST CASE 1 - GENERAL OPTIONS)
مثال زیر برای نشان دادن خروجیهای متفاوتی که توسط llvm-debuginfo-analyzer تولید میشود به کار رفته است. ما این مثال را برای یک هدف X86 ELF با Clang (-O0 -g) کامپایل کردهایم:
1 using INTPTR = const int *;
2 int foo(INTPTR ParamPtr, unsigned ParamUnsigned, bool ParamBool) {
3 if (ParamBool) {
4 typedef int INTEGER;
5 const INTEGER CONSTANT = 7;
6 return CONSTANT;
7 }
8 return ParamUnsigned;
9 }
حالت چاپ (PRINTING MODE)
در این حالت llvm-debuginfo-analyzer نمای منطقی یا بخشهایی از آن را بر اساس الگوهای معیار (شامل عبارات باقاعده) برای انتخاب نوع عناصر منطقی که باید در خروجی گنجانده شوند، چاپ میکند.
جزئیات پایه (BASIC DETAILS)
دستور زیر جزئیات پایهای را برای تمام عناصر منطقی مرتبشده بر اساس آفست داخلی اطلاعات اشکالزدایی چاپ میکند؛ این شامل سطح واژگانی (lexical level) و قالب اطلاعات اشکالزدایی آن است.
llvm-debuginfo-analyzer --attribute=level,format
--output-sort=offset
--print=scopes,symbols,types,lines,instructions
test-dwarf-clang.o
یا
llvm-debuginfo-analyzer --attribute=level,format
--output-sort=offset
--print=elements
test-dwarf-clang.o
هر ردیف نشاندهنده عنصری است که در اطلاعات اشکالزدایی وجود دارد. ستون نخست نشاندهنده سطح دامنه (scope level) است که پس از آن شماره خط مربوطه (در صورت وجود) و در نهایت شرح عنصر میآید.
Logical View:
[000] {File} 'test-dwarf-clang.o' -> elf64-x86-64
[001] {CompileUnit} 'test.cpp'
[002] 2 {Function} extern not_inlined 'foo' -> 'int'
[003] 2 {Parameter} 'ParamPtr' -> 'INTPTR'
[003] 2 {Parameter} 'ParamUnsigned' -> 'unsigned int'
[003] 2 {Parameter} 'ParamBool' -> 'bool'
[003] {Block}
[004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
[004] 5 {Line}
[004] {Code} 'movl $0x7, -0x1c(%rbp)'
[004] 6 {Line}
[004] {Code} 'movl $0x7, -0x4(%rbp)'
[004] {Code} 'jmp 0x6'
[004] 8 {Line}
[004] {Code} 'movl -0x14(%rbp), %eax'
[003] 4 {TypeAlias} 'INTEGER' -> 'int'
[003] 2 {Line}
[003] {Code} 'pushq %rbp'
[003] {Code} 'movq %rsp, %rbp'
[003] {Code} 'movb %dl, %al'
[003] {Code} 'movq %rdi, -0x10(%rbp)'
[003] {Code} 'movl %esi, -0x14(%rbp)'
[003] {Code} 'andb $0x1, %al'
[003] {Code} 'movb %al, -0x15(%rbp)'
[003] 3 {Line}
[003] {Code} 'testb $0x1, -0x15(%rbp)'
[003] {Code} 'je 0x13'
[003] 8 {Line}
[003] {Code} 'movl %eax, -0x4(%rbp)'
[003] 9 {Line}
[003] {Code} 'movl -0x4(%rbp), %eax'
[003] {Code} 'popq %rbp'
[003] {Code} 'retq'
[003] 9 {Line}
[002] 1 {TypeAlias} 'INTPTR' -> '* const int'
با بررسی دقیقتر، میتوانیم ببینیم چه چیزی میتواند یک مشکل بالقوه در اشکالزدایی باشد:
[003] {Block}
[003] 4 {TypeAlias} 'INTEGER' -> 'int'
تعریف 'INTEGER' در سطح [003] است، یعنی همان دامنه واژگانی {Block} ناشناس (شاخه 'true' برای دستور 'if')، در حالی که در کد منبع اصلی دستور typedef مشخصاً درون آن بلوک قرار دارد؛ بنابراین تعریف 'INTEGER' نیز باید در سطح [004] در داخل بلوک باشد..SS "انتخاب عناصر منطقی (SELECT LOGICAL ELEMENTS)"
دستور زیر تمام instructions، symbols و types که حاوی 'inte' یا 'movl' در نام یا نوع خود هستند را با استفاده از قالببندی ستونی (tab layout) و با نمایش تعداد موارد منطبق، چاپ میکند.
llvm-debuginfo-analyzer --attribute=level
--select-nocase --select-regex
--select=INTe --select=movl
--report=list
--print=symbols,types,instructions,summary
test-dwarf-clang.o
Logical View:
[000] {File} 'test-dwarf-clang.o'
[001] {CompileUnit} 'test.cpp'
[003] {Code} 'movl $0x7, -0x1c(%rbp)'
[003] {Code} 'movl $0x7, -0x4(%rbp)'
[003] {Code} 'movl %eax, -0x4(%rbp)'
[003] {Code} 'movl %esi, -0x14(%rbp)'
[003] {Code} 'movl -0x14(%rbp), %eax'
[003] {Code} 'movl -0x4(%rbp), %eax'
[003] 4 {TypeAlias} 'INTEGER' -> 'int'
[004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
-----------------------------
Element Total Found
-----------------------------
Scopes 3 0
Symbols 4 1
Types 2 1
Lines 17 6
-----------------------------
Total 26 8
حالت مقایسه (COMPARISON MODE)
در این حالت، llvm-debuginfo-analyzer نماهای منطقی (logical views) را برای ایجاد گزارشی از عناصر منطقیِ مفقود یا اضافهشده مقایسه میکند. این قابلیت یک ابزار بسیار قدرتمند برای یافتن تفاوتهای معنایی در اطلاعات اشکالزدایی تولیدشده توسط نسخههای مختلف زنجیره ابزار (toolchain) یا حتی زنجیرههای ابزار کاملاً متفاوت است (به عنوان مثال، کامپایلری که DWARF تولید میکند را میتوان مستقیماً با کامپایلر کاملاً متفاوتی که CodeView تولید میکند مقایسه کرد).
با توجه به مثال قبلی، ما با مقایسه در برابر یک کامپایلر دیگر، مشکل اطلاعات اشکالزدایی فوق (مربوط به مکان نامعتبر قبلی حوزه برای 'typedef int INTEGER') را شناسایی کردیم.
با استفاده از GCC برای تولید test-dwarf-gcc.o، میتوانیم یک الگوی گزینش را همراه با حالت چاپ اعمال کنیم تا خروجی نمای منطقی زیر به دست آید.
llvm-debuginfo-analyzer --attribute=level
--select-regex --select-nocase --select=INTe
--report=list
--print=symbols,types
test-dwarf-clang.o test-dwarf-gcc.o
Logical View:
[000] {File} 'test-dwarf-clang.o'
[001] {CompileUnit} 'test.cpp'
[003] 4 {TypeAlias} 'INTEGER' -> 'int'
[004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
Logical View:
[000] {File} 'test-dwarf-gcc.o'
[001] {CompileUnit} 'test.cpp'
[004] 4 {TypeAlias} 'INTEGER' -> 'int'
[004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
خروجی نشان میدهد که هر دو شیء شامل عناصر یکسانی هستند، اما 'typedef INTEGER' در سطح حوزه (scope level) متفاوتی قرار دارد. شیء تولیدشده توسط GCC مقدار '4' را نشان میدهد که مقدار صحیح است.
توجه داشته باشید که برای انجام مقایسه، الزامی مبنی بر اینکه GCC حتماً باید DWARF یکسان یا مشابهی با Clang تولید کند وجود ندارد. ما تنها معناشناسی (semantics) را مقایسه میکنیم. همین موضوع هنگام مقایسه اطلاعات اشکالزدایی CodeView تولیدشده توسط MSVC و Clang نیز صدق میکند.
۲ روش برای مقایسه وجود دارد: نمای منطقی (logical view) و عناصر منطقی (logical elements)..SS "نمای منطقی (LOGICAL VIEW)"
این بخش نمای منطقی را بهعنوان یک کلِ واحد مقایسه میکند؛ برای برقراری تطابق، هر عنصر منطقیِ مقایسهشده باید والدین و فرزندان یکسانی داشته باشد.
با استفاده از قابلیت مقایسه llvm-debuginfo-analyzer، میتوان آن مسئله را در بستری کلیتر که میتواند شامل نمای منطقی نیز باشد، مشاهده کرد.
خروجی در قالب نما، عناصر مفقود (-) و افزودهشده (+) را نشان میدهد، و با جابهجا کردن فایلهای شیءِ مرجع و هدف، زمینه بیشتری فراهم میکند.
llvm-debuginfo-analyzer --attribute=level
--compare=types
--report=view
--print=symbols,types
test-dwarf-clang.o test-dwarf-gcc.o
Reference: 'test-dwarf-clang.o'
Target: 'test-dwarf-gcc.o'
Logical View:
[000] {File} 'test-dwarf-clang.o'
[001] {CompileUnit} 'test.cpp'
[002] 1 {TypeAlias} 'INTPTR' -> '* const int'
[002] 2 {Function} extern not_inlined 'foo' -> 'int'
[003] {Block}
[004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
+[004] 4 {TypeAlias} 'INTEGER' -> 'int'
[003] 2 {Parameter} 'ParamBool' -> 'bool'
[003] 2 {Parameter} 'ParamPtr' -> 'INTPTR'
[003] 2 {Parameter} 'ParamUnsigned' -> 'unsigned int'
-[003] 4 {TypeAlias} 'INTEGER' -> 'int'
خروجی، مسیر نمای ادغامشده (مرجع و هدف) را به همراه عناصر مفقود و افزودهشده نمایش میدهد.
عناصر منطقی (LOGICAL ELEMENTS)
این بخش عناصر منطقی را بهصورت مجزا و بدون در نظر گرفتن یکسان بودن والدین آنها مقایسه میکند. برای هر دو روش مقایسه، معیارهای برابری شامل نام، مکان در کد منبع، نوع و سطح حوزه واژگانی (lexical scope level) است.
llvm-debuginfo-analyzer --attribute=level
--compare=types
--report=list
--print=symbols,types,summary
test-dwarf-clang.o test-dwarf-gcc.o
Reference: 'test-dwarf-clang.o'
Target: 'test-dwarf-gcc.o'
(1) Missing Types:
-[003] 4 {TypeAlias} 'INTEGER' -> 'int'
(1) Added Types:
+[004] 4 {TypeAlias} 'INTEGER' -> 'int'
----------------------------------------
Element Expected Missing Added
----------------------------------------
Scopes 4 0 0
Symbols 0 0 0
Types 2 1 1
Lines 0 0 0
----------------------------------------
Total 6 1 1
تغییر ترتیب Reference و Target:
llvm-debuginfo-analyzer --attribute=level
--compare=types
--report=list
--print=symbols,types,summary
test-dwarf-gcc.o test-dwarf-clang.o
Reference: 'test-dwarf-gcc.o'
Target: 'test-dwarf-clang.o'
(1) Missing Types:
-[004] 4 {TypeAlias} 'INTEGER' -> 'int'
(1) Added Types:
+[003] 4 {TypeAlias} 'INTEGER' -> 'int'
----------------------------------------
Element Expected Missing Added
----------------------------------------
Scopes 4 0 0
Symbols 0 0 0
Types 2 1 1
Lines 0 0 0
----------------------------------------
Total 6 1 1
با جابهجا شدن Reference و Target، موارد Added Types از حالت اول، اکنون در قالب Missing Types فهرست میشوند..SS "مورد آزمایشی ۲ - دستورالعملهای اسمبلی (TEST CASE 2 - ASSEMBLER INSTRUCTIONS)"
مثال زیر برای نشان دادن خروجیهای متفاوتی که توسط llvm-debuginfo-analyzer تولید میشوند، به کار رفته است. ما این مثال را برای هدفهای X86 Codeview و ELF با نسخههای اخیر Clang، GCC و MSVC (-O0 -g) برای Windows و Linux کامپایل کردهایم.
1 extern int printf(const char * format, ... );
2
3 int main()
4 {
5 printf("Hello, World\n");
6 return 0;
7 }
اینها نماهای منطقیای هستند که llvm-debuginfo-analyzer برای ۳ کامپایلر مختلف (MSVC، Clang و GCC) تولید میکند که قالبهای اطلاعات اشکالزدایی متفاوتی (CodeView، DWARF) را در Windows و Linux صادر میکنند.
llvm-debuginfo-analyzer --attribute=level,format,producer
--print=lines,instructions
hello-world-codeview-clang.o
hello-world-codeview-msvc.o
hello-world-dwarf-clang.o
hello-world-dwarf-gcc.o
CodeView - Clang (Windows)
Logical View:
[000] {File} 'hello-world-codeview-clang.o' -> COFF-x86-64
[001] {CompileUnit} 'hello-world.cpp'
[002] {Producer} 'clang version 14.0.0'
[002] {Function} extern not_inlined 'main' -> 'int'
[003] 4 {Line}
[003] {Code} 'subq $0x28, %rsp'
[003] {Code} 'movl $0x0, 0x24(%rsp)'
[003] 5 {Line}
[003] {Code} 'leaq (%rip), %rcx'
[003] {Code} 'callq 0x0'
[003] 6 {Line}
[003] {Code} 'xorl %eax, %eax'
[003] {Code} 'addq $0x28, %rsp'
[003] {Code} 'retq'
CodeView - MSVC (Windows)
Logical View:
[000] {File} 'hello-world-codeview-msvc.o' -> COFF-i386
[001] {CompileUnit} 'hello-world.cpp'
[002] {Producer} 'Microsoft (R) Optimizing Compiler'
[002] {Function} extern not_inlined 'main' -> 'int'
[003] 4 {Line}
[003] {Code} 'pushl %ebp'
[003] {Code} 'movl %esp, %ebp'
[003] 5 {Line}
[003] {Code} 'pushl $0x0'
[003] {Code} 'calll 0x0'
[003] {Code} 'addl $0x4, %esp'
[003] 6 {Line}
[003] {Code} 'xorl %eax, %eax'
[003] 7 {Line}
[003] {Code} 'popl %ebp'
[003] {Code} 'retl'
Logical View:
[000] {File} 'hello-world-dwarf-clang.o' -> elf64-x86-64
[001] {CompileUnit} 'hello-world.cpp'
[002] {Producer} 'clang version 14.0.0'
[002] 3 {Function} extern not_inlined 'main' -> 'int'
[003] 4 {Line}
[003] {Code} 'pushq %rbp'
[003] {Code} 'movq %rsp, %rbp'
[003] {Code} 'subq $0x10, %rsp'
[003] {Code} 'movl $0x0, -0x4(%rbp)'
[003] 5 {Line}
[003] {Code} 'movabsq $0x0, %rdi'
[003] {Code} 'movb $0x0, %al'
[003] {Code} 'callq 0x0'
[003] 6 {Line}
[003] {Code} 'xorl %eax, %eax'
[003] {Code} 'addq $0x10, %rsp'
[003] {Code} 'popq %rbp'
[003] {Code} 'retq'
[003] 6 {Line}
DWARF - GCC (Linux)
Logical View:
[000] {File} 'hello-world-dwarf-gcc.o' -> elf64-x86-64
[001] {CompileUnit} 'hello-world.cpp'
[002] {Producer} 'GNU C++14 9.3.0'
[002] 3 {Function} extern not_inlined 'main' -> 'int'
[003] 4 {Line}
[003] {Code} 'endbr64'
[003] {Code} 'pushq %rbp'
[003] {Code} 'movq %rsp, %rbp'
[003] 5 {Line}
[003] {Code} 'leaq (%rip), %rdi'
[003] {Code} 'movl $0x0, %eax'
[003] {Code} 'callq 0x0'
[003] 6 {Line}
[003] {Code} 'movl $0x0, %eax'
[003] 7 {Line}
[003] {Code} 'popq %rbp'
[003] {Code} 'retq'
[003] 7 {Line}
نمای منطقی، خطوط و دستورالعملهای اسمبلی درهمآمیخته را نشان میدهد که امکان مقایسهٔ کد تولیدشده توسط زنجیرهابزارهای مختلف را فراهم میسازد.
مورد آزمایشی ۳ - حوزه واژگانی نادرست برای TYPEDEF (TEST CASE 3 - INCORRECT LEXICAL SCOPE FOR TYPEDEF)
مثال زیر برای نشان دادن خروجیهای متفاوتی که توسط llvm-debuginfo-analyzer تولید میشود، به کار رفته است. ما این مثال را برای مقصدهای X86 Codeview و ELF با نسخههای اخیر Clang، GCC و MSVC کامپایل کردهایم (-O0 -g).
1 int bar(float Input) { return (int)Input; }
2
3 unsigned foo(char Param) {
4 typedef int INT; // ** Definition for INT **
5 INT Value = Param;
6 {
7 typedef float FLOAT; // ** Definition for FLOAT **
8 {
9 FLOAT Added = Value + Param;
10 Value = bar(Added);
11 }
12 }
13 return Value + Param;
14 }
آزمون بالا برای نشان دادن یک مشکل حوزهٔ دید (scope) که در کامپایلر Clang یافت شده استفاده میشود: PR44884 (Bugs LLVM) https://bugs.llvm.org/show_bug.cgi?id=44884 / PR44229 (GitHub LLVM) https://github.com/llvm/llvm-project/issues/44229
خطهای ۴ و ۷ شامل ۲ دستور typedef هستند که در حوزههای واژگانی متفاوتی تعریف شدهاند.
4 typedef int INT; 7 typedef float FLOAT;
اینها نماهای منطقیای هستند که llvm-debuginfo-analyzer برای ۳ کامپایلر مختلف (MSVC، Clang و GCC) تولید میکند که قالبهای مختلف اطلاعات اشکالزدایی (CodeView، DWARF) را در بسترهای گوناگون منتشر میکنند.
llvm-debuginfo-analyzer --attribute=level,format,producer
--print=symbols,types,lines
--output-sort=kind
pr-44884-codeview-clang.o
pr-44884-codeview-msvc.o
pr-44884-dwarf-clang.o
pr-44884-dwarf-gcc.o
Logical View:
[000] {File} 'pr-44884-codeview-clang.o' -> COFF-x86-64
[001] {CompileUnit} 'pr-44884.cpp'
[002] {Producer} 'clang version 14.0.0'
[002] {Function} extern not_inlined 'bar' -> 'int'
[003] {Parameter} 'Input' -> 'float'
[003] 1 {Line}
[002] {Function} extern not_inlined 'foo' -> 'unsigned'
[003] {Block}
[004] {Variable} 'Added' -> 'float'
[004] 9 {Line}
[004] 10 {Line}
[003] {Parameter} 'Param' -> 'char'
[003] {TypeAlias} 'FLOAT' -> 'float'
[003] {TypeAlias} 'INT' -> 'int'
[003] {Variable} 'Value' -> 'int'
[003] 3 {Line}
[003] 5 {Line}
[003] 13 {Line}
CodeView - MSVC (ویندوز)
Logical View:
[000] {File} 'pr-44884-codeview-msvc.o' -> COFF-i386
[001] {CompileUnit} 'pr-44884.cpp'
[002] {Producer} 'Microsoft (R) Optimizing Compiler'
[002] {Function} extern not_inlined 'bar' -> 'int'
[003] {Variable} 'Input' -> 'float'
[003] 1 {Line}
[002] {Function} extern not_inlined 'foo' -> 'unsigned'
[003] {Block}
[004] {Block}
[005] {Variable} 'Added' -> 'float'
[004] {TypeAlias} 'FLOAT' -> 'float'
[004] 9 {Line}
[004] 10 {Line}
[003] {TypeAlias} 'INT' -> 'int'
[003] {Variable} 'Param' -> 'char'
[003] {Variable} 'Value' -> 'int'
[003] 3 {Line}
[003] 5 {Line}
[003] 13 {Line}
[003] 14 {Line}
DWARF - Clang (لینوکس)
Logical View:
[000] {File} 'pr-44884-dwarf-clang.o' -> elf64-x86-64
[001] {CompileUnit} 'pr-44884.cpp'
[002] {Producer} 'clang version 14.0.0'
[002] 1 {Function} extern not_inlined 'bar' -> 'int'
[003] 1 {Parameter} 'Input' -> 'float'
[003] 1 {Line}
[003] 1 {Line}
[003] 1 {Line}
[002] 3 {Function} extern not_inlined 'foo' -> 'unsigned int'
[003] {Block}
[004] 9 {Variable} 'Added' -> 'FLOAT'
[004] 9 {Line}
[004] 9 {Line}
[004] 9 {Line}
[004] 9 {Line}
[004] 9 {Line}
[004] 10 {Line}
[004] 10 {Line}
[004] 10 {Line}
[004] 13 {Line}
[003] 3 {Parameter} 'Param' -> 'char'
[003] 7 {TypeAlias} 'FLOAT' -> 'float'
[003] 4 {TypeAlias} 'INT' -> 'int'
[003] 5 {Variable} 'Value' -> 'INT'
[003] 3 {Line}
[003] 5 {Line}
[003] 5 {Line}
[003] 13 {Line}
[003] 13 {Line}
[003] 13 {Line}
[003] 13 {Line}
Logical View:
[000] {File} 'pr-44884-dwarf-gcc.o' -> elf32-littlearm
[001] {CompileUnit} 'pr-44884.cpp'
[002] {Producer} 'GNU C++14 10.2.1 20201103'
[002] 1 {Function} extern not_inlined 'bar' -> 'int'
[003] 1 {Parameter} 'Input' -> 'float'
[003] 1 {Line}
[003] 1 {Line}
[003] 1 {Line}
[002] 3 {Function} extern not_inlined 'foo' -> 'unsigned int'
[003] {Block}
[004] {Block}
[005] 9 {Variable} 'Added' -> 'FLOAT'
[005] 9 {Line}
[005] 9 {Line}
[005] 9 {Line}
[005] 10 {Line}
[005] 13 {Line}
[004] 7 {TypeAlias} 'FLOAT' -> 'float'
[003] 3 {Parameter} 'Param' -> 'char'
[003] 4 {TypeAlias} 'INT' -> 'int'
[003] 5 {Variable} 'Value' -> 'INT'
[003] 3 {Line}
[003] 5 {Line}
[003] 13 {Line}
[003] 14 {Line}
[003] 14 {Line}
از نماهای منطقی پیشین، میتوان دریافت که کامپایلر Clang هر دو typedef را در یک حوزه لغوی یکسان (3) تولید میکند، که نادرست است. کامپایلرهای GCC و MSVC حوزه لغوی صحیحی را برای هر دو typedef صادر میکنند.
با استفاده از امکانات گزینش llvm-debuginfo-analyzer، میتوانیم یک خروجی جدولی ساده ایجاد کنیم که فقط انواع منطقی را که Typedef هستند نشان دهد.
llvm-debuginfo-analyzer --attribute=level,format
--output-sort=name
--select-types=Typedef
--report=list
--print=types
pr-44884-*.o
Logical View:
[000] {File} 'pr-44884-codeview-clang.o' -> COFF-x86-64
[001] {CompileUnit} 'pr_44884.cpp'
[003] {TypeAlias} 'FLOAT' -> 'float'
[003] {TypeAlias} 'INT' -> 'int'
Logical View:
[000] {File} 'pr-44884-codeview-msvc.o' -> COFF-i386
[001] {CompileUnit} 'pr_44884.cpp'
[004] {TypeAlias} 'FLOAT' -> 'float'
[003] {TypeAlias} 'INT' -> 'int'
Logical View:
[000] {File} 'pr-44884-dwarf-clang.o' -> elf64-x86-64
[001] {CompileUnit} 'pr_44884.cpp'
[003] 7 {TypeAlias} 'FLOAT' -> 'float'
[003] 4 {TypeAlias} 'INT' -> 'int'
Logical View:
[000] {File} 'pr-44884-dwarf-gcc.o' -> elf32-littlearm
[001] {CompileUnit} 'pr_44884.cpp'
[004] 7 {TypeAlias} 'FLOAT' -> 'float'
[003] 4 {TypeAlias} 'INT' -> 'int'
این امر همچنین نشان میدهد که اطلاعات اشکالزدایی CodeView شماره خطوط کد منبع را برای این انواع منطقی تولید نمیکند. نمای منطقی بر اساس نام انواع مرتب شده است..SS مورد آزمون ۴ - شمارشهای تودرتوی مفقود (TEST CASE 4 - MISSING NESTED ENUMERATIONS)
مثال زیر برای نشان دادن خروجیهای متفاوتی که توسط llvm-debuginfo-analyzer تولید میشود به کار رفته است. ما این مثال را برای مقصدهای X86 Codeview و ELF با نگارشهای اخیر Clang، GCC و MSVC کامپایل کردیم (-O0 -g).
1 struct Struct {
2 union Union {
3 enum NestedEnum { RED, BLUE };
4 };
5 Union U;
6 };
7
8 Struct S;
9 int test() {
10 return S.U.BLUE;
11 }
آزمون بالا برای نشان دادن یک مشکل حوزه (scope issue) یافتشده در کامپایلر Clang استفاده میشود: PR46466 (Bugs LLVM) https://bugs.llvm.org/show_bug.cgi?id=46466 / PR45811 (GitHub LLVM) https://github.com/llvm/llvm-project/issues/45811
اینها نماهای منطقی هستند که llvm-debuginfo-analyzer برای ۳ کامپایلر مختلف (MSVC، Clang و GCC) تولید میکند که قالبهای متفاوتی از اطلاعات اشکالزدایی (CodeView، DWARF) را روی بسترهای مختلف منتشر میسازند.
llvm-debuginfo-analyzer --attribute=level,format,producer
--output-sort=name
--print=symbols,types
pr-46466-codeview-clang.o
pr-46466-codeview-msvc.o
pr-46466-dwarf-clang.o
pr-46466-dwarf-gcc.o
CodeView - Clang (Windows)
Logical View:
[000] {File} 'pr-46466-codeview-clang.o' -> COFF-x86-64
[001] {CompileUnit} 'pr-46466.cpp'
[002] {Producer} 'clang version 14.0.0'
[002] {Variable} extern 'S' -> 'Struct'
[002] 1 {Struct} 'Struct'
[003] {Member} public 'U' -> 'Union'
[003] 2 {Union} 'Union'
[004] 3 {Enumeration} 'NestedEnum' -> 'int'
[005] {Enumerator} 'BLUE' = '0x1'
[005] {Enumerator} 'RED' = '0x0'
CodeView - MSVC (Windows)
Logical View:
[000] {File} 'pr-46466-codeview-msvc.o' -> COFF-i386
[001] {CompileUnit} 'pr-46466.cpp'
[002] {Producer} 'Microsoft (R) Optimizing Compiler'
[002] {Variable} extern 'S' -> 'Struct'
[002] 1 {Struct} 'Struct'
[003] {Member} public 'U' -> 'Union'
[003] 2 {Union} 'Union'
[004] 3 {Enumeration} 'NestedEnum' -> 'int'
[005] {Enumerator} 'BLUE' = '0x1'
[005] {Enumerator} 'RED' = '0x0'
Logical View:
[000] {File} 'pr-46466-dwarf-clang.o' -> elf64-x86-64
[001] {CompileUnit} 'pr-46466.cpp'
[002] {Producer} 'clang version 14.0.0'
[002] 8 {Variable} extern 'S' -> 'Struct'
[002] 1 {Struct} 'Struct'
[003] 5 {Member} public 'U' -> 'Union'
DWARF - GCC (Linux)
Logical View:
[000] {File} 'pr-46466-dwarf-gcc.o' -> elf64-x86-64
[001] {CompileUnit} 'pr-46466.cpp'
[002] {Producer} 'GNU C++14 9.3.0'
[002] 8 {Variable} extern 'S' -> 'Struct'
[002] 1 {Struct} 'Struct'
[003] 5 {Member} public 'U' -> 'Union'
[003] 2 {Union} 'Union'
[004] 3 {Enumeration} 'NestedEnum' -> 'unsigned int'
[005] {Enumerator} 'BLUE' = '0x1'
[005] {Enumerator} 'RED' = '0x0'
از نماهای منطقی پیشین، میتوان دریافت که اطلاعات اشکالزدایی DWARF تولیدشده توسط کامپایلر Clang شامل هیچ ارجاعی به شمارندههای RED و BLUE نیست. در حالی که DWARF تولیدشده توسط GCC، و CodeView تولیدشده توسط Clang و MSVC، حاوی چنین ارجاعاتی هستند.
با استفاده از امکانات گزینش llvm-debuginfo-analyzer، میتوانیم یک نمای منطقی تولید کنیم که تنها نوعهای منطقیِ Enumerator و والدین آنها را نشان دهد. این نمای منطقی بر اساس نام نوعها مرتب شده است.
llvm-debuginfo-analyzer --attribute=format,level
--output-sort=name
--select-types=Enumerator
--report=parents
--print=types
pr-46466-*.o
Logical View:
[000] {File} 'pr-46466-codeview-clang.o' -> COFF-x86-64
[001] {CompileUnit} 'pr-46466.cpp'
[002] 1 {Struct} 'Struct'
[003] 2 {Union} 'Union'
[004] 3 {Enumeration} 'NestedEnum' -> 'int'
[005] {Enumerator} 'BLUE' = '0x1'
[005] {Enumerator} 'RED' = '0x0'
Logical View:
[000] {File} 'pr-46466-codeview-msvc.o' -> COFF-i386
[001] {CompileUnit} 'pr-46466.cpp'
[002] 1 {Struct} 'Struct'
[003] 2 {Union} 'Union'
[004] 3 {Enumeration} 'NestedEnum' -> 'int'
[005] {Enumerator} 'BLUE' = '0x1'
[005] {Enumerator} 'RED' = '0x0'
Logical View:
[000] {File} 'pr-46466-dwarf-clang.o' -> elf64-x86-64
[001] {CompileUnit} 'pr-46466.cpp'
Logical View:
[000] {File} 'pr-46466-dwarf-gcc.o' -> elf64-x86-64
[001] {CompileUnit} 'pr-46466.cpp'
[002] 1 {Struct} 'Struct'
[003] 2 {Union} 'Union'
[004] 3 {Enumeration} 'NestedEnum' -> 'unsigned int'
[005] {Enumerator} 'BLUE' = '0x1'
[005] {Enumerator} 'RED' = '0x0'
با استفاده از امکانات گزینش llvm-debuginfo-analyzer، میتوانیم یک خروجی جدولی ساده شامل خلاصهای از نوعهای منطقی که Enumerator هستند تولید کنیم. این نمای منطقی بر اساس نام نوعها مرتب شده است.
llvm-debuginfo-analyzer --attribute=format,level
--output-sort=name
--select-types=Enumerator
--print=types,summary
pr-46466-*.o
Logical View:
[000] {File} 'pr-46466-codeview-clang.o' -> COFF-x86-64
[001] {CompileUnit} 'pr-46466.cpp'
[005] {Enumerator} 'BLUE' = '0x1'
[005] {Enumerator} 'RED' = '0x0'
-----------------------------
Element Total Found
-----------------------------
Scopes 5 0
Symbols 2 0
Types 6 2
Lines 0 0
-----------------------------
Total 13 2
Logical View:
[000] {File} 'pr-46466-codeview-msvc.o' -> COFF-i386
[001] {CompileUnit} 'pr-46466.cpp'
[005] {Enumerator} 'BLUE' = '0x1'
[005] {Enumerator} 'RED' = '0x0'
-----------------------------
Element Total Found
-----------------------------
Scopes 5 0
Symbols 2 0
Types 7 2
Lines 0 0
-----------------------------
Total 14 2
Logical View:
[000] {File} 'pr-46466-dwarf-clang.o' -> elf64-x86-64
[001] {CompileUnit} 'pr-46466.cpp'
-----------------------------
Element Total Found
-----------------------------
Scopes 4 0
Symbols 0 0
Types 0 0
Lines 0 0
-----------------------------
Total 4 0
Logical View:
[000] {File} 'pr-46466-dwarf-gcc.o' -> elf64-x86-64
[001] {CompileUnit} 'pr-46466.cpp'
[005] {Enumerator} 'BLUE' = '0x1'
[005] {Enumerator} 'RED' = '0x0'
-----------------------------
Element Total Found
-----------------------------
Scopes 5 0
Symbols 0 0
Types 2 2
Lines 0 0
-----------------------------
Total 7 2
مورد آزمون ۵ - حوزه لغوی نادرست برای متغیر (TEST CASE 5 - INCORRECT LEXICAL SCOPE FOR VARIABLE)
مثال زیر برای نشان دادن خروجیهای متفاوتی که توسط llvm-debuginfo-analyzer تولید میشود به کار میرود. ما مثال را برای هدفهای X86 Codeview و ELF با نسخههای اخیر Clang، GCC و MSVC کامپایل کردیم (-O0 -g).
// definitions.h
#ifdef _MSC_VER
#define forceinline __forceinline
#elif defined(__clang__)
#if __has_attribute(__always_inline__)
#define forceinline inline __attribute__((__always_inline__))
#else
#define forceinline inline
#endif
#elif defined(__GNUC__)
#define forceinline inline __attribute__((__always_inline__))
#else
#define forceinline inline
#error
#endif
از آنجا که آزمون به گزینههای inline کامپایلر وابسته است، فایل سربرگ فوق forceinline را تعریف میکند.
#include "definitions.h"
1 #include "definitions.h"
2 forceinline int InlineFunction(int Param) {
3 int Var_1 = Param;
4 {
5 int Var_2 = Param + Var_1;
6 Var_1 = Var_2;
7 }
8 return Var_1;
9 }
10
11 int test(int Param_1, int Param_2) {
12 int A = Param_1;
13 A += InlineFunction(Param_2);
14 return A;
15 }
آزمون بالا برای تشریح مشکل متغیری که در کامپایلر Clang یافت شده استفاده میشود: PR43860 (Bugs LLVM) https://bugs.llvm.org/show_bug.cgi?id=43860 / PR43205 (GitHub) https://github.com/llvm/llvm-project/issues/43205
اینها نماهای منطقی هستند که llvm-debuginfo-analyzer برای ۳ کامپایلر مختلف (MSVC، Clang و GCC) تولید میکند که قالبهای گوناگون اطلاعات اشکالزدایی (CodeView، DWARF) را در بسترهای مختلف منتشر میکنند.
llvm-debuginfo-analyzer --attribute=level,format,producer
--output-sort=name
--print=symbols
pr-43860-codeview-clang.o
pr-43860-codeview-msvc.o
pr-43860-dwarf-clang.o
pr-43860-dwarf-gcc.o
Logical View:
[000] {File} 'pr-43860-codeview-clang.o' -> COFF-x86-64
[001] {CompileUnit} 'pr-43860.cpp'
[002] {Producer} 'clang version 14.0.0'
[002] 2 {Function} inlined 'InlineFunction' -> 'int'
[003] {Parameter} '' -> 'int'
[002] {Function} extern not_inlined 'test' -> 'int'
[003] {Variable} 'A' -> 'int'
[003] {InlinedFunction} inlined 'InlineFunction' -> 'int'
[004] {Parameter} 'Param' -> 'int'
[004] {Variable} 'Var_1' -> 'int'
[004] {Variable} 'Var_2' -> 'int'
[003] {Parameter} 'Param_1' -> 'int'
[003] {Parameter} 'Param_2' -> 'int'
CODEVIEW - MSVC (ویندوز)
Logical View:
[000] {File} 'pr-43860-codeview-msvc.o' -> COFF-i386
[001] {CompileUnit} 'pr-43860.cpp'
[002] {Producer} 'Microsoft (R) Optimizing Compiler'
[002] {Function} extern not_inlined 'InlineFunction' -> 'int'
[003] {Block}
[004] {Variable} 'Var_2' -> 'int'
[003] {Variable} 'Param' -> 'int'
[003] {Variable} 'Var_1' -> 'int'
[002] {Function} extern not_inlined 'test' -> 'int'
[003] {Variable} 'A' -> 'int'
[003] {Variable} 'Param_1' -> 'int'
[003] {Variable} 'Param_2' -> 'int'
DWARF - Clang (لینوکس)
Logical View:
[000] {File} 'pr-43860-dwarf-clang.o' -> elf64-x86-64
[001] {CompileUnit} 'pr-43860.cpp'
[002] {Producer} 'clang version 14.0.0'
[002] 2 {Function} extern inlined 'InlineFunction' -> 'int'
[003] {Block}
[004] 5 {Variable} 'Var_2' -> 'int'
[003] 2 {Parameter} 'Param' -> 'int'
[003] 3 {Variable} 'Var_1' -> 'int'
[002] 11 {Function} extern not_inlined 'test' -> 'int'
[003] 12 {Variable} 'A' -> 'int'
[003] 13 {InlinedFunction} inlined 'InlineFunction' -> 'int'
[004] {Block}
[005] {Variable} 'Var_2' -> 'int'
[004] {Parameter} 'Param' -> 'int'
[004] {Variable} 'Var_1' -> 'int'
[003] 11 {Parameter} 'Param_1' -> 'int'
[003] 11 {Parameter} 'Param_2' -> 'int'
DWARF - GCC (لینوکس)
Logical View:
[000] {File} 'pr-43860-dwarf-gcc.o' -> elf64-x86-64
[001] {CompileUnit} 'pr-43860.cpp'
[002] {Producer} 'GNU C++14 9.3.0'
[002] 2 {Function} extern declared_inlined 'InlineFunction' -> 'int'
[003] {Block}
[004] 5 {Variable} 'Var_2' -> 'int'
[003] 2 {Parameter} 'Param' -> 'int'
[003] 3 {Variable} 'Var_1' -> 'int'
[002] 11 {Function} extern not_inlined 'test' -> 'int'
[003] 12 {Variable} 'A' -> 'int'
[003] 13 {InlinedFunction} declared_inlined 'InlineFunction' -> 'int'
[004] {Block}
[005] {Variable} 'Var_2' -> 'int'
[004] {Parameter} 'Param' -> 'int'
[004] {Variable} 'Var_1' -> 'int'
[003] 11 {Parameter} 'Param_1' -> 'int'
[003] 11 {Parameter} 'Param_2' -> 'int'
از نماهای منطقی پیشین، میتوان مشاهده کرد که اطلاعات اشکالزدایی CodeView تولیدشده توسط کامپایلر Clang نشان میدهد متغیرهای Var_1 و Var_2 در تابع InlineFuction در یک حوزهٔ واژگانی یکسان (4) قرار دارند. DWARF تولیدشده توسط GCC/Clang و CodeView تولیدشده توسط MSVC، این متغیرها را در حوزهٔ واژگانی درست نشان میدهند: بهترتیب 3 و 4.
با استفاده از امکانات گزینش llvm-debuginfo-analyzer، میتوانیم یک خروجی جدولی ساده تولید کنیم که تنها عناصر منطقی دارای الگوی var در نامشان را نشان میدهد. نمای منطقی بر اساس نام متغیرها مرتب شده است.
llvm-debuginfo-analyzer --attribute=level,format
--output-sort=name
--select-regex --select-nocase --select=Var
--report=list
--print=symbols
pr-43860-*.o
Logical View:
[000] {File} 'pr-43860-codeview-clang.o' -> COFF-x86-64
[001] {CompileUnit} 'pr-43860.cpp'
[004] {Variable} 'Var_1' -> 'int'
[004] {Variable} 'Var_2' -> 'int'
Logical View:
[000] {File} 'pr-43860-codeview-msvc.o' -> COFF-i386
[001] {CompileUnit} 'pr-43860.cpp'
[003] {Variable} 'Var_1' -> 'int'
[004] {Variable} 'Var_2' -> 'int'
Logical View:
[000] {File} 'pr-43860-dwarf-clang.o' -> elf64-x86-64
[001] {CompileUnit} 'pr-43860.cpp'
[004] {Variable} 'Var_1' -> 'int'
[003] 3 {Variable} 'Var_1' -> 'int'
[005] {Variable} 'Var_2' -> 'int'
[004] 5 {Variable} 'Var_2' -> 'int'
Logical View:
[000] {File} 'pr-43860-dwarf-gcc.o' -> elf64-x86-64
[001] {CompileUnit} 'pr-43860.cpp'
[004] {Variable} 'Var_1' -> 'int'
[003] 3 {Variable} 'Var_1' -> 'int'
[005] {Variable} 'Var_2' -> 'int'
[004] 5 {Variable} 'Var_2' -> 'int'
همچنین نشان میدهد که اطلاعات اشکالزدایی CodeView شماره خطوط کد منبع را برای آن نمادهای منطقی تولید نمیکند. نمای منطقی بر اساس نام نوعها مرتب شده است..SS "مورد آزمایشی ۶ - نمای منطقی کامل (TEST CASE 6 - FULL LOGICAL VIEW)"
برای کاربران پیشرفته، llvm-debuginfo-analyzer میتواند اطلاعات سطح پایینی را نمایش دهد که شامل آفستها درون بخش اطلاعات اشکالزدایی، عملوندهای مکان اشکالزدایی، نامهای پیوند و غیره است.
llvm-debuginfo-analyzer --attribute=all
--print=all
test-dwarf-clang.o
Logical View:
[0x0000000000][000] {File} 'test-dwarf-clang.o' -> elf64-x86-64
[0x000000000b][001] {CompileUnit} 'test.cpp'
[0x000000000b][002] {Producer} 'clang version 12.0.0'
{Directory} ''
{File} 'test.cpp'
{Public} 'foo' [0x0000000000:0x000000003a]
[0x000000000b][002] {Range} Lines 2:9 [0x0000000000:0x000000003a]
[0x00000000bc][002] {BaseType} 'bool'
[0x0000000099][002] {BaseType} 'int'
[0x00000000b5][002] {BaseType} 'unsigned int'
[0x00000000a0][002] {Source} '/test.cpp'
[0x00000000a0][002] 1 {TypeAlias} 'INTPTR' -> [0x00000000ab]'* const int'
[0x000000002a][002] 2 {Function} extern not_inlined 'foo' -> [0x0000000099]'int'
[0x000000002a][003] {Range} Lines 2:9 [0x0000000000:0x000000003a]
[0x000000002a][003] {Linkage} 0x2 '_Z3fooPKijb'
[0x0000000071][003] {Block}
[0x0000000071][004] {Range} Lines 5:8 [0x000000001c:0x000000002f]
[0x000000007e][004] 5 {Variable} 'CONSTANT' -> [0x00000000c3]'const INTEGER'
[0x000000007e][005] {Coverage} 100.00%
[0x000000007f][005] {Location}
[0x000000007f][006] {Entry} Stack Offset: -28 (0xffffffffffffffe4) [DW_OP_fbreg]
[0x000000001c][004] 5 {Line} {NewStatement} '/test.cpp'
[0x000000001c][004] {Code} 'movl $0x7, -0x1c(%rbp)'
[0x0000000023][004] 6 {Line} {NewStatement} '/test.cpp'
[0x0000000023][004] {Code} 'movl $0x7, -0x4(%rbp)'
[0x000000002a][004] {Code} 'jmp 0x6'
[0x000000002f][004] 8 {Line} {NewStatement} '/test.cpp'
[0x000000002f][004] {Code} 'movl -0x14(%rbp), %eax'
[0x0000000063][003] 2 {Parameter} 'ParamBool' -> [0x00000000bc]'bool'
[0x0000000063][004] {Coverage} 100.00%
[0x0000000064][004] {Location}
[0x0000000064][005] {Entry} Stack Offset: -21 (0xffffffffffffffeb) [DW_OP_fbreg]
[0x0000000047][003] 2 {Parameter} 'ParamPtr' -> [0x00000000a0]'INTPTR'
[0x0000000047][004] {Coverage} 100.00%
[0x0000000048][004] {Location}
[0x0000000048][005] {Entry} Stack Offset: -16 (0xfffffffffffffff0) [DW_OP_fbreg]
[0x0000000055][003] 2 {Parameter} 'ParamUnsigned' -> [0x00000000b5]'unsigned int'
[0x0000000055][004] {Coverage} 100.00%
[0x0000000056][004] {Location}
[0x0000000056][005] {Entry} Stack Offset: -20 (0xffffffffffffffec) [DW_OP_fbreg]
[0x000000008d][003] 4 {TypeAlias} 'INTEGER' -> [0x0000000099]'int'
[0x0000000000][003] 2 {Line} {NewStatement} '/test.cpp'
[0x0000000000][003] {Code} 'pushq %rbp'
[0x0000000001][003] {Code} 'movq %rsp, %rbp'
[0x0000000004][003] {Code} 'movb %dl, %al'
[0x0000000006][003] {Code} 'movq %rdi, -0x10(%rbp)'
[0x000000000a][003] {Code} 'movl %esi, -0x14(%rbp)'
[0x000000000d][003] {Code} 'andb $0x1, %al'
[0x000000000f][003] {Code} 'movb %al, -0x15(%rbp)'
[0x0000000012][003] 3 {Line} {NewStatement} {PrologueEnd} '/test.cpp'
[0x0000000012][003] {Code} 'testb $0x1, -0x15(%rbp)'
[0x0000000016][003] {Code} 'je 0x13'
[0x0000000032][003] 8 {Line} '/test.cpp'
[0x0000000032][003] {Code} 'movl %eax, -0x4(%rbp)'
[0x0000000035][003] 9 {Line} {NewStatement} '/test.cpp'
[0x0000000035][003] {Code} 'movl -0x4(%rbp), %eax'
[0x0000000038][003] {Code} 'popq %rbp'
[0x0000000039][003] {Code} 'retq'
[0x000000003a][003] 9 {Line} {NewStatement} {EndSequence} '/test.cpp'
-----------------------------
Element Total Printed
-----------------------------
Scopes 3 3
Symbols 4 4
Types 5 5
Lines 25 25
-----------------------------
Total 37 37
Scope Sizes:
189 (100.00%) : [0x000000000b][001] {CompileUnit} 'test.cpp'
110 ( 58.20%) : [0x000000002a][002] 2 {Function} extern not_inlined 'foo' -> [0x0000000099]'int'
27 ( 14.29%) : [0x0000000071][003] {Block}
Totals by lexical level:
[001]: 189 (100.00%)
[002]: 110 ( 58.20%)
[003]: 27 ( 14.29%)
جدول Scope Sizes سهم هر حوزه را بر حسب بایت در اطلاعات اشکالزدایی نشان میدهد، که میتوان از آن برای تشخیص تغییرات اندازهٔ غیرمنتظره در بخشهای DWARF بین نسخههای مختلف یک زنجیره ابزار استفاده کرد.
[0x000000002a][002] 2 {Function} extern not_inlined 'foo' -> [0x0000000099]'int'
[0x000000002a][003] {Range} Lines 2:9 [0x0000000000:0x000000003a]
[0x000000002a][003] {Linkage} 0x2 '_Z3fooPKijb'
[0x0000000071][003] {Block}
[0x0000000071][004] {Range} Lines 5:8 [0x000000001c:0x000000002f]
[0x000000007e][004] 5 {Variable} 'CONSTANT' -> [0x00000000c3]'const INTEGER'
[0x000000007e][005] {Coverage} 100.00%
[0x000000007f][005] {Location}
[0x000000007f][006] {Entry} Stack Offset: -28 (0xffffffffffffffe4) [DW_OP_fbreg]
صفت {Range} محدودههای خط را برای یک حوزهٔ منطقی توصیف میکند. در این مورد، تابع foo بین خطوط 2 و 9 قرار دارد.
صفتهای {Coverage} و {Location} مکان و پوشش اشکالزدایی را برای نمادهای منطقی توصیف میکنند. برای کدهای بهینهسازیشده، مقدار پوشش کاهش مییابد و این امر بر قابلیت اشکالزدایی برنامه اثر میگذارد..SS "پشتیبانی از وباسمبلی (WEBASSEMBLY SUPPORT)"
مثال زیر برای نشان دادن خروجی WebAssembly تولیدشده توسط llvm-debuginfo-analyzer به کار میرود. ما این مثال را برای یک مقصد ۳۲-بیتی WebAssembly با Clang (-O0 -g --target=wasm32) کامپایل کردیم:
1 using INTPTR = const int *;
2 int foo(INTPTR ParamPtr, unsigned ParamUnsigned, bool ParamBool) {
3 if (ParamBool) {
4 typedef int INTEGER;
5 const INTEGER CONSTANT = 7;
6 return CONSTANT;
7 }
8 return ParamUnsigned;
9 }
چاپ جزئیات پایه (PRINT BASIC DETAILS)
دستور زیر جزئیات پایه را برای تمام عنصرهای منطقی مرتبشده بر اساس آفست درونی اطلاعات اشکالزدایی چاپ میکند؛ این شامل سطح لغوی و قالب اطلاعات اشکالزدایی آن است.
llvm-debuginfo-analyzer --attribute=level,format
--output-sort=offset
--print=scopes,symbols,types,lines,instructions
test-clang.o
یا
llvm-debuginfo-analyzer --attribute=level,format
--output-sort=offset
--print=elements
test-clang.o
هر سطر نشاندهنده عنصری است که درون اطلاعات اشکالزدایی وجود دارد. ستون نخست بیانگر سطح حوزه، سپس شماره خط مربوطه (در صورت وجود) و در نهایت شرح آن عنصر است.
Logical View:
[000] {File} 'test-clang.o' -> WASM
[001] {CompileUnit} 'test.cpp'
[002] 2 {Function} extern not_inlined 'foo' -> 'int'
[003] 2 {Parameter} 'ParamPtr' -> 'INTPTR'
[003] 2 {Parameter} 'ParamUnsigned' -> 'unsigned int'
[003] 2 {Parameter} 'ParamBool' -> 'bool'
[003] {Block}
[004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
[004] 5 {Line}
[004] {Code} 'i32.const 7'
[004] {Code} 'local.set 10'
[004] {Code} 'local.get 5'
[004] {Code} 'local.get 10'
[004] {Code} 'i32.store 12'
[004] 6 {Line}
[004] {Code} 'i32.const 7'
[004] {Code} 'local.set 11'
[004] {Code} 'local.get 5'
[004] {Code} 'local.get 11'
[004] {Code} 'i32.store 28'
[004] {Code} 'br 1'
[004] - {Line}
[004] {Code} 'end'
[003] 4 {TypeAlias} 'INTEGER' -> 'int'
[003] 2 {Line}
[003] {Code} 'nop'
[003] {Code} 'end'
[003] {Code} 'i64.div_s'
[003] {Code} 'global.get 0'
[003] {Code} 'local.set 3'
[003] {Code} 'i32.const 32'
[003] {Code} 'local.set 4'
[003] {Code} 'local.get 3'
[003] {Code} 'local.get 4'
[003] {Code} 'i32.sub'
[003] {Code} 'local.set 5'
[003] {Code} 'local.get 5'
[003] {Code} 'local.get 0'
[003] {Code} 'i32.store 24'
[003] {Code} 'local.get 5'
[003] {Code} 'local.get 1'
[003] {Code} 'i32.store 20'
[003] {Code} 'local.get 2'
[003] {Code} 'local.set 6'
[003] {Code} 'local.get 5'
[003] {Code} 'local.get 6'
[003] {Code} 'i32.store8 19'
[003] 3 {Line}
[003] {Code} 'local.get 5'
[003] {Code} 'i32.load8_u 19'
[003] {Code} 'local.set 7'
[003] 3 {Line}
[003] {Code} 'i32.const 1'
[003] {Code} 'local.set 8'
[003] {Code} 'local.get 7'
[003] {Code} 'local.get 8'
[003] {Code} 'i32.and'
[003] {Code} 'local.set 9'
[003] {Code} 'block'
[003] {Code} 'block'
[003] {Code} 'local.get 9'
[003] {Code} 'i32.eqz'
[003] {Code} 'br_if 0'
[003] 8 {Line}
[003] {Code} 'local.get 5'
[003] {Code} 'i32.load 20'
[003] {Code} 'local.set 12'
[003] 8 {Line}
[003] {Code} 'local.get 5'
[003] {Code} 'local.get 12'
[003] {Code} 'i32.store 28'
[003] - {Line}
[003] {Code} 'end'
[003] 9 {Line}
[003] {Code} 'local.get 5'
[003] {Code} 'i32.load 28'
[003] {Code} 'local.set 13'
[003] {Code} 'local.get 13'
[003] {Code} 'return'
[003] {Code} 'end'
[003] 9 {Line}
[003] {Code} 'unreachable'
[002] 1 {TypeAlias} 'INTPTR' -> '* const int'
دستور زیر تمام instructions، symbols و types را که در نام یا نوع خود حاوی 'block' یا '.store' هستند، با استفاده از یک چیدمان تببندیشده و با ارائه تعداد موارد منطبق چاپ میکند.
llvm-debuginfo-analyzer --attribute=level
--select-nocase --select-regex
--select=BLOCK --select=.store
--report=list
--print=symbols,types,instructions,summary
test-clang.o
Logical View:
[000] {File} 'test-clang.o'
[001] {CompileUnit} 'test.cpp'
[003] {Code} 'block'
[003] {Code} 'block'
[004] {Code} 'i32.store 12'
[003] {Code} 'i32.store 20'
[003] {Code} 'i32.store 24'
[004] {Code} 'i32.store 28'
[003] {Code} 'i32.store 28'
[003] {Code} 'i32.store8 19'
-----------------------------
Element Total Printed
-----------------------------
Scopes 3 0
Symbols 4 0
Types 2 0
Lines 62 8
-----------------------------
Total 71 8
حالت مقایسه (COMPARISON MODE)
با توجه به مثال قبلی، با مقایسه در برابر یک کامپایلر دیگر، اشکال فوق در اطلاعات اشکالزدایی (مربوط به مکان نامعتبر پیشین حوزه برای 'typedef int INTEGER') را پیدا کردیم.
با استفاده از GCC برای تولید test-dwarf-gcc.o، میتوانیم یک الگوی انتخاب را به همراه حالت چاپ اعمال کنیم تا خروجی نمای منطقی زیر به دست آید.
llvm-debuginfo-analyzer --attribute=level
--select-regex --select-nocase --select=INTe
--report=list
--print=symbols,types
test-clang.o test-dwarf-gcc.o
Logical View:
[000] {File} 'test-clang.o'
[001] {CompileUnit} 'test.cpp'
[003] 4 {TypeAlias} 'INTEGER' -> 'int'
[004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
Logical View:
[000] {File} 'test-dwarf-gcc.o'
[001] {CompileUnit} 'test.cpp'
[004] 4 {TypeAlias} 'INTEGER' -> 'int'
[004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
خروجی نشان میدهد که هر دو شیء حاوی عناصر یکسانی هستند؛ اما 'typedef INTEGER' در سطح حوزه (scope level) متفاوتی قرار گرفته است. شیء تولیدشده توسط GCC مقدار '4' را نشان میدهد که مقدار صحیح است.
دو روش مقایسه وجود دارد: نمای منطقی و عناصر منطقی..SS "نمای منطقی (LOGICAL VIEW)"
این بخش، نمای منطقی را بهعنوان یک واحد کامل مقایسه میکند؛ برای برقراری تطابق، هر عنصر منطقی مقایسهشده باید والدین و فرزندان یکسانی داشته باشد.
خروجی، عناصر ازدسترفته (-) و اضافهشده (+) را در قالب نما نشان میدهد و با جابهجا کردن فایلهای شیء مرجع و هدف، زمینه و اطلاعات بیشتری ارائه میدهد.
llvm-debuginfo-analyzer --attribute=level
--compare=types
--report=view
--print=symbols,types
test-clang.o test-dwarf-gcc.o
Reference: 'test-clang.o'
Target: 'test-dwarf-gcc.o'
Logical View:
[000] {File} 'test-clang.o'
[001] {CompileUnit} 'test.cpp'
[002] 1 {TypeAlias} 'INTPTR' -> '* const int'
[002] 2 {Function} extern not_inlined 'foo' -> 'int'
[003] {Block}
[004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
+[004] 4 {TypeAlias} 'INTEGER' -> 'int'
[003] 2 {Parameter} 'ParamBool' -> 'bool'
[003] 2 {Parameter} 'ParamPtr' -> 'INTPTR'
[003] 2 {Parameter} 'ParamUnsigned' -> 'unsigned int'
-[003] 4 {TypeAlias} 'INTEGER' -> 'int'
خروجی، مسیر ادغام نما (مرجع و هدف) را همراه با عناصر ازدسترفته و اضافهشده نشان میدهد.
عناصر منطقی (LOGICAL ELEMENTS)
این حالت، عناصر منطقی منفرد را بدون در نظر گرفتن یکسان بودن والدین آنها مقایسه میکند. در هر دو روش مقایسه، معیارهای برابری شامل نام، مکان در کد منبع، نوع و سطح حوزهٔ لغوی (lexical scope level) است.
llvm-debuginfo-analyzer --attribute=level
--compare=types
--report=list
--print=symbols,types,summary
test-clang.o test-dwarf-gcc.o
Reference: 'test-clang.o'
Target: 'test-dwarf-gcc.o'
(1) Missing Types:
-[003] 4 {TypeAlias} 'INTEGER' -> 'int'
(1) Added Types:
+[004] 4 {TypeAlias} 'INTEGER' -> 'int'
----------------------------------------
Element Expected Missing Added
----------------------------------------
Scopes 4 0 0
Symbols 0 0 0
Types 2 1 1
Lines 0 0 0
----------------------------------------
Total 6 1 1
تغییر ترتیب Reference و Target:
llvm-debuginfo-analyzer --attribute=level
--compare=types
--report=list
--print=symbols,types,summary
test-dwarf-gcc.o test-clang.o
Reference: 'test-dwarf-gcc.o'
Target: 'test-clang.o'
(1) Missing Types:
-[004] 4 {TypeAlias} 'INTEGER' -> 'int'
(1) Added Types:
+[003] 4 {TypeAlias} 'INTEGER' -> 'int'
----------------------------------------
Element Expected Missing Added
----------------------------------------
Scopes 4 0 0
Symbols 0 0 0
Types 2 1 1
Lines 0 0 0
----------------------------------------
Total 6 1 1
با توجه به جابهجا شدن Reference و Target، موارد Added Types در حالت اول، اکنون بهعنوان Missing Types فهرست میشوند..SH "وضعیت خروج (EXIT STATUS)"
در صورتی که فایلهای ورودی با موفقیت تجزیه و چاپ شوند، llvm-debuginfo-analyzer مقدار 0 را برمیگرداند. در غیر این صورت، مقدار 1 را بازمیگرداند.
محدودیتها و مشکلات شناختهشده (LIMITATIONS AND KNOWN ISSUES)
به Limitations مراجعه کنید.
همچنین ببینید (SEE ALSO)
llvm-dwarfdump <llvm-dwarfdump.html>
نویسندگان (AUTHORS)
توسط تیم LLVM نگهداری میشود (https://llvm.org).
کپیرایت و تکثیر (COPYRIGHT)
2003-2026, LLVM Project
| 2026-07-15 | 22 |