понедельник, 2 декабря 2013 г.

Ассемблерный hello world на github

Немного обновил и причесал свой 64-битный hello world. И главное, выложил на github чтобы по возможности добавить еще примеров.


понедельник, 3 июня 2013 г.

Установка актуальных версий PostgreSQL на Debian/Ubuntu

Разрабы PostgreSQL сами поддерживают apt-репозиторий с актуальными версиями PostgreSQL. Это означает, что новую версию не придется собирать из исходников, если ее не добавили в оффициальный набор пакетов дистрибутива. Достаточно добавить этот репозиторий.
Вся информация и инструкция у них на вики: https://wiki.postgresql.org/wiki/Apt

воскресенье, 7 апреля 2013 г.

Gentoo. Не собирается xorg-server-1.13.1



При очередном обновлении не собрался xorg-server-1.13.1, выдавая при билде следующую ошибку:

/mnt/storage/portage_tmp/portage/x11-base/xorg-server-1.13.1/work/xorg-server-1.13.1/glx/createcontext.c: In function ‘__glXDisp_CreateContextAttribsARB’:
/mnt/storage/portage_tmp/portage/x11-base/xorg-server-1.13.1/work/xorg-server-1.13.1/glx/createcontext.c:190:29: error: ‘GLX_LOSE_CONTEXT_ON_RESET_ARB’ undeclared (first use in this function)
/mnt/storage/portage_tmp/portage/x11-base/xorg-server-1.13.1/work/xorg-server-1.13.1/glx/createcontext.c:190:29: note: each undeclared identifier is reported only once for each function it appears in
/mnt/storage/portage_tmp/portage/x11-base/xorg-server-1.13.1/work/xorg-server-1.13.1/glx/createcontext.c:248:10: error: ‘GLX_CONTEXT_ES2_PROFILE_BIT_EXT’ undeclared (first use in this function)
make[1]: *** [createcontext.lo] Error 1


Погуглив ошибку, наткнулся на обсуждение, но решения не нашел.


Итак, не собирается файл xorg-server-1.13.1/glx/createcontext.c. Не находятся два макроса-константы: GLX_LOSE_CONTEXT_ON_RESET_ARB и GLX_CONTEXT_ES2_PROFILE_BIT_EXT.



Поиск


Идем в createcontext.c. Для этого вытаскиваем из /usr/portage/distfiles/ архив с исходниками и распаковываем его в удобное место. Смотрим начало файла, где находятся все инклуды

#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif

#include <GL/glxtokens.h>
#include "glxserver.h"
#include "glxext.h"
#include "indirect_dispatch.h"

Хочу проверить, а соберется ли он просто так из исходников при помощи autotools. Захожу в директорию с распакованным xorg'ом и делаю:
$ ./configure
$ make

и обнаруживаю, что он спокойно себе собирается, не выдавая никаких ошибок. Значит ebuild так формирует параметры сборки, что подключаются не те заголовочные файлы.
Лезу в ebuild
less /usr/portage/x11-base/xorg-server/xorg-server-1.13.1.ebuild
и нахожу там:
# Xorg-server requires includes from OS mesa which are not visible for
# users of binary drivers.
mkdir -p "${T}/mesa-symlinks/GL"
for i in gl glx glxmd glxproto glxtokens; do
        ln -s "${EROOT}usr/$(get_libdir)/opengl/xorg-x11/include/$i.h" "${T}/mesa-symlinks/GL/$i.h" || die
done
for i in glext glxext; do
        ln -s "${EROOT}usr/$(get_libdir)/opengl/global/include/$i.h" "${T}/mesa-symlinks/GL/$i.h" || die
done
append-cppflags "-I${T}/mesa-symlinks"

xorg-2_src_configure

Т.е. специально подсовываются заголовочные файлы из /usr/lib64/opengl/xorg-x11/include/. Подозрение падает на glxtokens.h из-за названия и того, что он есть в сишном файле. Необходимых макросов-констант в нем не оказывается. Этот файл /usr/lib64/opengl/xorg-x11/include/glxtokens.h оказывается сиротой, т.е. о его принадлежности к конкретному пакету portage не знает. Это проверено следующей командой:
equery belongs usr/lib64/opengl/xorg-x11/include/glxtokens.h
Пытаюсь найти в системе файлы с таким названием, делая 

locate glxtokens.h
и нахожу такой же заголовочный файл принадлежащий x11-proto/glproto:

equery belongs /usr/include/GL/glxtokens.h
 * Searching for /usr/include/GL/glxtokens.h ... 
x11-proto/glproto-1.4.16 (/usr/lib64/opengl/xorg-x11/include/GL/glxtokens.h)

В этом glxtokens.h все необходимые-макросы константы есть:
# cat /usr/include/GL/glxtokens.h | grep GLX_LOSE_CONTEXT_ON_RESET_ARB
#define GLX_LOSE_CONTEXT_ON_RESET_ARB      0x8252

# cat /usr/include/GL/glxtokens.h | grep GLX_CONTEXT_ES2_PROFILE_BIT_EXT
#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT    0x0004

Решение

Удаляю usr/lib64/opengl/xorg-x11/include/glxtokens.h и заменяю его на симликом на /usr/include/GL/glxtokens.h


# rm /usr/lib64/opengl/xorg-x11/include/glxtokens.h
# ln -s /usr/include/GL/glxtokens.h /usr/lib64/opengl/xorg-x11/include/glxtokens.h

После чего xorg-server успешно собирается.


понедельник, 23 июля 2012 г.

Ссылка. Хорошая статья об операторах и методах сравнения в Ruby

Рассмотрены все методы и операторы сранения в Ruby. Пояснена их идеология, обговорено что нужно перегрузить, чтобы использовать свои классы в качестве ключей хэша, а что перегружать не стоит. Про то, что case...when..end использует оператор === узнал отсюда.
http://techbot.me/2011/05/ruby-basics-equality-operators-ruby/

суббота, 25 февраля 2012 г.

64-битный ассемблерный helloworld в linux

Цель - осилить 64-битный linux ассемблер.
Литературы и примеров под 64 бита сильно меньше, чем под 32. Поэтому начата попытка адаптации некоторых под x86_64. Для начала был написан helloworld.


Здесь описан тот же код, что и в викиучебнике и http://callumscode.com/blog/3
От первого отличается использованием 64-битного ABI , а от второго использованием GNU Assebler вместо nasm.

Что надо сделать, чтобы вывести на экран строку? Надо сделать системный вызов WRITE. Чтобы его сделать, необходимо знать следующие вещи: номер системного вызова и способ передачи аргументов. То, как передается номер системного вызова и его параметы описано в документе System V Application Binary Interface AMD64 Architecture Processor Supplement (A.2.1 Calling Conventions)

В данном случае:
  • Номер системного вызова - 1, передается через регистр %rax
  • Первый аргумент передается через регистр %rdi. Это номер файлового дескриптора. В данном случае это 1, т.к. используется стандартный поток вывода
  • Второй аргумент - указатель на строку, передается через регистр %rsi
  • Третий аргумент - длина строки, через регистр %rdx
  • После установки аргументов вызываем команаду syscall для системного вызова(К.О.)
Для корректного выхода из программу нужно повторить все это для системного вызова EXIT. Его номер - 60, а аргумент всего один - статус завершения. В данном случае ноль - процесс завершился успешно.

Номера 64-битных системных вызовов можно найти в системе /usr/include/asm/unistd_64.h или например здесь http://www.acsu.buffalo.edu/~charngda/linux_syscalls_64bit.html

Версия первая, с функцией main и прилинкованной стандартной библиотекой. Это фактически клон из викиучебника, поэтому за пояснениями можно обратиться туда.

/* GNU Assembler Hello World 64 bit edition */
/* Compile: gcc hello_world_64_with_main.s -o hello_world_64_with_main.bin 
 * Run: ./hello_world_64_with_main.bin
 */
/*
 * Начало сегмента данных
 */
.data
/*
 * Строка, которую будем печатать. Точнее метка указывающая
 * на ее начало.
 */
hello_str:
        /*
         * А это сами данные строки.
         */
        .string "Hello, 64-bit world!\n"
        /*
         * Вычисление длины строки и помещение ее(длины) в символ
         * hello_str_length. -1 нужен, чтобы не выводить нулевой
         * символ, который вставляет .string
         */
        .set hello_str_length, . - hello_str - 1

/*
 * Начало сегмента кода.
 */
.text

/*
 * Объявляем main глобавльным символом.
 */
.globl  main                  
.type   main, @function             /* main - функция (а не данные)       */
main:
        movq    $1, %rax            /*  поместить номер системного вызова 
                                        write = 1 в регистр %rax */     
        movq    $1, %rdi            /*  первый параметр - в регистр %ebx;
                                        номер файлового дескриптора 
                                        stdout - 1  */

        movq    $hello_str, %rsi    /*  второй параметр - в регистр %rsi;
                                        указатель на строку            */
        movq    $hello_str_length, %rdx /* третий параметр - в регистр
                                           %rdx; длина строки       */
        syscall             /*  системный вызов */
        movq    $60, %rax   /* номер системного вызова exit - 60   */
        movq    $0, %rdi    /* передать 0 как значение параметра  */
        syscall             /* вызвать exit(0)                    */
        .size   main, . - main    /* размер функции main            */
/*---------------------------end---------------------------------------------*/

Компилируем:
$ gcc hello_world_64_with_main.s -o hello_world_64_with_main.bin
Запускаем:
$  ./hello_world_64_with_main.bin
Hello, 64-bit world!
Смотрим, от каких разделяемых библиотек зависит программа:
$ ldd hello_world_64_with_main.bin 
        linux-vdso.so.1 =>  (0x00007fff3eeff000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f49fc054000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f49fc3bc000)
Смотрим размер файла:
$ stat hello_world_64_with_main.bin 
  File: `hello_world_64_with_main.bin'
  Size: 7850            Blocks: 16         IO Block: 4096   regular file
7850 - байт

Версия вторая, без функции main, без стандартной библиотеки.
/* GNU Assembler Hello World 64 bit edition */
/* Compile: gcc -nostdlib hello_world_64_without_main.s -o hello_world_64_without_main.bin 
 * Run: ./hello_world_64_without_main.bin
 */
/*
 * Начало сегмента данных
 */
.data
/*
 * Строка, которую будем печатать. Точнее метка указывающая
 * на ее начало.
 */
hello_str:
        /*
         * А это сами данные строки.
         */
        .string "Hello, 64-bit world!\n"
        /*
         * Вычисление длины строки и помещение ее(длины) в символ
         * hello_str_length. -1 нужен, чтобы не выводить нулевой
         * символ, который вставляет .string
         */
        .set hello_str_length, . - hello_str - 1

/*
 * Начало сегмента кода.
 */
.text

/*
 * Объявляем _start глобавльным символом.
 */
.globl  _start                  
.type   _start, @function             /* _start - функция (а не данные)       */
_start:
        movq    $1, %rax            /*  поместить номер системного вызова 
                                        write = 1 в регистр %rax */     
        movq    $1, %rdi            /*  первый параметр - в регистр %ebx;
                                        номер файлового дескриптора 
                                        stdout - 1  */

        movq    $hello_str, %rsi    /*  второй параметр - в регистр %rsi;
                                        указатель на строку            */
        movq    $hello_str_length, %rdx /* третий параметр - в регистр
                                           %rdx; длина строки       */
        syscall             /*  системный вызов */
        movq    $60, %rax   /* номер системного вызова exit - 60   */
        movq    $0, %rdi    /* передать 0 как значение параметра  */
        syscall             /* вызвать exit(0)                    */
/*---------------------------end---------------------------------------------*/

Компилируем:
$ gcc -nostdlib hello_world_64_without_main.s  -o hello_world_64_without_main.bin
Запускаем:
$ ./hello_world_64_without_main.bin
Hello, 64-bit world!
Смотрим от каких разделяемых библиотек зависит программа:
$ ldd hello_world_64_without_main.bin
        not a dynamic executable
Опа, а ничего ей не нужно.

Смотрим размер файла:
$ stat hello_world_64_without_main.bin
  File: `hello_world_64_without_main.bin'
  Size: 1003            Blocks: 8          IO Block: 4096   regular file
Почти в 8 раз меньше.
Пока наверное все.
Код доступен на github:

Ссылки по теме: