您的位置:首页 > 其它

链接脚本使用一例2---将二进制文件 如图片、MP3音乐、词典一类的东西作为目标文件中的一个段

2014-05-11 11:35 507 查看
参考文章:

《程序员的自我修养——链接、转载与库》P68

这里介绍两种方法,实现将将一张图片作为二进制可执行程序的一个段,其中第一种方法在我之前的博客中已经有所介绍,不过,那是采用的是交叉编译的方法,这次直接全部在PC机上完成;第二种方法是我在看上面的那本书的时候看到的,觉着也不错。

环境介绍:Win7+VirtualBox+Debian6+gccversion4.4.5(Debian4.4.5-8)

第一种方法

目录结构

pengdl@debian:~/test/c/pic2$tree-lh
.
|--[135]data.S
|--[811]main.c
|--[91]Makefile
`--[134K]peng.png

0directories,4files

data.S

.section.piggydata,"a".globlinput_datainput_data:.incbin"/home/pengdl/test/c/pic2/peng.png".globlinput_data_endinput_data_end:


这里需要注意:

这段代码是我直接从Linux内核中拷贝出来的,并做了修改,源文件如下(arch/arm/boot/compressed/piggy.S):

.section.piggydata,#alloc.globlinput_datainput_data:.incbin"arch/arm/boot/compressed/piggy.gz".globlinput_data_endinput_data_end:


但是上面的代码除了需要修改.incbin之外,第一行的段属性部分也需要修改,将"#alloc"修改为"a",意思是:这个段可以重定位。如果不加段属性"a",运行时会发生段错误:

[code]pengdl@debian:~/test/c/pic2$./main


input_data=(nil)


input_data_end=0x2187e


size=0x2187e




Segmentationfault

[/code]

使用objdump工具可以看看为什么?

先看看data.o:

[code]pengdl@debian:~/test/c/pic2$objdump-htdata.o




data.o:fileformatelf32-i386




Sections:


IdxNameSizeVMALMAFileoffAlgn


0.text000000000000000000000000000000342**2


CONTENTS,ALLOC,LOAD,READONLY,CODE


1.data000000000000000000000000000000342**2


CONTENTS,ALLOC,LOAD,DATA


2.bss000000000000000000000000000000342**2


ALLOC


3.piggydata0002187e0000000000000000000000342**0


CONTENTS,READONLY


SYMBOLTABLE:


00000000ld.text00000000.text


00000000ld.data00000000.data


00000000ld.bss00000000.bss


00000000ld.piggydata00000000.piggydata


00000000g.piggydata00000000input_data


0002187eg.piggydata00000000input_data_end

[/code]

再看看main:

[code]pengdl@debian:~/test/c/pic2$objdump-htmain|grepinput_data


0002187eg.piggydata00000000input_data_end


00000000g.piggydata00000000input_data

[/code]

从data.o的objdump信息可以看到,它的.piggydata是不能重定位的,再看看main的信息,input_data的地址直接就是0,在main.c中会发生访问0地址的段错误!!从main的运行打印信息中也可以看到:input_data=(nil)

把.piggydata的段属性重新设置为"a",再看看objdump信息:

[code]pengdl@debian:~/test/c/pic2$objdump-htdata.o




data.o:fileformatelf32-i386




Sections:


IdxNameSizeVMALMAFileoffAlgn


0.text000000000000000000000000000000342**2


CONTENTS,ALLOC,LOAD,READONLY,CODE


1.data000000000000000000000000000000342**2


CONTENTS,ALLOC,LOAD,DATA


2.bss000000000000000000000000000000342**2


ALLOC


3.piggydata0002187e0000000000000000000000342**0



CONTENTS,ALLOC,LOAD,READONLY,DATA
SYMBOLTABLE:


00000000ld.text00000000.text


00000000ld.data00000000.data


00000000ld.bss00000000.bss


00000000ld.piggydata00000000.piggydata


00000000g.piggydata00000000input_data


0002187eg.piggydata00000000input_data_end

[/code]


[code]pengdl@debian:~/test/c/pic2$objdump-htmain|grepinput_data


08069e63g.piggydata00000000input_data_end


080485e5g.piggydata00000000input_data

[/code]

可以看到,这下信息就正常了。

main.c



[code]#include<stdio.h>




intmain(intargc,constchar*argv[])


{


inti;




externconstunsignedlonginput_data;


externconstunsignedlonginput_data_end;




constunsignedchar*start=(constunsignedchar*)&input_data;


constunsignedchar*end=(constunsignedchar*)&input_data_end;


unsignedlongsize=end-start;




printf("input_data=%p\n",&input_data);


printf("input_data_end=%p\n",&input_data_end);


printf("size=%#0x\n",size);








for(i=0;i<size;i++)


{


if(i%16==0)


{


printf("\n%0#x\t\t",i);


}


printf("%3x",start[i]);


}




printf("\n");






return0;


}

[/code]

需要注意的是:如何使用data.S中的标号。

Makefile



[code]main:main.odata.o


$(CC)$^-o$@




data.o:data.S




main.c:main.o






clean:


$(RM)*.omain

[/code]

peng.png就是一张普通的文件,与图片的格式无关。

下面是运行结果:

pengdl@debian:~/test/c/pic2$./main
input_data=0x80485e5//数值跟main的objdump信息是一致的

input_data_end=0x8069e63

size=0x2187e//注意指针相减的含义

0089504e47da1aa000d49484452

0x10001280018982000b62539

0x20500097048597300ec400e

0x30c41952be1b002004944415478da

0x40ecbd675f2359b2afdb1febeeb3a7bbc

0x50dea7921bc24bc40de23efbdf0de4351

0x60a6ed9cfb1ef3f56642ea54d53367df

0x7017735e54fe9ed1242211a22b1f45c4b2

0x803f7dfeeb4ff0edafbf7af8e3cfafbfff

0x90c1e09cf9f2dbef2fdf7e7d7cf9fcf0e9

0xa05dc3e3e5ddddd9f5fdf9c5e5e9d5c5c

0xb082e3cbcba3f3abc3b3cb83b3b3fdd353

0xc0a67d7cdc3e3c681decb73a6dd0deefb4

下面是用winhex看到的:





第二种方法

使用objcopy工具

目录结构:

pengdl@debian:~/test/c/pic$tree-lh

.

|--[999]main.c

|--[77]Makefile

|--[135K]peng.o

`--[134K]peng.png

0directories,4files

peng.o

使用如下命令生成peng.o:

objdcopy–Ibinary–Oelf32-i386–Bi386peng.pngpeng.o

objdump–htpeng.o

参数解释:

-I--input-target<bfdname>Assumeinputfileisinformat<bfdname>

-O--output-target<bfdname>Createanoutputfileinformat<bfdname>

-B--binary-architecture<arch>Setarchofoutputfile,wheninputisbinary

-h,--[section-]headersDisplaythecontentsofthesectionheaders

-t,--symsDisplaythecontentsofthesymboltable(s)



[code]pengdl@debian:~/test/c/pic$objdump-htpeng.o




peng.o:fileformatelf32-i386




Sections:


IdxNameSizeVMALMAFileoffAlgn


0.data0002187e0000000000000000000000342**0



CONTENTS,ALLOC,LOAD,DATA
SYMBOLTABLE:


00000000ld.data00000000.data


00000000g.data00000000_binary_peng_png_start


0002187eg.data00000000_binary_peng_png_end


0002187eg*ABS*00000000_binary_peng_png_size

[/code]

符号“_binary_peng_png_start”、“_binary_peng_png_end”和“_binary_peng_png_size”分别表示该图片文件在内存中的起始地址、结束地址和大小。

可以看到,图片数据被放到了.data段。

main.c



[code]#include<stdio.h>




intmain(intargc,constchar*argv[])


{


inti;




externconstunsignedlong_binary_peng_png_start;


externconstunsignedlong_binary_peng_png_size;


externconstunsignedlong_binary_peng_png_end;




constunsignedchar*start=(constunsignedchar*)&_binary_peng_png_start;


constunsignedlongsize=(constunsignedlong)&_binary_peng_png_size;


constunsignedchar*end=(constunsignedchar*)&_binary_peng_png_end;




printf("_binary_peng_png_start=%p\n",&_binary_peng_png_start);


printf("_binary_peng_png_size=%p\n",&_binary_peng_png_size);


printf("_binary_peng_png_end=%p\n",&_binary_peng_png_end);








for(i=0;i<size;i++)


{


if(i%16==0)


{


printf("\n%0#x\t\t",i);


}


printf("%3x",start[i]);


}




printf("\n");






return0;


}

[/code]

Makefile



[code]main:main.openg.o


$(CC)$^-o$@




main.c:main.o






clean:


$(RM)*.omain

[/code]

下面是运行结果:

pengdl@debian:~/test/c/pic$./main
_binary_peng_png_start=0x80496f4

_binary_peng_png_size=0x2187e

_binary_peng_png_end=0x806af72

089504e47da1aa000d49484452

0x10001280018982000b62539

0x20500097048597300ec400e

0x30c41952be1b002004944415478da

0x40ecbd675f2359b2afdb1febeeb3a7bbc

0x50dea7921bc24bc40de23efbdf0de4351

0x60a6ed9cfb1ef3f56642ea54d53367df

0x7017735e54fe9ed1242211a22b1f45c4b2

0x803f7dfeeb4ff0edafbf7af8e3cfafbfff

0x90c1e09cf9f2dbef2fdf7e7d7cf9fcf0e9

0xa05dc3e3e5ddddd9f5fdf9c5e5e9d5c5c

。。。。。。

完!!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: