После прочтения статьи (что не обязательно; ваш вопрос должен стоять сам по себе), мне не ясно, как определяются массивы. В статье используется
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.