Динамические интерпретируемые языки программирования высокого уровня пользуются популярностью в качестве инструмента для прототипирования и непосредственной разработки различных программных систем [7].
Одним из ярких примеров динамического языка программирования, получившего большое распространение в последние годы, является Ruby. Этот мультипарадигмальный язык общего назначения был разработан Юкихиро Мацумото (Yukihiro Matsumoto) в середине девяностых годов прошлого века, однако обрёл особенную популярность лишь спустя десятилетие с появлением платформы Ruby on Rails, предоставляющей множество удобных инструментов для упрощения процесса разработки веб-сайтов и веб-сервисов [8].
К ключевым особенностям Ruby, которые делают его эффективным и удобным инструментом разработки, относятся выразительность и гибкость данного языка программирования. Первое позволяет программисту наиболее полно и чётко выражать в программном коде свои намерения и максимально подробно описывать поведение программы, опустив при этом излишние в данном контексте детали реализации. Гибкость же вкупе с динамической природой Ruby даёт возможность прямо в ходе исполнения программы не только узнать о структуре и содержимом любого объекта системы (т.н. отражение или рефлексия), но и изменять сам смысл и поток работы программного кода путём добавления новых классов и методов, переопределения логики работы функций и так далее. Иными словами, Ruby располагает набором мощных средств для метапрограммирования, что даёт разработчикам возможность переложить рутинную работу по написанию служебного кода на сам язык, в то время как они будут заниматься лишь описанием высокоуровневых бизнес- процессов.
Разумеется, как и у любого инструмента, у Ruby есть и недостатки. Как уже было сказано, Ruby — язык интерпретируемый, то есть программы на этом языке не преобразуется в машинные коды напрямую (как в случае с компилируемыми языками), а обрабатываются по мере их выполнения специальной виртуальной машиной. Фактически это размывает привычные границы между непосредственно самой программой, предназначенной для запуска пользователем, и исходным кодом этой программы. Хотя Ruby и используется в большей степени для разработки веб-сайтов [9] (где прямого доступа к исходным кодам у пользователей нет — вся работа происходит в формате запрос-ответ), то даже в таком случае может возникнуть, например, необходимость развернуть некий веб-сервис на аппаратном обеспечении одного из клиентов. При этом, разумеется, передача исходных кодов напрямую недопустима, поскольку возможно их незаконное использование: например раскрытие уникальной бизнес-логики и алгоритмов обработки данных.
Одним из решений данной проблемы является использование байткода Ruby в качестве промежуточной формы представления программ. Несмотря на то, что Ruby — язык интерпретируемый, перед непосредственным началом интерпретации программы виртуальной машиной, она проходит своего рода «компиляцию», которая преобразует исходный код в набор инструкций для виртуальной машины (по мере возможности оптимизированный для повышения производительности). Такой байт-код, хоть и является довольно высокоуровневым и отражает всю семантику исходного кода, а так же содержит в себе большое количество метаданных (вплоть до номеров строк и названий переменных), всё же крайне неудобен для чтения и понимания человеком. Это делает такое промежуточное представление привлекательным способом передачи программы клиенту, которую он сможет запустить, но исходные коды которой не сможет прочитать без специальных знаний и умений.
Полученный байт-код можно дополнительно зашифровать при помощи специальных инструментов, например, RubyEncoder: это набор утилит, которые с одной стороны позволяют авторам программы преобразовать её в зашифрованный байт-код, недоступный для чтения, а с другой стороны дают возможность клиенту запустить полученные им зашифрованные файлы программы и использовать их как обычные файлы исходного кода на языке Ruby [10].
Разработка подобных инструментов и средств представления программ на языке Ruby в промежуточной форме требует постоянной проверки корректности генерируемого байт-кода для поиска и устранения ошибок при совершении преобразований. Однако, на текущий момент не существует инструментов обратного преобразования (т.н. декомпиляции), которые бы позволяли восстановить исходный код программы, получая на вход лишь сгенерированный заранее набор инструкций байт-кода. Это приводит к необходимости использования ручного тестирования, которое значительно увеличивает время разработки, одновременно понижая процент найденных дефектов из-за человеческого фактора.
Целью данной работы является реализация такого автоматического декомпилятора, поддерживающего базовые конструкции языка Ruby и способного автоматизировать ручное восстановление исходного кода.
Основные задачи данной работы:
1. Изучить процесс интерпретации программ, написанных на языке программирования Ruby, а также формат генерируемого интерпретатором этого языка байт-кода.
2. Изучить возможные подходы к декомпиляции байт-кода и определиться со структурой разрабатываемого декомпилятора. Обозначить набор требований к декомпилятору, в том числе множе ство конструкций байт-кода и соответствующих им конструкций языка программирования Ruby, которые подлежат декомпиляции.
3. Реализовать декомпилятор в формате динамической библиотеки языка программирования Ruby, поддерживающей обработку ранее определённого набора конструкций языка.
4. Удостовериться в корректности работы декомпилятора на обозначенном наборе конструкций языка путём модульного тестирования компонентов декомпилятора, а также интеграционного тестирования декомпилятора в целом при работе в качестве библиотеки языка программирования Ruby.
В работе исследован и описан формат инструкций виртуальной машины Ruby, рассмотрены вопросы генерации и особенности интерпретации данных инструкций. Выработаны шаблоны отображения конструкций байт-кода в соответствующие им конструкции исходного кода на языке Ruby. Разработан декомпилятор, позволяющий производишь такое отображение автоматически для заданного набора конструкций байт-кода.
Таким образом, цель работы достигнута, её результаты могут быть использованы в дальнейшем при исследовании особенностей работы виртуальной машины Ruby.
1. Introduction to metaprogramming. [Электронный ресурс] / IBM. developerWorks. URL: https://www.ibm .com/developerworks/library/l- metaprog1 (дата обращения 14.04.2017)
2. Meta Programming. [Электронный ресурс] / Cunningham & Cunningham, Inc. URL: http://wiki.c2.com/?MetaProgramming (дата обращения 14.04.2017)
3. Virtual machine. [Электронный ресурс] / Wikimedia Foundation, Inc. URL: https://en.wikipedia.org/wiki/Virtual_machine (дата обращения 13.04.2017)
4. Bytecode. [Электронный ресурс] / Wikimedia Foundation, Inc. URL: https://en.wikipedia.org/wiki/Bytecode (дата обращения 08.04.2017)
5. Interpreter. [Электронный ресурс] / Wikimedia Foundation, Inc. URL: https://en.wikipedia.org/wiki/Interpreter (дата обращения 14.04.2017)
6. P. Shaughnessy. Ruby Under a Microscope. Изд.: No Starch Press, 2013. — 360 c.
7. L. Tratt. Dynamically typed languages. Advances in Computers, 2009, vol. 77, pp. 149-184.
8. What is Rails? [Электронный ресурс] / Ruby on Rails. URL: http:// guides.rubyonrails.org/getting_started.html#what-is-rails-questionmark (дата обращения 14.04.2017)
9. Web Development: Ruby on Rails. [Электронный ресурс] / Developer Shed. URL: https://www.devarticles.com/c/a/Ruby-on-Rails/Web- Development-Ruby-on-Rails/ (дата обращения 13.04.2017)
10. RubyEncoder Overview. [Электронный ресурс] / SourceGuardian Ltd. URL: https://www.rubyencoder.com/overview.html (дата обращения 13.04.2017)
11. Koichi Sasada. YARV: yet another RubyVM: innovating the ruby interpreter. In Companion to the 20th annual ACM SIGPLAN conference on Object-oriented programming, systems, languages, and applications 2005 (OOPSLA ’05). ACM, New York, USA, pp. 158-159.
12. Ruby 1.9.0 is released. [Электронный ресурс] / Yukihiro Matsumoto. URL: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/284720 (дата обращения 15.04.2017)
13. The Many Interpreters and Runtimes of the Ruby Programming Language. [Электронный ресурс] / Toptal LLC. URL: https:// www.toptal.com/ruby/the-many-shades-of-the-ruby-programming- language (дата обращения 15.04.2017)
14. Ruby Hacking Guide. [Электронный ресурс] / Minero AOKI.
URL: https://ruby-hacking-guide.github.io/module.html (дата обращения 16.04.2017)
15. Ruby Language Optimization Techniques. [Электронный ресурс] / N. Bender, B. Neely, J. Otander. URL: https://github.com/johnotander/ ruby_optimization_techniques (дата обращения 16.04.2017)...21