На этот ответ нельзя ответить вообще. Технически, если вы скомпилировали свой исполняемый файл с исчерпывающей отладочной информацией (код все еще может быть оптимизированной версией выпуска), тогда исполняемый файл будет содержать дополнительные разделы, обеспечивающие некоторую отражательную способность двоичного файла. В системах * nix (вы ссылались на dl_open
) это осуществляется с помощью отладки данных DWARF в дополнительных разделах двоичного файла ELF . Аналогично это работает для Mach Universal Binaries на MacOS X.
Windows PE, однако, использует совершенно другой формат, поэтому, к сожалению, DWARF не является полностью кроссплатформенным (фактически, на ранних этапах разработки моего 3D-движка я реализовал загрузчик ELF / DWARF для Windows, так что я мог использовать общий формат для У двигателей разные модули, поэтому с некоторыми серьезными усилиями такое можно сделать).
Если вы не хотите внедрять свои собственные загрузчики или отлаживать средства доступа к информации, то вы можете встраивать информацию об отражении через некоторые дополнительные символы, экспортируемые (по некоторой стандартной схеме именования), которые ссылаются на таблицу имен функций, сопоставление их подписи. В случае с исходными файлами на Си написание парсера для извлечения информации из самого исходного файла довольно тривиально. C ++ OTOH настолько сложно правильно проанализировать, что вам нужен какой-то полноценный компилятор, чтобы все было правильно. Для этой цели был разработан GCCXML, технически GCC, который испускает AST в форме XML вместо двоичного объекта. Извлеченный XML тогда намного легче разобрать.
Из извлеченной информации создайте исходный файл со своего рода связанным списком / массивом / и т. Д. структура, описывающая каждую функцию. Если вы не экспортируете символ каждой функции напрямую, а вместо этого инициализируете какое-то поле в структуре отражения с помощью указателя на функцию, вы получаете действительно хорошую и чистую аннотированную схему экспорта. Технически вы также можете поместить эту информацию в отдельный раздел двоичного файла, но размещение ее в разделе данных только для чтения тоже подойдет.
Однако, если вы получили бинарный файл третьей стороны - скажем, в худшем случае, он был скомпилирован из источника C, никакой отладочной информации и все символы, на которые нет внешней ссылки, удалены - вы в значительной степени испорчены. Лучшее, что вы могли сделать, - это применить некоторый двоичный анализ того, как функция обращается к различным местам, в которых можно передавать параметры.
Это скажет вам только количество параметров и размер каждого значения параметра, но не тип или имя / значение. При обратном проектировании какой-либо программы (например, анализ вредоносных программ или аудит безопасности) определение типа и значения параметров, передаваемых функциям, является одним из основных усилий. Недавно я наткнулся на какой-то драйвер, который мне пришлось отменить для целей отладки, и вы не можете поверить, насколько я был поражен тем, что я нашел символы C ++ в модуле ядра Linux (вы не можете использовать C ++ в ядре Linux в здравом смысле). ), но также с облегчением, потому что искажение имени в C ++ дало мне много информации.