链接脚本使用----- 将二进制文件作为一个段
2014-03-13 20:10
302 查看
在分析Linux内核编译流程的时候,看到arch/arm/boot/compressed/piggy.gzip.S将压缩后的Linux内核(arch/arm/boot/compressed/piggy.gzip)包含进来:
[/code]
[/code]
我们是不是也可以利用这种方法将一副图片作为可执行程序的一个段,然后再程序中访问这个段来达到显示图片的目的?下面是我的做法:
![](http://images.cnitblog.com/blog/480488/201403/132010016901344.png)
仿照piggy.gzip.S实现demo.S:
[/code]
[/code]
main.c
[/code]
Makefile
[/code]
load.lds
[/code]
下面是运行main的结果:
![](http://images.cnitblog.com/blog/480488/201403/132010055363170.png)
用winhex打开logo.jpg可以看到如下:
![](http://images.cnitblog.com/blog/480488/201403/132010096653210.png)
可以看到二者是一致的。(29626 = 0x73BA)
[code] [code] .section .piggydata,#alloc
.globl input_data
t_data:
.incbin "arch/arm/boot/compressed/piggy.gzip"
.globl input_data_end
t_data_end:
[/code]
[/code]
我们是不是也可以利用这种方法将一副图片作为可执行程序的一个段,然后再程序中访问这个段来达到显示图片的目的?下面是我的做法:
![](http://images.cnitblog.com/blog/480488/201403/132010016901344.png)
仿照piggy.gzip.S实现demo.S:
[code] [code] .section .peng
.incbin "./logo.jpg"
[/code]
[/code]
main.c
[code] #include <stdio.h>
extern unsigned int __peng_start;
extern unsigned int __peng_end;
char *p = (char *)(&__peng_start);
//我们要获取__peng_start的存放地址,作为字符串首地址,或者数组名来使用。
int main(int argc, const char *argv[])
{
int i;
unsigned int len = 0;
len = (unsigned int)(&__peng_end) - (unsigned int)(&__peng_start);
printf("len = %x\n", len);
printf("%p\n", &__peng_start);
printf("%p\n", &__peng_end);
for(i=0; i<len; i++)
{
if (i % 16 == 0)
{
printf("\n");
}
printf("%3x ", *p++&0xff);
}
return 0;
}
[/code]
Makefile
[code] CC=gcc -Wall
main:main.o demo.o
$(CC) $^ -Tload.lds -o $@
main.o:main.c
demo.o:demo.S
clean:
$(RM) *.o main
[/code]
load.lds
[code] OUTPUT_FORMAT("elf32-i386", "elf32-i386",
"elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(_start)
SEARCH_DIR("/usr/i486-linux-gnu/lib32"); SEARCH_DIR("/usr/local/lib32"); SEARCH_DIR("/lib32"); SEARCH_DIR("/usr/lib32"); SEARCH_DIR("/usr/i486-linux-gnu/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");
SECTIONS
{
/* Read-only sections, merged into text segment: */
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x08048000)); . = SEGMENT_START("text-segment", 0x08048000) + SIZEOF_HEADERS;
.interp :{ *(.interp)}
.note.gnu.build-id :{ *(.note.gnu.build-id)}
.hash :{ *(.hash)}
.gnu.hash :{ *(.gnu.hash)}
.dynsym :{ *(.dynsym)}
.dynstr :{ *(.dynstr)}
.gnu.version :{ *(.gnu.version)}
.gnu.version_d :{ *(.gnu.version_d)}
.gnu.version_r :{ *(.gnu.version_r)}
.peng :
{
. = ALIGN(4);
__peng_start = .;
*(.peng);
__peng_end = .;
. = ALIGN(4);
}
.rel.dyn :
{
*(.rel.init)
*(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)
*(.rel.fini)
*(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)
*(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*)
*(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
*(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)
*(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)
*(.rel.ctors)
*(.rel.dtors)
*(.rel.got)
*(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)
*(.rel.ifunc)
}
.rel.plt :
{
*(.rel.plt)
PROVIDE_HIDDEN (__rel_iplt_start = .);
*(.rel.iplt)
PROVIDE_HIDDEN (__rel_iplt_end = .);
}
.init :
{
KEEP (*(.init))
} =0x90909090
.plt :{ *(.plt) *(.iplt)}
.text :
{
*(.text.unlikely .text.*_unlikely)
*(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
} =0x90909090
.fini :
{
KEEP (*(.fini))
} =0x90909090
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata :{ *(.rodata .rodata.* .gnu.linkonce.r.*)}
.rodata1 :{ *(.rodata1)}
.eh_frame_hdr :{ *(.eh_frame_hdr)}
.eh_frame : ONLY_IF_RO{ KEEP (*(.eh_frame))}
.gcc_except_table : ONLY_IF_RO{ *(.gcc_except_table .gcc_except_table.*)}
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
/* Exception handling */
.eh_frame : ONLY_IF_RW{ KEEP (*(.eh_frame))}
.gcc_except_table : ONLY_IF_RW{ *(.gcc_except_table .gcc_except_table.*)}
/* Thread Local Storage sections */
.tdata :{ *(.tdata .tdata.* .gnu.linkonce.td.*)}
.tbss :{ *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon)}
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
}
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
}
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
PROVIDE_HIDDEN (__fini_array_end = .);
}
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
}
.jcr :{ KEEP (*(.jcr))}
.data.rel.ro :{ *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*)}
.dynamic :{ *(.dynamic)}
.got :{ *(.got) *(.igot)}
. = DATA_SEGMENT_RELRO_END (12, .);
.got.plt :{ *(.got.plt) *(.igot.plt)}
.data :
{
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
}
.data1 :{ *(.data1)}
_edata = .; PROVIDE (edata = .);
__bss_start = .;
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections.
FIXME: Why do we need it? When there is no .bss section, we don't
pad the .data section. */
. = ALIGN(. != 0 ? 32 / 8 : 1);
}
. = ALIGN(32 / 8);
. = ALIGN(32 / 8);
_end = .; PROVIDE (end = .);
. = DATA_SEGMENT_END (.);
/* Stabs debugging sections. */
.stab 0 :{ *(.stab)}
.stabstr 0 :{ *(.stabstr)}
.stab.excl 0 :{ *(.stab.excl)}
.stab.exclstr 0 :{ *(.stab.exclstr)}
.stab.index 0 :{ *(.stab.index)}
.stab.indexstr 0 :{ *(.stab.indexstr)}
.comment 0 :{ *(.comment)}
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 :{ *(.debug)}
.line 0 :{ *(.line)}
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 :{ *(.debug_srcinfo)}
.debug_sfnames 0 :{ *(.debug_sfnames)}
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 :{ *(.debug_aranges)}
.debug_pubnames 0 :{ *(.debug_pubnames)}
/* DWARF 2 */
.debug_info 0 :{ *(.debug_info .gnu.linkonce.wi.*)}
.debug_abbrev 0 :{ *(.debug_abbrev)}
.debug_line 0 :{ *(.debug_line)}
.debug_frame 0 :{ *(.debug_frame)}
.debug_str 0 :{ *(.debug_str)}
.debug_loc 0 :{ *(.debug_loc)}
.debug_macinfo 0 :{ *(.debug_macinfo)}
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 :{ *(.debug_weaknames)}
.debug_funcnames 0 :{ *(.debug_funcnames)}
.debug_typenames 0 :{ *(.debug_typenames)}
.debug_varnames 0 :{ *(.debug_varnames)}
/* DWARF 3 */
.debug_pubtypes 0 :{ *(.debug_pubtypes)}
.debug_ranges 0 :{ *(.debug_ranges)}
.gnu.attributes 0 :{ KEEP (*(.gnu.attributes))}
/DISCARD/ :{ *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*)}
}
[/code]
下面是运行main的结果:
![](http://images.cnitblog.com/blog/480488/201403/132010055363170.png)
用winhex打开logo.jpg可以看到如下:
![](http://images.cnitblog.com/blog/480488/201403/132010096653210.png)
可以看到二者是一致的。(29626 = 0x73BA)
相关文章推荐
- 链接脚本使用一例2---将二进制文件 如图片、MP3音乐、词典一类的东西作为目标文件中的一个段
- 将PHP作为Shell脚本语言使用
- 如何将PHP作为Shell脚本语言使用
- Gnu arm汇编说明 包括链接脚本文件的使用
- 将PHP作为Shell脚本语言使用
- 链接脚本使用一例1
- 使用XML作为项目的配置文件使用,并解析之,获得数据作为链接数据库的参数
- 在IE中使用Python作为开发脚本(转)
- 如何使用小脚本和表达式链接数据库输出emp表的数据
- 使用XML作为项目的配置文件使用,并解析之,获得数据作为链接数据库的参数
- makefile使用.lds链接脚本以及 $@ ,$^, $,< 解析【转】
- 揪出gcc默认使用的ld链接脚本
- 由迅雷“使用迅雷下载链接”功能引发的JS脚本
- 将PHP作为Shell脚本语言使用
- makefile使用.lds链接脚本以及 $@ ,$^, $,< 解析
- C代码中如何使用链接脚本中定义的变量
- 如何将PHP作为Shell脚本语言使用
- 在IE中使用Python作为开发脚本
- linux上使用脚本排序列出所有TCP链接的本地IP地址
- Groovy 作为系统脚本使用