Встраивание любого файла в скомпилированную программу g cc и доступ к нему внутри программы - PullRequest
0 голосов
/ 16 января 2020

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

Program.c compile with picture.jpg
Program is now the output file that has picture.jpg inside of it
Program runs and then creates a new file called pic.jpg
Program reads somewhere(?) in its own code to find the data of the picture.jpg
Program writes the data to pic.jpg
Now pic.jpg and picture.jpg are the same file.

Я немного прочитал и нашел небольшую статью, которая объясняет это: https://codeplea.com/embedding-files-in-c-programs

Наверх «Альтернатива - прямое связывание блоба»

Вопрос, который у меня возникает, как

extern const char binary_some_file_jpg_start[];
extern const char binary_some_file_jpg_end[];

говорит мне, где мои данные есть? Могли ли это быть случайные имена, и он все еще знает, где go найти данные?

1 Ответ

2 голосов
/ 16 января 2020

После прочтения статьи (что не обязательно; ваш вопрос должен стоять сам по себе), мне не ясно, как определяются массивы. В статье используется

gcc -c my_program.c -o my_program.o
ld -r -b binary -o some_file.o some_file.jpg
gcc my_program.o some_file.o -o my_program

для встраивания файла JPG some_file.jpg в объектный файл (some_file.o).

Обложки руководства GNU ld -b binary. Опытным путем, после создания (двоичного) объектного файла из image.jpg, вы получите некоторые определенные символы:

$ ld -r -b binary -o image.o image.jpg
$ nm image.o
00000000000442d0 D _binary_image_jpg_end
00000000000442d0 A _binary_image_jpg_size
0000000000000000 D _binary_image_jpg_start
$

Результатом операции ld -r -b binary … является «объектный файл», в котором определены три символа, и содержит один раздел .data и определяет три символа. Имена символов определяются по ld из имени двоичного файла, который он дается для обработки.

$ objdump -h image.o

image.o:     file format elf64-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .data         000442d0  0000000000000000  0000000000000000  00000040  2**0
                  CONTENTS, ALLOC, LOAD, DATA
$ objdump -t image.o

image.o:     file format elf64-x86-64

SYMBOL TABLE:
0000000000000000 l    d  .data  0000000000000000 .data
0000000000000000 g       .data  0000000000000000 _binary_image_jpg_start
00000000000442d0 g       .data  0000000000000000 _binary_image_jpg_end
00000000000442d0 g       *ABS*  0000000000000000 _binary_image_jpg_size

$

Обратите внимание, что эти символы имеют подчеркивание в начале. Вы можете использовать этот код для распечатки адресов и т. Д. c. Обратите внимание, что он использует квалификатор t для типа ptrdiff_t - это тип результата вычитания двух указателей:

#include <stdio.h>

extern char _binary_image_jpg_start[];
extern char _binary_image_jpg_end[];

int main(void)
{
    printf("Image start: %p\n", _binary_image_jpg_start);
    printf("Image end:   %p\n", _binary_image_jpg_end);
    printf("Image size:  0x%tx\n", _binary_image_jpg_end - _binary_image_jpg_start);
    return 0;
}

Пример вывода:

$ gcc -o image main.c image.o
$ ./image
Image start: 0x6008e8
Image end:   0x644bb8
Image size:  0x442d0
$

Рассчитанный размер изображения соответствует размеру, указанному nm image.o. Таким образом, код может go для чтения данных из массива _binary_image_jpg_start.

Это зависит от особенностей кода программы GNU ld. Он может не работать с любым другим ld - если программа не эмулирует GNU ld.

Демо, созданное на античном RHEL 5 (2.6.18-128.el5 # 1 SMP, от 2008-12-17) с использованием G CC 9.2.0 и GNU ld (GNU Binutils) 2.25.1.

...