一种调试操作系统内核态程序的方法及装置的制作方法

文档序号:6386245阅读:157来源:国知局
专利名称:一种调试操作系统内核态程序的方法及装置的制作方法
技术领域
本发明涉及一种操作系统内核态程序的调试方法及装置,特别是涉及一种可以使用普通调试器对内核态程序进行调试的方法及装置。
背景技术
操作系统为了安全的考虑为程序设计了两种运行态用户态和内核态。普通应用程序运行在用户态,部分特殊程序和操作系统本身运行在内核态。目前的调试器设计来调试用户态的程序,对于内核态的程序,只能使用打印或专用芯片调试接口来进行调试,其缺点是1)使用打印方法其实是没有调试功能,完全根据经验仿制打印语句,而且每次必须重新编译,造成调试效率低下。
2)使用专用芯片调试接口的使用方法与芯片相关,各不相同,有较长的学习周期。
3)芯片调试接口只能进行原始的语句调试,不能感知进程状态,内存使用等信息,使用很不方便。
以上的种种不便使内核态程序的调试很不方便,也导致了开发的困难。因此一般做法是尽量减少内核态程序的编写,只将驱动等简单流程的程序放入内核态,而其它部分放在用户态运行,期望以简单的内核态程序来弥补调试的困难,但这不是根本的解决之道,而且对于性能要求较高的实时应用来说,应尽量将程序放入内核态,以减少不同运行状态之间切换的开销,因此,迫切需要一种能方便在内核态进行程序调试的方法。

发明内容
本发明所要解决的技术问题是提供一种调试操作系统内核态程序的方法及装置,解决普通调试器不能调试运行在操作系统内核态的程序的缺点。
为达到上述目的,本发明提供了一种调试操作系统内核态程序的方法,其特点在于,通过设置运行在内核态的调试桩模块和运行在用户态的前台调试代理模块,使所述前台调试代理模块与所述调试桩模块进行通信,所述调试桩模块接收来自所述前台调试代理模块的调试信息、控制内核线程的运行并获取内核线程的异常信息;所述内核线程将所述异常信息发送给所述调试桩模块,所述调试桩模块将所述异常信息发送给所述前台调试代理模块并由所述前台调试代理模块返回给调试器,从而使调试器进行对内核态程序的调试。
上述的方法,其特点在于,所述内核线程的运行控制包括断点异常处理、单步异常处理、内核信号的处理、读/写内核的内存以及读/写内核的寄存器。
上述的方法,其特点在于,所述异常信息包括断点异常信息和/或单步异常信息。
上述的方法,其特点在于,所述断点异常处理包括遇到一个断点之后,触发一次异常,判断该异常是普通的内核异常还是真正断点异常,如果是普通的内核异常,则转入普通的内核异常处理程序;如果是断点异常则执行正常的断点处理程序。
上述的方法,其特点在于,所述断点异常处理进一步包括如果被调试内核线程停止在普通内核空间,则所述异常不是真正断点异常,仿真一次单步的执行,使线程先从普通内核空间返回到内核应用程序空间中;如果被调试内核线程停止在内核应用程序空间,则所述异常是真正断点异常;如果是内核线程本身发生异常,则所述异常是真正断点异常。
上述的方法,其特点在于,所述单步异常处理包括判断异常是普通的内核异常还是真正单步异常,如果是普通的内核异常,则转入普通的内核异常处理程序;如果是真正单步异常则执行正常的单步异常处理程序。
上述的方法,其特点在于,所述单步异常处理进一步包括如果线程运行在普通内核空间,则该异常不是真正单步异常,退出该异常处理,返回线程所在的原程序;如果该线程是内核线程,则该异常是真正单步异常,转入正常的单步异常处理程序。
上述的方法,其特点在于,所述内核信号处理包括打开被调试的内核线程的断点异常信号、单步异常信号和停止信号的信号屏蔽,使得内核线程在接收所述三种信号的时候能够处理该信号;增加信号处理时机,在调试的时候,使内核线程从普通内核空间跳转到内核线程空间的时候进行一次信号处理。
上述的方法,其特点在于,所述读/写内核的内存空间包括内核调试桩判断该次读/写是否发生在调试状态,是则由内核调试桩接管该次读写内存的任务。
上述的方法,其特点在于,所述内核调试桩读内核的内存空间包括对访问的地址进行检查看判断所述地址是否在内核空间的范围之内,是则执行下一步,否则进行异常处理;如果读取操作要拷贝的长度为L,则L=m×4+n×2+k×1,其中m表示该长度有多少个4字节,n表示减去所有4字节之后还剩下多少个2字节,k表示减去所有4字节和2字节后还剩下多少个1字节,根据起始地址依次拷贝m个四字节,n个2字节,k个1字节;如果出错,则进行异常处理。
上述的方法,其特点在于,所述读/写内核的寄存器包括内核调试桩判断该次读写寄存器是发生在调试状态后,执行如下步骤给任务控制块新增加一个成员变量,在进入异常或者中断的时候将当前异常发生时候的堆栈指针的值保存到该成员变量中;在读取寄存器的时候以该成员变量的值作为基地址来读取发生异常前的各个寄存器的值;在退出异常或者中断的时候,清空该成员变量;在读写堆栈指针寄存器的时候进行特殊的处理,将当前的成员变量值加上堆栈指针寄存器在寄存器结构的位置作为当前堆栈指针寄存器的值。
上述的方法,其特点在于,所述控制内核线程的运行并取得内核线程的异常信息,是通过在系统的关键函数处加入调试桩模块的代码来实现。
上述的方法,其特点在于,进一步包括如下步骤步骤一,通过系统调用的方式,所述前台调试代理模块发送调试信息给所述调试桩模块,所述调试桩模块接收所述调试信息;步骤二,所述调试桩模块对所述调试信息进行相应处理;步骤三,进行断点异常处理;步骤四,进行单步异常处理;步骤五,进行内核信号处理;步骤六,读写内核内存空间;步骤七,读写内核的寄存器;步骤八,将所述异常信息、内存内容或寄存器内容返回给前台调试代理模块。
为了更好的实现本发明的目的,本发明还提供了一种调试操作系统内核态程序的装置,其特点在于,包括调试器、前台调试代理模块、调试桩模块、内核应用程序模块和内核线程模块;所述调试器连接所述前台调试代理模块,所述前台调试代理模块连接所述调试桩模块和所述内核应用程序模块,所述内核线程模块连接所述调试桩模块和所述内核应用程序模块;所述调试桩模块、内核线程模块和内核应用程序模块运行在内核态,运行在用户态的前台调试代理模块与所述调试桩模块进行通信,所述调试桩模块接收来自所述前台调试代理模块的调试信息、控制内核线程的运行并取得内核线程的异常信息;所述内核线程模块将所述异常信息发送给所述调试桩模块,所述调试桩模块将所述状态信息返回给所述前台调试代理模块并由所述前台调试代理模块返回给调试器,从而使调试器进行对内核态程序的调试。
本发明的技术效果在于本发明所述方法设计了一运行在内核态的内核调试桩,调试器通过内核调试桩控制内核线程并返回信息,从而解决了调试器不能调试内核线程的重大难题,使得调试内核线程跟调试用户进程或者用户线程一样方便。且该调试桩是以独立的形式存在,与操作系统关联较少,可以移植到各种通用操作系统之上。
下面结合附图进一步详细说明本发明的具体实施例。


图1是调试系统架构示意图;图2调试桩组成结构图;图3断点异常处理流程图;图4单步异常处理流程图。
具体实施例方式
本发明为了克服普通调试器不能调试运行在操作系统内核态程序的缺点,提出了新的调试架构,如图1所示,调试系统架构具体包括设计一个内核调试桩11,该调试桩11运行在内核态。前台调试代理12同调试桩11进行通信,该调试桩11控制内核线程13的运行。内核线程13在遇到异常事件的时候将异常信息反馈给调试桩11,调试桩11收到该异常信息后将该信息返回给前台调试代理12,前台调试代理12收到该消息返回给调试器14。从而可以用普通的用户态调试器14调试核心态的程序,方便内核态程序的开发。
本发明的方法具体包括以下几个步骤步骤一前台调试代理发送调试信息给内核调试桩。内核调试桩接收用户态前台调试代理发送过来的信息。信息发送是通过系统调用的方式来完成的。
步骤二内核调试桩根据命令信息进行相应处理。处理前台调试代理发送过来的信息。
步骤三断点异常处理在遇到一个断点之后会触发一次断点异常,由于这次异常处理发生在内核态,因此我们接管这次异常。判断它是一次断点异常还是一次普通的内核异常。如果是普通的内核异常,则转入普通的内核异常处理程序中去,否则转入我们的断点异常处理程序中来。具体步骤如下在异常处理中首先要判断被调试内核线程是否停止在普通内核空间,如果是的话,要仿真一次单步的执行,让其先从普通内核空间返回到内核应用程序空间中。也就是说只有发生在内核应用程序的断点异常才是真正的断点异常,否则跳到单步处理。
如果是内核线程发生该异常的话,则认为是一次断点异常,而不是内核异常。因此须转到正常的断点处理程序中。
步骤四单步异常处理同上述步骤三一样,如果是普通的内核异常,则转入普通内核异常处理程序中去,否则由内核调试桩接管该异常,具体步骤如下在该异常处理中首先要判断是否运行在普通内核空间,如果是的话,则退出该异常处理,连续运行该程序。
否则的话,判断该线程是不是内核线程,如果是的话,转入正常的单步异常处理程序。
步骤五内核信号处理
在我们这个方法中,最终的调试手段的实现都是通过信号来完成的,因为在断点异常或者单步异常发生后,都会发送一个断点异常或者单步异常信号给它自己,然后在退出异常处理的时候处理该信号,唤醒父进程。
我们首先需要打开被调试的内核线程的断点异常、单步异常信号、停止信号等3个信号屏蔽,使得内核线程在接收到这些信号的时候能够处理该信号。
增加了信号处理时机,在调试的时候,内核线程从普通内核空间跳转到内核线程空间的时候会进行一次信号处理。
步骤六读写内核内存空间。首先内核调试桩判断该次读写是否发生在调试状态,如果是的话,则内核调试桩接管该次读写内存的任务,内核调试桩读取内核内存空间分以下步骤首先对访问的地址进行检查看是否在内核空间的范围之内。
如果拷贝长度为L的话,则L=m*4+n*2+k*1,m表示该长度有多少个4字节,n表示减去那么多4字节之后还剩下多少个2字节,k依次类推。
根据起始地址依次拷贝m个四字节,n个2字节,k个1字节。
如果出错,则进行异常处理。
步骤七读写内核的寄存器。首先内核调试桩判断该次读写寄存器是否发生在调试状态,如果是的话,则内核调试桩接管这次读写寄存器的任务,内核调试桩读写寄存器的步骤如下首先,给任务控制块新增加一个成员变量,在进入异常或者中断的时候将当前异常发生时候的堆栈指针的值保存到该成员变量中。
在读取寄存器的时候以该成员变量的值作为基地址来读取发生异常前的各个寄存器的值。
在退出异常或者中断的时候,清空该成员变量。
在读写堆栈指针寄存器的时候进行特殊的处理,将当前的成员变量值加上堆栈指针寄存器在寄存器结构的位置就是当前堆栈指针寄存器的值。
步骤八将异常信息或者内存内容或者寄存器内容返回给前台调试代理。
下面结合附图,以本发明在Linux操作系统上的应用为列来做进一步的详细说明
Linux操作系统的内核态程序以使用模块加载的形式进入内核运行,因此内核态应用程序以内核模块的形式存在。如图1,图2所示原理,内核调试桩11内还包括命令处理模块111和异常处理模块112,内核调试桩11的功能是1)获知内核态程序运行状态;2)提供对内存和寄存器的访问3)控制内核态程序的运行,以下分别叙述具体实现获知内核态程序运行状态Linux内核调试桩进入内核后,首先在系统异常处理,系统关键函数(如进程创建,删除等)处加上自己的处理代码,这段处理代码就是异常处理代码,具体的可以分为断点异常处理代码和单步异常处理代码;其中的断点异常处理流程图如图3所示,包括步骤301,发生断点后,判断是否处在普通内核,是则执行步骤305,否则执行步骤302;步骤302,判断线程是否为内核线程且处在跟踪状态,是则执行步骤307,否则执行步骤303;步骤303,判断是否处在普通内核空间,是则执行步骤304,否则执行步骤307;步骤304,转入内核异常处理,转到步骤308;步骤305,置退出普通内核标识;步骤306,模拟一次单步的运行,转到步骤308;步骤307,发送异常信号给被跟踪的进程;步骤308,返回原程序。
单步异常处理流程如图4所示,包括步骤401,判断线程是否运行在普通内核空间,是则执行步骤405,否则执行步骤402;步骤402,判断该线程是否为用户进程,是则执行步骤403,否则执行步骤404;步骤403,对硬件断点进行处理;步骤404,发送单步信号给当前内核线程,转到步骤406;步骤405,禁止单步执行;步骤406,返回原程序。
在图3的断点异常或图4的单步异常发生后,会进入我们设置的处理代码中,在处理代码的末尾我们会发送一信号返回到调试桩,然后进行以下处理if(当前处理的程序是被调试的程序){纪录当前程序执行状态if(是异常处理)暂停程序运行,并通知调试器}跳转回原本处理函数通过以上操作,内核桩模块可以在被调试内核态程序出现异常时通知调试器进行调试,而在程序新创建和删除时,可以获知其状态,供调试器查询。
对内存和寄存器的访问分为两个,第一对内存的访问首先前台调试代理发送读写内存的请求给调试桩,调试桩收到该请求之后,该请求格式定义如下#define PTRACE_PEEKTEXT 1#define PTRACE_POKETEXT 4分别表示读取指定内存空间以及写指定内存的空间,该调试桩收到该请求之后首先判断该地址是否在内核空间之内,如果是,则认为是访问内核应用程序空间,启动调试桩的安全拷贝功能,安全拷贝流程如图3所示。
第二个是对寄存器的访问,调试桩收到读写寄存器的请求之后,取得发生异常时候保存的,该值是在内核发生异常或者中断的时候保存的,我们新开了一个空间,专门用来保存该堆栈指针的值,这个空间在任务控制块的末尾开的,task_struct{…………….
void*kth;int *kth_esp_stack;}kth_esp_stack保存的是异常发生的时候保存现场之后的地址值,但根据用户态现场堆栈保存规律,得出内核线程运行时候的堆栈指针值是(*kth_esp_stack)+0x34,这样就根据该基地址加上各寄存器的偏移量得出各个寄存器的值。
控制内核态程序的运行,前台调试代理通过发送以下调试命令给调试桩控制被调试程序的运行,命令如下表所示#define PTRACE_CONT7连续运行线程#define PTRACE_KILL8杀死线程#define PTRACE_SINGLESTEP 9单步线程#define PTRACE_ATTACH 0x10跟棕一个线程#define PTRACE_DETACH 0x11对一个线程解除跟踪调试代理桩收到以上命令之后switch(命令){case继续运行线程命令调用调试桩继续运行命令接口case对指定线程跟踪调用调试桩跟踪指定线程接口…………………….
}这样就实现了对指定内核程序的控制功能。
由上可知,本发明方法设计了一运行在内核态的内核调试桩,调试器通过内核调试桩控制内核线程并返回信息,从而解决了调试器不能调试内核线程的重大难题,使得调试内核线程跟调试用户进程或者用户线程一样方便。且该调试桩是以独立的形式存在,与操作系统关联较少,可以移植到各种通用操作系统之上。
以上所述仅为本发明的较佳实施例,并非用来限定本发明的实施范围;凡是依本发明所作的等效变化与修改,都被本发明的专利范围所涵盖。
权利要求
1.一种调试操作系统内核态程序的方法,其特征在于,通过设置运行在内核态的调试桩模块和运行在用户态的前台调试代理模块,使所述前台调试代理模块与所述调试桩模块进行通信,所述调试桩模块接收来自所述前台调试代理模块的调试信息、控制内核线程的运行并获取内核线程的异常信息;所述内核线程将所述异常信息发送给所述调试桩模块,所述调试桩模块将所述异常信息发送给所述前台调试代理模块并由所述前台调试代理模块返回给调试器,从而使调试器进行对内核态程序的调试。
2.根据权利要求1所述的方法,其特征在于,所述内核线程的运行控制包括断点异常处理、单步异常处理、内核信号的处理、读/写内核的内存以及读/写内核的寄存器。
3.根据权利要求2所述的方法,其特征在于,所述异常信息包括断点异常信息和/或单步异常信息。
4.根据权利要求3所述的方法,其特征在于,所述断点异常处理包括遇到一个断点之后,触发一次异常,判断该异常是普通的内核异常还是真正断点异常,如果是普通的内核异常,则转入普通的内核异常处理程序;如果是断点异常则执行正常的断点处理程序。
5.根据权利要求4所述的方法,其特征在于,所述断点异常处理进一步包括如果被调试内核线程停止在普通内核空间,则所述异常不是真正断点异常,仿真一次单步的执行,使线程先从普通内核空间返回到内核应用程序空间中;如果被调试内核线程停止在内核应用程序空间,则所述异常是真正断点异常;如果是内核线程本身发生异常,则所述异常是真正断点异常。
6.根据权利要求3所述的方法,其特征在于,所述单步异常处理包括判断异常是普通的内核异常还是真正单步异常,如果是普通的内核异常,则转入普通的内核异常处理程序;如果是真正单步异常则执行正常的单步异常处理程序。
7.根据权利要求6所述的方法,其特征在于,所述单步异常处理进一步包括如果线程运行在普通内核空间,则该异常不是真正单步异常,退出该异常处理,返回线程所在的原程序;如果该线程是内核线程,则该异常是真正单步异常,转入正常的单步异常处理程序。
8.根据权利要求2、3、4、5、6或7所述的方法,其特征在于,所述内核信号处理包括打开被调试的内核线程的断点异常信号、单步异常信号和停止信号的信号屏蔽,使得内核线程在接收所述三种信号的时候能够处理该信号;增加信号处理时机,在调试的时候,使内核线程从普通内核空间跳转到内核线程空间的时候进行一次信号处理。
9.根据权利要求8所述的方法,其特征在于,所述读/写内核的内存空间包括内核调试桩判断该次读/写是否发生在调试状态,是则由内核调试桩接管该次读写内存的任务。
10.根据权利要求9所述的方法,其特征在于,所述内核调试桩读内核的内存空间包括对访问的地址进行检查看判断所述地址是否在内核空间的范围之内,是则执行下一步,否则进行异常处理;如果读取操作要拷贝的长度为L,则L=m×4+n×2+k×1,其中m表示该长度有多少个4字节,n表示减去所有4字节之后还剩下多少个2字节,k表示减去所有4字节和2字节后还剩下多少个1字节,根据起始地址依次拷贝m个四字节,n个2字节,k个1字节;如果出错,则进行异常处理。
11.根据权利要求8所述的方法,其特征在于,所述读/写内核的寄存器包括内核调试桩判断该次读写寄存器是发生在调试状态后,执行如下步骤给任务控制块新增加一个成员变量,在进入异常或者中断的时候将当前异常发生时候的堆栈指针的值保存到该成员变量中;在读取寄存器的时候以该成员变量的值作为基地址来读取发生异常前的各个寄存器的值;在退出异常或者中断的时候,清空该成员变量;在读写堆栈指针寄存器的时候进行特殊的处理,将当前的成员变量值加上堆栈指针寄存器在寄存器结构的位置作为当前堆栈指针寄存器的值。
12.根据权利要求8所述的方法,其特征在于,所述控制内核线程的运行并取得内核线程的异常信息,是通过在系统的关键函数处加入调试桩模块的代码来实现。
13.根据权利要求1所述的方法,其特征在于,进一步包括如下步骤步骤一,通过系统调用的方式,所述前台调试代理模块发送调试信息给所述调试桩模块,所述调试桩模块接收所述调试信息;步骤二,所述调试桩模块对所述调试信息进行相应处理;步骤三,进行断点异常处理;步骤四,进行单步异常处理;步骤五,进行内核信号处理;步骤六,读写内核内存空间;步骤七,读写内核的寄存器;步骤八,将所述异常信息、内存内容或寄存器内容返回给前台调试代理模块。
14.一种调试操作系统内核态程序的装置,其特征在于,包括调试器、前台调试代理模块、调试桩模块、内核应用程序模块和内核线程模块;所述调试器连接所述前台调试代理模块,所述前台调试代理模块连接所述调试桩模块和所述内核应用程序模块,所述内核线程模块连接所述调试桩模块和所述内核应用程序模块;所述调试桩模块、内核线程模块和内核应用程序模块运行在内核态,运行在用户态的前台调试代理模块与所述调试桩模块进行通信,所述调试桩模块接收来自所述前台调试代理模块的调试信息、控制内核线程的运行并取得内核线程的异常信息;所述内核线程模块将所述异常信息发送给所述调试桩模块,所述调试桩模块将所述状态信息返回给所述前台调试代理模块并由所述前台调试代理模块返回给调试器,从而使调试器进行对内核态程序的调试。
全文摘要
本发明公开了一种调试操作系统内核态程序的方法及装置,方法包括通过设置运行在内核态的调试桩模块和运行在用户态的前台调试代理模块,使所述前台调试代理模块与所述调试桩模块进行通信,所述调试桩模块接收来自所述前台调试代理模块的调试信息、控制内核线程的运行并获取内核线程的异常信息;所述内核线程将所述异常信息发送给所述调试桩模块,所述调试桩模块将所述异常信息发送给所述前台调试代理模块并由所述前台调试代理模块返回给调试器,从而使调试器进行对内核态程序的调试。本发明解决了普通调试器不能调试运行在操作系统内核态的程序的缺点。
文档编号G06F11/36GK1779652SQ20041000985
公开日2006年5月31日 申请日期2004年11月24日 优先权日2004年11月24日
发明者刘飞, 程圣宇, 李翌, 缪敬 申请人:中兴通讯股份有限公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1