LINUX.ORG.RU

Сообщения SZT

 

Как получить список библиотек, которые можно передать через -l...

Для линковки с разными библиотеками есть разные опции, например -lm -lpthread -ldl итд. Каким образом компилятор сопоставляет эти -l(что-то-там) с конкретной библиотекой(где эта информация хранится) и как эти связи посмотреть в gcc и clang(какой библиотеке какой -lчто-то-там соотвествует)? Как добавить туда какую-то свою библиотеку, чтобы с ней можно было линковаться через gcc -lmylib ?

 , ,

SZT
()

Добавить секцию в готовый elf бинарник

Мне надо добавить новую секцию с исполняемым кодом в уже готовый elf бинарник и поменять entry point чтобы выполнение начиналось именно с нее. Попробовал сделать это через objcopy, секцию оно добавляет, но пишет ворнинг:

$ objcopy --add-section .mytext=my_asm.bin --set-section-flags .mytext=readonly,code,alloc --change-section-address .mytext=66666666 test test2
BFD: test2: warning: allocated section `.mytext' not in segment
readelf показывает такую картину:
Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         00000000004000b0  000000b0
       0000000000000034  0000000000000000  AX       0     0     16
  [ 2] .data             PROGBITS         00000000006000e4  000000e4
       000000000000000e  0000000000000000  WA       0     0     4
  [ 3] .mytext           PROGBITS         0000000003f940aa  001940aa
       0000000000000350  0000000000000000  AX       0     0     1
  [ 4] .shstrtab         STRTAB           0000000000000000  001943fa
       000000000000002f  0000000000000000           0     0     1
  [ 5] .symtab           SYMTAB           0000000000000000  001945f0
       0000000000000108  0000000000000018           6     7     8
  [ 6] .strtab           STRTAB           0000000000000000  001946f8
       000000000000002a  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)
....

 Section to Segment mapping:
  Segment Sections...
   00     .text 
   01     .data 

Как(чем) мне добавить секцию .mytext в этот Section to Segment mapping? (Чем поменять entry point я как-нибудь сам разберусь, в крайнем случае через hex редактор это сделаю)

 , ,

SZT
()

inline callback-функций как способ метапрограммирования

Я вот задумался. Взять например функцию qsort() из стандартной библиотеки сей, ну которая принимает указатель на массив, количество элементов в этом самом массиве, размер одного элемента массива и функцию которая принимает два указателя на элементы массива, делает сравнение и возвращает int. Что если реализовать механизм встраивания всей этой фигни (за исключением разве что указателя на тот самый массив, который сортировать надо) и можно значительно ускорить процесс сортировки. Например, тут https://books.google.com/books?id=RPnWe6QKnCcC&pg=PA201&lpg=PA201&amp... говорят что std::sort быстрее qsort т.к. там компилятор может заинлайнить это. Но это не универсально. Если в компилтайме нам например неизвестен способ сравнивания двух элементов массива(т.е. мы это узнаем только на этапе выполнения), там ничего не заинлайнится. Например, как решать такую задачу : программа читает некий массив чисел(неизвестно заранее сколько, допустим читаем из файла. Пусть это будет тип float), пользователь вводит некую формулу, например y=x*x+2*(x-1) и каждое число из списка подставляются последовательно в эту формулу как x, вычисляется y и записывается потом куда-то в файл. Самый простой способ реализовать подобное на C - генерить в рантайме на основе введенной формулы некий исходник на C, компилировать его как .so, подгружать через dlopen и запустить. Желательно при этом, чтобы сам цикл с последовательным применением формулы был тоже сгенерирован внутри этой самой библиотеки, чтобы не было проседаний на каждый вызов функции. Шаблоны из плюсов тут ничем не помогут в плане оптимизации, они не могут отработать в процессе выполнения кода и что-либо там менять-добавлять. А через inline callback-функции это было бы очень просто сделать без особых проблем. Например, мы получаем от пользователя нуль-терминированную строку вида «x*x+2*(x-1)». Значит нам нужна функция, которая бы принимала указатель на строку, указатель на массив-источник, указатель на массив-назначение и кол-во элементов в массиве, которое надо по этой формуле преобразовать. Назовем эту функцию apply_ar. Получим что-то вроде

void (*apply_arr(char *str, float *src, float *dst, size_t nmemb))(void)
{
    какой-то_код;
    return somestuff;
}

Так оно просто вернет указатель на функцию, которая вообще ничего не принимает т.е. просто встроит в функцию все аргументы. Будет в итоге сгенерирована функция, которая по неким вшитым в код адресам в цикле читает флоаты, применяет вшитую в код формулу и записывает результат в заранее оговоренную область памяти. Получилось очень неуниверсально. Задачу можно изменить, например может потребоваться обрабатывать много массивов разной длины с разными адресами *src *dst но по одинаковой формуле. Тогда надо городить другую функцию, на этот раз принимающую только строку, описывающую формулу преобразования и которая возвращает функцию, принимающую указатель на источник, назначение, количество элементов. Примерно так:

void (*apply_arr(char *str))(float *src, float *dst, size_t nmemb)
{
    какой-то_код;
    return somestuff;
}
Получается что-то вроде каррирования с суперкомпиляцией, специализация программ методом частичных вычислений: http://keldysh.ru/papers/2008/prep12/prep2008_12.html#_Toc193602742

А теперь насчет callback-ов и их встраивания. Можно передавать в нашу функцию еще и код, который бы делал само вычисление по формуле. Для этого можно сделать функцию, в которую если передать например строку вида «x*x+2*(x-1)» вернет указатель на функцию вида

float calculate(float s)
{
    return x*x+2*(x-1);
}
И результат этой функции передавать в функцию apply_arr. Таким образом, если кто-нибудь захочет задавать формулу например в обратной польской записи, то мы просто напишем еще одну функцию и в случае чего будем передавать ее результат. Только тут просто указатель на функцию передать в рантайме не выйдет (нам ведь надо чтобы оно инлайнилось в функцию, которая будет сгенерирована функцией), таким образом нужно вводить некий байткод, промежуточное представление, которое потом бы компилировалось. Можно взять готовое, например формат промежуточного представления от какого-нибудь компилятора. В самой нашей функции apply_arr тогда тоже надо хранить этот байткод, и наша функция должна два эти байткода (свой и тот который в нее передается) уметь комбинировать и выдавать на выходе указатель на функцию с нативным кодом. Что самое интересное, если это все как следует продумать, можно сделать полноценный лисп поверх C, только с ручным управлением памятью. Самое замечательное, что это хоть сейчас можно в какой-то степени реализовать, только вместо байткода надо брать обычный сишный код, а для «встраивания» кода внутрь кода использовать что-то вроде
printf("some code;\n"
"%s\n"
"some code;\n");
, потом кормить этим компилятор и загружать получившийся код в исполняемую область памяти. Для более нормальной реализации всего этого, надо каким-то образом переделать компилятор. Саму специализацию можно делать как на этапе компиляции, так и в рантайме. Если промежуточное представление сделать как AST, это будет вообще замечательно. Всю программу можно собрать из этих коллбеков, и не будет ни одной нормальной привычной функции. Вся программа это функция, в которую передается массив из функций, каждая из функций может быть например оператором сложения int с int, float с float, разыменование указателя, операцией приведения типа, вызов какой-то функции. При том, необязательно все это дело инлайнить. Сами функции могут просто вызываться обычным путем, несмотря на возможность их заинлайнить. Таким образом можно переопределить любое действие, при том в рантайме (например можно сделать, что при попытке записи в или чтения из памяти по такому-то адресу, это событие логировалось. Или смотреть статистику, какие функции с какими аргументами вызываются)

Так вот, вопрос: какие могут быть сложности в реализации всего вышеописанного? Имеет ли смысл создавать такую систему метапрограммирования поверх C (если нет, то поверх чего)? В каких-нибудь языках программирования без сборки мусора, с ручным управлением памятью и с возможностью компилировать в нативный код (без всяких там интерпретаторов) уже реализовано подобное? Желательна так же возможность прямой работы с памятью, с сырыми указателями. Вообще, все это напоминает какой-то лисп, но лисп мне не подходит по вышеобозначенным критериям.

 , , , ,

SZT
()

strace не ловит вызовы gettimeofday, clock_gettime

Сабж. Пример кода:

#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <inttypes.h>

inline uint64_t gettime1(void)
{
  struct timespec tm;
  clock_gettime(CLOCK_REALTIME, &tm);
  return (uint64_t)tm.tv_sec * 1000000000ull + tm.tv_nsec;
}

inline uint64_t gettime2(void)
{
  struct timeval tm;
  gettimeofday(&tm, NULL);
  return (tm.tv_sec * 1000000 + tm.tv_usec) * 1000ULL;
}

int main(void)
{
  uint64_t b = gettime2();
  uint64_t a = gettime1();
  printf("%"PRIu64"\n""%"PRIu64"\n", a, b);
  return 0;
}
Система Linux user-MS-7519 3.13.0-49-generic #83-Ubuntu SMP Fri Apr 10 20:11:33 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

Выхлоп strace

strace -c ./a.out 
1433046804438570051
1433046804438568000
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 28.99    0.000040           5         8           mmap
 17.39    0.000024           6         4           mprotect
 13.04    0.000018           6         3         3 access
 10.87    0.000015           8         2           write
  7.97    0.000011           6         2           open
  7.97    0.000011          11         1           munmap
  5.80    0.000008           3         3           fstat
  2.90    0.000004           2         2           close
  2.17    0.000003           3         1           read
  1.45    0.000002           2         1           arch_prctl
  0.72    0.000001           1         1           brk
  0.72    0.000001           1         1           execve
------ ----------- ----------- --------- --------- ----------------
100.00    0.000138                    29         3 total

В чем может быть проблема?

 ,

SZT
()

Определение модели процессора через JS в браузере

Прочитал тут недавно новость http://www.opennet.ru/opennews/art.shtml?num=42092 и задумался, а можно ли через браузер, посредством подсовывания ему какого-нибудь javascript кода и мерянья скорости выполнения, определить модель процессора, если точно известна версия браузера и ОС? И решил я сделать такой бенчмарк, взял уже написанную сортировку пузырьком на жабаскрипте, приделал измерение времени через Date.now() и начал тестить в разных браузерах пока что на одном и том же железе. http://dump.bitcheese.net/files/yxegyly/browsertest2.html вот что получилось. Обнаружил, что Chromium через несколько последовательных запусков пытается «оптимизировать» эту сортировку, отчего она работает медленее, и время становится устойчиво бОльшим. Эту «оптимизацию» можно вызвать после нажатия run 10. Потом можно много раз жать run 1 или run 10, без разницы. Перезагрузка страницы через F5 сбрасывает эту «оптимизацию» и скорость опять становится нормальной

Например до «оптимизации»: 3875 3875 3871 3880 3872

После «оптимизации»: 4358 4357 4352 4353 4352

Тут даже на глаз видно отличие матожидания для этих двух независимых выборок, без всяких там t-критериев Стьюдента. В Firefox тоже иногда происходит «замедление»

Вопросы: Что надо написать на Javascript, чтобы по замерам времени выполнения этого «чего-то» можно было бы как можно точнее определить модель процессора, который это «что-то» выполняет? Желательно чтобы jit оптимизации не меняли скорость работы спустя какое-то время, и чтобы скорость работы этого кода минимально отличалась от браузера к браузеру в пределах одного «железа». И насколько вообще реально определить модель процессора и/или например частоту оперативной памяти и системной шины таким способом?

 , ,

SZT
()

Функция, возвращающая указатель на функцию такого же типа

Возможно ли в C или C++ сделать чтобы функция возвращала (или например принимала в качестве аргументов) указатель на функцию такого же типа, что у нее самой?

Вариант

typedef funct * (*funct)(void);
не работает.

 , ,

SZT
()

Баг в gdk-pixbuf при открытии обрезанного png

Есть один баг в либе gdk-pixbuf. Проявляется он в том, что если сделать укороченный png (т.е. просто убрать часть байт с конца файла) и потом открыть его какой-нибудь gtk-шной гляделкой картинок (проверено в risetto и eog, баг еще проявляется в pidgin, если такой png поставить аватаркой) то в области, соответствующей той части, которую отрезали от файла, будет всякий мусор. Этим мусором часто оказывается кусок другой картинки, которую перед этим просматривали. При некоторых условиях программа просто падает.

Про баг я отрепортил еще в 2013 году, но его почему-то так и не пофиксили. Вопрос: насколько этот баг критичный? Похоже что это ошибка типа buffer over-read (как и хорошо известный Heartbleed) но я не могу найти никакого софта, в котором была бы эта бага и чтобы при этом через этот баг можно было что-нибудь ценное дампнуть из памяти. В каких критичных местах этот gdk-pixbuf используется? Может если такой пример софта будет, багу быстрее починят?

 

SZT
()

-----BEGIN RSA PRIVATE KEY----- в прошивке от HP Integrated Lights-Out

Сабж

wget http://www.zlib.net/zpipe.c
gcc -lz zpipe.c -o zpipe
wget http://pingtool.org/downloads/ilo195.bin
dd if=ilo195.bin of=out1 bs=1 skip=78000
./zpipe -d < out1 > outdecode1
dd if=ilo195.bin of=out2 bs=1 skip=165508
./zpipe -d < out2 > outdecode2 
Оффсеты 78000 и 165508 вычислены исходя из расположения последовательности двух байт 0x78 0x9C после чего я пытался это распаковать. Если воспользоваться вышеприведенным скриптом, в outdecode2 можно обнаружить BEGIN RSA PRIVATE KEY и еще какие-то куски веб-интерфейса. Это вообще нормальная практика, засовывать PRIVATE KEY в прошивку, которую при желании можно вот так распаковать? Для чего оно там нужно?

 

SZT
()

смысл функции ftok()

Есть такая функция key_t ftok(const char *pathname, int proj_id) , которая генерирует IPC ключ на основе пути к какому-то обязательно существующему файлу и значению proj_id

Какой смысл в этом? Почему файл должен обязательно существовать? Если ftok просто считает некий хеш от пути к файлу и proj_id и возвращает его как key_t, какое ему дело до того, есть там файл по этому пути или нет? Или он учитывает время создания файла, права доступа, владельца и прочие характеристики? Если да, то какие характеристики файла могут влиять на то, какой ключ будет сгенерирован? И зачем вообще опираться при генерации IPC ключа на некий файл в файловой системе?

 , ftok,

SZT
()

Безопасное использование функции alloca и определение размера стека

В C есть функция alloca, выделяющая память на стеке. Эта память автоматически освобождается при выходе из функции. При выделении чрезмерного количества памяти, происходит переполнение стека. Есть ли способ узнать, сколько памяти можно выделить в стеке? Хочется сделать что-то вроде такого:

if(в_стеке_хватит_места_чтобы_сделать_alloca(столько-то_байт) )
  tmp = alloca(столько-то_байт);
else
{
  tmp = malloc(столько-то_байт);
  if (tmp == NULL) 
    error();
  needfreetmp = 1;
}
...
какой-то_код;
...
if (needfreetmp)
  free(tmp)
И есть ли стандартный способ увеличить стек, например выделив достаточно большой кусок памяти через malloc, перекопировать туда весь используемый стек, переставить регистры EBP и ESP и дальше работать с этой памятью как со стеком?

 , , ,

SZT
()

Хеллоуворлд на С из ассемблерных вставок

Здравствуйте. Я тут попробовал сделать сабж, столкнулся с некоторым не совсем понятным явлением. Вот этот код под 64 бит

const char msg[] = {'H','e','l','l','o',',',' ','W','o','r','l','d','\n'};
const char sz = sizeof(msg);

void _start(void)
{
  asm volatile (
  "mov $1,  %%rax\n\t" //  1 - SYS_write
  "mov $1,  %%rdi\n\t" //  1 - STDOUT_FILENO
  "mov %0,  %%rsi\n\t" // msg
  "mov %1,  %%rdx\n\t" // size
  "syscall\n"
  :
  : "g" (msg), "g" (sz)
  : "%rsi", "%rdx"
  );
  
  
  asm volatile (
  "mov $60, %rax\n\t" // 60 - SYS_exit
  "mov $0,  %rdi\n\t" //  0 - EXIT_SUCCESS
  "syscall\n");
  __builtin_unreachable();
}
компилируется таким образом: gcc -O3 -nostartfiles -nostdlib -o hello hello.c и работает нормально.

Если же вынести объявление-инициализацию переменных в _start :


void _start(void)
{
  const char msg[] = {'H','e','l','l','o',',',' ','W','o','r','l','d','\n'};
  const char sz = sizeof(msg);
  asm volatile (
  "mov $1,  %%rax\n\t" //  1 - SYS_write
  "mov $1,  %%rdi\n\t" //  1 - STDOUT_FILENO
  "mov %0,  %%rsi\n\t" // msg
  "mov %1,  %%rdx\n\t" // size
  "syscall\n"
  :
  : "g" (msg), "g" (sz)
  : "%rsi", "%rdx"
  );
  
  
  asm volatile (
  "mov $60, %rax\n\t" // 60 - SYS_exit
  "mov $0,  %rdi\n\t" //  0 - EXIT_SUCCESS
  "syscall\n");
  __builtin_unreachable();
}
никакого текста не выводится.

gcc version 4.5.1 20101208

Почему так?

 , , ,

SZT
()

RSS подписка на новые темы