Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2159604
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: LINUX

2016-08-24 15:16:35

1.现在己经把ELF格式的kernel.bin加载到了0x70000处,
现在要解析ELF格式中的数据到0x1500
1.2 错误的代码
  1. cong@msi:/work/os/code/5kernel$ cat ./loader.S_bad
  2. org 0x500
  3. jmp begin
  4. ;segment discript
  5. TYPE_8 equ 0x8 ;code -->exec
  6. TYPE_2 equ 0x2 ;data -->r/w

  7. S_0 equ (0x0<<4) ;s=0-->gate
  8. S_1 equ (0x1<<4) ;s=1-->data/code

  9. DPL_0 equ (0x0<<5) ;privilege level
  10. DPL_3 equ (0x3<<5)

  11. P_0 equ (0x00<<7) ;not in memory
  12. P_1 equ (0x01<<7) ;in memory

  13. AVL_0 equ (0x00<<8)

  14. DB_0 equ (0x00<<10) ;16bit data&code
  15. DB_1 equ (0x01<<10) ;32bit data&code

  16. G_0 equ (0x00<<11) ;g=0,byte
  17. G_1 equ (0x01<<11) ;g=1,4K

  18. TI_0 equ (0x0<<2) ;TI=0,gdt
  19. TI_1 equ (0x1<<2) ;TI=1,ldt

  20. RPL_0 equ (0x0)

  21. ;PAGE
  22. PAGE_POS equ 0x1F0000 ;0xF0000-->0xFFFFF-->64K
  23. ;PAGE_POS equ 0x1F0100 ;0x100000-->1M
  24. PG_P_0 equ (0x0) ;not in memory
  25. PG_P_1 equ (0x1) ;in memory

  26. PG_RW_0 equ (0x0<<1) ;read,not write
  27. PG_RW_1 equ (0x1<<1) ;read,write

  28. PG_US_0 equ (0x0<<2) ;supervisor
  29. PG_US_1 equ (0x1<<2) ;user

  30. PG_PWT_0 equ (0x0<<3) ;memory
  31. PG_PWT_1 equ (0x1<<3) ;memory and cache

  32. PG_PCD_0 equ (0x0<<4) ;disable page level cache
  33. PG_PCD_1 equ (0x1<<4) ;enable page level cache

  34. PG_A_0 equ (0x0<<5) ;not accessed
  35. PG_A_1 equ (0x1<<5) ;accessed

  36. PG_D_0 equ (0x0<<6) ;not dirty
  37. PG_D_1 equ (0x1<<6) ;dirty

  38. PG_PAT_0 equ (0x0<<7) ;page attribute tabel
  39. PG_PAT_1 equ (0x1<<7) ;

  40. PG_G_0 equ (0x0<<8) ;global-->TLB
  41. PG_G_1 equ (0x1<<8) ;

  42. PG_AVL_0 equ (0x0<<9) ;available
  43. PG_AVL_1 equ (0x1<<9) ;

  44. ;PE
  45. PT_NULL equ 0

  46. %macro DESC 3
  47.     dw %1 & 0xFFFF ;limit[0-15]
  48.     dw %2 & 0xFFFF ;base[0-15]
  49.     db (%2>>16)&0xFF ;base[16-23]
  50.     db (%3&0xFF) ;prop[0-7]
  51.     db (((%1>>16)&0xF) | (%3>>4)&0xF0) ;limit[16-19]prop[8-11]
  52.     db (%2>>24) & 0xFF
  53. %endmacro
  54. gdt_base: DESC 0, 0, 0 ;desc_dummy
  55. gdt_code: DESC 0xFFFFFF, 0x0, (G_0|DB_1|AVL_0|P_1|DPL_0|S_1|TYPE_8)
  56. gdt_data: DESC 0xFFFFF, 0x0, (G_1|DB_1|AVL_0|P_1|DPL_0|S_1|TYPE_2)
  57. gdt_video: DESC 0xFFFF, 0xB8000, (G_0|DB_1|AVL_0|P_1|DPL_0|S_1|TYPE_2)

  58. gdt_ptr:
  59.     dw 32 ;gdt_limit: 4*8=32, only 4 gdt item
  60.     dd gdt_base ;gdt_base

  61. select_code equ (0x01<<3)|TI_0|RPL_0
  62. select_data equ (0x02<<3)|TI_0|RPL_0
  63. select_video equ (0x03<<3)|TI_0|RPL_0
  64. begin:
  65.     mov cx, ax
  66.     ;----------------- 打开A20 ----------------
  67.     in al,0x92
  68.     or al,0000_0010B
  69.     out 0x92,al

  70.     ;----------------- 加载GDT ----------------
  71.     lgdt [gdt_ptr]

  72.     ;----------------- cr0第0位置1 ----------------
  73.     mov eax, cr0
  74.     or eax, 0x00000001
  75.     mov cr0, eax

  76.     ;----------------- 跳到保护模式 ----------------
  77.     jmp select_code:protect_mode
  78. [bits 32]
  79. protect_mode:
  80.     mov ax, select_data
  81.     mov ds, ax
  82.     mov es, ax
  83.     mov ax, select_video
  84.     mov gs, ax
  85.     mov byte [gs:160], 'P'
  86.     mov byte [gs:161], 0xA4

  87.     call setup_page_table    

  88.     sgdt [gdt_ptr]
  89.     
  90.     or dword [gdt_ptr+2], 0xC0000000 ;gdt_ptr
  91.     or byte [gdt_base+7], 0xC0 ;change gdt_code base addr
  92.     or byte [gdt_base+8+7], 0xC0 ;change gdt_data base addr
  93.     or byte [gdt_base+16+7], 0xC0 ;change gdt_video base addr

  94.     or esp, 0xC0000000

  95.     mov eax, PAGE_POS
  96.     mov cr3, eax
  97.         
  98.     ;打开cr0的pg位
  99.     mov eax, cr0
  100.     or eax, 0x80000000
  101.     mov cr0, eax

  102.     lgdt [gdt_ptr]

  103.     mov byte [gs:162], 'G'
  104.     mov byte [gs:163], 0xA4

  105.  jmp select_code:enter_kernel     ;强制刷新流水线,更新gdt

  106. enter_kernel:
  107.    call kernel_init
  108.    mov esp, 0xc009f000
  109.    jmp 0xc0001500 ;read from PE


  110. ;----------------- 将kernel.bin中的segment拷贝到编译的地址 -----------
  111. kernel_init:
  112.    xor eax, eax
  113.    xor ebx, ebx        ;ebx记录程序头表地址
  114.    xor ecx, ecx        ;cx记录程序头表中的program header数量
  115.    xor edx, edx        ;dx 记录program header尺寸,即e_phentsize

  116.    mov dx, [0x70000+42]     ; 偏移文件42字节处的属性是e_phentsize,表示program header大小
  117.    mov ebx, [0x70000+28] ; 偏移文件开始部分28字节的地方是e_phoff,表示第1 个program header在文件中的偏移量
  118.                      ; 其实该值是0x34,不过还是谨慎一点,这里来读取实际值
  119.    add ebx, 0x70000
  120.    mov cx, [0x70000 + 44] ; 偏移文件开始部分44字节的地方是e_phnum,表示有几个program header
  121. _each_segment:
  122.    cmp byte [ebx + 0], PT_NULL         ; 若p_type等于 PT_NULL,说明此program header未使用。
  123.    je .PTNULL

  124.    ;为函数memcpy压入参数,参数是从右往左依然压入.函数原型类似于 memcpy(dst,src,size)
  125.    push dword [ebx + 16]         ; program header中偏移16字节的地方是p_filesz,压入函数memcpy的第三个参数:size
  126.    mov eax, [ebx + 4]             ; 距程序头偏移量为4字节的位置是p_offset
  127.    add eax, 0x70000     ; 加上kernel.bin被加载到的物理地址,eax为该段的物理地址
  128.    push eax                 ; 压入函数memcpy的第二个参数:源地址
  129.    push dword [ebx + 8]             ; 压入函数memcpy的第一个参数:目的地址,偏移程序头8字节的位置是p_vaddr,这就是目的地址
  130.    call mem_cpy                 ; 调用mem_cpy完成段复制
  131.    add esp,12                 ; 清理栈中压入的三个参数
  132. .PTNULL:
  133.    add ebx, edx                 ; edx为program header大小,即e_phentsize,在此ebx指向下一个program header
  134.    loop _each_segment
  135.    ret

  136. ;---------- 逐字节拷贝 mem_cpy(dst,src,size) ------------
  137. ;输入:栈中三个参数(dst,src,size)
  138. ;输出:
  139. ;---------------------------------------------------------
  140. mem_cpy:        
  141.    cld
  142.    push ebp
  143.    mov ebp, esp
  144.    push ecx         ; rep指令用到了ecx,但ecx对于外层段的循环还有用,故先入栈备份
  145.    mov edi, [ebp + 8]     ; dst
  146.    mov esi, [ebp + 12]     ; src
  147.    mov ecx, [ebp + 16]     ; size
  148.    rep movsb         ; 逐字节拷贝

  149.    ;恢复环境
  150.    pop ecx        
  151.    pop ebp
  152.    ret

  153. setup_page_table:
  154.     mov ecx, 0x400 ;1PTE:4K=0x1000
  155.     xor esi, esi
  156.     xor eax, eax
  157. _init_page_table:
  158.     mov [PAGE_POS+esi], eax
  159.     add esi,0x04
  160.     loop _init_page_table

  161.     ;PDE0, PDE768 use the same PTE0
  162.     mov eax, (PG_US_1|PG_RW_1|PG_P_1)
  163.     or eax, ((PAGE_POS+0x1000)&0xFFF000)
  164.     mov [PAGE_POS+0x0], eax
  165.     mov [PAGE_POS+0xc00], eax
  166.     sub eax, 0x1000
  167.     mov [PAGE_POS+0xFFC], eax

  168.     ;PTE for PDE0 and PDE768
  169.     mov ecx,256
  170.     xor esi,esi
  171.     mov eax, (PG_US_1|PG_RW_1|PG_P_1)
  172. _create_pte:
  173.     mov [PAGE_POS+0x1000+esi],eax
  174.     add esi,0x04
  175.     add eax,0x1000
  176.     loop _create_pte

  177.     ;create other PDE for kernel


  178.     ret
1.2.a 调试时发现用到了ss
  1. <bochs:21>
  2. Next at t=157027543
  3. (0) [0x000000000609] 0008:00000609 (unk. ctxt): call .+8 (0xc0000616) ; e808000000
  4. <bochs:22>
  5. (0).[157027548] [0x00000000061b] 0008:0000061b (unk. ctxt): mov edi, dword ptr ss:[ebp+8] ; 8b7d08
  6. Next at t=157027549
  7. (0) [0x0000fffffff0] f000:fff0 (unk. ctxt): jmpf 0xf000:e05b ; ea5be000f0
  8. <bochs:23> quit
  9. (0).[157027549] [0x0000fffffff0] f000:fff0 (unk. ctxt): jmpf 0xf000:e05b ; ea5be000f0
但是代码里面没有体现ss,   添加 mov ss, ax
1.2.b 
在jmp之前查看0x1500的数据,说明是正确的
  1. Next at t=157028922
  2. (0) [0x0000000005d0] 0008:000005d0 (unk. ctxt): jmp .-1073737941 (0x80001500) ; e92b0f00c0
  3. <bochs:40> xp /32 0x1500
  4. [bochs]:
  5. 0x00001500 <bogus+ 0>:    0xebe58955    0x000000fe    0x00000014    0x00000000
  6. 0x00001510 <bogus+ 16>:    0x00527a01    0x01087c01    0x04040c1b    0x00000188
  7. 0x00001520 <bogus+ 32>:    0x00000018    0x0000001c    0xffffffd8    0x00000005
  8. 0x00001530 <bogus+ 48>:    0x080e4100    0x0d420285    0x00000005    0x00000000
  9. 0x00001540 <bogus+ 64>:    0x00000000    0x00000000    0x00000000    0x00000000
  10. 0x00001550 <bogus+ 80>:    0x00000000    0x00000000    0x00000000    0x00000000
  11. 0x00001560 <bogus+ 96>:    0x00000000    0x00000000    0x00000000    0x00000000
  12. 0x00001570 <bogus+ 112>:    0x00000000    0x00000000    0x00000000    0x00000000
  13. <bochs:41> n
  14. (0).[157028922] [0x0000000005d0] 0008:000005d0 (unk. ctxt): jmp .-1073737941 (0x80001500) ; e92b0f00c0
  15. Next at t=157028923
  16. (0) [0x0000fffffff0] f000:fff0 (unk. ctxt): jmpf 0xf000:e05b ; ea5be000f0
  17. 但是在下一步跳转时出现了错误
1.2.c 
错误的gdt
  1. GDT[0x00]=??? descriptor hi=0xc0000000, lo=0x00000000
  2. GDT[0x01]=Code segment, base=0xc0000000, limit=0x000fffff, Execute-Only, Non-Conforming, Accessed, 32-bit
  3. GDT[0x02]=Data segment, base=0xc0000000, limit=0xffffffff, Read/Write, Accessed
  4. GDT[0x03]=Data segment, base=0x000b8000, limit=0x0000ffff, Read/Write, Accessed
正确的gdt
  1. GDT[0x00]=??? descriptor hi=0x00000000, lo=0x00000000
  2. GDT[0x01]=Code segment, base=0x00000000, limit=0xffffffff, Execute-Only, Non-Conforming, Accessed, 32-bit
  3. GDT[0x02]=Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
  4. GDT[0x03]=Data segment, base=0xc00b8000, limit=0x00007fff, Read/Write, Accessed
发现是gdt中的code segment出错了,当然data segment也不对
1.3 正确的代码
  1. org 0x500
  2. jmp begin
  3. ;segment discript
  4. TYPE_8 equ 0x8 ;code -->exec
  5. TYPE_2 equ 0x2 ;data -->r/w

  6. S_0 equ (0x0<<4) ;s=0-->gate
  7. S_1 equ (0x1<<4) ;s=1-->data/code

  8. DPL_0 equ (0x0<<5) ;privilege level
  9. DPL_3 equ (0x3<<5)

  10. P_0 equ (0x00<<7) ;not in memory
  11. P_1 equ (0x01<<7) ;in memory

  12. AVL_0 equ (0x00<<8)

  13. DB_0 equ (0x00<<10) ;16bit data&code
  14. DB_1 equ (0x01<<10) ;32bit data&code

  15. G_0 equ (0x00<<11) ;g=0,byte
  16. G_1 equ (0x01<<11) ;g=1,4K

  17. TI_0 equ (0x0<<2) ;TI=0,gdt
  18. TI_1 equ (0x1<<2) ;TI=1,ldt

  19. RPL_0 equ (0x0)

  20. ;PAGE
  21. ;PAGE_POS equ 0x1F0000 ;0xF0000-->0xFFFFF-->64K
  22. PAGE_POS equ 0x100000 ;0xF0000-->0xFFFFF-->64K
  23. ;PAGE_POS equ 0x1F0100 ;0x100000-->1M
  24. PG_P_0 equ (0x0) ;not in memory
  25. PG_P_1 equ (0x1) ;in memory

  26. PG_RW_0 equ (0x0<<1) ;read,not write
  27. PG_RW_1 equ (0x1<<1) ;read,write

  28. PG_US_0 equ (0x0<<2) ;supervisor
  29. PG_US_1 equ (0x1<<2) ;user

  30. PG_PWT_0 equ (0x0<<3) ;memory
  31. PG_PWT_1 equ (0x1<<3) ;memory and cache

  32. PG_PCD_0 equ (0x0<<4) ;disable page level cache
  33. PG_PCD_1 equ (0x1<<4) ;enable page level cache

  34. PG_A_0 equ (0x0<<5) ;not accessed
  35. PG_A_1 equ (0x1<<5) ;accessed

  36. PG_D_0 equ (0x0<<6) ;not dirty
  37. PG_D_1 equ (0x1<<6) ;dirty

  38. PG_PAT_0 equ (0x0<<7) ;page attribute tabel
  39. PG_PAT_1 equ (0x1<<7) ;

  40. PG_G_0 equ (0x0<<8) ;global-->TLB
  41. PG_G_1 equ (0x1<<8) ;

  42. PG_AVL_0 equ (0x0<<9) ;available
  43. PG_AVL_1 equ (0x1<<9) ;

  44. ;PE
  45. PT_NULL equ 0

  46. %macro DESC 3
  47.     dw %1 & 0xFFFF ;limit[0-15]
  48.     dw %2 & 0xFFFF ;base[0-15]
  49.     db (%2>>16)&0xFF ;base[16-23]
  50.     db (%3&0xFF) ;prop[0-7]
  51.     db (((%1>>16)&0xF) | (%3>>4)&0xF0) ;limit[16-19]prop[8-11]
  52.     db (%2>>24) & 0xFF
  53. %endmacro
  54. gdt_base: DESC 0, 0, 0 ;desc_dummy
  55. gdt_code: DESC 0xFFFFF, 0x0, (G_1|DB_1|AVL_0|P_1|DPL_0|S_1|TYPE_8)    -->改gdt_code的granularity由字节到4K,增大code的段界限
  56. gdt_data: DESC 0xFFFFF, 0x0, (G_1|DB_1|AVL_0|P_1|DPL_0|S_1|TYPE_2)
  57. gdt_video: DESC 0xFFFF, 0xB8000, (G_0|DB_1|AVL_0|P_1|DPL_0|S_1|TYPE_2)

  58. gdt_ptr:
  59.     dw 32 ;gdt_limit: 4*8=32, only 4 gdt item
  60.     dd gdt_base ;gdt_base

  61. select_code equ (0x01<<3)|TI_0|RPL_0
  62. select_data equ (0x02<<3)|TI_0|RPL_0
  63. select_video equ (0x03<<3)|TI_0|RPL_0
  64. begin:
  65.     mov cx, ax
  66.     ;----------------- 打开A20 ----------------
  67.     in al,0x92
  68.     or al,0000_0010B
  69.     out 0x92,al

  70.     ;----------------- 加载GDT ----------------
  71.     lgdt [gdt_ptr]

  72.     ;----------------- cr0第0位置1 ----------------
  73.     mov eax, cr0
  74.     or eax, 0x00000001
  75.     mov cr0, eax

  76.     ;----------------- 跳到保护模式 ----------------
  77.     jmp select_code:protect_mode
  78. [bits 32]
  79. protect_mode:
  80.     mov ax, select_data
  81.     mov ds, ax
  82.     mov es, ax
  83.     mov ss, ax               -->因为下面有函数调用需要使用栈,所以这儿设置一下ss
  84.     mov ax, select_video
  85.     mov gs, ax
  86.     mov byte [gs:160], 'P'
  87.     mov byte [gs:161], 0xA4

  88.     call setup_page_table    

  89.     sgdt [gdt_ptr]
  90.     
  91.     or dword [gdt_ptr+2], 0xC0000000 ;gdt_ptr
  92.     ;or byte [gdt_base+7], 0xC0 ;change gdt_code base addr     -->不用改gdt_code的基址
  93.     ;or byte [gdt_base+8+7], 0xC0 ;change gdt_data base addr   -->不用改gdt_data的基址
  94.     or byte [gdt_base+16+7], 0xC0 ;change gdt_video base addr

  95.     or esp, 0xC0000000

  96.     mov eax, PAGE_POS
  97.     mov cr3, eax
  98.         
  99.     ;打开cr0的pg位
  100.     mov eax, cr0
  101.     or eax, 0x80000000
  102.     mov cr0, eax

  103.     lgdt [gdt_ptr]

  104.     mov byte [gs:162], 'G'
  105.     mov byte [gs:163], 0xA4

  106.  jmp select_code:enter_kernel     ;强制刷新流水线,更新gdt

  107. enter_kernel:
  108.    call kernel_init
  109.    mov esp, 0xc009f000
  110.    ;mov dword [0xC0001500], 0x00
  111.    jmp dword 0xC0001500 ;read from PE
  112.    ;jmp 0x1500 ;read from PE


  113. ;----------------- 将kernel.bin中的segment拷贝到编译的地址 -----------
  114. kernel_init:
  115.    xor eax, eax
  116.    xor ebx, ebx        ;ebx记录程序头表地址
  117.    xor ecx, ecx        ;cx记录程序头表中的program header数量
  118.    xor edx, edx        ;dx 记录program header尺寸,即e_phentsize

  119.    mov dx, [0x70000+42]     ; 偏移文件42字节处的属性是e_phentsize,表示program header大小
  120.    mov ebx, [0x70000+28] ; 偏移文件开始部分28字节的地方是e_phoff,表示第1 个program header在文件中的偏移量
  121.                      ; 其实该值是0x34,不过还是谨慎一点,这里来读取实际值
  122.    add ebx, 0x70000
  123.    mov cx, [0x70000 + 44] ; 偏移文件开始部分44字节的地方是e_phnum,表示有几个program header
  124. _each_segment:
  125.    cmp byte [ebx + 0], PT_NULL         ; 若p_type等于 PT_NULL,说明此program header未使用。
  126.    je .PTNULL

  127.    ;为函数memcpy压入参数,参数是从右往左依然压入.函数原型类似于 memcpy(dst,src,size)
  128.    push dword [ebx + 16]         ; program header中偏移16字节的地方是p_filesz,压入函数memcpy的第三个参数:size
  129.    mov eax, [ebx + 4]             ; 距程序头偏移量为4字节的位置是p_offset
  130.    add eax, 0x70000     ; 加上kernel.bin被加载到的物理地址,eax为该段的物理地址
  131.    push eax                 ; 压入函数memcpy的第二个参数:源地址
  132.    push dword [ebx + 8]             ; 压入函数memcpy的第一个参数:目的地址,偏移程序头8字节的位置是p_vaddr,这就是目的地址
  133.    call mem_cpy                 ; 调用mem_cpy完成段复制
  134.    add esp,12                 ; 清理栈中压入的三个参数
  135. .PTNULL:
  136.    add ebx, edx                 ; edx为program header大小,即e_phentsize,在此ebx指向下一个program header
  137.    loop _each_segment
  138.    ret

  139. ;---------- 逐字节拷贝 mem_cpy(dst,src,size) ------------
  140. ;输入:栈中三个参数(dst,src,size)
  141. ;输出:
  142. ;---------------------------------------------------------
  143. mem_cpy:        
  144.    cld
  145.    push ebp
  146.    mov ebp, esp
  147.    push ecx         ; rep指令用到了ecx,但ecx对于外层段的循环还有用,故先入栈备份
  148.    mov edi, [ebp + 8]     ; dst
  149.    mov esi, [ebp + 12]     ; src
  150.    mov ecx, [ebp + 16]     ; size
  151.    rep movsb         ; 逐字节拷贝

  152.    ;恢复环境
  153.    pop ecx        
  154.    pop ebp
  155.    ret

  156. setup_page_table:
  157.     mov ecx, 0x400 ;1PTE:4K=0x1000
  158.     xor esi, esi
  159.     xor eax, eax
  160. _init_page_table:
  161.     mov [PAGE_POS+esi], eax
  162.     add esi,0x04
  163.     loop _init_page_table

  164.     ;PDE0, PDE768 use the same PTE0
  165.     mov eax, (PG_US_1|PG_RW_1|PG_P_1)
  166.     or eax, ((PAGE_POS+0x1000)&0xFFF000)
  167.     mov [PAGE_POS+0x0], eax
  168.     mov [PAGE_POS+0xc00], eax
  169.     sub eax, 0x1000
  170.     mov [PAGE_POS+0xFFC], eax

  171.     ;PTE for PDE0 and PDE768
  172.     mov ecx,256
  173.     xor esi,esi
  174.     mov eax, (PG_US_1|PG_RW_1|PG_P_1)
  175. _create_pte:
  176.     mov [PAGE_POS+0x1000+esi],eax
  177.     add esi,0x04
  178.     add eax,0x1000
  179.     loop _create_pte

  180.     ;create other PDE for kernel
  181.     mov eax, (PG_US_1|PG_RW_1|PG_P_1)
  182.     or eax, ((PAGE_POS+0x2000)&0xFFF000)
  183.     mov ecx,254
  184.     mov esi,0x04
  185. _create_pde:
  186.     mov [PAGE_POS+0xc00+esi], eax
  187.     add esi, 0x04
  188.     add eax, 0x1000
  189.     loop _create_pde

  190.     ret
1.4 代码打包
6kernel.rar(下载后改名为6kernel.rar)

附录: ELF解析测试程序
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <errno.h>
  5. #include <sys/types.h>
  6. #include <sys/stat.h>
  7. #include <fcntl.h>
  8. #include <stdint.h>
  9. #define dbmsg(fmt, args ...) printf("%s:%s[%d]: "fmt"\n", __FILE__,__FUNCTION__, __LINE__,##args)

  10. typedef uint16_t Elf32_Half;
  11. typedef uint32_t Elf32_Word;
  12. typedef uint32_t Elf32_Addr;
  13. typedef uint32_t Elf32_Off;

  14. #define EI_NIDENT (16)

  15. typedef struct
  16. {
  17.     unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
  18.     Elf32_Half e_type; /* Object file type */
  19.     Elf32_Half e_machine; /* Architecture */
  20.     Elf32_Word e_version; /* Object file version */
  21.     Elf32_Addr e_entry; /* Entry point virtual address */
  22.     Elf32_Off e_phoff; /* Program header table file offset */
  23.     Elf32_Off e_shoff; /* Section header table file offset */
  24.     Elf32_Word e_flags; /* Processor-specific flags */
  25.     Elf32_Half e_ehsize; /* ELF header size in bytes */
  26.     Elf32_Half e_phentsize; /* Program header table entry size */
  27.     Elf32_Half e_phnum; /* Program header table entry count */
  28.     Elf32_Half e_shentsize; /* Section header table entry size */
  29.     Elf32_Half e_shnum; /* Section header table entry count */
  30.     Elf32_Half e_shstrndx; /* Section header string table index */
  31. } Elf32_Ehdr;


  32. int readelf(int fd)
  33. {
  34.     int i;
  35.     unsigned char* p;
  36.     unsigned char buf[2048];    
  37.     Elf32_Ehdr h;
  38.     read(fd, &h, sizeof(h));
  39.     p = (unsigned char*)&h;
  40.     for(i=0; i<sizeof(h); i++)
  41.     {
  42.         printf("%2d=0x%02x ", i, p[i]);
  43.         if((i+1)%16==0)
  44.             printf("\n");
  45.     }
  46.     printf("\n");
  47.     printf("header_size=%d\n", sizeof(h));
  48.     printf("type=0x%x,mach=0x%x\n",h.e_type, h.e_machine);
  49.     printf("entry=0x%x,phnum=0x%x\n",h.e_entry, h.e_phnum);
  50.     return 0;
  51. }

  52. int main ( int argc, char *argv[] )
  53. {
  54.     int fd = open("./kernel.bin", O_RDWR);
  55.     if(fd < 0)
  56.     {
  57.         dbmsg("open error");
  58.         return -1;
  59.     }
  60.     readelf(fd);
  61.     return EXIT_SUCCESS;
  62. }


阅读(1288) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~