Новый 2013 год и подведение итогов 2012



6 коммент.
Очередной понедельничный пост, на сей раз новогодний. Решил подвести немного итогов года, оглянуться назад и почить на лаврах :-)

Как оно было?

Год выдался весьма плодотворным: было много конференций, узнал много нового, обновил парк ноутбуков и реализовал хрустальную мечту юности (Lenovo X201 Tablet).

В смысле постов - их было столько же, сколько и в предыдущем году. Стало больше гостевых постов, и это радостно: гостевые посты вносят свежую струю в блог, и так я узнаю много нового и интересного (и надеюсь, не только я).

Запущен в тестовом режиме Лунодром "Дебианити". Это совсем мелкие заметки на манжетах, ссылки и прочие наброски, не подходящие под формат записок. Итог моих экспериментов со scriptogr.am и markdown, а так же временное решение проблемы хранения мелких набросков под рукой (ещё один блог заводить не хочется, здесь публиковать рано или ни к чему, а пригодиться могут).

Теперь итоги. Посты были разные, и интересно взглянуть на то, что понравилось из написанного мне, и что - читателям.

Топ5 постов, которые нравятся мне

Есть посты, которые пишутся в формате "чтобы не забылось" - и это почти всё про LaTeX и Gnuplot, которыми я пользуюсь постоянно. Но есть и нечто особенное, что стоит много часов и дней усилий по сбору материала и выпиливанию подробностей. Итак, мой Топ-5 постов за этот год, которые мне нравятся.

Странное рождение и долгая жизнь UNIX

Пост года, во всяком случае для меня, и самый большой перевод с английского на русский. На перевод и утрясание копирайтов с IEEE ушло почти четыре дня, но результат того стоил. Хотя переводчик с меня не очень хороший, смысл, думаю, передать удалось. Пост важен с исторической точки зрения, дабы помнить, с чего всё начиналось.
Статистика: +31 Plus one, 27 Comments, 5977 Views.

Markdown - гаечный ключ для забивания треугольных болтов

После того, как я нашёл применение Markdown в качестве простого и быстрого генератора вложенных списков для LaTeX, он стал частью моего workflow. Но этому предшествовала переписка с iv_vl, которая, надо сказать, направила меня по ложному следу. Пост был написан после того, как я перепробовал массу опенсорсных сноповязалок и прочих велосипедов с квадратными колёсами :-)
Статистика: +24 Plus one, 33 Comments, 2699 Views.

Краткий обзор современных окружений рабочего стола

Несколько неожиданный для меня экспромт Vlsu, ставший отличным постом. Прекрасные иллюстрации, структура и описания, хотя самый первый вариант был вызывающе неполиткорректным :-) Тем не менее, пост более чем стоил усилий, на него потраченных - один из лучших постов этого года, и абсолютный лидер по количеству просмотров. Браво, Vlsu, снимаю шляпу.
Статистика: +25 Plus one, 72 Comments, 13020 Views.

Pomodoro: тайм-менеджмент, который работает

Pomodoro я использую уже больше года, и для меня это было большим прорывом в плане учёта и анализа собственной продуктивности. Позволяет делать больше без стахановских рывков и прочего ненужного героизма. Пост, один из самых подробных за этот год, писался долго и был сильно улучшен усилиями комментаторов.
Статистика: +28 Plus one, 26 Comments, 3991 Views.

Настольный Змей Горыныч

Один из наиболее информативных постов для меня лично - узнал много нового про multihead, хотя это стоило некоторых денег (купленные переходники, хотя и используются время от времени, но tripple-head на ноутбуке не вышел). Пост нравится своей структурированностью, которая стоила немалых усилий. Кроме того, один из немногих постов, почти полностью написанный в Markdown.
Статистика: +22 Plus one, 18 Comments, 2169 Views.



Топ5 постов, которые понравились читателям

Здесь я ориентировался по числу PlusOne и просмотрам. В комментариях можно отвести душу и привести свои списки, но здесь балом правит бездушная статистика.

Вскрытие 9В батарейки: в поисках батареек АААА

Написанный за час и почти не стоивший усилий, пост неожиданно понравился народу на Хабре и собрал больше всех ПлюсАдынов за этот год (почти полсотни). Все деньги, потраченные на его написание, с лихвой отбились кассовыми сборами с рекламы :-)
Статистика: +46 Plus one, 18 Comments, 5041 Views.

Странное рождение и долгая жизнь UNIX

Здесь наши симпатии совпадают - второй пост по плюсадинам. Кривизну перевода сильно выправил тов. Minoru, за что ему большое спасибо.
Статистика: +31 Plus one, 27 Comments, 5977 Views.

Краткий обзор современных окружений рабочего стола

Самый комментируемый и самый посещаемый пост года от Vlsu. Уже растащен на скриншоты, понаставлена куча ссылок и есть по крайней мере два репоста. Как говорится, признание к художнику приходит не тогда, когда его работы в первый раз выставят, а тогда, когда их в первый раз украдут :-)
Статистика: +25 Plus one, 72 Comments, 13020 Views.

Возможности настройки GRUB2 в Linux

Второй пост по числу просмотров в этом году, и не мой, а написанный Yamamaya. Очень подробный и насыщенный деталями, хотя это и было главным объектом критики ведущего. Тем не менее, пост информативный и второй по количеству просмотров за год.
Статистика: +24 Plus one, 29 Comments, 10591 Views.

Как редактировать в Vim без порчи и бибиканья

Снова гостевой пост, на этот раз от Pento, о текстовом редакторе, который пищит и всё портит. Несмотря на краткость и лаконичность, набрал почти 9000 просмотров и часто появляется в поисковых запросах о Vim.
Статистика: +6 Plus one, 38 Comments, 8480 Views.

И ещё немного статистики

Отбирать что-то лучшее всегда непросто, поэтому я приведу Топ5 самых посещаемых, самых комментируемых и собравших больше всех +1 постов, опубликованных в этом году. Ваше слово, товарищ Статистика!

Самые плюсадинистые


Название постаPlus oneCommentsViews
Вскрытие 9В батарейки: в поисках батареек АААА46185041
Странное рождение и долгая жизнь UNIX31275977
Pomodoro: тайм-менеджмент, который работает28263991
Краткий обзор современных окружений рабочего стола257213020
Возможности настройки GRUB2 в Linux242910591
Markdown - гаечный ключ для забивания24332699

 

Самые комментируемые

Название постаPlus oneCommentsViews
Краткий обзор современных окружений рабочего стола257213020
Вычислительный танк заряженный свободой: ThinkPad  15675854
Как редактировать в Vim без порчи и бибиканья6388480
Назад в мезозой к программным динозаврам 19372001
Markdown - гаечный ключ для забивания24332699
Консольный Mplayer: мощь без границ21333371

Самые просматриваемые


Название постаPlus oneCommentsViews
Краткий обзор современных окружений рабочего стола257213020
Возможности настройки GRUB2 в Linux242910591
Как редактировать в Vim без порчи и бибиканья6388480
Навигационные программы для Android6318227
Странное рождение и долгая жизнь UNIX31275977



Глядя в даль...

В следующем году будет... а, впрочем, кто его знает, что там будет. Много черновиков и идей, мало времени, много интересного. Приоткрывая пухлую папку черновиков, можно видеть наброски про латех, гнуплот, программирование на C и Матлаб, не очень много про железо, немного про ядро, пара забойных обзоров и ещё кое-что про Андроид. Ну и что там гостевые авторы понапишут. Кстати, ваши посты тоже тут могут засветиться - гостевые посты принимаются в любое время.


Открывая шампанское...

С новым годом Линукса на Десктопе! Чтоб никогда ничего не падало, чтоб фич было много, а багов - мало. Чтоб была свобода, Столлман, равенство и братство :-)

Ну и уж этот-то год точно станет Годом Линукса на Десктопе :-)
Читать далее

Декомпиляторы, или Что делать, если нужно восстановить исходники из бинарников?



19 коммент.
Проблема восстановления исходного кода из скомпилированных бинарников возникает сравнительно часто и протекает остро, с воем и рыданиями. Здесь нам, до некоторой степени, помогут замечательные программы-декомпиляторы, и в этом посте автор собрал свои скромные попытки выдрать исходники (или хотя бы намёки на них) из скомпилированных из С-шного кода бинарников.


Задача для декомпилятора бинарников, собранных из С кода:
Классический случай: один деятель на факультете написал на правильном ANSI C (и используя библиотеки BLAS и LAPACK) нужные и хорошие алгоритмы, и скомпилировал их в виде MEX-файлов для использования (это С-шный код, который можно вызывать из МАТЛАБ).

Но потом он повздорил с народом, разозлился и свалил в частную контору, унеся все исходники с собой. Документации нет. Копий исходников нет. Есть обрывки личной переписки и намёки в сопровождающих файлах на тип алгоритма. Вариант физического воздействия на автора тупыми тяжёлыми предметами не рассматривается.

Нужно восстановить исходники если и не до компилируемого состояния, то во всяком случае выудить оттуда алгоритмы и ключевые методы, использованные при реализации.


Кратко: суть и сложность проблемы
Декомпилятор (Decompiler) пытается перевести скомпилированный бинарный файл обратно в некое подобие исходного кода. Качество выхлопа зависит от особенностей языка исходника:
  • Для C# или Java есть много декомпиляторов - байткод на java содержит  много информации. Это помогает восстанавливать декомпилятору исходник до состояния, пригодного к повторной компиляции.
  • Совершенно другая история с двоичными файлами, в которых, как правило, отладочной информации нет. Тем не менее, динамически связанные библиотеки функций, как правило, вызываются по имени. Часто, типы параметров библиотечных функций известны, и это может помочь до известных пределов. 
Декомпиляторы пытаются восстановить информацию, которая частично утрачена при компиляции в бинарный файл - в этом и заключается основная сложность.

Если вы думаете, что с помощью декомпилятора вы получите обратно красивый код на С - вы будете сильно разочарованы.  В лучшем случае на выходе будет общая (и довольно грубая) структура программы, в худшем - только имена функций и немного мусора.

Так что ответ на вопрос заголовка поста: "Обхватить голову руками и закричать #$@@@@@!" :-)


Программы для декомпилирования (decompilers) для C/C++
Декомпиляторов для C/C++ немного, и ниже список из наиболее работоспособных. Здесь нет разделения на опенсорс или Linux-only - для такого дела, как вскрытие исходников, можно (и нужно) поступиться своими светлыми идеалами и наступить на горло собственной песне.

Сразу замечу: скорее всего, ни один декомпилятор не выдаст вам сразу компилируемый код. Придётся потратить порядком времени и сил, чтобы это месиво превратить в код, который можно читать (желательно, не только компилятору).


Boomerang
Boomerang это C decompiler с открытыми исходами:
  • поддерживаемые бинарные форматы:  ELF  PE-COFF Mac-OS
  • платформы: Windows/Linux
  • поддерживаемые архитектуры: IA32 MIPS PPC
  • метод работы: поточный, есть жалкий графический интерфейс, лучше использовать CLI.
Весьма продвинутый набор алгоритмов анализа кода, что не удивительно - один из соавтором защитил на этом докторскую диссертацию [Michael James Van Emmerik, Static Single Assignment for Decompilation, Ph.D. thesis, the University of Queensland, Australia. PDF, mirror PDF].

Качество кода, выдаваемого декомпилятором:
  • Структурирование: очень хорошее
  • Переменные: хорошее
  • Типы данных: очень хорошее
Выдаваемое качество кода сильно варьируется: некоторые функции почти идеально восстановлены, хорошо видна структура кода и есть указание типа переменных. В других случаях функции сильно запутаны и их почти невозможно прочитать.

Программа всё ещё в состоянии бета-версии и для больших проектов не подходит. Скачать можно здесь.


RecStudio
Интерактивный декомпилятор RecStudio для С и (отчасти) С++, закрытая разработка:
  • поддерживаемые бинарные форматыELF  PE-COFF AOUT RAW PS-X
  • платформы: Windows/Linux/MacOS
  • поддерживаемые архитектуры: x86 (ia32) x86_64 Mips PowerPC mc68k
  • метод работы: поточный и интерактивный, есть графический интерфейс.
Использует продвинутый набор алгоритмов анализа (partial Single Static Assignment, SSA), хотя до сих пор (и это после 20 лет!) в стадии разработки. Качество кода, выдаваемого декомпилятором:
  • Структурирование: хорошее
  • Переменные: частично
  • Типы данных: частично или никак
Выдаваемое качетсво кода, как правило, хуже, чем у Boomerang, хотя обновлённый RecStudio более подробен.

Программа работает вполне стабильно, есть сборки под Linux. Скачать можно здесь.



dcc - DOS to C decompiler
Поточный декомпилятор Dcc, только ANSI C  и для exe-файлов, с открытым исходным кодом под GPL:
  • поддерживаемые бинарные форматыEXE/COM
  • платформы: Windows
  • поддерживаемые архитектуры: x86
  • метод работы: поточный.
Один из первых декомпиляторов вообще, и только под DOS. Сильная сторона - структурирование кода. Качество кода, выдаваемого декомпилятором:
  • Структурирование: хорошее
  • Переменные: частично
  • Типы данных: частично или никак
Разработка Cristina Cifuentes, которая защитила PhD в Queensland University of Technology  на этом деле [можно полистать, если что - C. Cifuentes, Reverse Compilation Techniques].

Скачать можно отсюда (на сайте университета).



Hex Rays - plugin для IDA Pro
На самом деле Hex Rays не является отдельной программой - это плагин-декомпилятор для IDA Pro. Комбинация продвинутых возможностей IDA Pro (это дизассемблер) и Hex Rays в качестве декомпилятора очень впечатляет, как и аэрокосмическая цена.
По причине закрытости продукта (нет даже демо-версии) и нереальной цены в этом разделе про Hex Rays больше ничего написано не будет.




Ходовые испытания в реальных условиях
Для начала попробуем декомпилировать что-нибудь совсем простенькое и написанное на ANSI C и с использованем библиотеки BLAS для векторых и матричных операций. Бинарный файл можно скачать здесь.



1. Простенький C-шный бинарник + BLAS
Собственно, код на C для перемножения матрицы и вектора (используется CBLAS). Исходник:


#include <stdio.h>
#include <cblas.h>

double m[] = {
  3, 1, 3,
  1, 5, 9,
  2, 6, 5
};

double x[] = {
  -1, -1, 1
};

double y[] = {
  0, 0, 0
};

int main(void)
{
  int i, j;

  for (i=0; i<3; ++i) {
    for (j=0; j<3; ++j) printf("%5.1f", m[i*3+j]);
    putchar('\n');
  }

  cblas_dgemv(CblasRowMajor, CblasNoTrans, 3, 3, 1.0, m, 3, x, 1, 0.0, y, 1);


  for (i=0; i<3; ++i)  printf("%5.1f\n", y[i]);

  return 0;
}

После перемножения выдаст результат на консоль.

Выхлоп Boomerang
У него много ключей и параметров, часть которых не знает даже официальная, скажем так, документация. Тем не менее, для ключа -Td (Use data-flow-based type analysis) мы имеем выхлоп в стиле дзен:

double y;
double m = 3.;

// address: 0x80484e4
int main(int argc, char **argv, char **envp) {
    void *local23;   // r28

    for(;;) {
        proc1();
    }
}

Скажем так, не слишком ободряюще. Ключ  -Tc (Use old constraint-based type analysis) выдаёт больше информации к размышлению:

char y[24];
long long m[9] = { 0x4008000000000000LL, 0x3ff0000000000000LL, 0x4008000000000000LL, 0x3ff0000000000000LL, 0x4014000000000000LL, 0x4022000000000000LL, 0x4000000000000000LL, 0x4018000000000000LL, 0x4014000000000000LL };

// address: 0x80484e4
int main(int argc, char **argv, char **envp) {
    int local10;   // r24
    int local13;   // r28
    int local14;   // r29
    int local15;   // r32
    int local2;   // m[r28 + 72]{60}
    int local3;   // r28{181}
    int local6;   // m[r28 + 72]{119}
    int local7;   // m[r28 + 72]{149}
    int local8;   // m[r28 + 76]{9}
    int local9;   // m[r28 + 76]{49}

    *(int*)(local13 - 4) = local14;
    *(int*)(local13 - 12) = 0;
    local3 = local13 - 84;
    if (*(int*)(local3 + 72) > 2) {
        *(int*)(local3 + 52) = 1;
        *(int*)(local3 + 48) = 0x8049868;
        *(long long*)(local3 + 40) = 0.;
        *(int*)(local3 + 36) = 1;
        *(int*)(local3 + 32) = 0x8049848;
        *(int*)(local3 + 28) = 3;
        *(int*)(local3 + 24) = 0x8049800;
        *(long long*)(local3 + 16) = 1.;
        *(int*)(local3 + 12) = 3;
        *(int*)(local3 + 8) = 3;
        *(int*)(local3 + 4) = 111;
        *(int*)local3 = 101;
        cblas_dgemv();
        local6 = 0;
        for(;;) {
            *(long long*)(local3 + 4) = y[0];
            *(int*)local3 = 0x80486b6;
            proc1();
            local7 = *(int*)(local3 + 72) + 1;
        }
    }
    local8 = 0;
    for(;;) {
        local10 = *(int*)(local3 + 72) + *(int*)(local3 + 72) + *(int*)(local3 + 72);
        local15 = m[local10];
        *(long long*)(local3 + 4) = local15;
        *(int*)local3 = 0x80486b0;
        proc1();
        local9 = *(int*)(local3 + 76) + 1;
    }
} 
 

Подробностей тут больше, и тут выловлен самый главный ключик - cblas_dgemv();    


Выхлоп RecStudio
Намного более обилен и представляет собой следующий поток сознания:


// Generated by Rec Studio 4 - build Oct 20 2012

_init()
{// addr = 0x08048398
    _unknown_ __ebx;                       // r1
    _unknown_ __ebp;                       // r6
    _unknown_ _t2;                         // _t2

    __esp = __esp - 4;
    L1();
    _pop(__ebx);
    if( *((intOrPtr*)(_t2 + 0x1414)) != 0) {
        __gmon_start__();
    }
    frame_dummy();
    __do_global_ctors_aux();
    _pop(__eax);
    return;
}

L080483A4()
{
    _unknown_ _t2;                         // _t2

    _pop(__ebx);
    if( *((intOrPtr*)(_t2 + 0x1414)) != 0) {
        __gmon_start__();
    }
    frame_dummy();
    __do_global_ctors_aux();
    _pop(__eax);
    _pop(__ebx);
    __esp = __ebp;
    _pop(__ebp);
    return;
}

__gmon_start__()
{// addr = 0x080483D8
    goto __imp____gmon_start__;
}

putchar()
{// addr = 0x080483E8
    goto __imp__putchar;
}

__libc_start_main()
{// addr = 0x080483F8
    goto __imp____libc_start_main;
}

cblas_dgemv()
{// addr = 0x08048408
    goto __imp__cblas_dgemv;
}

printf()
{// addr = 0x08048418
    goto __imp__printf;
}

_start(
    signed int __eax,                      // r0
    _unknown_ __edx                        // r3
)
{// addr = 0x08048430
    _unknown_ __ebx;                       // r1
    signed int _t5;                        // _t5
    _unknown_ _t6;                         // _t6
    _unknown_ _t10;                        // _t10

    __edx = __edx;
    _t4 = __eax;
    _pop(__esi);
    __ecx = __esp;
    __esp = __esp & 240;
    _push(__eax);
    _push(__esp);
    _push(__edx);
    _push(__libc_csu_fini);
    _push(__libc_csu_init);
    _push(__ecx);
    _push(_t10);
    _push(main);
    __libc_start_main();
    asm("hlt ");
    0;
    0;
    _push(0);
    _push(_t6);
    __esp = __esp - 4;
    if(completed.5982 != 0) {
    } else {
        _t4 = dtor_idx.5984;
        _t6 = ( &__DTOR_END__ -  &__DTOR_LIST__ >> 2) - 1;
        if(_t4 >= _t6) {
        } else {
            do {
                _t5 = _t4 + 1;
                dtor_idx.5984 = _t5;
                 *((intOrPtr*)(_t5 * 4 +  &__DTOR_LIST__))();
                _t4 = dtor_idx.5984;
            } while(_t4 < _t6);
        }
        completed.5982 = 1;
    }
    __esp = __esp + 4;
    _pop(__ebx);
    _pop(__ebp);
    return;
}

__do_global_dtors_aux(
    _unknown_ __esi                        // r5
)
{// addr = 0x08048460
    _unknown_ __ebx;                       // r1
    _unknown_ __ebp;                       // r6
    _unknown_ _t4;                         // _t4
    signed int _t5;                        // _t5
    signed int _t6;                        // _t6
    _unknown_ _t10;                        // _t10

    if(completed.5982 == 0) {
        _t5 = dtor_idx.5984;
        _t10 = ( &__DTOR_END__ -  &__DTOR_LIST__ >> 2) - 1;
        if(_t5 >= _t10) {
L4:
            completed.5982 = 1;
            return;
        }
        do {
            _t6 = _t5 + 1;
            dtor_idx.5984 = _t6;
             *((intOrPtr*)(_t6 * 4 +  &__DTOR_LIST__))();
            _t5 = dtor_idx.5984;
        } while(_t5 < _t10);
        goto L4;
    }
    return;
}

frame_dummy()
{// addr = 0x080484C0
    _unknown_ __ebp;                       // r6

    __eax = __JCR_LIST__;
    if(__JCR_LIST__ == 0) {
    } else {
        __eax = 0;
        if(__eax != 0) {
             *__esp =  &__JCR_LIST__;
             *__eax();
            return;
        }
    }
    return;
}

main(
    _unknown_ __fp0                        // r28
)
{// addr = 0x080484E4
    signed int _v8;                        // _cfa_fffffff8
    signed int _v12;                       // _cfa_fffffff4
    intOrPtr _v32;                         // _cfa_ffffffe0
    char* _v36;                            // _cfa_ffffffdc
    intOrPtr _v48;                         // _cfa_ffffffd0
    char* _v52;                            // _cfa_ffffffcc
    intOrPtr _v56;                         // _cfa_ffffffc8
    char* _v60;                            // _cfa_ffffffc4
    intOrPtr _v72;                         // _cfa_ffffffb8
    intOrPtr _v76;                         // _cfa_ffffffb4
    intOrPtr _v80;                         // _cfa_ffffffb0
    _unknown_ __ebp;                       // r6

    __fp0 = __fp0;
    __esp = __esp & 240;
    __esp = __esp - 80;
    _v12 = 0;
    while(_v12 <= 2) {
        _v8 = 0;
        while(_v8 <= 2) {
            __fp0 ?_?  *((long long*)((_v12 + __edx + __edx + _v8) * 8 +  &m));
            asm("fstp qword [esp+0x4]");
             *__esp = 134514352;
            printf();
            _v8 = _v8 + 1;
        }
         *__esp = 10;
        putchar();
        _v12 = _v12 + 1;
    }
    _v32 = 1;
    _v36 =  &y;
    asm("fldz ");
    asm("fstp qword [esp+0x28]");
    _v48 = 1;
    _v52 =  &x;
    _v56 = 3;
    _v60 =  &m;
    asm("fld1 ");
    asm("fstp qword [esp+0x10]");
    _v72 = 3;
    _v76 = 3;
    _v80 = 111;
     *__esp = 101;
    cblas_dgemv();
    _v12 = 0;
    while(_v12 <= 2) {
        __fp0 ?_?  *((long long*)(_v12 * 8 +  &y));
        asm("fstp qword [esp+0x4]");
         *__esp = "%5.1f\n";
        printf();
        _v12 = _v12 + 1;
    }
    return 0;
}

__libc_csu_fini()
{// addr = 0x080485F0
    _unknown_ __ebp;                       // r6

    return;
}

__libc_csu_init(
    intOrPtr _a4,                          // _cfa_4
    intOrPtr _a8,                          // _cfa_8
    intOrPtr _a12                          // _cfa_c
)
{// addr = 0x08048600
    intOrPtr _v36;                         // _cfa_ffffffdc
    intOrPtr _v40;                         // _cfa_ffffffd8
    _unknown_ __ebx;                       // r1
    _unknown_ __edi;                       // r4
    signed int __esi;                      // r5
    _unknown_ __ebp;                       // r6
    _unknown_ _t14;                        // _t14
    _unknown_ _t15;                        // _t15
    signed int _t18;                       // _t18

    __i686.get_pc_thunk.bx();
    _t15 = _t14 + 4529;
    __esp = __esp - 28;
    _init();
    _t18 = _t15 + -248 - _t15 + -248 >> 2;
    if(_t18 == 0) {
    } else {
        __esi = 0;
        do {
            _v36 = _a12;
            _v40 = _a8;
             *__esp = _a4;
             *((intOrPtr*)(_t15 + -248 + __esi * 4))();
            __esi = __esi + 1;
        } while(__esi < _t18);
    }
    __esp = __esp + 28;
    return;
}

__i686.get_pc_thunk.bx()
{// addr = 0x0804865A
    return;
}

__do_global_ctors_aux()
{// addr = 0x08048660
    intOrPtr* __ebx;                       // r1
    _unknown_ __ebp;                       // r6

    __eax = __CTOR_LIST__;
    if(__eax == 255) {
    } else {
        __ebx =  &__CTOR_LIST__;
        asm("o16 nop ");
        do {
            __ebx = __ebx - 4;
             *__eax();
            __eax =  *__ebx;
        } while(__eax != 255);
    }
    return;
}

_fini()
{// addr = 0x0804868C
    _unknown_ __ebx;                       // r1
    _unknown_ __ebp;                       // r6
    _unknown_ _t1;                         // _t1

    __esp = __esp - 4;
    L1();
    _pop(__ebx);
    __do_global_dtors_aux(__esi);
    _pop(__ecx);
    return;
}

L08048698()
{
    _unknown_ _t1;                         // _t1

    _pop(__ebx);
    __do_global_dtors_aux(__esi);
    _pop(__ecx);
    _pop(__ebx);
    __esp = __ebp;
    _pop(__ebp);
    return;
}

L08048698()
{
    _unknown_ _t1;                         // _t1

    _pop(__ebx);
    @rec __do_global_dtors_aux@__do_global_dtors_aux@(__esi);
    _pop(__ecx);
    _pop(__ebx);
    __esp = __ebp;
    _pop(__ebp);
    return;
}

// Statistics:
//      74 Register nodes
//      35 Temporaries nodes
//       5 Casts
//     207 Statements
//       2 Labels
//       1 Gotos
//      17 Blocks
//     469 Nodes
//      10 Assembly nodes
//      27 Unknown Types


Total time: 0 seconds.


Структура программы (вначале) в общем несколько лучше, чем у Boomerang, и куда больше подробностей.



2. Бен, ай нид хелп: MEX-файл, написанный на C  + BLAS, исходников которому нет.
Этот пример в посте приводить не стану, так как он длинный, но желающим попробовать своё декомпиляйшн-кунфу такая возможность предоставится:
Некоторые входные данные: это оптимизационный алгоритм для Quadratic Programming типа Branch-and-Bound (почитать тут и здесь). Алгоритм в целом прост и незатейлив, но самая сложная часть в нём - определить lower/upper bound через решение упрощённой оптимизационной задачи, и делать это быстро. Как такое сделать - хороший вопрос, и именно он меня интересует более всего. 

Короче, важен не столько алгоритм, сколько его составные компоненты (стратегия и подпрограммы для lower bound estimation).

Автор этих строк, поковыряв выхлоп RecStudio, нашёл для себя подсказку на строчке 12319:
qps_mq_sub( .....

и особенно на строчке 12088:
getalp( ....
что позволило автору предположить, что для lower/upper bounds  использутеся Liner Programming.  Не слишком много, но по крайней мере понятно, в какую сторону копать.

Если у кого-то вдруг проявится желание потыкать в оный бинарник палочкой, IDA Pro и ещё чем - не стесняйтесь отписываться в комментариях.
Обновление: теперь можно сравнить выдачи Boomerang, RecStudio, и (спасибо, Григорий!) IDA Pro. В самом деле, выдача IDA Pro куда лучше того, что дают остальные, особенно boomerang. Можно выудить (до некоторой степени) структуру программы и даже сообщения об ошибках.


Ссылки
Интересующийся читатель может попробовать полистать вебстраницы автора RecStudio с полезной информацией, сходить на wiki-ресурс по обратной разработке.

Помимо познавательных диссертаций Michael James Van Emmerik (Boomerang) и Cristina Cifuentes [C. Cifuentes, Reverse Compilation Techniques], есть хорошие книжки по теме:
  • "Compilers - Principles, Techniques and Tools", Aho, Sethi, Ullman, 1986 Addison-Wesley Publishing Co.  ISBN 0-201-10088-6.
  • "Advanced Compiler Design & Implementation", Steven Muchnick, 1997 Morgan Kaufmann Publishers, ISBN 1-55860-320-4.
  • "How debuggers work - Algorithms, Data Structures, and Architecture", Jonathan Rosemberg, 1996 John Wiley and Sons, ISBN 0-471-14966-7.

Дело это интересное, но весьма утомительное, хотя может помочь при раскопках очередного legacy-software и сэкономить вам полжизни.
Читать далее

Как оформить исходный код программ в LaTeX без адских страданий



32 коммент.
Иногда в документ LaTeX нужно вставить кусок программного кода или псевдокод, поясняющий алгоритм. В зависимости от языка программирования и целей, подсветка кода в LaTeX достигается подключаемыми пакетами расширений разной степени кривизны и безумия документации.

Пост подвергался чистке и правке после публикации:
Автор заходил править этот пост 16 августа 2013 года.

Читать далее

Как содрать DVD в AVI и записать обратно: AVI to DVD write and rip in Linux



23 коммент.
Копирование DVD в AVI и тем более запись фильмов обратно на DVD не то, что автор этих строк делает часто. А когда надо, начинается чесание затылка и судорожные попытки вспомнить, как оно делалось однажды при синей луне. Далее небольшая заметка по созданию и сдиранию (rip) фильмов из видеофайлов на DVD и обратно.

Читать далее

График в Gnuplot с условиями: conditional data plotting in Gnuplot



19 коммент.
Как известно, одна картинка стоит тысячи слов. Вместо длинного и занудного изложения лучше привести график и его прокомментировать. Сложность в том, что иногда в график нужно запихнуть много данных, и дизайн графика превращается в самостоятельную задачу. Одна из таких задач - построение точек на графике в зависимости от условий (conditional data plotting).

Читать далее

Настольный Змей Горыныч, или Как подключить много мониторов - Multihead in Linux



21 коммент.
В своё время автор этих строк купил себе новый ноутбук, водрузил на него Debian и воткнул внешний монитор. Казалось бы, ну и всё - что ещё надо джигиту для счастья? Одна голова — хорошо, а две — лучше, подумал автор, глядя на ещё одну электродырку в ноутбуке под названием DisplayPort. И подумалось мне: это ж можно задаром ещё и третий монитор прицепить, и будет неземное счастье. Но счастье обломилось (о чём ниже), а обзорчик от поисков решения остался ...


Читать далее

Thinkpad X201 - рабочее пони с сенсорным поворотным экраном



30 коммент.

Мой старый-добрый ноутбук Asus M5200AE, который я купил ещё студентом в 2006, долгое время был моей основной рабочей машиной. И матлабовские скрипты на нём писал, и посты, и даже собрал в свою красноглазую молодость для него RT-ядро. Кстати, на нём до сих пор стоит Debian Etch - несколько консервативно, зато стабильно, олдскульно и ортодоксально, чего хватает этого для написания постов, электропочты, обзоров в LaTeX GTD и прочей мелочи. Но годы берут своё, и вот уже 512Mb памяти уже маловато, и жёсткий диск начал сдавать, и батарея померла, и кнопки понемногу отказывают. А тут на Ebay один мелкий австралийский магазин выложил old stock - собственно, Thinkpad X201 Tablet с поворотным экраном и за 800 долларов. Такой случай предоставляется не часто, и автор им воспользовался.

Как выглядит Thinkpad X201 Tablet

Ноутбук очень маленький и компактный, с отличной клавиатурой и ярким поворотным экраном, чувствительным к нажатию. Замечательно, что наличие сенсорной прослойки на экране не сказывается на качестве изображения.


Экран можно повернуть, чтобы было удобнее читать длинный текст в книге.  Но самое замечательное в X201 даже не экран, а неимоверное разнообразие способов взаимодействия:
  1. Сенсорный экран - экран воспринимает нажатие и перемещает указатель мыши вместе с вашим пальцем. Навигация по табам в броузере становится довольно забавным опытом.
  2. Стилус - ручка-стилус от Wacom, которая может использоваться для рисования и для заметок в специальных программах. Стилус обнаруживается  при поднесении на расстояние 1-2 сантиметров к экрану. Убирается внутрь ноутбука.
  3. Трекпоинт - красный сексапильный шпынёк, который удобно использовать вместо мыши и тачпада.
  4. Тачпад - небольшой, удобный и чувствительный.
  5. Клавиатура - очень мягкая легендарная IBMовская клавиатура с тихим кликом, которая достойна занять место в палате Мер и Весов.
Всё это изобилие методов ввода можно использовать для рукописных заметок, аннотирования PDF-документов и коллективного обсуждения текстов.
Немного критики. Автор этих строк всегда очень не любит, когда какой-нибудь балбес приходит и начинает ломать то, что всех устраивало. Так случилось с КДЕ4 и Гном3. Но хуже всего то, что в Lenovo пришли похожие ковбои и начали ломать наследие IBM. И вот эти узкоглазые выкинули легендарную, лучшую в мире ноутбучную клавиатуру с новых моделей. И хотя красный сексапильный трекпоинт всё ещё с нами, ему видимо уже недолго осталось жить. Новые клавиатуры, говорят, не так уж плохи. Но позвольте, если в обзорах каждый раз чествуют клавиатуру IBM, зачем же её выносить вперёд ногами?!
Это она - лучшая в мире клавиатура, из палаты Мер и Весов.

Наличие нормальной клавиатуры и было мотивацией покупки именно X201. Кроме того:
  • старая и любимая клавиатура: 97.5% моей работы - набор текстов (кода или статей), а островными клавиатурами пусть давятся макинтошники и любители дешёвых корейских поделок.
  • цена: для задач второго ноутбука 2000$ за новый Х230t это слишком дорого, а тут сбили цену почти втрое.
  • мощность: Core i7 на этой машине (запасной) не обязателен, i5 вполне сойдёт. Тем более, что гонять на нём симуляции не планируется, максимум - вечернее ковыряние кода.
  • периферия: проводной Ethernet обязателен, модем - тоже неплохо, жаль нет встроенного оптического привода. Никаких SSD, тем более распаянных на плате.
  • плюшки: планшет это хорошо, но полезнее использовать палец вместо мыши для управления окнами - в поездках мышами особо не поразмахиваешь. На поворотном экране удобно что-то обсуждать вдвоём/втроём (особенно текст статьи), повернув экран к собеседнику. Mobile broadband не особо нужен, но раз идёт в комплекте - пусть будет.
    В общем, теперь Asus M5200 отправился в коробку, а его место на столе занял Thinkpad X201. На ноутбук была предустановлена Windows 7, которую автор обновил до Debian GNU/Linux v6.0 Squeeze.


    Технические характеристики
    С точки зрения железа X201 представляет собой компромисс между компактностью и мощностью:

    Processor: Intel Core i5-560M 2.66Ghz (3.2 Ghz in turbo mode)
    Operating system: Debian GNU/Linux i386 Virens remix ``Old School Warm Tube'' 
    Display type: 12.1" WXGA (1280 X 800) LED Backlit with Enhanced MultiTouch Wide Viewing Angle Display
    System graphics: Intel HD graphics
    Total memory:4GB RAM DDR3
    Keyboard: Soft IBM Keyboard - US English
    Pointing device:TrackPoint
    Camera: 720p HD Camera with Microphone
    Hard drive:320 GB SATA HDD 7200RPM
    Optical device: NONE
    System expansion slots:Express Card Slot, 4-in-1 Card Reader
    Audio device: Intel Corporation Cougar Point High Definition Audio
    Bluetooth:Broadcom Bluetooth 3.0 with antenna
    Integrated WiFi wireless LAN adapters: Intel WiFi 6200N 802.11 a/g/n
    Ethernet:1Gb Ethernet Networking Port



    Оптического привода в ноутбуке нет в силу его скромных габаритов.
    Стоит отметить, что экран очень яркий и наличие сенсорной сетки не делает картинку слегка размытой. В комплекте с ноутбуком шёл стилус и 8-cell battery, что обеспечивает до 7 часов автономной работы (kpowersave рисует страшные цифры в 10 часов, но мне в них верится с большим трудом).


    Сразу после включения...

    Сразу после включения ноутбука засветилась Windows 7 и начала меня принуждать к миру к принятию пользовательского соглашения с Микрософтом. После этого Windows написала, что “Конфигурация будет продолжена после перезагрузки” - и Windows даже не подозревала, насколько это будет правдой…

    Конфигурация в самом разгаре: идёт заливка Debian GNU/Linux Squeeze + Lenny + Backports.

    После перезагрузки в X201 была воткнута флешка с уже настроенной системой Debian GNU/Linux, обкатанной на вычислительном танке Thinkpad T420.  Иксы сразу распознали видеокарту:
    $ glxinfo
    name of display: :0.0
    display: :0  screen: 0
    direct rendering: Yes
    server glx vendor string: SGI
    server glx version string: 1.4
    server glx extensions:
     Нашёлся звук:
    [    6.883970] input: HDA Intel HDMI/DP,pcm=3 as /devices/pci0000:00/0000:00:1b.0/sound/card0/input11
    [    6.884295] input: HDA Intel Mic as /devices/pci0000:00/0000:00:1b.0/sound/card0/input12
    [    6.884600] input: HDA Intel Dock Mic as /devices/pci0000:00/0000:00:1b.0/sound/card0/input13
    [    6.884850] input: HDA Intel Dock Headphone as /devices/pci0000:00/0000:00:1b.0/sound/card0/input14
    [    6.885102] input: HDA Intel Headphone as /devices/pci0000:00/0000:00:1b.0/sound/card0/input15
    а также тачпад, трекпоинт, и проводная сеть. Отдельно пришлось настраивать только сенсорный экран и WiFi.

    Беспроводная сеть

    Собственно, как и в случае с Thinkpad T420, за беспроводную сеть отвечает драйвер iwlwifi.
    [    6.394602] iwlwifi 0000:02:00.0: loaded firmware version 9.221.4.1 build 25532
    [    6.394946] iwlwifi 0000:02:00.0: CONFIG_IWLWIFI_DEBUG disabled
    [    6.394948] iwlwifi 0000:02:00.0: CONFIG_IWLWIFI_DEBUGFS disabled
    [    6.394949] iwlwifi 0000:02:00.0: CONFIG_IWLWIFI_DEVICE_TRACING disabled
    [    6.394951] iwlwifi 0000:02:00.0: CONFIG_IWLWIFI_DEVICE_TESTMODE disabled
    [    6.394953] iwlwifi 0000:02:00.0: CONFIG_IWLWIFI_P2P disabled
    [    6.394955] iwlwifi 0000:02:00.0: Detected Intel(R) Centrino(R) Advanced-N 6200 AGN, REV=0x74
    [    6.395012] iwlwifi 0000:02:00.0: L1 Enabled; Disabling L0S
    [    6.411167] iwlwifi 0000:02:00.0: device EEPROM VER=0x436, CALIB=0x6
    [    6.411170] iwlwifi 0000:02:00.0: Device SKU: 0x1F0
    [    6.411172] iwlwifi 0000:02:00.0: Valid Tx ant: 0x6, Valid Rx ant: 0x6
    [    6.411189] iwlwifi 0000:02:00.0: Tunable channels: 13 802.11bg, 24 802.11a channels
    [    6.411323] Registered led device: phy0-led
    Физически установлен следующий чип:
    Network controller: Intel Corporation Centrino Advanced-N 6200 (rev 35)
    Поэтому мы отправляемся за фирмварью 6000 Images for Intel Centrino Ultimate-N 6300 and Advanced-N 6200 вот сюда. Скачанный архив iwlwifi-6000-ucode-9.221.4.1.tgz распаковывается в директорию:
    /lib/firmware
    и после перезагрузки (или включения wicd) загорится лампочка WiFi.

    Сенсорный экран

    Для поддержки стилуса и сенсорного экрана нужно установить пакет:
    xserver-xorg-input-wacom - X.Org X server – Wacom input driver
    В моём случае в системе есть пакеты из Squeeze и Lenny, и немного Backports, установка выглядела несколько более эротично: пакет не хотел ставиться вообще, независимо от репозитория, пока я не скачал его отдельно и не воткнул с помощью dpkg.



    Немного о стилусе
    Стилус при поднесении к экрану перемещает курсор мыши, причём экран его чувствует с 1-2 сантиметров. Кнопка на стилусе одна, но xournal её почему-то не признаёт. На другом конце есть ластик (красный), которым можно стирать изображение в GIMP и myPaint.

    В моём случае стилус просто работает (после установки драйверов) и сила нажатия там адекватна. Но некоторые пользователи жаловались на то, что по умолчанию нажимать на экран стилусом приходится слишком сильно. Это можно исправить традиционно опенсорсным способом, а именно вскрыв стилус и поправив чувствительность.

    На самом деле, всё не так сложно: для вскрытия нам потребуется тонкая плоская отвёртка или ножик. Нужно поддеть кнопку на ручке:

    Под кнопкой находится небольшой винтик (по всей видимости, это потенциометр). Если повернуть его чуть-чуть по часовой стрелке, то чувствительность ручки увеличится. Если же повернуть винт против часовой стрелки, то чувствительность уменьшится


    Забавно, но если вывернуть винт слишком далеко против часовой стрелки, то стилус станет регистрировать нажатие даже просто от наклона.

    Зачем нужен сенсорный экран, когда есть планшеты?

    Сенсорный экран добавляет много удобств при работе с ноутбуком:
    • Можно не использовать мышь для работы с окнами, что удобно в поездках. 
    • Особенно удобно обсуждать текст, повернув экран к собеседнику, и сразу вносить изменения по ходу. 
    • При чтении длинных текстов можно сложить экран на клавиатуру и использовать, как планшет.
    • Можно делать рукописные заметки на экране.
    Собственно, рукописные заметки и работа со стилусом сильно роднит X201 с планшетом. Здесь всё несколько неоднозначно: софт для Android куда более полированный, чем линуксовые десктопные огрызки, но X201 это полноценный ноутбук, в котором можно использовать весь десктопный софт.

    Помимо управления окнами с помощью пальца и стилуса, можно использовать дополнительные возможности в виде чувствительности к нажатию в программах:
    • myPaint - есть возможность использования кистей, чьи параметры зависят от нажатия.
    • gimp - поддержка pressure sensitiviy имеет место быть, но с X201 она почему-то не работает.
    • xournal - отличное (и единственно работающее) приложение для рукописных заметок с поддержкой pressure sensitivity.
    Так что сенсорный экран доставляет много радости и пользы. Ну и конечно, Thinkpad X201 - отличный "второй" ноутбук для работы дома и в поездках, чтобы с собой главный вычислительный танк не таскать.
    Читать далее