Я хотів би отримати версію GCC, яка використовується для компіляції даного виконуваного файлу. Я спробував, readelf
але інформації не отримав. Будь-які думки?
Я хотів би отримати версію GCC, яка використовується для компіляції даного виконуваного файлу. Я спробував, readelf
але інформації не отримав. Будь-які думки?
Відповіді:
Зазвичай він зберігається в розділі коментарів
strings -a <binary/library> |grep "GCC: ("
повертає GCC: (GNU) XXX
strip -R .comment <binary>
strings -a <binary/library> |grep "GCC: ("
не повертає вихідних даних
Не рідко видаляють розділ .comment (а також .note), щоб зменшити розмір через
strip --strip-all -R .note -R .comment <binary>
strip --strip-unneeded -R .note -R .comment <library>
Примітка: рядки busybox за замовчуванням визначають параметр -a, який необхідний для розділу .comment
Змінити: На відміну від відповіді Берендри Тусла, для роботи цього методу його не потрібно компілювати з будь-якими прапорцями налагодження.
Двійковий приклад:
# echo "int main(void){}">a.c
# gcc -o a a.c -s
# strings -a a |grep GCC
GCC: (GNU) 4.3.4
# strip -R .comment a
# strings -a a |grep GCC
#
Приклад об'єкта:
# gcc -c a.c -s
# strings -a a.o |grep GCC
GCC: (GNU) 4.3.4
# strip -R .comment a.o
# strings -a a |grep GCC
#
Зверніть увагу на відсутність прапорців -g (налагодження) та наявність прапора -s, який позбавляє непотрібних символів. Інформація про GCC все ще доступна, якщо розділ .comment не буде видалено. Якщо вам потрібно зберегти цю інформацію в цілості, можливо, вам доведеться перевірити ваш файл make (або відповідний сценарій збірки), щоб переконатися, що -fno-ident відсутній у ваших $ CFLAGS, а в команді $ STRIP відсутній -R .comment. -fno-ident заважає gcc генерувати ці символи в розділі коментарів.
strings
.
-a
параметр strings
, оскільки утиліта .comment
за замовчуванням не буде заглядати всередину розділу.
На завершення сказаного іншими: він не зберігається у файлі об’єкта (або exe), якщо ви не скомпілюєте інформацію про налагодження ! (варіант -g
). Якщо ви компілюєте інформацію про налагодження, ви можете повернути її за допомогою readelf
:
$ cat a.c
int main(void){ return 0; }
$ gcc a.c
$ readelf -wi a.out
$ gcc a.c -g
$ readelf -wi a.out
Contents of the .debug_info section:
Compilation Unit @ offset 0x0:
Length: 0x42 (32-bit)
Version: 2
Abbrev Offset: 0
Pointer Size: 4
<0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)
< c> DW_AT_producer : (indirect string, offset: 0x0): GNU C 4.4.3 20100108 (prerelease)
<10> DW_AT_language : 1 (ANSI C)
<11> DW_AT_name : a.c
<15> DW_AT_comp_dir : (indirect string, offset: 0x22): /tmp
<19> DW_AT_low_pc : 0x8048394
<1d> DW_AT_high_pc : 0x804839e
<21> DW_AT_stmt_list : 0x0
<1><25>: Abbrev Number: 2 (DW_TAG_subprogram)
<26> DW_AT_external : 1
<27> DW_AT_name : (indirect string, offset: 0x27): main
<2b> DW_AT_decl_file : 1
<2c> DW_AT_decl_line : 1
<2d> DW_AT_prototyped : 1
<2e> DW_AT_type : <0x3e>
<32> DW_AT_low_pc : 0x8048394
<36> DW_AT_high_pc : 0x804839e
<3a> DW_AT_frame_base : 0x0 (location list)
<1><3e>: Abbrev Number: 3 (DW_TAG_base_type)
<3f> DW_AT_byte_size : 4
<40> DW_AT_encoding : 5 (signed)
<41> DW_AT_name : int
Подивіться, як там написано GNU C 4.4.3 20100108 (prerelease)
.
Ще два способи (можливо, трохи простіші), про які я щойно читав тут: /unix/719/can-we-get-compiler-information-from-an-elf-binary
$ readelf -p .comment /usr/lib64/flash-plugin/libflashplayer.so
String dump of section '.comment':
[ 1] GCC: (GNU) 4.3.2 20081105 (Red Hat 4.3.2-7)
[ 2e] GCC: (GNU) 4.3.2
...
і
$ objdump -s --section .comment /usr/lib64/flash-plugin/libflashplayer.so
/usr/lib64/flash-plugin/libflashplayer.so: file format elf64-x86-64
Contents of section .comment:
0000 00474343 3a202847 4e552920 342e332e .GCC: (GNU) 4.3.
0010 32203230 30383131 30352028 52656420 2 20081105 (Red
0020 48617420 342e332e 322d3729 00004743 Hat 4.3.2-7)..GC
0030 433a2028 474e5529 20342e33 2e320000 C: (GNU) 4.3.2..
...
-p
опція не існує в моїй давній копії readelf
(from binutils 2.14
), тому мені довелося знайти індекс розділу .comment, а потім шістнадцятковим readelf --hex-dump=$(readelf -S <so_file> | grep .comment | awk '{ print $1 }' | tr -d '[]') <so_file>
Ця інформація не зберігається у складеному об'єкті (c).
Насправді для коду С вам зовсім не пощастило. Однак для коду С ++ ви можете знайти деяку інформацію з версій символів. Деякі функції з бібліотек середовища виконання C ++ є специфічними для версії та позначені як такі в об'єктних файлах. Спробуйте це:
readelf -Wa file.exe | grep 'GCC[[:alnum:]_.]*' --only-match | sort | uniq | tail -n 1
Однак він не покаже вам використовувану версію GCC. Відображається версія символів під час виконання, що надається компілятору. Зазвичай час виконання - це відправлення компілятора, і його версія не менше, ніж показана з наведеною вище командою.