注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

熊猫正正的博客

熊猫正正的天空

 
 
 

日志

 
 

Vista的启动调试(摘)  

2012-03-09 00:15:51|  分类: BookKit学习与研 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

在Vista之前,NTLDR是Windows操作系统的加载程序,它负责将CPU从实模式切换为保护模式,加载内核文件和启动类型的驱动程序,然后把执行权交给内核文件的入口函数,即KiSystemStartup。

从要完成的任务角度来看,NTLDR内部又分为两个部分,一部分负责接受执行权,做模式切换,硬件检查,即启动的准备工作,这部分通常称为boot;另一部分负责加载内核文件,并为内核的运行做必要的准备,通常称为OsLoader。

Vista将以上两个部分分成两个独立的程序文件,即BootMgr和WinLoad.exe。下图描述了BootMgr和WinLoad的相互关系和它们在启动过程中的作用。



与调试NTLDR需要替换check版本的NTLDR不同,在BootMgr和WinLoad内部都已经内建了调试引擎,这与内核的做法是一致的。因此,如果要调试BootMgr和WinLoad只要启动它们内部的调试引擎,不需要替换这两个程序文件。

启用BOOTMGR调试的方法是在具有管理员权限的控制台窗口中执行如下命令:
bcdedit /set {bootmgr} bootdebug on
bcdedit /set {bootmgr} debugtype serial
bcdedit /set {bootmgr} debugport 1
bcdedit /set {bootmgr} baudrate 115200

其中后三行是设置调试器与调试引擎的连接方式,如果使用1394,那么应该设置为:

bcdedit /set {bootmgr} debugtype 1394
bcdedit /set {bootmgr} channel 22

做以上设置后,重新启动系统,BIOS阶段过后,屏幕会保持黑色,呈现无法继续启动的样子,事实上,这是BootMgr在等待与调试器建立连接。连接好电缆后,启动WinDBG调试器,二者就会建立连接,显示类似下面这样的信息:

Microsoft (R) Windows Debugger Version 6.9.0003.113 X86
Copyright (c) Microsoft Corporation. All rights reserved.

Opened \\.\com1
Waiting to reconnect…
BD: Boot Debugger Initialized
Connected to Windows Boot Debugger 6000 x86 compatible target, ptr64 FALSE
Kernel Debugger connection established.
Symbol search path is: SRV*d:\symbols*http://msdl.microsoft.com/download/symbols
Executable search path is:
Windows Boot Debugger Kernel Version 6000 UP Free x86 compatible
Product: unknown , suite: SmallBusiness Enterprise BackOffice CommunicationServer TerminalServer SmallBusinessRestricted EmbeddedNT DataCenter SingleUserTS Personal Blade EmbeddedRestricted SecurityAppliance StorageServer ComputeServer <8000>
Primary image base = 0×00400000 Loaded module list = 0x004ffff8
System Uptime: not available

其中0×00400000是BootMgr模块的基地址。BootMgr的主要代码都是32位的,只有一小部分16位代码,负责从固件那里接过控制权。另外,值得说明的是,BootMgr是工作在保护模式下的,但它没有启用分页机制,只是使用分页机制。观察CR0和CR3寄存器的取值,可以证明这一点:

kd> r cr0
cr0=00000011
kd> r cr3
cr3=00000000

建立连接后,WinDBG会让BootMgr继续运行,BootMgr通常会显示启动菜单。此时按下Ctrl+Break键,那么BootMgr就会中断到调试器中,此时可以执行各种内核调试命令,比如:

kd> lm
start end module name
00400000 00514000 bootmgr (pdb symbols) d:\symbols\bootmgr.pdb\819F5A93195D47E3857ED729B0D341191\bootmgr.pdb
微软的符号服务器提供了BootMgr的公开符号文件,因此只要设置好符号服务器的路径,那么WinDBG就可以自动下载合适的符号文件。

kd> x bootmgr!*
0042b3fd bootmgr!TpmApiAuthSessCreateOSAP =
0044c4da bootmgr!CmpGetIndexElementSize =
00452d54 bootmgr!RcConsoleBaudRates =
0042f56f bootmgr!OsxmlBrowser::~OsxmlBrowser =
00431b10 bootmgr!XslStylesheet::getContents =

…….

当然也可以使用栈回溯命令来观察函数调用情况:

kd> kv
ChildEBP RetAddr Args to Child
00061e34 00430c7e 001b6380 00000001 00061e90 bootmgr!DbgBreakPoint
00061e44 0043024f 00061e8c 001b63b8 00061e88 bootmgr!BlXmlConsole::getInput+0xe
00061e90 004024c1 00000002 004021f3 00000000 bootmgr!OsxmlBrowser::browse+0xe0
00061e98 004021f3 00000000 00000000 00061f8f bootmgr!BmDisplayGetBootMenuStatus+0×13 (FPO: [0,0,1])
00061f10 004017a4 00104f9c 001f4280 00000002 bootmgr!BmDisplayBootMenu+0×174
00061f6c 00401261 00104f9c 00061f9c 00000002 bootmgr!BmpGetSelectedBootEntry+0xf8
00061ff0 000209ea 000249a8 7d8b697c 74ff8514 bootmgr!BmMain+0×261
WARNING: Frame IP not in any known module. Following frames may be wrong.
00000000 f000ff53 f000e2c3 f000ff53 f000ff53 0x209ea
00000000 00000000 f000e2c3 f000ff53 f000ff53 0xf000ff53

通过以上栈回溯可以看到,BmMain是BootMgr的32位代码入口函数;BmDisplayBootMenu是负责显示和管理启动菜单的主要函数。BmMain下方的几个栈帧应该是16位代码执行时留下的痕迹。

对BmpGetSelectedBootEntry函数的返回地址00401261设置个断点后,按F5让目标系统继续执行,此时目标系统的菜单可以活动了,选择引导Vista的一项后,刚才设置的断点立刻命中,单步跟踪可以看到BootMgr加载WinLoad的过程,其中的主要函数有:

bootmgr!BmpLaunchBootEntry

bootmgr!ImgArchPcatStartBootApplication

在BootMgr将执行权交给WinLoad之前,它会调用BlBdStop与调试器断开连接。

如果想继续调试WinLoad,那么应该先启用WinLoad中的调试引擎,其命令是:
bcdedit /set {GUID} bootdebug on

WinLoad启动后,如果它的调试引擎已经启用,那么调试引擎也会与调试器建立连接,并显示与前面类似的建立链接信息。以下是WinLoad中的几个重要函数:

winload!MmArchInitialize
winload!ArchBuildKernelGdt
winload!OslArchpKernelSetupPhase0
winload!OslArchTransferToKernel
其中最后一个负责将执行权转交给内核。移交执行权之前,WinLoad也会调用BlBdStop函数来切断调试会话。如果要继续调试内核,那么应该先启用内核调试,然后在内核阶段再与其建立连接。
如果系统是从休眠中恢复,那么BootMgr会加载WinResume,WinResume中也集成了一个调试引擎,因此也可以对其进行跟踪和调试,例如,下面的栈回溯显示了WinResume程序初始化的过程:
kd> kPL
ChildEBP RetAddr
00120ad8 0059da7f winresume!RtlpBreakWithStatusInstruction
00120cf0 0059d97d winresume!vDbgPrintExWithPrefixInternal+0×100
00120d00 0059641a winresume!DbgPrint+0×11
00120d28 00587550 winresume!BlStatusPrint+0×60
00120d6c 00585524 winresume!ConsoleFirmwareOpen+0×64
00120d88 0058373d winresume!ConsoleOpen+0×58
00120da8 00583242 winresume!BlpDeviceOpen+0x13c
00120dc4 0058bd5b winresume!BlDeviceOpen+0×16
00120ed8 0058bcc7 winresume!DsppRegisterConsole+0×56
00120f6c 0058b999 winresume!DsppInitialize+0xfd
00120f78 005950a2 winresume!BlpDisplayInitialize+0×26
00120f94 0057c0c6 winresume!InitializeLibrary+0×176
00120fe8 004444fa winresume!HbMain+0xc6
WARNING: Frame IP not in any known module. Following frames may be wrong.
00000000 f000eef3 0x4444fa
00000000 00000000 0xf000eef3

概而言之,在一个安装好的Vista系统中,已经内建了四个调试引擎,分别位于BootMgr、WinLoad、WinResume和NTOSKRNL.exe中,可以将这几个调试引擎同时启用,也可以根据需要启用其中的某一个。前三个调试引擎是根据位于内核中的内核调试引擎(KD)克隆出来的,它们使用与KD兼容的协议,对调试器(WinDBG)来说,它并不区分对方是真正的KD还是KD的克隆。因此在BootMgr中断调试会话时,WinDBG提示的信息和内核退出时的信息一样的。

摘自:http://advdbg.org/blogs/advdbg_system/articles/784.aspx

  评论这张
 
阅读(99)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017