链接脚本使用一例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
这里需要注意:
这段代码是我直接从Linux内核中拷贝出来的,并做了修改,源文件如下(arch/arm/boot/compressed/piggy.S):
但是上面的代码除了需要修改.incbin之外,第一行的段属性部分也需要修改,将"#alloc"修改为"a",意思是:这个段可以重定位。如果不加段属性"a",运行时会发生段错误:
[/code]
使用objdump工具可以看看为什么?
先看看data.o:
[/code]
再看看main:
[/code]
从data.o的objdump信息可以看到,它的.piggydata是不能重定位的,再看看main的信息,input_data的地址直接就是0,在main.c中会发生访问0地址的段错误!!从main的运行打印信息中也可以看到:input_data=(nil)
把.piggydata的段属性重新设置为"a",再看看objdump信息:
CONTENTS,ALLOC,LOAD,READONLY,DATA
[/code]
[/code]
可以看到,这下信息就正常了。
main.c
[/code]
需要注意的是:如何使用data.S中的标号。
Makefile
[/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看到的:
目录结构:
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)
CONTENTS,ALLOC,LOAD,DATA
[/code]
符号“_binary_peng_png_start”、“_binary_peng_png_end”和“_binary_peng_png_size”分别表示该图片文件在内存中的起始地址、结束地址和大小。
可以看到,图片数据被放到了.data段。
main.c
[/code]
Makefile
[/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
。。。。。。
完!!!
《程序员的自我修养——链接、转载与库》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
。。。。。。
完!!!
相关文章推荐
- 链接脚本使用----- 将二进制文件作为一个段
- 使用流式文件读取或写入图片(jpg,png等)或视频(mp4)或音频(mp3)文件
- 使用SQLite数据库存取mp3和图片等二进制数据
- 使用Python脚本将Bing的每日图片作为桌面的教程
- 使用MediaPlayer控件播放MP3等音乐文件
- 获取MP3和M4A音乐文件的歌曲信息以及专辑图片
- 获取MP3和M4A音乐文件的歌曲信息以及专辑图片--备用
- 使用当前目录作为编译目标/可执行文件名称
- C#使用MediaPlayer控件播放MP3等音乐文件
- 怎样使用链接脚本文件实现分散加载
- 使用XML作为项目的配置文件使用,并解析之,获得数据作为链接数据库的参数
- 使用cxfreeze将python脚本转化二进制可执行文件
- Gnu arm汇编说明 包括链接脚本文件的使用
- 使用连接器ld生成不同格式的二进制目标文件
- 用脚本链接目标文件
- Python脚本--批量更改本地md文件的图片链接
- 使用XML作为项目的配置文件使用,并解析之,获得数据作为链接数据库的参数
- C#/.NET使用MediaPlayer控件播放MP3等音乐文件
- Linux Ubuntu 使用play命令播放音乐 mp3 wav 等文件