LINUX.ORG.RU

Упаковать блоб в ro data секцию ELF и PE

 , , ,


4

0

Имеются табличные данные, объемом с десяток мегабайт. Хочется таскать их прямо в исполнимом файле, влинкованными.

Самый простой вариант — вывалить данные в исходник на Си вида «const char my_data[] = {0x4, 0x9, 0x10, 0x3, ....};» и прогнать через компилятор и линковщик. Если бы табличка была размером в пару килобайт, я на этом бы и успокоился. Но вот поступать так с десятком мегабайт? Существует для этого какой-то менее костыльный способ?

★★★★★

Последнее исправление: Manhunt (всего исправлений: 2)

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

devl547 ★★★★★
()

Сгенерируй таким костылем 1 раз объектный файл, а потом уже прилинковывай его. Или библиотечку запили.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Manhunt

И что, таки будешь переименовывать .data в .rodata как сделал автор по ссылке?

anonymous
()

так и делай.

тока не ручками.

qulinxao ★★☆
()

Упаковываешь в .zip и пришпандориваешь к бинарнику. В коде ищешь смещение начала архива и распаковываешь.

anonymous
()

Ещё можешь использовать директиву gas .incbin.

Из бонусов — сразу можно указать нужную секцию.

.section .rodata;.incbin foo.txt

или, в си

asm(".section .rodata;.incbin foo.txt");
anonymous
()
Ответ на: комментарий от Manhunt

Продублирую рецепт тут, на случай, если бложик по ссылке прикажет долго жить:

$ echo 'Hello, World!' > foo.txt
$ ld -r -b binary -o foo.o foo.txt
$ objdump -x foo.o
foo.o: file format elf32-i386

Sections:
Idx Name Size VMA LMA File off Algn
0 .data 0000000d 00000000 00000000 00000034 2**0
CONTENTS, ALLOC, LOAD, DATA
SYMBOL TABLE:
00000000 l d .data 00000000 .data
0000000d g .data 00000000 _binary_foo_txt_end
0000000d g *ABS* 00000000 _binary_foo_txt_size
00000000 g .data 00000000 _binary_foo_txt_start

Manhunt ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Да, это тоже вариант. Благодарю.

Manhunt ★★★★★
() автор топика
Ответ на: комментарий от FIL

Если данные используются для случайного доступа, то если их пожать объём гарантированно увеличится, потому что в памяти тогда будут храниться и сжатые и разжатые данные.

В оригинальном сообщении написано «хочется таскать», поэтому правильное решение тут ровно одно - этот бред должен перестать хотеться. Храните данные как отдельный файл с данными.

slovazap ★★★★★
()

В культях для этого есть даже компилятор ресурсов uic и URI-схема ":/file.ext", позволяющая получить доступ к файлам во «внутреннем хранилище» исполнительного файла.

Кросс-платформенно, в Android/iOS тоже такой подход работает.

EXL ★★★★★
()
Ответ на: комментарий от slovazap

Храните данные как отдельный файл с данными.

Проблема в том, что это:
1. Усложняет дистрибуцию. Одинокостоящий elf/pe можно просто поставлять «как есть». А если нужно поставлять россыпь файлов, то придётся их опакечивать (rpm, deb, msi, и еще целый зоопарк креативных высеров дистростроения).
2. Влечет необходимость вручную делать mmap на файл с данными. Вызова mmap в стандарте Си нет, и придётся рожать платформо-специфичный код. Можно, конечно, сделать fread, но по ублюдочности такое решение мало отличается от предложений что-то там разархивировать во время запуска программы.

Manhunt ★★★★★
() автор топика
Последнее исправление: Manhunt (всего исправлений: 3)
Ответ на: комментарий от anonymous

objres: command not found

Хотелось бы ограничиться чем-то из состава официальных binutils или gcc, без лишних приключений.

Manhunt ★★★★★
() автор топика
Последнее исправление: Manhunt (всего исправлений: 1)
Ответ на: комментарий от Manhunt

1. Усложняет дистрибуцию. Одинокостоящий elf/pe можно просто поставлять «как есть». А если нужно поставлять россыпь файлов, то придётся их опакечивать (rpm, deb, msi, и еще целый зоопарк креативных высеров дистростроения).

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

2. Влечет необходимость вручную делать mmap на файл с данными. Вызова mmap в стандарте Си нет

mmap есть в POSIX, точка.

Можно, конечно, сделать fread, но по ублюдочности

Depends. Если программа будет вызываться в одном экземпляре и делать много random access к этим данным, от mmap профита не будет никакого, и fread только ускорит выполнение, потому что все данные сразу будут в памяти.

Ну и если уж на то пошло, в чём проблема со способом предложенным в первом посте и какая разница сколько данных запихнуть в бинарник как const char my_data[], килобайт или сотню мегабайт?

slovazap ★★★★★
()
Ответ на: комментарий от slovazap

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

У меня нет денег, чтобы оплатить их труд. И нет жажды общения, достаточной, чтобы уболтать их всех проделать эту работу безвозмездно.

Если это слишком сложно для понимания, разницы всё равно нет - если вы считаете что вам нужно что-то опакечивать, то одинокий бинарник вам нужно опакечивать точно также.

Одинокий бинарник опакечивать не обязательно. Все, кому он интересен, смогут запустить его прямо из директории Downloads/ {нудное бла-бла-бла про mount noexec поскипано}

Тем более вы говорили об одном файле, а не россыпи.

Речь как раз о том, чтобы остаться в рамках одного-единственного файла.

Если программа будет вызываться в одном экземпляре и делать много random access к этим данным, от mmap профита не будет никакого, и fread только ускорит выполнение, потому что все данные сразу будут в памяти.

Разница в цене swap out.

Ну и если уж на то пошло, в чём проблема со способом предложенным в первом посте и какая разница сколько данных запихнуть в бинарник как const char my_data[], килобайт или сотню мегабайт?

Не хочу заниматься тестированием компиляторного парсера под нетипичной для него нагрузкой. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=29087

Manhunt ★★★★★
() автор топика
Последнее исправление: Manhunt (всего исправлений: 1)
Ответ на: комментарий от Manhunt

Дык, я ведь и не спорю, что можно и по другому. ;) Ты спросил, как упаковать любые бинарные данные в C-сырцы, я тебе указал на готовую тулзу. И без плясок с objdump — т.е. полностью платформонезависимо. А кило- или мега-байты — это уже без разницы.

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 2)
Ответ на: комментарий от beastie

полностью платформонезависимо

file2c: command not found

Ты спросил, как упаковать любые бинарные данные в C-сырцы

Ты невнимательно прочитал вопрос: я спрашивал, как обойтись без подобных костылей.

Manhunt ★★★★★
() автор топика
Последнее исправление: Manhunt (всего исправлений: 1)
Ответ на: комментарий от Manhunt

У меня нет денег, чтобы оплатить их труд. И нет жажды общения, достаточной, чтобы уболтать их всех проделать эту работу безвозмездно.

Зачем им платить? Софт попадает в дистрибутивы сам, если он кому-то нужен. Если не нужен, то зачем ты его пишешь? Или, погоди, может у тебя проприетарщина?

Одинокий бинарник опакечивать не обязательно. Все, кому он интересен, смогут запустить его прямо из директории Downloads/

Разницы между бинарником и архивом с бинарником и данными нет.

Разница в цене swap out.

Разве что.

Не хочу заниматься тестированием компиляторного парсера под нетипичной для него нагрузкой.

Не занимайся - просто возьми и собери. Оно или соберётся или нет. Если соберётся то что вообще обсуждать?

slovazap ★★★★★
()
Ответ на: комментарий от Manhunt
objcopy --input binary --output elf32-i386 --binary-architecture i386 file.bin file.o

Прилинковываешь file.o. В основном коде пишешь

extern char _binary_file_bin_start;
extern char _binary_file_bin_end;
...
char *p = &_binary_file_bin_start;

while(p++ != &_binary_file_bin_end)
{
   ... читаем байт данных из *p ...
}

С архитектурами сам разберёшься.

alex_custov ★★★★★
()
Последнее исправление: alex_custov (всего исправлений: 2)
Ответ на: комментарий от slovazap

Софт попадает в дистрибутивы сам, если он кому-то нужен.

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

Если не нужен, то зачем ты его пишешь?

Just for fun же.

Или, погоди, может у тебя проприетарщина?

gplv3

Разницы между бинарником и архивом с бинарником и данными нет.

Упаковать блоб в ro data секцию ELF и PE (комментарий)

Manhunt ★★★★★
() автор топика
Ответ на: комментарий от Manhunt

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

Госпади.... сделайте установщик, который делает make install (хотя за такое надо руки отрывать, но раз уж вы не хотите делать нормальные пакеты это выход). Просто bash скрипт внутри которого ваша прога целиком (я такое порно видел пару раз) в виде переменных и пара команд типа

echo $pron > ./myprogram.bin

mv ./myprogram.bin /opt/pron

А вообще запаковываете вашу прогу, вместе со всякими другими файлами, в архив и не совокупляетесь с головным мозгом окружающих.

RiseOfDeath ★★★★
()
Последнее исправление: RiseOfDeath (всего исправлений: 2)
Ответ на: комментарий от Manhunt

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

Для этого есть git clone && cmake . && make ( && make install ). Никакой бинарник никогда не будет «тем что может беспрепятственно запуститься у того кому он интересен», потому что разные дистрибутивы, системы и архитектуры. Или ты собрался собирать бинарники в том числе и под NetBSD/armv6?

Упаковать блоб в ro data секцию ELF и PE (комментарий)

Я же вроде ясно написал что это бред.

slovazap ★★★★★
()
Последнее исправление: slovazap (всего исправлений: 1)
Ответ на: комментарий от Manhunt

Ради того, что бы не делать по-нормальному - упаковать в пакет, или хотя бы в архив.

RiseOfDeath ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.