1.现在己经把ELF格式的kernel.bin加载到了0x70000处,
现在要解析ELF格式中的数据到0x1500
1.2 错误的代码
-
cong@msi:/work/os/code/5kernel$ cat ./loader.S_bad
-
org 0x500
-
jmp begin
-
;segment discript
-
TYPE_8 equ 0x8 ;code -->exec
-
TYPE_2 equ 0x2 ;data -->r/w
-
-
S_0 equ (0x0<<4) ;s=0-->gate
-
S_1 equ (0x1<<4) ;s=1-->data/code
-
-
DPL_0 equ (0x0<<5) ;privilege level
-
DPL_3 equ (0x3<<5)
-
-
P_0 equ (0x00<<7) ;not in memory
-
P_1 equ (0x01<<7) ;in memory
-
-
AVL_0 equ (0x00<<8)
-
-
DB_0 equ (0x00<<10) ;16bit data&code
-
DB_1 equ (0x01<<10) ;32bit data&code
-
-
G_0 equ (0x00<<11) ;g=0,byte
-
G_1 equ (0x01<<11) ;g=1,4K
-
-
TI_0 equ (0x0<<2) ;TI=0,gdt
-
TI_1 equ (0x1<<2) ;TI=1,ldt
-
-
RPL_0 equ (0x0)
-
-
;PAGE
-
PAGE_POS equ 0x1F0000 ;0xF0000-->0xFFFFF-->64K
-
;PAGE_POS equ 0x1F0100 ;0x100000-->1M
-
PG_P_0 equ (0x0) ;not in memory
-
PG_P_1 equ (0x1) ;in memory
-
-
PG_RW_0 equ (0x0<<1) ;read,not write
-
PG_RW_1 equ (0x1<<1) ;read,write
-
-
PG_US_0 equ (0x0<<2) ;supervisor
-
PG_US_1 equ (0x1<<2) ;user
-
-
PG_PWT_0 equ (0x0<<3) ;memory
-
PG_PWT_1 equ (0x1<<3) ;memory and cache
-
-
PG_PCD_0 equ (0x0<<4) ;disable page level cache
-
PG_PCD_1 equ (0x1<<4) ;enable page level cache
-
-
PG_A_0 equ (0x0<<5) ;not accessed
-
PG_A_1 equ (0x1<<5) ;accessed
-
-
PG_D_0 equ (0x0<<6) ;not dirty
-
PG_D_1 equ (0x1<<6) ;dirty
-
-
PG_PAT_0 equ (0x0<<7) ;page attribute tabel
-
PG_PAT_1 equ (0x1<<7) ;
-
-
PG_G_0 equ (0x0<<8) ;global-->TLB
-
PG_G_1 equ (0x1<<8) ;
-
-
PG_AVL_0 equ (0x0<<9) ;available
-
PG_AVL_1 equ (0x1<<9) ;
-
-
;PE
-
PT_NULL equ 0
-
-
%macro DESC 3
-
dw %1 & 0xFFFF ;limit[0-15]
-
dw %2 & 0xFFFF ;base[0-15]
-
db (%2>>16)&0xFF ;base[16-23]
-
db (%3&0xFF) ;prop[0-7]
-
db (((%1>>16)&0xF) | (%3>>4)&0xF0) ;limit[16-19]prop[8-11]
-
db (%2>>24) & 0xFF
-
%endmacro
-
gdt_base: DESC 0, 0, 0 ;desc_dummy
-
gdt_code: DESC 0xFFFFFF, 0x0, (G_0|DB_1|AVL_0|P_1|DPL_0|S_1|TYPE_8)
-
gdt_data: DESC 0xFFFFF, 0x0, (G_1|DB_1|AVL_0|P_1|DPL_0|S_1|TYPE_2)
-
gdt_video: DESC 0xFFFF, 0xB8000, (G_0|DB_1|AVL_0|P_1|DPL_0|S_1|TYPE_2)
-
-
gdt_ptr:
-
dw 32 ;gdt_limit: 4*8=32, only 4 gdt item
-
dd gdt_base ;gdt_base
-
-
select_code equ (0x01<<3)|TI_0|RPL_0
-
select_data equ (0x02<<3)|TI_0|RPL_0
-
select_video equ (0x03<<3)|TI_0|RPL_0
-
begin:
-
mov cx, ax
-
;----------------- 打开A20 ----------------
-
in al,0x92
-
or al,0000_0010B
-
out 0x92,al
-
-
;----------------- 加载GDT ----------------
-
lgdt [gdt_ptr]
-
-
;----------------- cr0第0位置1 ----------------
-
mov eax, cr0
-
or eax, 0x00000001
-
mov cr0, eax
-
-
;----------------- 跳到保护模式 ----------------
-
jmp select_code:protect_mode
-
[bits 32]
-
protect_mode:
-
mov ax, select_data
-
mov ds, ax
-
mov es, ax
-
mov ax, select_video
-
mov gs, ax
-
mov byte [gs:160], 'P'
-
mov byte [gs:161], 0xA4
-
-
call setup_page_table
-
-
sgdt [gdt_ptr]
-
-
or dword [gdt_ptr+2], 0xC0000000 ;gdt_ptr
-
or byte [gdt_base+7], 0xC0 ;change gdt_code base addr
-
or byte [gdt_base+8+7], 0xC0 ;change gdt_data base addr
-
or byte [gdt_base+16+7], 0xC0 ;change gdt_video base addr
-
-
or esp, 0xC0000000
-
-
mov eax, PAGE_POS
-
mov cr3, eax
-
-
;打开cr0的pg位
-
mov eax, cr0
-
or eax, 0x80000000
-
mov cr0, eax
-
-
lgdt [gdt_ptr]
-
-
mov byte [gs:162], 'G'
-
mov byte [gs:163], 0xA4
-
-
jmp select_code:enter_kernel ;强制刷新流水线,更新gdt
-
-
enter_kernel:
-
call kernel_init
-
mov esp, 0xc009f000
-
jmp 0xc0001500 ;read from PE
-
-
-
;----------------- 将kernel.bin中的segment拷贝到编译的地址 -----------
-
kernel_init:
-
xor eax, eax
-
xor ebx, ebx ;ebx记录程序头表地址
-
xor ecx, ecx ;cx记录程序头表中的program header数量
-
xor edx, edx ;dx 记录program header尺寸,即e_phentsize
-
-
mov dx, [0x70000+42] ; 偏移文件42字节处的属性是e_phentsize,表示program header大小
-
mov ebx, [0x70000+28] ; 偏移文件开始部分28字节的地方是e_phoff,表示第1 个program header在文件中的偏移量
-
; 其实该值是0x34,不过还是谨慎一点,这里来读取实际值
-
add ebx, 0x70000
-
mov cx, [0x70000 + 44] ; 偏移文件开始部分44字节的地方是e_phnum,表示有几个program header
-
_each_segment:
-
cmp byte [ebx + 0], PT_NULL ; 若p_type等于 PT_NULL,说明此program header未使用。
-
je .PTNULL
-
-
;为函数memcpy压入参数,参数是从右往左依然压入.函数原型类似于 memcpy(dst,src,size)
-
push dword [ebx + 16] ; program header中偏移16字节的地方是p_filesz,压入函数memcpy的第三个参数:size
-
mov eax, [ebx + 4] ; 距程序头偏移量为4字节的位置是p_offset
-
add eax, 0x70000 ; 加上kernel.bin被加载到的物理地址,eax为该段的物理地址
-
push eax ; 压入函数memcpy的第二个参数:源地址
-
push dword [ebx + 8] ; 压入函数memcpy的第一个参数:目的地址,偏移程序头8字节的位置是p_vaddr,这就是目的地址
-
call mem_cpy ; 调用mem_cpy完成段复制
-
add esp,12 ; 清理栈中压入的三个参数
-
.PTNULL:
-
add ebx, edx ; edx为program header大小,即e_phentsize,在此ebx指向下一个program header
-
loop _each_segment
-
ret
-
-
;---------- 逐字节拷贝 mem_cpy(dst,src,size) ------------
-
;输入:栈中三个参数(dst,src,size)
-
;输出:无
-
;---------------------------------------------------------
-
mem_cpy:
-
cld
-
push ebp
-
mov ebp, esp
-
push ecx ; rep指令用到了ecx,但ecx对于外层段的循环还有用,故先入栈备份
-
mov edi, [ebp + 8] ; dst
-
mov esi, [ebp + 12] ; src
-
mov ecx, [ebp + 16] ; size
-
rep movsb ; 逐字节拷贝
-
-
;恢复环境
-
pop ecx
-
pop ebp
-
ret
-
-
setup_page_table:
-
mov ecx, 0x400 ;1PTE:4K=0x1000
-
xor esi, esi
-
xor eax, eax
-
_init_page_table:
-
mov [PAGE_POS+esi], eax
-
add esi,0x04
-
loop _init_page_table
-
-
;PDE0, PDE768 use the same PTE0
-
mov eax, (PG_US_1|PG_RW_1|PG_P_1)
-
or eax, ((PAGE_POS+0x1000)&0xFFF000)
-
mov [PAGE_POS+0x0], eax
-
mov [PAGE_POS+0xc00], eax
-
sub eax, 0x1000
-
mov [PAGE_POS+0xFFC], eax
-
-
;PTE for PDE0 and PDE768
-
mov ecx,256
-
xor esi,esi
-
mov eax, (PG_US_1|PG_RW_1|PG_P_1)
-
_create_pte:
-
mov [PAGE_POS+0x1000+esi],eax
-
add esi,0x04
-
add eax,0x1000
-
loop _create_pte
-
-
;create other PDE for kernel
-
-
-
ret
1.2.a
调试时发现用到了ss
-
<bochs:21>
-
Next at t=157027543
-
(0) [0x000000000609] 0008:00000609 (unk. ctxt): call .+8 (0xc0000616) ; e808000000
-
<bochs:22>
-
(0).[157027548] [0x00000000061b] 0008:0000061b (unk. ctxt): mov edi, dword ptr ss:[ebp+8] ; 8b7d08
-
Next at t=157027549
-
(0) [0x0000fffffff0] f000:fff0 (unk. ctxt): jmpf 0xf000:e05b ; ea5be000f0
-
<bochs:23> quit
-
(0).[157027549] [0x0000fffffff0] f000:fff0 (unk. ctxt): jmpf 0xf000:e05b ; ea5be000f0
但是代码里面没有体现ss, 添加 mov ss, ax
1.2.b
在jmp之前查看0x1500的数据,说明是正确的
-
Next at t=157028922
-
(0) [0x0000000005d0] 0008:000005d0 (unk. ctxt): jmp .-1073737941 (0x80001500) ; e92b0f00c0
-
<bochs:40> xp /32 0x1500
-
[bochs]:
-
0x00001500 <bogus+ 0>: 0xebe58955 0x000000fe 0x00000014 0x00000000
-
0x00001510 <bogus+ 16>: 0x00527a01 0x01087c01 0x04040c1b 0x00000188
-
0x00001520 <bogus+ 32>: 0x00000018 0x0000001c 0xffffffd8 0x00000005
-
0x00001530 <bogus+ 48>: 0x080e4100 0x0d420285 0x00000005 0x00000000
-
0x00001540 <bogus+ 64>: 0x00000000 0x00000000 0x00000000 0x00000000
-
0x00001550 <bogus+ 80>: 0x00000000 0x00000000 0x00000000 0x00000000
-
0x00001560 <bogus+ 96>: 0x00000000 0x00000000 0x00000000 0x00000000
-
0x00001570 <bogus+ 112>: 0x00000000 0x00000000 0x00000000 0x00000000
-
<bochs:41> n
-
(0).[157028922] [0x0000000005d0] 0008:000005d0 (unk. ctxt): jmp .-1073737941 (0x80001500) ; e92b0f00c0
-
Next at t=157028923
-
(0) [0x0000fffffff0] f000:fff0 (unk. ctxt): jmpf 0xf000:e05b ; ea5be000f0
-
但是在下一步跳转时出现了错误
1.2.c
错误的gdt
-
GDT[0x00]=??? descriptor hi=0xc0000000, lo=0x00000000
-
GDT[0x01]=Code segment, base=0xc0000000, limit=0x000fffff, Execute-Only, Non-Conforming, Accessed, 32-bit
-
GDT[0x02]=Data segment, base=0xc0000000, limit=0xffffffff, Read/Write, Accessed
-
GDT[0x03]=Data segment, base=0x000b8000, limit=0x0000ffff, Read/Write, Accessed
正确的gdt
-
GDT[0x00]=??? descriptor hi=0x00000000, lo=0x00000000
-
GDT[0x01]=Code segment, base=0x00000000, limit=0xffffffff, Execute-Only, Non-Conforming, Accessed, 32-bit
-
GDT[0x02]=Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
-
GDT[0x03]=Data segment, base=0xc00b8000, limit=0x00007fff, Read/Write, Accessed
发现是gdt中的code segment出错了,当然data segment也不对
1.3 正确的代码
-
org 0x500
-
jmp begin
-
;segment discript
-
TYPE_8 equ 0x8 ;code -->exec
-
TYPE_2 equ 0x2 ;data -->r/w
-
-
S_0 equ (0x0<<4) ;s=0-->gate
-
S_1 equ (0x1<<4) ;s=1-->data/code
-
-
DPL_0 equ (0x0<<5) ;privilege level
-
DPL_3 equ (0x3<<5)
-
-
P_0 equ (0x00<<7) ;not in memory
-
P_1 equ (0x01<<7) ;in memory
-
-
AVL_0 equ (0x00<<8)
-
-
DB_0 equ (0x00<<10) ;16bit data&code
-
DB_1 equ (0x01<<10) ;32bit data&code
-
-
G_0 equ (0x00<<11) ;g=0,byte
-
G_1 equ (0x01<<11) ;g=1,4K
-
-
TI_0 equ (0x0<<2) ;TI=0,gdt
-
TI_1 equ (0x1<<2) ;TI=1,ldt
-
-
RPL_0 equ (0x0)
-
-
;PAGE
-
;PAGE_POS equ 0x1F0000 ;0xF0000-->0xFFFFF-->64K
-
PAGE_POS equ 0x100000 ;0xF0000-->0xFFFFF-->64K
-
;PAGE_POS equ 0x1F0100 ;0x100000-->1M
-
PG_P_0 equ (0x0) ;not in memory
-
PG_P_1 equ (0x1) ;in memory
-
-
PG_RW_0 equ (0x0<<1) ;read,not write
-
PG_RW_1 equ (0x1<<1) ;read,write
-
-
PG_US_0 equ (0x0<<2) ;supervisor
-
PG_US_1 equ (0x1<<2) ;user
-
-
PG_PWT_0 equ (0x0<<3) ;memory
-
PG_PWT_1 equ (0x1<<3) ;memory and cache
-
-
PG_PCD_0 equ (0x0<<4) ;disable page level cache
-
PG_PCD_1 equ (0x1<<4) ;enable page level cache
-
-
PG_A_0 equ (0x0<<5) ;not accessed
-
PG_A_1 equ (0x1<<5) ;accessed
-
-
PG_D_0 equ (0x0<<6) ;not dirty
-
PG_D_1 equ (0x1<<6) ;dirty
-
-
PG_PAT_0 equ (0x0<<7) ;page attribute tabel
-
PG_PAT_1 equ (0x1<<7) ;
-
-
PG_G_0 equ (0x0<<8) ;global-->TLB
-
PG_G_1 equ (0x1<<8) ;
-
-
PG_AVL_0 equ (0x0<<9) ;available
-
PG_AVL_1 equ (0x1<<9) ;
-
-
;PE
-
PT_NULL equ 0
-
-
%macro DESC 3
-
dw %1 & 0xFFFF ;limit[0-15]
-
dw %2 & 0xFFFF ;base[0-15]
-
db (%2>>16)&0xFF ;base[16-23]
-
db (%3&0xFF) ;prop[0-7]
-
db (((%1>>16)&0xF) | (%3>>4)&0xF0) ;limit[16-19]prop[8-11]
-
db (%2>>24) & 0xFF
-
%endmacro
-
gdt_base: DESC 0, 0, 0 ;desc_dummy
-
gdt_code: DESC 0xFFFFF, 0x0, (G_1|DB_1|AVL_0|P_1|DPL_0|S_1|TYPE_8) -->改gdt_code的granularity由字节到4K,增大code的段界限
-
gdt_data: DESC 0xFFFFF, 0x0, (G_1|DB_1|AVL_0|P_1|DPL_0|S_1|TYPE_2)
-
gdt_video: DESC 0xFFFF, 0xB8000, (G_0|DB_1|AVL_0|P_1|DPL_0|S_1|TYPE_2)
-
-
gdt_ptr:
-
dw 32 ;gdt_limit: 4*8=32, only 4 gdt item
-
dd gdt_base ;gdt_base
-
-
select_code equ (0x01<<3)|TI_0|RPL_0
-
select_data equ (0x02<<3)|TI_0|RPL_0
-
select_video equ (0x03<<3)|TI_0|RPL_0
-
begin:
-
mov cx, ax
-
;----------------- 打开A20 ----------------
-
in al,0x92
-
or al,0000_0010B
-
out 0x92,al
-
-
;----------------- 加载GDT ----------------
-
lgdt [gdt_ptr]
-
-
;----------------- cr0第0位置1 ----------------
-
mov eax, cr0
-
or eax, 0x00000001
-
mov cr0, eax
-
-
;----------------- 跳到保护模式 ----------------
-
jmp select_code:protect_mode
-
[bits 32]
-
protect_mode:
-
mov ax, select_data
-
mov ds, ax
-
mov es, ax
-
mov ss, ax -->因为下面有函数调用需要使用栈,所以这儿设置一下ss
-
mov ax, select_video
-
mov gs, ax
-
mov byte [gs:160], 'P'
-
mov byte [gs:161], 0xA4
-
-
call setup_page_table
-
-
sgdt [gdt_ptr]
-
-
or dword [gdt_ptr+2], 0xC0000000 ;gdt_ptr
-
;or byte [gdt_base+7], 0xC0 ;change gdt_code base addr -->不用改gdt_code的基址
-
;or byte [gdt_base+8+7], 0xC0 ;change gdt_data base addr -->不用改gdt_data的基址
-
or byte [gdt_base+16+7], 0xC0 ;change gdt_video base addr
-
-
or esp, 0xC0000000
-
-
mov eax, PAGE_POS
-
mov cr3, eax
-
-
;打开cr0的pg位
-
mov eax, cr0
-
or eax, 0x80000000
-
mov cr0, eax
-
-
lgdt [gdt_ptr]
-
-
mov byte [gs:162], 'G'
-
mov byte [gs:163], 0xA4
-
-
jmp select_code:enter_kernel ;强制刷新流水线,更新gdt
-
-
enter_kernel:
-
call kernel_init
-
mov esp, 0xc009f000
-
;mov dword [0xC0001500], 0x00
-
jmp dword 0xC0001500 ;read from PE
-
;jmp 0x1500 ;read from PE
-
-
-
;----------------- 将kernel.bin中的segment拷贝到编译的地址 -----------
-
kernel_init:
-
xor eax, eax
-
xor ebx, ebx ;ebx记录程序头表地址
-
xor ecx, ecx ;cx记录程序头表中的program header数量
-
xor edx, edx ;dx 记录program header尺寸,即e_phentsize
-
-
mov dx, [0x70000+42] ; 偏移文件42字节处的属性是e_phentsize,表示program header大小
-
mov ebx, [0x70000+28] ; 偏移文件开始部分28字节的地方是e_phoff,表示第1 个program header在文件中的偏移量
-
; 其实该值是0x34,不过还是谨慎一点,这里来读取实际值
-
add ebx, 0x70000
-
mov cx, [0x70000 + 44] ; 偏移文件开始部分44字节的地方是e_phnum,表示有几个program header
-
_each_segment:
-
cmp byte [ebx + 0], PT_NULL ; 若p_type等于 PT_NULL,说明此program header未使用。
-
je .PTNULL
-
-
;为函数memcpy压入参数,参数是从右往左依然压入.函数原型类似于 memcpy(dst,src,size)
-
push dword [ebx + 16] ; program header中偏移16字节的地方是p_filesz,压入函数memcpy的第三个参数:size
-
mov eax, [ebx + 4] ; 距程序头偏移量为4字节的位置是p_offset
-
add eax, 0x70000 ; 加上kernel.bin被加载到的物理地址,eax为该段的物理地址
-
push eax ; 压入函数memcpy的第二个参数:源地址
-
push dword [ebx + 8] ; 压入函数memcpy的第一个参数:目的地址,偏移程序头8字节的位置是p_vaddr,这就是目的地址
-
call mem_cpy ; 调用mem_cpy完成段复制
-
add esp,12 ; 清理栈中压入的三个参数
-
.PTNULL:
-
add ebx, edx ; edx为program header大小,即e_phentsize,在此ebx指向下一个program header
-
loop _each_segment
-
ret
-
-
;---------- 逐字节拷贝 mem_cpy(dst,src,size) ------------
-
;输入:栈中三个参数(dst,src,size)
-
;输出:无
-
;---------------------------------------------------------
-
mem_cpy:
-
cld
-
push ebp
-
mov ebp, esp
-
push ecx ; rep指令用到了ecx,但ecx对于外层段的循环还有用,故先入栈备份
-
mov edi, [ebp + 8] ; dst
-
mov esi, [ebp + 12] ; src
-
mov ecx, [ebp + 16] ; size
-
rep movsb ; 逐字节拷贝
-
-
;恢复环境
-
pop ecx
-
pop ebp
-
ret
-
-
setup_page_table:
-
mov ecx, 0x400 ;1PTE:4K=0x1000
-
xor esi, esi
-
xor eax, eax
-
_init_page_table:
-
mov [PAGE_POS+esi], eax
-
add esi,0x04
-
loop _init_page_table
-
-
;PDE0, PDE768 use the same PTE0
-
mov eax, (PG_US_1|PG_RW_1|PG_P_1)
-
or eax, ((PAGE_POS+0x1000)&0xFFF000)
-
mov [PAGE_POS+0x0], eax
-
mov [PAGE_POS+0xc00], eax
-
sub eax, 0x1000
-
mov [PAGE_POS+0xFFC], eax
-
-
;PTE for PDE0 and PDE768
-
mov ecx,256
-
xor esi,esi
-
mov eax, (PG_US_1|PG_RW_1|PG_P_1)
-
_create_pte:
-
mov [PAGE_POS+0x1000+esi],eax
-
add esi,0x04
-
add eax,0x1000
-
loop _create_pte
-
-
;create other PDE for kernel
-
mov eax, (PG_US_1|PG_RW_1|PG_P_1)
-
or eax, ((PAGE_POS+0x2000)&0xFFF000)
-
mov ecx,254
-
mov esi,0x04
-
_create_pde:
-
mov [PAGE_POS+0xc00+esi], eax
-
add esi, 0x04
-
add eax, 0x1000
-
loop _create_pde
-
-
ret
1.4 代码打包
6kernel.rar(下载后改名为6kernel.rar)
附录: ELF解析测试程序
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <string.h>
-
#include <errno.h>
-
#include <sys/types.h>
-
#include <sys/stat.h>
-
#include <fcntl.h>
-
#include <stdint.h>
-
#define dbmsg(fmt, args ...) printf("%s:%s[%d]: "fmt"\n", __FILE__,__FUNCTION__, __LINE__,##args)
-
-
typedef uint16_t Elf32_Half;
-
typedef uint32_t Elf32_Word;
-
typedef uint32_t Elf32_Addr;
-
typedef uint32_t Elf32_Off;
-
-
#define EI_NIDENT (16)
-
-
typedef struct
-
{
-
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
-
Elf32_Half e_type; /* Object file type */
-
Elf32_Half e_machine; /* Architecture */
-
Elf32_Word e_version; /* Object file version */
-
Elf32_Addr e_entry; /* Entry point virtual address */
-
Elf32_Off e_phoff; /* Program header table file offset */
-
Elf32_Off e_shoff; /* Section header table file offset */
-
Elf32_Word e_flags; /* Processor-specific flags */
-
Elf32_Half e_ehsize; /* ELF header size in bytes */
-
Elf32_Half e_phentsize; /* Program header table entry size */
-
Elf32_Half e_phnum; /* Program header table entry count */
-
Elf32_Half e_shentsize; /* Section header table entry size */
-
Elf32_Half e_shnum; /* Section header table entry count */
-
Elf32_Half e_shstrndx; /* Section header string table index */
-
} Elf32_Ehdr;
-
-
-
int readelf(int fd)
-
{
-
int i;
-
unsigned char* p;
-
unsigned char buf[2048];
-
Elf32_Ehdr h;
-
read(fd, &h, sizeof(h));
-
p = (unsigned char*)&h;
-
for(i=0; i<sizeof(h); i++)
-
{
-
printf("%2d=0x%02x ", i, p[i]);
-
if((i+1)%16==0)
-
printf("\n");
-
}
-
printf("\n");
-
printf("header_size=%d\n", sizeof(h));
-
printf("type=0x%x,mach=0x%x\n",h.e_type, h.e_machine);
-
printf("entry=0x%x,phnum=0x%x\n",h.e_entry, h.e_phnum);
-
return 0;
-
}
-
-
int main ( int argc, char *argv[] )
-
{
-
int fd = open("./kernel.bin", O_RDWR);
-
if(fd < 0)
-
{
-
dbmsg("open error");
-
return -1;
-
}
-
readelf(fd);
-
return EXIT_SUCCESS;
-
}
阅读(1283) | 评论(0) | 转发(0) |