xomachine
@xomachine

Возможно ли узнать сигнатуру виртуального метода из рантайма?

Существует проект для подмены соглашений о вызовах MSVC на GCC для steam API. Саму подмену успешно реализует WINE, но требует для этого заголовочные файлы steam API.
Всё бы ничего, но steam API постоянно меняется и старые приложения из стима используют старые версии (запрашивают у steamclient.{so, dll} нужную версию) API. Доступа к заголовочным файлам для старых версий API нет.

Это было предисловие, а теперь непосредственно к проблеме
Согласно соглашению о вызовах thiscall в MSVC аргументы вызываемого метода помещаются в стек, и вызываемый метод должен удалить их из стека перед возвращением управления.
В аналогичной ситуации GCC возлагает обязанность удаления аргументов из стека на вызывающий код.
(подробнее)
(и ещё подробнее на примере stdcall и cdecl)
Таким образом если я хочу обернуть вызов мне нужно в прослойке между кодом MSVC и GCC очистить стек от аргументов метода (и провести ещё несколько операций, но это уже проще), а для этого нужно знать сигнатуру метода. А её-то, как я уже заметил в предисловии, я и не знаю для старых версий steam API.

Соответственно вопрос: возможно ли на уровне рантайма узнать сколько аргументов было помещено в стек перед вызовом виртуального метода (по виду стека, по виртуальной таблице объекта или другой информации доступной в рантайме)?
Или в другой формулировке: Как не спутать аргумент метода в стеке с локальной переменной из кода верхнего уровня?
  • Вопрос задан
  • 231 просмотр
Решения вопроса 1
xomachine
@xomachine Автор вопроса
Сам спросил, сам нашёл решение (пусть и не универсальное)
Можно с высокой долей вероятности успешно вычислить сигнатуру метода по глубине стека, на которую обращаются инструкции. Для этого потребуется дизассемблировать метод и отследить регистры связанные со стеком.
Рабочий прототип отслеживающей процедуры для моего случая можно найти тут. Прототип написан на Nim с использованием libopcode и libbfd из пакета binutils, который входит в большинство дистрибутивов линукс.

На скриншоте результат подобного угадывания количества аргументов методов (CAdapterSteamClient017, справа) и (слева) кусок исходника, соответствующий данному классу. (надеюсь, Valve меня не забанят за публикацию скриншота с маленьким куском исходников)
Как видно из скриншота, предсказанное количество аргументов соответствует реальному.
5a4e980def378215372175.png
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
возможно ли на уровне рантайма узнать сколько аргументов было помещено в стек перед вызовом виртуального метода (по виду стека, по виртуальной таблице объекта или другой информации доступной в рантайме)?

Традиционно в C++ типы параметров функции кодируются компилятором в её имени.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы