符号&数组名&变量

来源:互联网 发布:中国柬埔寨关系 知乎 编辑:程序博客网 时间:2024/05/03 10:13

    最近在将一个图片内置到程序中时,遇到了符号相关的问题,下面是将图片内置到程序中的方法:

1、  使用objcopy将图片转化成elf格式的目标文件:objcopy -I binary -O elf32-i386 -B i386 test.jpgimage.o 

2、  查看目标文件中的符号,objdump、readelf、nm均可,符号_binary_test_jpg_start是数据开始的地址,_binary_test_jpg_end是数据结束的地址, _binary_test_jpg_size是数据字节数。

3、  使用符号对图片数据进行操作

插一句,这种方法相比于将图片转换成数组更加灵活,可以方便地更换图片,缺点是没有可移植性。


    运行程序的时候出现了segment fault,原因是我在引用image.o的符号时声明错误:

extern char *_binary_test_jpg_start;

extern char  *_binary_test_jpg_end;

extern int _binary_test_jpg_size;


   正确的声明应该这样:

extern char _binary_test_jpg_start[];

extern char _binary_test_jpg_end[];

extern char _binary_test_jpg_size[];

 

下面深入研究下错误的原因:符号是如此定义的:

Typedef struct  {

Elf32_Word st_name;

    Elf32_Addr st_value;

    Elf32_Word st_size;

    Unsigned char st_info;

    Unsigned char st_other;

    Elf32_Half st_shndx;

} Elf32_Sym;

        符号指代的值是st_value,符号的值的类型取决于符号的类型(st_info),可能是一个地址值,也可能是一个绝对值。我们可以”readelf –s image.o”看下符号类型,可以看到里面的_binary_test_jpg_start 、_binary_test_jpg_end、_binary_test_jpg_size 都是NOTYPE,为未知符号类型(还有OBJECT数据对象、FUNC函数等)。

       再回到上面的那个错误,当将符号声明为指针的时候(extern char  *symbol_name),在使用的时候,连接器会取该符号的st_value做为指针symbol_name的地址值,该地址值对应的数据既为该变量的值。当将符号声明为数组的时候(extern char  symbol_name[]),symbol_name既为st_value的值。既:如若声明为数组,_binary_test_jpg_start[0]相当st_value[0],既图片的第一个字节;若声明为指针,相当于(*st_value)[0],自然会出现segment default了~


      简单概括下数组名与变量以及符号的关系:

          1、  全局的变量及数组,编译后产生的elf格式可执行文件(linux)会有相应的符号记录在符号表中。

          2、  变量的值即是该变量编译后对应符号值所指向的值(*(st_value)),其地址是对应符号的值st_value。

          3、  数组名的值就是对应符号的值st_value,我们想要使用符号的值的时候,声明为数组名即可。数组名是指针的说法不正确,不过我们当然可以将数组名指代的值赋值给指针。

0 0