创建Linux下可运行的超小型ELF可执行文件(3)
来源:互联网 发布:java 18.3 编辑:程序博客网 时间:2024/05/16 16:05
p { margin-bottom: 0.21cm; }
我们的程序本身只有7字节,难道ELF真的需要361字节的额外空间吗?
我们用objdump来看一下文件内容:
$objdump -x a.out | less
让我们看看块列表:
Sections:
IdxName Size VMA LMA File off Algn
0.text 00000007 08048080 08048080 00000080 2**4
CONTENTS,ALLOC, LOAD, READONLY, CODE
1.comment 0000001c 00000000 00000000 00000087 2**0
CONTENTS,READONLY
完整的.text节显示是7字节,这说明完全控制我们程序的机器码很安全。
但是.comment节是做什么用的呢?它有28字节!我们并不确定.comment节是做什么用的,但是看起来它并不是必要的代码。。。
我们可以看看.comment节到底存储了什么内容,在文件偏移0x00000087处,使用hexdump查看:
00000080:31C0 40B3 2ACD 8000 5468 6520 4E65 7477 1.@.*...The Netw
00000090:6964 6520 4173 7365 6D62 6C65 7220 302E ide Assembler 0.
000000A0:3938 0000 2E73 796D 7461 6200 2E73 7472 98...symtab..str
谁能想到nasm会暗中做这些事?也许我们该换用gas,AT&T:
;tiny.s
.globl_start
.text
_start:
xorl%eax, %eax
incl%eax
movb$42, %bl
int$0x80
$gcc -s -nostdlib tiny.s
$./a.out ; echo $?
42
$wc -c a.out
368a.out
一样的结果!
但是,通过objdump可以发现文件内容不同了:
Sections:
IdxName Size VMA LMA File off Algn
0.text 00000007 08048074 08048074 00000074 2**2
CONTENTS,ALLOC, LOAD, READONLY, CODE
1.data 00000000 0804907c 0804907c 0000007c 2**2
CONTENTS,ALLOC, LOAD, DATA
2.bss 00000000 0804907c 0804907c 0000007c 2**2
ALLOC
又多了两节,虽然他们的长度为零,但是仍然导致了额外的空间。
对于这些额外消耗,我们怎样避免呢?
要回答这个问题,我们需要理解ELF文件格式。
关于intel-386架构下ELF文件格式的正式描述可以参考http://refspecs.freestandards.org/elf/elf.pdf。你也可以参考普通文本格式的1.0版http://www.muppetlabs.com/~breadbox/software/ELF.txt。这些规范覆盖了很多方面,所以如果你不想自己读完全部的文档,我也可以理解。基本上,我们需要懂得如下内容就可以了:
每一个ELF文件都是以一个叫做ELFheader的结构体开始的。这个结构体有52字节长,它包含一些描述文件内容的信息。比如,第一个16字节包含文件的魔数签名(7F45 4C 46),还有1字节的标志位表明是32位还是64位,大尾还是小尾编码,等等。ELFheader里的其他字段包含信息比如目标处理器架构,文件类型喂可执行,目标文件还是共享目标文件,程序的起始地址,programheader table和sectionheader table的位置。
Programheader table和sectionheader table能够出现在文件的任何位置,但是前者一般紧跟在ELFheader之后,后者一般出现在文件末尾或者接近末尾的地方。这两个表完成相似的目的,都是为了标示文件中的组件块。尽管如此,Sectionheader table倾向于标示程序中各种块在文件中的位置,而programheader table描述这些块怎样被加载到内存中的什么位置。简单地讲,sectionheader table对编译器和链接器有用,而programheader table对程序加载器有用。Programheader table对于目标文件来说是可选的,在实际应用中从来不出现。同样地,sectionheader table对于可执行文件是可选的,但是在实际应用中总是出现。
那么,这就是我们第一个问题的答案。程序中的一些过度的空间消耗用于完全没必要的sectionheader table,和一些同样对程序的内存映像毫无帮助的没有用的块。
接下来,我们转向第二个问题:怎样除掉这些无用块呢?
没有标准的工具用于制作不包含sectionheader table之类的可执行文件。如果想做这样的事,那只能靠我们自己了。
但是那并不意味着我们必须打开二进制编辑器手写十六进制代码。nasm有一种普通二进制文本输出格式,那正好适合我们用。我们所需要的全部信息就是一个空ELF可执行文件的内存映像,然后把我们的程序填进去。
我们能够看ELF规范,和/usr/include/linux/elf.h,并参考标准工具创建的可执行文件,来推断一个空的ELF可执行文件应该是什么样。但是,如果你不是很有耐心,那么可以用下面提供的:
BITS32
org 0x08048000
ehdr: ; Elf32_Ehdr
db 0x7F, "ELF", 1, 1, 1, 0 ; e_ident
times8 db 0
dw 2 ; e_type
dw 3 ; e_machine
dd 1 ; e_version
dd _start ; e_entry
dd phdr - $$ ; e_phoff
dd 0 ; e_shoff
dd 0 ; e_flags
dw ehdrsize ; e_ehsize
dw phdrsize ; e_phentsize
dw 1 ; e_phnum
dw 0 ; e_shentsize
dw 0 ; e_shnum
dw 0 ; e_shstrndx
ehdrsize equ $ - ehdr
phdr: ; Elf32_Phdr
dd 1 ; p_type
dd 0 ; p_offset
dd $$ ; p_vaddr
dd $$ ; p_paddr
dd filesize ; p_filesz
dd filesize ; p_memsz
dd 5 ; p_flags
dd 0x1000 ; p_align
phdrsize equ $ - phdr
_start:
;your program here
filesize equ $ - $$
这个映像包含一个ELFheader,标示文件是intel386可执行文件,没有sectionheader,programheader table包含一个元素。前文中讲过programheader引导程序加载器把整个文件加载到内存映像中地址0x08048000处,这是默认的可执行文件的加载地址。接着就开始执行_start处的代码,它紧随programheader table之后。没有.data段,没有.bss段,没有注释,除了真正必须的信息。
我们的小程序现在变成:
;tiny.asm
org 0x08048000
;
;(as above)
;
_start:
mov bl, 42
xor eax, eax
inc eax
int 0x80
filesize equ $ - $$
试一下:
$nasm -f bin -o a.out tiny.asm
$chmod +x a.out
$./a.out ; echo $?
42
$wc -c a.out
91a.out
- 创建Linux下可运行的超小型ELF可执行文件(3)
- 创建Linux下可运行的超小型ELF可执行文件(1)
- 创建Linux下可运行的超小型ELF可执行文件(2)
- 创建Linux下可运行的超小型ELF可执行文件(4)
- 怎样创建真正很小的Linux下的ELF可执行文件
- 怎样创建真正很小的Linux下的ELF可执行文件
- Linux下ELF可执行文件装载与运行
- Linux下的ELF可执行文件学习总结
- 在linux平台上创建超小的ELF可执行文件
- 在linux平台上创建超小的ELF可执行文件
- 在linux平台上创建超小的ELF可执行文件
- 在linux平台上创建超小的ELF可执行文件
- 在Linux平台上创建超小的ELF可执行文件
- Linux下的ELF可执行文件的格式解析
- Linux下的ELF可执行文件的格式解析
- elf,out,coff 三种Linux下可执行文件的历史渊源
- 怎样创建真正很小的Linux下的ELF可执行文件————X86-64 Ubuntu实践
- Linux系统下可执行文件的运行过程
- 中缀表达式 转换成 前缀表达式(二叉树实现)
- 创建Linux下可运行的超小型ELF可执行文件(2)
- 谈新手对CString的使用 dai2255(原作)
- 额
- 小红点使用
- 创建Linux下可运行的超小型ELF可执行文件(3)
- rand和srand函数用法
- 创建Linux下可运行的超小型ELF可执行文件(4)
- 宏定义,想说爱你不容易!!
- UCGUI 消息机制实现分析
- JAVA中关于异常需要注意的地方
- 【翠字营原创】 应用程序在读写SQLite数据是否需要自己加锁保障?
- Flex 遍历组件的实现
- java