Оптимизация динамической загрузки библиотек на архитектуре ARM

Автор: Кудряшов Е.А., Мельник Д.М., Монаков А.В.

Журнал: Труды Института системного программирования РАН @trudy-isp-ran

Статья в выпуске: 1 т.28, 2016 года.

Бесплатный доступ

В статье рассматривается подход к оптимизации вызовов внешних функций в позиционно-независимом коде, основанный на выдаче вызовов непосредственно через глобальную таблицу смещений (GOT), минуя таблицу компоновки процедур (PLT). Стандартные механизмы кодогенерации на операционной системе Linux предполагают создание PLT не только для основного модуля (который является позиционно-зависимым и полагается на механизм PLT для вызовов внешних процедур), но и для динамических библиотек, где PLT используется также для организации ленивого связывания; однако использование PLT требует дополнительной инструкции перехода, может иметь низкую локальность по кешу и на некоторых архитектурах накладывает дополнительные ограничения на работу компилятора в месте вызова. Реализация вызовов внешних функций в виде косвенных переходов на адреса, загруженные непосредственно из GOT в месте вызова, позволяет избежать недостатков вызовов через PLT ценой отказа от возможности ленивого связывания и, возможно, увеличения размера кода. Была исследована реализация этой оптимизации для архитектур x86 и ARM в компиляторе GCC. Было обнаружено, что на архитектуре ARM отсутствуют типы релокаций, которые позволили бы генерировать оптимальный код для загрузок из GOT. Для решения этой проблемы в GCC и Binutils (в ассемблере и компоновщике) были реализованы недостающие типы релокаций, позволяющие построить адрес позиции в GOT относительно счетчика команд, используя инструкции movt, movw. Проведенное тестирование свидетельствует, что предложенная оптимизация позволяет получить увеличение производительности, несмотря на увеличение размеров динамических библиотек.

Еще

Оптимизация программ, динамический загрузчик, глобальная таблица смещений, таблица компоновки процедур, релокация, архитектура arm

Короткий адрес: https://sciup.org/14916330

IDR: 14916330   |   DOI: 10.15514/ISPRAS-2016-28(1)-4

Dynamic loader optimization for ARM

The paper discusses an optimization approach for external calls in position-independent code that is based on loading the callee address immediately at the call site from the Global Offset Table (GOT), avoiding the use of the Procedure Linkage Table (PLT). Normally the Linux toolchain creates the PLT both in the main executable (which comprises position-dependent code and has to rely on the PLT mechanism to make external calls) and in shared libraries, where the PLT serves to implement lazy binding of dynamic symbols, but is not required otherwise. However, calls via the PLT have some overhead due to an extra jump instruction and poorer instruction cache locality. On some architectures, binary interface of PLT calls constrains compiler optimization at the call site. It is possible to avoid the overhead of PLT calls by loading the callee address from the GOT at the call site and performing an indirect call, although it prevents lazy symbol resolution and may cause increase in code size. We implement this code generation variant in GCC compiler for x86 and ARM architectures. On ARM, loading the callee address from the GOT at call site normally needs a complex sequence with three load instructions. To improve that, we propose new relocation types that allow to build a PC-relative address of a given GOT slot with a pair of movt, movw instructions, and implement these relocation types in GCC and Binutils (assembler and linker) for both ARM and Thumb-2 modes. Our evaluation results show that proposed optimization yields performance improvements on both x86 (up to 12% improvement with Clang/LLVM built with multiple shared libraries, on big translation units) and ARM (up to 7% improvement with SQLite, average over several tests), even though code size on ARM also grows by 13-15%.

Еще

Список литературы Оптимизация динамической загрузки библиотек на архитектуре ARM

  • J. Levine. Linkers and Loaders. Morgan-Kauffman, p. 256, October 1999.
  • J. Greenhalgh. Tighten direct call pattern to repair -fno-plt. https://gcc.gnu.org/ml/gcc-patches/2015-08/msg00152.html.
  • A. Monakov. PIC calls without PLT, generic implementation. https://gcc.gnu.org/ml/gcc-patches/2015-05/msg00225.html.
  • D. Melnik. Developing Interblock Combine Pass in GCC. GNU Tools Cauldron 2013. https://gcc.gnu.org/wiki/cauldron2013.
  • ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition, Section A2.8.6.60, 04 June 2009.
  • Веб-сайт SQLite. http://www.sqlite.org/about.html.