已经阅读了这篇文章(这不是必需的;您的问题应该独立存在),我不清楚数组是如何确定的。文章使用
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
$
请注意,这些符号的开头有一个下划线。您可以使用此代码打印出地址等。请注意,它使用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 给出的大小。所以代码可以继续从数组_binary_image_jpg_start中读取数据。
这取决于 GNU ld 程序的代码特性。它可能不适用于任何其他 ld — 除非程序模拟 GNU ld。
使用 GCC 9.2.0 和 GNU ld (GNU Binutils) 2.25.1 在古董 RHEL 5(2.6.18-128.el5 #1 SMP,日期 2008-12-17)上创建的演示。