23 апреля 2010

Перепаковка initrd

Упаковщиком исполнимых файлов UPX я давно и успешно пользовался для уменьшения размера файлов exe и dll в Windows. И только недавно обратил внимание, что поддерживается также и большое количество других, в том числе и linux-форматов. Давайте опробуем UPX и посмотрим, что у нас из этого выйдет.

Скачать упаковщик можно с его официальной страницы. Текущая версия 3.04 от 27.09.2009 представлена в вариантах для Windows и для Linux. Какой из них вы будете пользоваться — дело привычки, по своим возможностям они идентичны.

Итак, я собираюсь перепаковать initrd — начальный RAM-диск, набор программ и скриптов, необходимый на начальной стадии загрузки Linux. Операция эта — потенциально опасная, и я не несу никакой ответственности за сохранность вашей системы. Используйте всё нижеизложенное только на свой страх и риск! В моём случае я обезопасил себя тем, что во-первых, сохранил исходный файл, а во-вторых, у меня на машине установлен небольшой «зоопарк» из микро- и мини-линуксов, и если что-то пойдет не так, то я смогу загрузиться из другого линукса и восстановить исходный файл.

«Подопытным кроликом» у меня сегодня выступает дистрибутив PuppyRus Linux версии Jeans, а всё действие происходит в дистрибутиве SliTaz 3.0. Во-первых, я создаю рабочую папку на диске с родной файловой системой Linux (у меня это ext3) — никаких FAT или NTFS! Копирую в эту папку файл initrd.gz из папки Frugal-установки PuppyRus (у меня это /hda1/puppy301/) и приступаю к таинству.

В рабочей папке открываем терминал (F4) и берем себе права root командой su. Файл initrd.gz содержит в себе файловую систему, упакованную утилитой cpio и сжатую архиватором gzip. Сначала распакуем его командой

gzip -d initrd.gz

Теперь извлечем файловую систему:

cpio -iF initrd

альтернативный синтаксис этой команды:

cpio -i < initrd

И, наконец, удалим промежуточный файл (чтобы не путался под ногами):

rm initrd

Рядом с окном терминала открыто окно PCManFM и можно наглядно увидеть структуру распакованной файловой системы. Нас интересует папка bin/, только в ней содержатся исполнимые файлы. Переходим в неё командой cd bin. Для простоты, в эту же папку кидаем и исполнимый файл upx.

Рассмотрим файлы поближе. Реально из 91 файла лишь 17 являются исполнимыми, остальные — ссылки (и их мы упаковывать не станем). Так, на главный исполнимый файл busybox ссылаются cat, chmod, grep и другие, что позволяет сэкономить место. Но сейчас мы его ещё более сэкономим.

В простейшем случае для упаковки можно дать команду

./upx имя_файла

либо

./upx -число имя_файла

где число изменяется от 1 (сжимает быстрее) до 9 (сжимает сильнее). Конечно, торопиться нам некуда и мы даём команду

./upx -9 busybox

Можно сжать сильнее? Да! Используем опцию --best (самое лучшее сжатие):

./upx --best busybox

Хм! Ошибочка вышла, говорит, что файл уже упакован. В таком случае, сначала распакуем его командой

./upx -d busybox

И снова упакуем его с ключом best. Можно ли сжать ещё сильнее? В некоторых случаях — да. Для этого используются ключи:

  • --brute — перепробовать все доступные методы сжатия и фильтры (медленно);
  • --ultra-brute — перепробовать ещё большее количество вариантов сжатия (очень медленно).

Итак, в папке bin несколько файлов были уже до нас упакованы при помощи UPX. Их повторная перепаковка (последовательная распаковка и упаковка) дали несколько меньший размер, чем был. Несжатые файлы уменьшились в размере примерно в два раза! И с парой файлов UPX не смог что-либо сделать вообще, оставим их.

Теперь нужно всё это запаковать обратно. Не забываем удалить сам файл UPX из папки bin! Возвращаемся обратно командой cd .. и даём команду упаковки (например так):

find ./ | cpio -H newc -ouv > initrd

Сжимаем получившийся initrd:

gzip initrd

Оригинальный файл в папке /puppy301/ переименовываем на initrd.gz.old, закидываем сюда свежеиспеченный initrd.gz.
Сравниваем размер. Оригинал — 2400 Кб, наш файл — 1170 Кб. Это — не много и не мало, это — из разряда «мелочь, но приятно». Это позволяет сделать маленький линукс ещё меньше.

Кроме того, в этой же папке лежит и ядро линукса — файл vmlinuz, который UPX тоже способен сжать! (Читайте справку, господа).

Тут всё просто — копируем ядро в нашу папку с UPX, даём команду

./upx --best vmlinuz

и наблюдаем, как размер ядра уменьшился с 1704 Кб до 1566 Кб.
Но вот распаковать упакованное ядро уже не получится. UPX выдает такую ошибку:

upx: vmlinuz: CantUnpackExeption: build a new kernel instead :-)

то есть «лучше вместо этого соберите новое ядро :-)»

Теперь наступает самый ответственный момент. Опробуем в деле свеже-сжатые RAM-диск и ядро. Перезагружаем машину, в GRUB выбираем PuppyRus...

Система оказалась полностью работоспособной, с чем себя и поздравляем!

0 коммент.:

Отправить комментарий