2006-03-17

反汇编银河麒麟操作系统

Views: 12143 | 2 Comments

反汇编银河麒麟操作系统

看到一些煽情的宣传颇为恼火所以反汇编了一下,工具就用的qemu+gdb,详细方法与调试FreeBSD或者Linux内核差不多,只是麒麟内核中的符号很少调试起来不太方便。

本想详细的写一下反汇编的结果并臭骂一通,不过,也算了,我文笔不好OS又太大,少了文字写不清楚。仅仅说说我得到的结论吧。

麒麟的内核就是FreeBSD5内核,并不是什么微内核,其中有轻微的修改,可能是为了优化,另外,编译的选项上加了很强的优化,从反汇编的代码可以看出来,这大概是为什么官方声称比 FreeBSD与Linux快了(配置的内核一般总比generic内核快)。

证据有很多,大致讲,初始化代码与FreeBSD雷同;使用默认的引导选项时内核打印的信息与 FreeBSD打印的雷同,包括FreeBSD版权信息都没有去掉;内核的系统调用入口与FreeBSD雷同,随机找了几个系统调用的实现与 FreeBSD相同;内核使用了FreeBSD的KSE实现,内核的上下文切换算法与FreeBSD雷同;进程调度器与FreeBSD的4BSD调度器相同………………

看来,我要是不把详细的步骤写出来,会被怀疑居心不良了。

1。反汇编环境。

下载麒麟第一张ISO到文件/mnt/data/kylin.iso,并将其挂载到/cdrom,使用一个已经装好FreeBSD的qemu硬盘~/FreeBSD。

你需要有gdb。准备两个shell,shell1一个启动qemu,如果自己没有FreeBSD代码,可以到这里看 http://fxr.watson.org/ shell2启动gdb

2.开始

在shell2中,

[prime@~] $ gdb /cdrom/boot/kernel/kernel_smp
GNU gdb 6.1.1 [FreeBSD] Copyright 2004 Free Software Foundation, 
Inc. GDB is free software, covered by the GNU General Public License, 
and you are welcome to change it and/or distribute copies of it under certain conditions. 
Type "show copying" to see the conditions. There is absolutely no warranty for GDB. 
Type "show warranty" for details. This GDB was configured as "i386-marcel-freebsd"... 
(no debugging symbols found)... 
(gdb) target remote localhost:1234

在shell1中,

[prime@~] $ qemu -cdrom /mnt/data/kylin.iso -hda FreeBSD -boot d -s &
[1] 660
[prime@~] $ Waiting gdb connection on port 1234

然后qemu启动了,在shell2中出现


Remote debugging using localhost:1234 0x00008789 in ?? () warning: no shared library support for this OS / ABI (gdb)

现在还没有加载内核,我们先设置断点在btext的开始,这是内核的入口,用ELF工具可以看到btext的地址是0xc0443a40,但是注意这时候内核没有启用页表,所以实际的断点位置应该是0xc0443a40 - 0xc0000000 = 0x443a40

在shell2中

(gdb) break *0x443a40 Breakpoint 1 at 0x443a40
(gdb) c Continuing. Breakpoint 1, 0x00443a40 in ?? ()
(gdb)

这时候qemu已经停止,内核完全加载进入了内存,先看看btext开始的代码,1000是个随便的数字,只要足够大,以便看到足够多的指令。

(gdb) x /1000i 0x443a40
0x443a40: movw $0x1234,0x472
0x443a49: push %ebp
0x443a4a: mov %esp,%ebp
0x443a4c: push $0x2
0x443a4e: popf
0x443a4f: mov %ds,%ax
0x443a52: mov %eax,%fs
0x443a54: mov %eax,%gs
0x443a56: mov $0x9f45dc,%ecx
0x443a5b: mov $0x99ed78,%edi
0x443a60: sub %edi,%ecx
0x443a62: xor %eax,%eax
0x443a64: cld
0x443a65: repz stos %al,%es:(%edi)
0x443a67: call 0x443b38
0x443a6c: mov $0x905e40,%esp
0x443a71: call 0x443bcc
0x443a76: call 0x443d0a
0x443a7b: testl $0x2,0x997450
0x443a85: je 0x443a90
0x443a87: mov %cr4,%eax
0x443a8a: or $0x1,%eax
0x443a8d: mov %eax,%cr4
---Type to continue, or q to quit---
0x443a90: mov 0x905eac,%eax
0x443a95: mov %eax,%cr3
0x443a98: mov %cr0,%eax
0x443a9b: or $0x80000001,%eax
0x443aa0: mov %eax,%cr0
0x443aa3: push $0xc0443aa9
0x443aa8: ret
0x443aa9: mov 0xc0905eb8,%eax
0x443aae: lea 0x1da0(%eax),%esp
0x443ab4: xor %ebp,%ebp
0x443ab6: mov 0xc0905eac,%esi
0x443abc: mov %esi,0x1da0(%eax)
0x443ac2: pushl 0xc0905e98
0x443ac8: call 0x867847
0x443acd: add $0x4,%esp
0x443ad0: call 0x65c64b
0x443ad5: add $0x0,%esp
0x443ad8: call *0x10(%esp)
0x443adc: lea 0x20(%esp),%eax
0x443ae0: push %eax
0x443ae1: testl $0x20000,0x54(%eax)
0x443ae8: jne 0x443aed
0x443aea: movl 0x14(%eax),%gs
---Type to continue, or q to quit---
......

下面的我就不贴了,你现在可以打开FreeBSD5.3的源代码进行比较了。

[prime@~] $ less /sys/i386/i386/locore.s

下面省略了文件的版权与宏定义等部分,只列出实际的部分代码

.text NON_GPROF_ENTRY(btext)
movw $0x1234,0x472
pushl %ebp
movl %esp, %ebp
pushl $PSL_KERNEL
popfl mov %ds, %ax
mov %ax, %fs
mov %ax, %gs
movl $R(end),%ecx
movl $R(edata),%edi
subl %edi,%ecx
xorl %eax,%eax
cld rep stosb
call recover_bootinfo
movl $R(tmpstk),%esp
call identify_cpu
call create_pagetables
testl $CPUID_VME, R(cpu_feature)
jz 1f
movl %cr4, %eax
orl $CR4_VME, %eax
movl %eax, %cr4
movl R(IdlePTD), %eax
movl %eax,%cr3
movl %cr0,%eax
orl $CR0_PE|CR0_PG,%eax
movl %eax,%cr0
pushl $begin ret
begin:
movl proc0kstack,%eax
leal (KSTACK_PAGES*PAGE_SIZE-PCB_SIZE)(%eax),%esp
xorl %ebp,%ebp
......

好先分析这些,我们看看create_pagetables,identify_cpu, recover_bootinfo的内核地址 0xc0443d0a 0xc0443bcc 0xc0443b38 那么在启动页表前的地址就是0x443d0a,0x443bcc,0x443b38 那么前面的call 0x443b38 就是call recover_bootinfo其他两个类推。

其他的函数名与变量名都用这个方法,自己比较吧。看看差别多少。

自己阅读/sys/i386/i386/locore.s,我省略了很多注释,宏定义,条件编译与数据定义,只贴了代码。

现在我们进入保护模式启用页表,这样调试起来会方便一点。

在shell2中,因为从begin这一点开始内核进入了保护模式并启用了页表,所以可以直接用begin这个符号。

(gdb) break begin Breakpoint 2 at 0xc0443aa9
(gdb) c Continuing. Breakpoint 2, 0xc0443aa9 in begin () (gdb)

现在来反汇编btext会更清楚一点,另外create_pagetables等函数的比较我就不贴了,有兴趣的自己比较。

(gdb) disassemble btext
Dump of assembler code for function btext:
0xc0443a40 : movw $0x1234,0x472
0xc0443a49 : push %ebp
0xc0443a4a : mov %esp,%ebp
0xc0443a4c : push $0x2
0xc0443a4e : popf
0xc0443a4f : mov %ds,%ax
0xc0443a52 : mov %eax,%fs
0xc0443a54 : mov %eax,%gs
0xc0443a56 : mov $0x9f45dc,%ecx
0xc0443a5b : mov $0x99ed78,%edi
0xc0443a60 : sub %edi,%ecx
0xc0443a62 : xor %eax,%eax
0xc0443a64 : cld
0xc0443a65 : repz stos %al,%es:(%edi)
0xc0443a67 : call 0xc0443b38
0xc0443a6c : mov $0x905e40,%esp
0xc0443a71 : call 0xc0443bcc
0xc0443a76 : call 0xc0443d0a
0xc0443a7b : testl $0x2,0x997450
0xc0443a85 : je 0xc0443a90
0xc0443a87 : mov %cr4,%eax
0xc0443a8a : or $0x1,%eax
---Type to continue, or q to quit---

我们要反汇编init386与mi_startup,当然你可以单步跟进到这两个函数,看看执行流程。不过这里直接进入了。

在shell2中

(gdb) break init386 Breakpoint 3 at 0xc086784d
(gdb) break mi_startup Breakpoint 4 at 0xc065c651
(gdb)c Continuing. Breakpoint 3, 0xc086784d in init386 () 
(gdb)disass Dump of assembler code for function init386:

0xc0867847 : push %ebp
0xc0867848 : mov %esp,%ebp
0xc086784a : push %edi
0xc086784b : push %esi
0xc086784c : push %ebx
0xc086784d : sub $0x28,%esp
0xc0867850 : mov 0xc0905eb4,%eax
0xc0867855 : mov %eax,0xc09b7d84
0xc086785a : mov 0xc0905eb8,%eax
0xc086785f : mov %eax,0xc09b7ef4
0xc0867864 : add $0x1da0,%eax
0xc0867869 : mov %eax,0xc09b7ec4
0xc086786e : movl $0xc09b7dc0,0x8(%esp)
0xc0867876 : movl $0xc09b7f20,0x4(%esp)
0xc086787e : movl $0xc09b7be0,(%esp)
0xc0867885 : call 0xc0696e88
0xc086788a : mov $0x0,%edi
0xc086788f : cmpl $0x0,0xc0905e90
0xc0867896 : je 0xc08678b5
0xc0867898 : mov 0xc0905e90,%eax
0xc086789d : sub $0x40000000,%eax
0xc08678a2 : mov %eax,0xc09c00fc
---Type to continue, or q to quit---
0xc08678a7 : movl $0xc0000000,(%esp)
0xc08678ae : call 0xc06a7228
0xc08678b3 : jmp 0xc08678ba
0xc08678b5 : mov $0x1,%edi
0xc08678ba : cmpl $0x1,0xc099dd38
0xc08678c1 : jne 0xc08678cf
0xc08678c3 : movl $0xc099dd3c,0xc09bb320
0xc08678cd : jmp 0xc08678e7
0xc08678cf : cmpl $0x0,0xc0905e8c
0xc08678d6 : je 0xc08678e7
0xc08678d8 : mov 0xc0905e8c,%eax
0xc08678dd : sub $0x40000000,%eax
0xc08678e2 : mov %eax,0xc09bb320
0xc08678e7 : call 0xc06a764c
0xc08678ec : movl $0xffffffff,0xc0997a30
0xc08678f6 : movl $0xffffffff,0xc0997a3c
0xc0867900 : mov $0xffc00000,%esi
0xc0867905 : movl $0x2,0xc0997a48
0xc086790f : mov %esi,0xc0997a44
0xc0867915 : movl $0xffc00040,0xc0997a50
0xc086791f : mov $0x0,%ebx
0xc0867924 : lea 0xc09ee920(,%ebx,8),%eax
0xc086792b : mov %eax,0x4(%esp)
---Type to continue, or q to quit---
............

自己比较吧,FreeBSD的init386在/sys/i386/i386/machdep.c,mi_startup在 /sys/kern/init_main.c 在mi_startup中调用了内核的子系统初始化函数。单步执行,对各个调用的函数进行反汇编与FreeBSD比较。注意,这个函数调用的函数非常的多,最好有心理准备。比如要比较mi_switch函数,那么,

在shell2中,

(gdb) disassemble mi_switch
Dump of assembler code for function mi_switch:

0xc0692c6d : push %ebp
0xc0692c6e : mov %esp,%ebp
0xc0692c70 : push %edi
0xc0692c71 : push %esi
0xc0692c72 : push %ebx
0xc0692c73 : sub $0x40,%esp
0xc0692c76 : mov %fs:0x0,%eax
0xc0692c7c : mov %eax,0xffffffcc(%ebp)
0xc0692c7f : mov (%eax),%edi
0xc0692c81 : testl $0x1,0x8(%ebp)
0xc0692c88 : je 0xc0692c92
0xc0692c8a : mov 0x2c(%edi),%eax
0xc0692c8d : incl 0x40(%eax)
0xc0692c90 : jmp 0xc0692c98
0xc0692c92 : mov 0x2c(%edi),%eax
0xc0692c95 : incl 0x44(%eax)
0xc0692c98 : lea 0xffffffe4(%ebp),%ebx
0xc0692c9b : mov %ebx,(%esp)
0xc0692c9e : call 0xc0695040
0xc0692ca3 : lea 0xac(%edi),%esi
0xc0692ca9 : mov 0x4(%esi),%ecx
0xc0692cac : mov 0x8(%esi),%ebx
---Type to continue, or q to quit---
......

好了,先写这么多。

创建于: 2006-02-16 22:36:14,修改于: 2006-02-20 12:16:56,已浏览3520次,有评论9条


部分网友评论(并不是全部的网友评论,我只转载部分---ideawu.net注)

网友:BSDlover 时间:2006-02-25 12:20:50 IP地址:159.226.21.★

呵呵,基于BSD的系统多了去了,比如CISCO的IOS。没什么好奇怪的,关键是看他们自己做了多少工作。老实说,现在任何一个新的操作系统想要成功,都得站在巨人的肩膀上。当然现在只有两个肩膀站。

网友:MingyanGuo 时间:2006-02-25 17:09:14 IP地址:211.87.218.★

关键的是宣传的太煽情。以现有的OS为基础并没什么丢人的,大大方方的承认也就没什么了。
重新发明轮子并不是什么值得赞赏的事情。

网友:boimagine 时间:2006-02-26 23:03:31 IP地址:203.88.204.★

请问可以转载吗? 想等更多的人知道.

网友:MingyanGuo 时间:2006-02-27 07:20:36 IP地址:211.87.218.★
呵呵,随便转载

转载自:http://www.cublog.cn/u/10543/?u=http://www.cublog.cn/u/10543/showart.php?id=75549

Related posts:

  1. PHP的continue 2
  2. 安装Linux的ATI显卡驱动,支持硬件3D加速
  3. 为什么iComet比nginx-push-stream-module更好?
  4. 编写简单的计算器。
  5. git 常用操作
Posted by ideawu at 2006-03-17 18:30:58

2 Responses to "反汇编银河麒麟操作系统"

Leave a Comment