Подмножество x86 без регистра% gs: двоичный код исправления, который использует% gs вместо перехвата в эмуляцию? - PullRequest
4 голосов
/ 02 августа 2011

По причинам, слишком сложным для объяснения, у меня есть необходимость запустить программу Linux, скомпилированную GCC x86, на платформе, являющейся подмножеством x86 Эта платформа не имеет регистра% gs, это означает, что его нужно эмулировать, поскольку GCC зависит от наличия регистра% gs.

В настоящее время у меня есть оболочка, которая перехватывает исключения, когда программа пытается получить доступ к регистру% gs, и эмулирует его. Но это собака медленно. Есть ли способ, которым я могу заранее исправлять коды операций в ELF с помощью эквивалентных инструкций, чтобы избежать ловушки и эмуляции?

Ответы [ 2 ]

4 голосов
/ 02 августа 2011

Вы пытались скомпилировать свой код с опцией -mno-tls-direct-seg-refs? С моей страницы руководства GCC (i686-apple-darwin10-gcc-4.2.1):

   -mtls-direct-seg-refs
   -mno-tls-direct-seg-refs
       Controls whether TLS variables may be accessed with offsets from
       the TLS segment register (%gs for 32-bit, %fs for 64-bit), or
       whether the thread base pointer must be added.  Whether or not this
       is legal depends on the operating system, and whether it maps the
       segment to cover the entire TLS area.

       For systems that use GNU libc, the default is on.
3 голосов
/ 02 августа 2011

(Предполагается, что решение Адама Розенфилда неприменимо. Возможно, это лучший способ его решения или аналогичный подход).

Вы не указали, как эмулировать% gs.зарегистрируйтесь, но, вероятно, будет непросто пропатчить каждое использование в целом, если у вас нет специальных знаний о программе, потому что в противном случае у вас есть только 2 байта (в худшем, обычном случае), которые вы можете изменить с помощьюваш патч.Конечно, если вы используете что-то вроде% es =% gs, это должно быть относительно просто.

Если предположить, что это как-то может работать в вашем случае, стратегия состоит в том, чтобы сканировать исполняемые секции ELF-файл и исправление любой инструкции, которая использует или изменяет регистр GS.Это как минимум следующих инструкций:

  • Любая инструкция с префиксом переопределения сегмента GS (65 ожидается для инструкций ветвления, в этом случае префикс указывает на что-то еще)
  • push gs (0F A8)
  • pop gs (0F A9)
  • mov r/m16, gs (8C /r)
  • mov gs, r/m16 (8E /r)
  • mov gs, r/m64 (REX.W 8E /r) (если вы поддерживаете 64-битный режим)

И любые другие инструкции, которые разрешают регистры сегментов (я не думаю,это гораздо больше, но я не уверен на 100%).

Это все из Руководство разработчика программного обеспечения для архитектуры Intel® 64 и IA-32, Объединенные тома 2A и 2B: Справочник по наборам инструкций, AZ .Имейте в виду, что инструкции иногда имеют префикс других префиксов, иногда нет, поэтому вам, вероятно, следует использовать библиотеку для декодирования команд, а не вслепую искать последовательности байтов.

Некоторые изПриведенные выше инструкции должны быть относительно простыми, чтобы их можно было преобразовать в call my_patch или аналогичные, но у вас, вероятно, возникнут проблемы с поиском чего-то, что умещается в два байта и работает в целом.int XX (CD XX) может быть хорошим кандидатом, если вы можете установить вектор прерывания, но я не уверен, что он будет быстрее, чем метод, который вы используете в настоящее время.Вам, конечно, нужно будет записать, какая инструкция была исправлена, и обработчик прерываний (или что-то еще) реагирует по-разному в зависимости от адреса возврата (который получает ваш обработчик).

Возможно, вы сможете установить батут, еслиВы можете найти место в пределах -128,127 байт и использовать JMP rel8 (EB cb), чтобы прыгнуть на батут (обычно другой JMP, но на этот раз с большим количеством места для целевого адреса), который затем обрабатывает инструкциюэмуляции и переходит обратно к инструкции, следуя исправленному использованию% gs.

Наконец, я бы порекомендовал оставить код trap-and-emulate запущенным, чтобы перехватывать любые случаи, о которых вы, возможно, не подумали (самоизменение иливведенный код например).Таким образом, вы также можете регистрировать любые необработанные случаи и добавлять их в свое решение.

...