反汇编银河麒麟操作系统
看到一些煽情的宣传颇为恼火所以反汇编了一下,工具就用的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