-
-
[原创]windows下用elf(Relocatable)作为目标文件格式
-
发表于: 2008-10-9 08:39 11148
-
windows平台下用elf作为目标文件格式
------22:46 2008-10-8 ljhhh0123-
近来发现一个Tiny C Compiler,一个ANSI C编译器,
支持linux和windows平台,
短小精悍,支持部分GNUC扩展,包括嵌入AT&T汇编等,在偶然间发现
它生成的目标文件格式竟是elf(Relocatable),
windows下最后生成PE可执行文件,真是令人吃惊,先学习之.
我所不解之处就是符号elf32_sym.st_shndx取小于0值的含义,
请高手赐教.谢谢.
方法是:把test.o文件倾印下来边看资料边细分,并做注释.
工具:记事本+winhex+IDA+若干elf文件格式学习资料(包括elf_format.pdf)+其它
软件:Tiny C Compiler version 0.9.24 for windows
auther: Fabrice Bellard
下载地址:7ebK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3c8D9x3#2)9J5k6h3y4K6k6r3&6Q4x3X3g2F1k6i4c8Q4x3V1k6X3k6q4)9J5k6i4m8Z5M7q4)9K6c8X3W2Q4x3@1b7K6z5e0f1J5y4U0f1I4x3K6l9H3y4U0f1@1y4q4)9J5y4R3`.`.
官网:cb3K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6i4c8A6L8Y4W2U0j5#2)9J5k6h3!0J5k6H3`.`.
3d0K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3k6S2j5Y4u0A6j5$3g2Q4x3X3g2T1k6h3I4D9j5i4u0V1i4K6u0W2k6Y4u0W2k6g2)9J5k6h3k6J5i4K6u0r3N6r3y4U0i4K6u0r3
学习文件格式,就读二进制!
----开始----
7F454C46 01 01 01 000000000000000000 "\177ELF" 32位 little-endlian 版本1
0100 文件类型为可重定位文件
0300 i386
01000000 当前版本
00000000 入口的虚拟地址
00000000 程序头部表格的偏移量(没有即为0)
44020000 节区头部表格的偏移量
00000000 保存与文件相关的,特定于处理器标志
3400 elf头部大小(以字节计算)
0000 程序头部表格的表项大小
0000 程序头部表格的表项数目
2800 节区头部表格的表项大小
0800 节区头部表格的表项数目
0700 节区头部表格中与节区名称表相关的表项的索引
如果没有节区名称表,可为0.
--空隙(第0个节区)--
000000000000000000000000
----第一个节区0x8d字节--并按0x20字节对齐--
5589E581EC10000000908B4510C1E802
8945F056578B4DF08B45108B7D088B75
0CF3A5A8020F84FCFFFFFF66A5A8010F
84FCFFFFFFA4894DFC897DF88975F45F
5E8B4508E900000000C9C3 到此为my_memcpy函数的机器码,大小为0x4b
5589E581EC
0000000090B80000000050E8FCFFFFFF
83C404B81400000050B80000000050B8
0000000050E8FCFFFFFF83C40CB80000
000050E8FCFFFFFF83C404C9C3
00000000000000000000000000000000
000000
----第二个节区0x14字节----
68656C6C6F20776F
726C64210A000000
00000000
--空隙--
000000000000000000000000
--第四个节区-0x90-符号表-
00000000000000000000000000000000 第一项为全0
01000000 "test.c" 名字在字符串表中的索引
00000000 值
00000000 大小
04 绑定属性 | 符号类型(STT_FILE)即文件名
00 无意义
F1FF 有特殊的含义,我现在还不知道:).
12000000 "L..1\0"
2D000000 符号的取值,在节区偏移0x2d的位置
00000000
01 STB_LOCAL(高半字节局部符号)+STT_OBJECT(对象类型低半字节)
00
0100 在.text节表
17000000 "L..2"
36000000 在节区偏移0x36的位置
00000000
01 STB_LOCAL + STT_OBJECT
00
0100
08000000 "my_memcpy"
00000000
4B000000 大小
12 绑定(全局) + 函数(STT_FUNC)
00
0100 在.text节区
1C000000 "buff"
00000000 在节区偏移0x0的位置
14000000 大小
11 全局(STB_GLOBAL)+对象(STT_OBJECT)
00
0200 .data节区
21000000 "buff2"
01000000
14000000 size
11 STB_GLOBAL | STT_OBJECT
00
F2FF 我不知此值的意义:)
27000000 "main"
4B000000
42000000 size
12 STB_GLOBAL | STT_OBJECT
00
0100
2C000000 "printf"
00000000
00000000
12 STB_GLOBAL | STT_FUNC
00
0000
--第五个节区-0x33-按四字节对齐--
00746573742E63006D795F6D656D6370
79004C2E2E31004C2E2E320062756666
006275666632006D61696E007072696E
746600
00
--第六个节区--0x48--
27000000020200003100000002030000
56000000010500005C00000002080000
6A000000010500007000000001060000
76000000020400007E00000001060000
8400000002080000
--第七个节区--0x36--
002E74657874002E64617461002E6273
73002E73796D746162002E7374727461
62002E72656C2E74657874002E736873
747274616200
0000 作填充之用
----节区头部表格8项----
00000000 节区名称(是在字符串节区内的索引值)
00000000 0表示此是非活动的,以下的成员值无意义.
0000000000000000
0000000000000000
0000000000000000
0000000000000000
--第一个节区表头--
01000000 ".text"节区名称(是在节区名称表内的索引值),即最后一个节区.
01000000 此节区包含程序定义信息
06000000 节区属性 SHF_ALLOC | SHF_EXECINSTR 占用内存和可执行
00000000 节区第一个字节应处的位置
40000000 节区的第一个字节与文件头之间的偏移
8D000000 节区的长度
00000000 节区头部表索引链接
00000000 附加信息
20000000 这个节区内容按32字节对齐
00000000 此节并不包含固定大小的项目,所以项目数为0.
--第二个--
07000000 ".data"
01000000 包含程序定义信息
03000000 可写和占用内存
00000000
E0000000 节区与文件头之间的偏移
14000000 长度
00000000
00000000
20000000 按32字节对齐
00000000
--第三个--
0D000000 ".bss"
08000000 SHT_NOBITS此节区不占用空间
03000000 可写,给分配内存
00000000
00010000 文件偏移
00000000 没有长度
00000000
00000000
20000000
00000000
--第四个--
12000000 ".symtab"
02000000 节区类型为符号表 SHT_SYMTAB
00000000 未定义
00000000
00010000 同上个节起始位置一样,实际就是这个节起效用
90000000 长度
05000000 相关联的字符串节区头部索引
04000000 最后一个局部符号的索引值加1.
04000000 按四字节对齐
10000000
--第五个--
1A000000 ".strtab"
03000000 可写及给分配内存
00000000
00000000
90010000
33000000 长度
00000000
00000000
01000000
00000000
--第六个--
22000000 ".rel.text"
09000000
00000000
00000000
C4010000
48000000
04000000
01000000
04000000
08000000
--第七个(加上第0个总共8个)--
2C000000 ".shstrtab"
03000000 包含字符串表
00000000 未定义
00000000
0C020000 偏移
36000000 长度
00000000
00000000
01000000 按一字节对齐
00000000
-------------------------------------------
附录1:相关的数据结构格源码.
typedef __u32 Elf32_Addr;
typedef __u16 Elf32_Half;
typedef __u32 Elf32_Off;
typedef __s32 Elf32_Sword;
typedef struct elf32_hdr{
unsigned char e_ident[EI_NIDENT]; /* 16 */
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry; /* Entry point */
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} Elf32_Ehdr;
typedef struct {
Elf32_Word sh_name;
Elf32_Word sh_type;
Elf32_Word sh_flags;
Elf32_Addr sh_addr;
Elf32_Off sh_offset;
Elf32_Word sh_size;
Elf32_Word sh_link;
Elf32_Word sh_info;
Elf32_Word sh_addralign;
Elf32_Word sh_entsize;
} Elf32_Shdr;
typedef struct elf32_sym{
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;
/******test.c******/
#include <stdio.h>
void * my_memcpy(void * to, const void * from, size_t n)
{
int d0, d1, d2;
__asm__ __volatile__(
"rep ; movsl\n\t"
"testb $2,%b4\n\t"
"je 1f\n\t"
"movsw\n"
"1:\ttestb $1,%b4\n\t"
"je 2f\n\t"
"movsb\n"
"2:"
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
:"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
: "memory");
return (to);
}
char buff[20]="hello world!\n\0";
char buff2[20];
void main(void){
printf(buff);
my_memcpy(buff2, buff, 20);
printf(buff2);
}
----本文完毕------
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课