Определение компилятора и версии, используемых для сборки общего объекта в операционной системе *ix

Я работаю над некоторым программным обеспечением, которое загружает набор указанных пользователем общих объектов. Я хотел бы добавить некоторый код в наш компонент «загрузчик», который может запрашивать каждый указанный общий объект и выяснять, какой компилятор и какая версия компилятора использовалась для создания/связывания этого общего объекта.

В прошлом я мог использовать подход «strings -a | grep», как показано ниже. Однако этот подход не работает для кода, скомпилированного с помощью g++ 4.8 в мощной AIX, и он не очень хорошо работает для кода, скомпилированного с помощью g++ 4.8 в x86 linux.

Я также хотел бы найти более чистый способ получения этой информации, чем поиск строк, если это возможно.

Кто-нибудь может дать совет, как запросить у общего объекта имя компилятора, который его создал, а также версию этого компилятора?


Вот пример команды и результат моей текущей техники:

на скомпилированном общем объекте x86 linux g++ 4.1:

$ strings -a libshareme.so | grep GNU
GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-50)
<etc>

(здесь много повторяющихся выводов, но ясно, что версия GCC 4.1.2)

на скомпилированном объекте Power AIX xlC v11

$ strings -a libshareme.so | grep XL
XL  
IBM XL C/C++ for AIX, Version 11.1.0.6
IBM XL C/C++ for AIX, Version 10.1.0.6

(сбивает с толку то, что он показывает v11 и v10, но XL C понятен)

на скомпилированном общем объекте x86 linux g++ 4.8:

$ strings -a libshareme.so | grep GNU
GCC: (GNU) 4.4.6 20120305 (Red Hat 4.4.6-4)
GCC: (GNU) 4.8.2 20131111 (Red Hat 4.8.2-4)
GNU C++ 4.8.2 20131111 (Red Hat 4.8.2-4) -m32 -mtune=generic -march=i686 -g -fmessage-length=0 -fPIC

(здесь также сбивает с толку то, что он показывает несколько версий)

на мощном скомпилированном объекте AIX g++ 4.8

$ strings -a libshareme.so | grep GNU
<no output>

На x86/linux я обычно вижу строку типа «GNU» в выводе «strings -a», который я могу сопоставить. Однако использование строк -a в этом libshareme.so, скомпилированном на power/aix с g++ 4.8, не показывает мне ничего очевидного в отношении версии компилятора.


person fahrradler    schedule 14.10.2014    source источник
comment
Совместно используемые библиотеки — это не объекты, это библиотеки объектов, и каждый объект в одной библиотеке мог быть скомпилирован с помощью другого компилятора. Что касается последнего, почему вы ожидаете GNU на мощном AIX g++ 4.8?   -  person mmmmmm    schedule 15.10.2014
comment
Какой смысл это делать? Если вы не являетесь экспертом в ABI конкретной платформы и компиляторах на этой платформе, вам, как правило, следует избегать загрузки общих библиотек, скомпилированных случайным образом разными компиляторами со случайными разными параметрами компилятора. И вы не сможете прочитать точный компилятор, версию и используемые параметры из двоичных объектных файлов, потому что они там не хранятся.   -  person Laszlo Valko    schedule 15.10.2014
comment
@Laszlo Valko: обычно вам следует избегать загрузки общих библиотек, скомпилированных случайным образом разными компиляторами. Это именно то, чего я хочу избежать. В этом программном обеспечении (которое принадлежит мне) пользователи указывают, какие совместно используемые объекты они хотят загрузить, и программное обеспечение загружает их. Я хочу, чтобы программное обеспечение могло определить, какой компилятор использовался (здесь, g++ или xlC) для создания этих общих объектов, и выдавать четкую ошибку, если есть смесь. Да, вы получаете загрузку и другие ошибки в ситуации «микширования», но это не слишком удобно для пользователя.   -  person fahrradler    schedule 16.10.2014


Ответы (2)


Я нашел этот способ благодаря коллеге, чтобы определить, скомпилирована ли библиотека с помощью g++ в AIX:

dump -X32_64 -Tv libshareme.so  | grep libgcc 

[1]     0x00000000    undef      IMP     DS EXTref libgcc_s.a(shr.o) __cxa_finalize
[2]     0x00000000    undef      IMP     DS EXTref libgcc_s.a(shr.o) __register_frame_info_table
[3]     0x00000000    undef      IMP     DS EXTref libgcc_s.a(shr.o) __deregister_frame_info
[4]     0x00000000    undef      IMP     DS EXTref libgcc_s.a(shr.o) __cmpdi2
[5]     0x00000000    undef      IMP     DS EXTref libgcc_s.a(shr.o) __gcc_qdiv
[6]     0x00000000    undef      IMP     DS EXTref libgcc_s.a(shr.o) __udivdi3
[7]     0x00000000    undef      IMP     DS EXTref libgcc_s.a(shr.o) _Unwind_Resume
[635]   0x20118d70    .data      EXP     DS   Ldef        [noIMid] __init_aix_libgcc_cxa_atex

it

Этот подход плюс подходы в исходном вопросе, по сути, позволяют мне писать код, который обнаруживает компиляторы (по крайней мере, те, с которыми я работаю) и любое потенциальное несоответствие компиляторов во время сбоя загрузки.

person fahrradler    schedule 31.10.2014

Невозможно безошибочно делать то, чего вы хотите достичь. Иногда вы можете найти случайные признаки компилятора или некоторые флаги компилятора, но, конечно же, нет общего способа получить эту информацию. И большая часть этой информации просто отсутствует в объектных файлах (например, ни один известный мне компилятор не хранит точные флаги компилятора, используемые в объектных файлах).

Вы можете посмотреть, что сделали авторы других пакетов, я бы сначала проверил Perl. Perl использует свой собственный сценарий "./configure", который собирает пути различных инструментов и флаги, которые будут использоваться с ними, а затем эта информация используется при компиляции двоичного файла Perl и поставляемых там стандартных модулей. Эта информация также компилируется в двоичный файл perl и может быть позже распечатана для удобства (perl -V) или использована для компиляции «соответствующих» дополнительных модулей perl с помощью собственной вспомогательной библиотеки perl make (см. perl Makefile.PL). Даже средства Perl не являются надежными, так как вы можете попытаться загрузить несовместимо скомпилированные/связанные общие библиотеки.

person Laszlo Valko    schedule 16.10.2014