Использование v-table thunks для объединения вызовов процедур в цепочку
Вопрос
Я читал несколько статей в сети, касающихся Vtable thunks, и я где-то читал, что thunks можно использовать для подключения / цепочки вызовов процедур.
Достижимо ли это?
Кто-нибудь знает, как это работает, также я не могу найти хороший ресурс, объясняющий thunks.Есть какие-нибудь предложения по этому поводу?
Решение
Реализация raw thunk в стиле v-table thunks - это последнее средство.Все, что вам нужно выполнить, скорее всего, может быть достигнуто с помощью функции-оболочки, и это будет гораздо менее болезненно.
В общем, thunk выполняет следующее:
- Исправьте входные параметры (например, преобразуйте в другой формат)
- Назовите реальную реализацию
- Шаг очистки 1 / исправьте выходные параметры
Чтобы увидеть пример того, как это работает, давайте обратимся к нашему хорошему другу Рэймонду Чену и его обсуждению возможностей настройщика:
http://blogs.msdn.com/oldnewthing/archive/2004/02/06/68695.aspx
Удар, который он использовал, был следующим:
[thunk]:CSample::QueryInterface`adjustor{4}':
sub DWORD PTR [esp+4], 4 ; this -= sizeof(lpVtbl)
jmp CSample::QueryInterface
Как он описывает, у вас есть класс, который реализует одни и те же методы через несколько интерфейсов, поэтому он имеет несколько v-таблиц.(Если вы не знаете COM, все, что вам нужно знать, это то, что он работает напрямую с v-tables, поэтому указатель на определенный интерфейс должен содержать указатели функций на все методы этого интерфейса по порядку.)
Если вы реализуете два интерфейса с разными методами в определенном слоте, вам понадобится несколько v-таблиц.Но вы пишете перекрывающиеся методы только один раз, поэтому этот метод должен быть способен работать с обоими указателями "this".Чтобы сделать это, компилятор генерирует метод, который выполняет необходимое исправление и вызывает исходную реализацию.
Итак, этот thunk выполняет следующие шаги:
- Исправьте входные параметры, а именно скрытый указатель "this", в первой строке.
- Вызовите реальную реализацию во второй строке.
- Очистка:не требуется (см. ниже)
Это то место, где jmp
поступает инструкция.Обычно, если бы вы вызывали функцию с помощью call
, это вернулось бы к вам, и вам пришлось бы ret
вернемся к вашему абоненту.Поскольку очистка не требуется, компилятор выполняет оптимизацию, при которой он перемещает выполнение прямо к реальной реализации, и пусть оператор return реальной реализации возвращается к ваш звонивший.Это всего лишь оптимизация, а не фундаментальная часть thunking.Например, 16/32-разрядные thunks преобразуют параметры ввода / вывода между 16 и 32 битами по мере необходимости, поэтому он не может пропустить этап очистки;это должно call
, не jmp
.
Мораль этой истории такова:если вам нужно что-то сделать, например, jmp
оптимизация, которую вы не можете написать непосредственно на C ++ или другом выбранном вами языке высокого уровня, продолжайте писать на языке ассемблера thunk.В противном случае просто напишите оболочку и покончите с этим.
Честно говоря, это звучит так, как будто вы просите оптимизации производительности, и в большинстве случаев (1) компилятор оптимизируется лучше, чем мы думаем, и (2) это не даст вам такого большого улучшения, как вы думаете.
Другие советы
Ну, вы прочитали, что удары - это решение, и теперь вы ищете проблему, которую нужно решить?
Thunks, как правило, представляют собой короткие функции "пересылки", которые обеспечивают незначительные - обычно жестко запрограммированные - корректировки.
Фрагменты VTable очень хорошо объяснены в википедия на данный момент.Они используют общий шаблон:создайте небольшую функцию, чтобы избежать вычислений / дополнительной работы во время выполнения.
Другие места, которые я видел / использовал thunks:
Связывание дескриптора окна с объектом window:для каждого окна, подлежащего разделению на подклассы, на лету генерируется небольшой фрагмент, который вызывает оконную процедуру со ссылкой на объект, затем этот фрагмент используется как оконная процедура.
Задержка загрузки DLL-файлов:функция thunk гарантирует, что DLL загружается при первом вызове любой функции.
Перехватывание вызовов COM-интерфейса:кнопки обеспечивают точку впрыска для диагностики и переходят к фактическому методу.