Основным препятствием является конфликт по базовому адресу сегмента GS (GS.base), поддерживаемый ЦП под управлением ОС.
В 64-битной Windows GS.base используется для храненияадрес структуры блока среды потока (TEB) для каждого потока.Приложения Windows ожидают доступа к TEB, используя %gs
-относительные адреса.Это жестко запрограммировано в коде приложения, а не в функции API.
В macOS GS.base используется для хранения базы области локального хранилища потока struct _pthread
,внутренняя деталь реализации реализации Pthreads.В приложениях Mac реже встречаются жестко запрограммированные %gs
-относительные доступы, но некоторые делают и делают системные библиотеки.
В Linux GS.base доступен для 64-битных приложенийиспользовать для своих целей.Итак, Wine просто устанавливает его, используя механизм, предоставляемый ОС.Wine не может сделать это на macOS.Мало того, что ОС не предоставляет никакого механизма для этого, но, если Wine сможет, это сломает системные библиотеки.(Это также создает потенциальные проблемы для ядра при переключении контекста, и / или ядро может не восстановить любое значение, которое мог установить Wine.)
Решение, которое мы выяснили, является лишь частичным решением.К наиболее часто используемым полям структуры TEB относятся поле self (%gs:0x30
) и поле для реализации локального хранилища потока (%gs:0x58
).Часто, если приложениям требуется доступ к другим полям, они сначала читают поле self, а затем ссылаются на него.
В macOS %gs:0x30
и %gs:0x58
соответствуют определенным слотам области локального потока потока,Они принадлежат Apple (а не, скажем, приложениям).Мы обнаружили, что один из этих слотов не использовался.Другой использовался для функции ttyname()
в библиотеке C.Как это случается, Wine никогда не вызывает эту функцию, и нет никаких оснований ожидать, что любая из системных библиотек, которые он использует для этого, тоже.
Итак, Wine просто задает соответствующие значения в этих %gs
-относительныхместах.Поэтому, когда 64-битный код приложения Windows читает их, он получает то, что ему нужно.Фактический TEB, выделенный Wine, находится в другом месте (в выделенной куче памяти), но приложения находят адрес TEB в месте, которое, как они ожидают, являются собственным полем TEB, поэтому они находят его таким образом.
Apple с тех пор любезно зарезервировала оба этих слота для использования как Wine.ttyname()
теперь использует другой слот.
Тем не менее, как уже упоминалось выше, это решение является лишь частичным.Некоторые приложения обращаются к другим полям TEB напрямую, используя %gs
-относительные адреса со смещениями, отличными от 0x30
или 0x58
.Когда они это делают, они получают нежелательные значения и / или значения перезаписи, используемые другими частями системы.Таким образом, поддержка Wine для 64-битных приложений Windows не завершена в macOS.Некоторые такие приложения будут аварийно завершать работу или работать неправильно.К счастью, это случается довольно редко, и на практике это не представляет большой проблемы.
Для справки, вот коммиты, которые реализуют это решение:
http://source.winehq.org/git/wine.git/?a=commit;h=7501942008f91a9a137fe598ce5ce7cb47de5522 http://source.winehq.org/git/wine.git/?a=commit;h=3d8efb238808a519902e047d8673237debb0f0a2