Использование v-table thunks для объединения вызовов процедур в цепочку

StackOverflow https://stackoverflow.com/questions/1090755

  •  11-09-2019
  •  | 
  •  

Вопрос

Я читал несколько статей в сети, касающихся Vtable thunks, и я где-то читал, что thunks можно использовать для подключения / цепочки вызовов процедур.

Достижимо ли это?

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

Это было полезно?

Решение

Реализация raw thunk в стиле v-table thunks - это последнее средство.Все, что вам нужно выполнить, скорее всего, может быть достигнуто с помощью функции-оболочки, и это будет гораздо менее болезненно.

В общем, thunk выполняет следующее:

  1. Исправьте входные параметры (например, преобразуйте в другой формат)
  2. Назовите реальную реализацию
  3. Шаг очистки 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 выполняет следующие шаги:

  1. Исправьте входные параметры, а именно скрытый указатель "this", в первой строке.
  2. Вызовите реальную реализацию во второй строке.
  3. Очистка:не требуется (см. ниже)

Это то место, где 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-интерфейса:кнопки обеспечивают точку впрыска для диагностики и переходят к фактическому методу.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top