n路運行時互操作調試的制作方法
【專利摘要】在多種類型的運行時環(huán)境中運行的同時代碼調試可以由n路互操作調試環(huán)境來執(zhí)行。在特定運行時內運行的代碼可以與其他運行時內運行的代碼同時在單個進程內被調試。提供對檢查和執(zhí)行控制的進程外調試支持。兼容調試器或運行時通信協(xié)議被使用。從一個運行時到另一運行時的轉移可被檢測到。在一個運行時中拋出的異??杀涣硪粋€運行時捕獲。步進操作可在多個運行時中發(fā)生。包括來自多個運行時的各幀的調用??杀蛔卟?。
【專利說明】n路運行時互操作調試
[0001]背景
[0002]在調試進程時,可生成調試事件。調試器通常監(jiān)聽調試事件,并對調試事件作出響應。調試事件可以在進程被創(chuàng)建時、在模塊被加載時、在異常被拋出時、及在斷點被遇到時等被創(chuàng)建。調試器使用調試事件和檢查應用編程接口(API)來實現(xiàn)調試操作。在調試事件被分派時,被調試程序(被調試的進程)通常被停止,直到調試器繼續(xù)調試事件。在被調試程序被停止時,調試器可以檢查該被調試程序的狀態(tài)。當被調試程序被繼續(xù)時,該進程運行,直到下一個調試事件被遇到。通常,托管代碼調試和本機代碼調試具有不同的調試事件集合,和在停止狀態(tài)和運行狀態(tài)之間的不同轉移方式。
[0003]本機調試通常由操作系統(tǒng)(OS)來實現(xiàn)。該OS提供用于監(jiān)聽和繼續(xù)調試事件的調試API。在調試事件發(fā)生時,OS凍結被調試程序(正被調試的進程)。本機調試是進程外操作,即該進程被凍結并且該進程之外的代碼(在OS中)檢查來自被凍結進程的值。進程外調試不需要來自被調試程序的協(xié)作。本機被調試程序停止狀態(tài)被稱為凍結,因為該進程已被OS停止,并且沒有代碼在該進程內部執(zhí)行,直到OS再次啟動該進程。
[0004]操作系統(tǒng)不對已凍結進程執(zhí)行虛擬機環(huán)境中(例如,Eclipse中或微軟的Visual Studio?中)的調試。虛擬機環(huán)境中的調試通常由虛擬機的運行時環(huán)境來實現(xiàn),并且是進程中操作。進程內部的代碼執(zhí)行以進行調試操作。OS沒有該類型的調試何時發(fā)生的知識。被調試程序停止狀態(tài)有時被稱為“同步的”,因為從OS的角度來看同步進程是活的,但所有這些線程都被運行時環(huán)境停止。虛擬機調試事件可以被“構建在”本機調試事件“的上方”或使用本機調試事件來實現(xiàn)。
[0005]虛擬機運行時服務實現(xiàn)虛擬機調試操作,而不實現(xiàn)本機調試操作。類似地,本機調試API不提供對虛擬機環(huán)境中的調試的支持。虛擬機環(huán)境中的調試操作和本機調試操作被不同地實現(xiàn)。例如,在Visual Studio?中,托管步進由運行時環(huán)境API來實現(xiàn),而本機步進由消費本機調試事件的本機調試庫來實現(xiàn)。本機執(zhí)行控制(對步進操作和斷點的控制)通常使用OS異常處理來實現(xiàn),并且在本機調試API中缺少顯式支持。托管調試API顯式地具有斷點和步進功能。托管調試的抽象層和本機調試的抽象層中的差異防止在托管調試操作和本機調試操作之間的代碼共享。
[0006]某些IDE能夠在單個調試會話中調試在虛擬機運行時環(huán)境中以及在本機運行時中運行的代碼。這被稱為互操作調試。由于底層的沖突調試架構設計,在已知的互操作調試器中使用的機制是受限的,并且依賴于本機運行時調試器和虛擬機運行時調試器之間單調而脆弱的操作。
[0007]概述
[0008]對在多種類型的運行時環(huán)境中運行的、單個被調試程序進程內的代碼的調試可以使用可擴展調試架構在相同的調試會話中同步執(zhí)行。這樣的同步調試在此被稱為n路互操作調試。N路互操作調試可以提供包括在單個被調試程序進程中(在單個調試會話)執(zhí)行的所有運行時環(huán)境的邏輯視圖在內的整個被調試程序進程的整體視圖。各運行時調試器之間的交互也可被查看。對虛擬機運行時環(huán)境的調試支持允許使用一組調試器接口來促進調試操作的互操作調試。虛擬機運行時環(huán)境所創(chuàng)建的調試支持不會干預對該進程中的其他運行時被調試程序的調試。
[0009]互操作調試允許執(zhí)行控制、使從一個運行時運行的被調試程序代碼步進到另一運行時、在多個運行時被調試程序中設置斷點、檢查來自多個運行時被調試程序的值、以及執(zhí)行包含來自多個運行時調試器的代碼的調用棧。運行時調試器被排定優(yōu)先級,使得最高優(yōu)先級的運行時調試器控制執(zhí)行并展開這個棧。
[0010]符合的運行時被調試程序可以由n路互操作調試器互操作地調試。符合的運行時被調試程序是使用對檢查和執(zhí)行控制的進程外調試支持、使用兼容的調試器/被調試程序通信協(xié)議、可以為執(zhí)行控制和棧展開檢測運行時被調試程序之內和之外的邊界的被調試程序。對于拋出異常的那些運行時被調試程序,各兼容的運行時調試器可以檢測出從一個運行時被調試程序拋出并在另一個運行時被調試程序內捕獲的異常。進程外調試不會涉及被調試程序進程中的執(zhí)行代碼,使得各運行時不會干預彼此的線程模型或執(zhí)行模型。符合的運行時調試器可以被插入到n路互操作調試器中。
[0011]在此描述的各接口和各機制可用作用于步進調試器中的各操作的通用可擴展性模型。
[0012]提供本概述是為了以簡化的形式介紹將在以下詳細描述中進一步描述的選擇的概念。本概述并不旨在標識所要求保護主題的關鍵特征或必要特征,也不旨在用于限制所要求保護主題的范圍。
[0013]附圖簡述
[0014]在附圖中:
[0015]圖1示出了根據(jù)此處所公開的主題的各方面的用于n路互操作調試的系統(tǒng)100的示例;
[0016]圖2a是根據(jù)此處所公開的主題的各方面的用于n路互操作調試的方法200的示例的流程圖;
[0017]圖2b示出了根據(jù)此處所公開的主題的各方面的走查調用棧250的方法的示例;
[0018]圖2c示出了根據(jù)此處所公開的主題的各方面的處理異常270的方法的示例;
[0019]圖3是根據(jù)此處所公開主題的各方面的計算環(huán)境的示例的框圖;以及
[0020]圖4是根據(jù)此處所公開的主題的各方面的集成開發(fā)環(huán)境的示例的框圖。
[0021]詳細描述
[0022]概覽
[0023]根據(jù)此處所公開的主題的各方法,描述了可以用進程中的任何兼容運行時調試器互操作地調試的運行時調試器架構。在n路互操作兼容運行時被調試程序上運行的代碼可以使用進程外操作來調試??梢允褂貌灰笤诒徽{試程序進程內執(zhí)行代碼的OS原語從被調試程序進程的外部執(zhí)行包括但不限于數(shù)據(jù)檢查、執(zhí)行控制和棧展開的核心調試器操作。部分由于在運行時被調試程序進程中執(zhí)行代碼可以在該進程被停止時生成更多調試事件,以及出于其他原因,避免在運行時被調試程序進程中執(zhí)行代碼。進程外調試確保多個運行時被調試程序不會在調試時間干預彼此的線程模塊。它還確保了檢查被調試程序進程內的運行時將不會導致其他運行時調試器無法處理的副作用。
[0024]讀/寫進程存儲器原語允許調試器讀存儲器/將存儲器寫入被調試程序進程。獲取并設置線程上下文原語允許訪問并修改被調試程序進程中的寄存器設置。寫在OS原語上方的調試器原語包括斷點和單步指令。單步操作告訴處理器執(zhí)行單個指令,隨后停止并通知調試器。調試API可以向調試器通知被調試程序進程中發(fā)生的一組事件,包括進程創(chuàng)建和破壞、模塊加載和卸載、斷點命中、單步完成、異常發(fā)生。來自通信信道的通知也使用進程外模型來完成,使得在斷點被命中時,通知被發(fā)送到調試器,而不在被調試程序進程中運行代碼。
[0025]被調試程序進程和進程外調試器之間的兼容協(xié)議被用于與n路互操作調試兼容的運行時。即,運行時被調試程序向調試器通知在被調試程序進程中調試事件已以不會導致其他運行時調試器失靈或無法通信的方式發(fā)生??墒褂玫呐cn路互操作調試兼容的一個協(xié)議是微軟公司所創(chuàng)建的Win32?調試事件模型。
[0026]該進程中與n路互操作兼容的各運行時被調試程序之間的邊界在運行時調試器控制調試操作時是可識別的。例如,如果在運行時調試器A上運行的代碼調用在運行時調試器B上運行的代碼,則運行時調試器B可以檢測到控制已被轉移到運行時調試器B中,并且運行時調試器B可以接管控制調試操作。
[0027]支持異常模型的與n路互操作調試兼容的各運行時調試器能夠標識異常何時被其運行時調試器捕獲。異??梢云鹪从谝粋€運行時調試器,并可在另一個運行時調試器中被捕獲。例如,假設在運行時被調試程序A上運行的代碼調用在運行時被調試程序B上運行的代碼,并且用戶正步進通過在運行時被調試程序B上運行的代碼。如果在該步進操作發(fā)生時拋出了異常,則那個異??梢员贿\行時被調試程序A捕獲。在這種情況下,調試器步進操作可以在那個時刻被掛起。當運行時調試器檢測到異常何時被其運行時被調試程序捕獲時,可生成處理程序發(fā)現(xiàn)通知。來自一個運行時被調試程序的各異??梢员挥米鞅徽{試的另一個運行時的各異常的實現(xiàn)。例如,通用語言運行時(CLR)內拋出的異常實際上是本機的結構化異常處理程序異常。因此,本機調試器不知道某步進在異常被拋出并被捕獲時就完成了,直到CLR的調試器可以檢查處理程序塊以后。各兼容的被調試程序不必使用異常模型來指示錯誤。
[0028]n路互操作調試
[0029]圖1示出了根據(jù)此處所公開的主題的各方面的用于n路運行時互操作調試的系統(tǒng)100的示例。系統(tǒng)100的全部或部分可以駐留在諸如以下參考圖3所描述的計算機之類的一個或多個計算機上。系統(tǒng)100可在諸如參考圖4所描述的軟件開發(fā)計算機之類的軟件開發(fā)計算機上執(zhí)行。系統(tǒng)100可以整體地或部分地在諸如IDE104之類的IDE內執(zhí)行或者可以整體地或部分地在IDE之外執(zhí)行。IDE104可以是諸如參考圖4所描述的IDE之類的IDE,或者可以是任何其它IDE。系統(tǒng)100的全部或部分可被實現(xiàn)為插件或附件。
[0030]系統(tǒng)100可包括諸如計算機102之類的一個或多個計算設備或計算機,包括:諸如處理器142等的一個或多個處理器、諸如存儲器144之類的存儲器、諸如調試器106之類的n路互操作調試器、被調試程序108、和一組調試API120。調試器106可包括一個或多個模塊,包括含步進管理器110和調試監(jiān)視器118的一個或多個模塊。根據(jù)在此所公開的主題的各方面,在被調試程序進程中執(zhí)行的開發(fā)者調試程序代碼可以使用調試器106同時調試多個運行時。開發(fā)者可以從在一個運行時被調試程序中運行的代碼步進到在另一個被調試程序運行時中運行代碼。斷點可被設置在于被調試程序進程中執(zhí)行的運行時被調試程序中的任何一個、部分或全部中。被調試程序值(例如,變量值等)可在一個運行時調試程序中被檢查,同時另一個運行時正被查看。與調試器106相關聯(lián)的調用??砂▉碜远鄠€運行時的代碼。調試器106可包括以下中的一個或多個:本機運行時調試器114、解釋器調試器116、棧提供器117和一個或多個托管運行時調試器112等。調試器106也可以包括棧提供器117。調試器106可以是可擴展的,使得一個或多個n路互操作兼容調試器可被插入到調試器106中。
[0031]被調試程序108可包括以下中的部分或所有:一個或多個托管運行時被調試程序122等、本機運行時被調試程序124和解釋器被調試程序126。模塊的實例可被加載到被運行時標記為轉移模塊(例如,托管運行時被調試程序122的轉移模塊136、本機運行時被調試程序124中的轉移模塊138、解釋器被調試程序126中的轉移模塊140)的被調試程序進程中。也可以包括本領域公知的其他組件,但此處未示出。將理解,以上中的一個或多個可被加載到存儲器144中以使得諸如處理器142等一個或多個處理器執(zhí)行歸于一起執(zhí)行n路互操作調試的一個或多個模塊的動作,如以下更全面描述的。
[0032]步進管理器110可包括在諸如托管運行時調試器112等、本機運行時調試器114和解釋器調試器116的各運行時調試器之間提供通信信道的模塊或類。步進管理器110可實現(xiàn)步進仲裁,如以下更全面描述的。步進管理器110可包括接收存儲包括步進的類型(步進通過、步進進入、步進離開)、步進的單位(語句、行、或指令)及開始幀基數(shù)和地址在內的有關該步進的狀態(tài)的單步請求的模塊。諸如調試監(jiān)視器118之類的調試監(jiān)視器可包括管理調試器(例如,調試器106)和被調試程序(例如,被調試程序108)之間的通信信道的模塊或類。調試監(jiān)視器118可以將調試事件路由到相應的調試器處。例如,在托管運行時被調試程序122中生成的各事件可以被調試監(jiān)視器118路由到托管運行時調試器112處,在本機運行時被調試程序124中生成的各事件可被托管運行時調試器112路由到本機運行時調試器114處,在解釋器126中生 成的各事件可被調試監(jiān)視器118路由到解釋器調試器116處,并以此類推。調試監(jiān)視器118可包括實現(xiàn)調試事件循環(huán)(例如,Win32調試事件循環(huán))的模塊或類。調試監(jiān)視器118可包括可將來自調試器進程運行時的調試事件轉換成與調試API120兼容的調試事件的調試監(jiān)視器模塊或類。
[0033]n路互操作調試器引擎105可以從調用棧窗口接收開始走查各調用棧幀(諸如,調用棧128的幀1130、幀2132……幀nl34)的請求。n路互操作調試器引擎105可以將該調用路由到棧提供器117。棧提供器117可以向每一運行時調試器(例如,托管運行時調試器112等、本機運行時調試器114、解釋器運行時調試器116)詢問該運行時調試器是否擁有當前位置,即當前正被執(zhí)行的指令是否處于屬于那個運行時調試器的幀范圍內。這些運行時調試器按優(yōu)先級次序被詢問。當運行時調試器聲明該位置處于調用棧128中時,各幀由申明運行時(當前控制的運行時調試器)從調用棧128處請求,并被聲明運行時調試器處理,直到申明運行時調試器檢測到不屬于它的幀。各運行時調試器被排定優(yōu)先級,因為一個運行時調試器可以被實現(xiàn)在另一個運行時調試器的上方。各運行時調試器的優(yōu)先級次序是有用的,因為可能諸如解釋器之類的較高級的運行時調試器要使用諸如托管或本機運行時調試器之類的另一運行時來實現(xiàn)。例如,在解釋器運行時調試器用托管代碼來實現(xiàn)的情況下,解釋器運行時調試器可被給予在托管運行時調試器之前展開該幀的機會。假設運行時調試器A被實現(xiàn)在運行時調試器B的上方。運行時調試器A可獲得比運行時調試器B高的優(yōu)先級,以確保較高優(yōu)先級的運行時調試器(即,運行時調試器A)能夠進行執(zhí)行控制并可展開該棧。例如,假設解釋器運行時調試器是用托管代碼來實現(xiàn)的。在這種情況下,解釋器運行時調試器具有比托管代碼運行時調試器高的優(yōu)先級。最后,所有代碼都是本機的,使得本機執(zhí)行引擎和棧展開器可以是最低優(yōu)先級的運行時。
[0034]在n路互操作調試器(諸如調試器106)中的各運行時調試器中的每一個表示正調試特定被調試程序進程的運行時調試器的單個實例。可在調試器106中執(zhí)行的不同類型的運行時調試器的示例包括本機運行時調試器實例、虛擬機運行時調試器實例和解釋器運行時調試器實例。每一運行時調試器實例負責理解并實現(xiàn)對特定運行時被調試程序的調試。即,托管運行時調試器112調試托管運行時被調試程序112,本機運行時調試器114調試本機運行時被調試程序124,并以此類推。
[0035]系統(tǒng)100可提供對檢測和執(zhí)行控制的進程外調試支持。進程外調試被使用,因為雖然托管運行時環(huán)境可以在被調試程序進程中實現(xiàn)調試支持,但這樣做會引入各運行時之間的不兼容性。例如,進程內調試器在被調試應用進程內運行調試器代碼。諸如本機調試器之類的進程外調試器將不允許被調試程序線程在該調試器處于斷點模式時運行。因為進程內調試器可選自大量可能的線程模型中的任何一個,所以為任何進程內調試器都定義允許n路互操作調試的兼容模型是一個難以對付的問題。因此,進程外調試器模型被實現(xiàn)在系統(tǒng)100中。
[0036]符合“進程外”調試器模型的運行時的一個示例是微軟的本機Win32運行時。被設計成調試在Win32操作系統(tǒng)上運行的本機代碼的各調試器使用以下各項的組合:pdb (程序數(shù)據(jù)庫)文件、保持調試和項目狀態(tài)信息的文件、Win32調試AP1、以及關于用于執(zhí)行諸如步進、檢測變量狀態(tài)之類的各種調試器任務的硬件的特征。例如,為了在本機應用中檢查該棧上的本地變量,本機運行時調試器首先查找與Pdb中的變量有關的信息。Pdb中的信息包括該變量的類型、該變量在存儲器中被如何格式化、以及該變量駐留在存儲器中的何處。調試器使用進程外讀存儲器API來從被調試程序進程中獲得該變量的字節(jié)。隨后可如pdb中所描述那樣格式化該值,并將經格式化的信息顯示給用戶。進程外操作的另一示例是步進本機Win32應用。為了執(zhí)行步進操作,本機調試器可以查找被調試程序在pdb中的當前指令指針,以獲得存儲器范圍映射的源行??梢允褂弥T如單步指令和斷點指令之類的原語來使得被調試程序進程執(zhí)行,直到遇到源范圍的末端。
[0037]諸如解釋器或虛擬機運行時環(huán)境之類的需要運行時和調試器之間的更多動態(tài)交互的運行時可以將各數(shù)據(jù)結構展示在公知的位置,以允許相應的調試器在調試時間使用進程外讀存儲器API來讀這些數(shù)據(jù)結構。相應的運行時調試器可以從這些數(shù)據(jù)結構讀并寫入這些數(shù)據(jù)結構,以影響運行時行為。例如,為了在解釋器源行上設置斷點,調試器可以定位斷點數(shù)據(jù)結構,并將信息寫入該數(shù)據(jù)結構,以啟用該斷點。運行時被調試程序可以在執(zhí)行到達該斷點時觸發(fā)該斷點。步進可以被類似地實現(xiàn)。例如,調試器可以將步進信息寫入定義線程的數(shù)據(jù)結構。解釋器可以在步進完成時停止。可以經由進程外讀存儲器API來使得有關線程的棧的信息對數(shù)據(jù)檢查操作可用。調試器可以選擇正確的棧幀,使用進程外讀存儲器來使其與被調試程序中的正確棧幀對象匹配、并使用該數(shù)據(jù)結構來獲取該棧幀上的變量的名稱、值和類型。
[0038]基于即時(JIT)運行時可以以調試器可以使用進程外API來訪問各數(shù)據(jù)結構的方式來展示這些數(shù)據(jù)結構。數(shù)據(jù)結構可以被抽象化成駐留在調試器進程中的較高級對象。調試器可以使用讀和寫進程存儲器來消費各對象。諸如步進和斷點之類的執(zhí)行控制操作可以使用本機代碼會使用的相同的硬件原語(單步和硬件斷點)來實現(xiàn)。從源行到指令地址的實際映射可以基于JIT編譯器的輸出,并因此可以是動態(tài)的。實際映射(和步進范圍)可以通過從進程外讀出各數(shù)據(jù)結構來獲得。
[0039]n路互操作兼容可調試運行時必須具有將各調試事件傳送到調試器的方式。為了支持n路互操作,協(xié)議必須與調試該進程的其他運行時調試器兼容。確保兼容性的一種方式是實現(xiàn)與進程外模型一起工作、而不會導致各個運行時調試器之間的事件混淆的協(xié)議。某些運行時調試器架構出于這個目的而使用諸如命名管道之類的較高級協(xié)議,但這樣的協(xié)議通常違反進程外模型。因此,根據(jù)在此公開的主題的各方面,諸如但不限于Win32調試流水線的本機調試流水線被實現(xiàn)。包括WaitForDebugEvent (等待調試事件)函數(shù)和ContinueDebugEvent (繼續(xù)調試事件)函數(shù)在內的各函數(shù)可被用來允許調試器接收有關進程中正在發(fā)生什么的通知,并在該調試器已完成處理調試事件后繼續(xù)對被調試程序的執(zhí)行。調試事件包括創(chuàng)建進程事件、創(chuàng)建線程事件、加載模塊事件和異常??梢允褂锰囟ó惓4a將命中斷點事件和完成單步事件實現(xiàn)在各異常上方。為了使得多個運行時調試器能夠通過調試API來接收這些事件,n路互操作調試架構可以將調試事件循環(huán)從實際的運行時調試器實現(xiàn)中劃分出來,如下面更全面描述的。
[0040]根據(jù)在此公開的主題的各方面,為了在n路互操作調試器中實現(xiàn)執(zhí)行控制(即,互操作執(zhí)行控制),轉移到運行時和從運行時轉移走必須是可檢測的,因為開始步進操作的運行時調試器可能不是結束該步進操作的運行時調試器。例如,在步進進入操作過程中,如果遇到調用指令,則可以在該進程中可以對在另一運行時被調試程序內運行的代碼作出該調用。當前處于該操作的控制之下的運行時調試器(“當前控制的運行時調試器”)必須能夠放棄控制,并讓另一運行時調試器接管控制。對轉移到另一運行時被調試程序的檢測可以用包括但不限于以下描述的那些方式的各種方式來實現(xiàn)。
[0041 ] 運行時被調試程序可以將標準模塊(即,轉移模塊)用于進入點。即,在步進操作使被調試程序的指令指針抵達轉移模塊的任何時候,到另一運行時被調試程序的可能轉變已被遇到。響應于當前控制運行時調試器可能停止步進,給予其他運行時調試器完成該步進的機會。如果沒有遇到新的控制運行時調試器,則原始運行時調試器可以完成該步進。允許其他運行時調試器檢查當前指令指針和接管控制的過程在此被稱為“步進仲裁”。
[0042]運行時被調試程序可能具有在運行時轉移時被調用的公知函數(shù),從而使得運行時被調試程序能夠將端點設置在這些函數(shù)中。當這些端點在步進操作期間被命中時,針對那個運行時的運行時調試器可以請求先前的控制運行時調試器放棄對該操作的控制。
[0043]包括但不限于CLR的解釋器或其他被嚴密控制的運行時被調試程序可能能夠將調試事件激發(fā)到轉移點處的調試器中。如果步進操作發(fā)生,則運行時被調試程序的調試器可以請求之前的運行時調試器放棄對該操作的控制。當展開調用棧時,運行時的展開器可以意識到該調用棧中的有在運行時上運行的代碼存在的各區(qū)域。這確保了為調用棧的特定區(qū)域調用正確的運行時展開器。由于一個運行時調試器可以被實現(xiàn)在另一運行時調試器的上方,較高級別的運行時調試器可以被給予防止較低級別的運行時調制器將調用棧的錯誤部分展開的優(yōu)先級。[0044]最后,與n路互操作調試器兼容的運行時被調試程序必須能夠檢測運行時被調試程序中的處理程序何時捕獲了一異常,即使該異常最初是從另一運行時被調試程序處被拋出的。至少一些運行時被調試程序處理某種錯誤。當錯誤發(fā)生在一個運行時環(huán)境中并且它轉移到另一運行時環(huán)境中時,如果運行時能夠停止該進程并處理該錯誤狀況,則該運行時可以停止執(zhí)行控制。不支持異常的運行時被調試程序不必檢測所捕獲的異常。能夠檢測所捕獲的異常允許步進操作在處理程序被發(fā)現(xiàn)時完成,即使該異??邕^了運行時被處理程序的邊界。某些運行時調試器必須在其處理程序發(fā)現(xiàn)通知被激發(fā)時發(fā)起仲裁,因為其異常模型被實現(xiàn)在另一運行時被調試程序的異常模型的上方。
[0045]圖2a示出了根據(jù)此處所公開的主題的各方面的用于在n路互操作調試器中步進的方法的示例。在202,調試器響應于接收到用戶請求而請求新的步進操作??梢詣?chuàng)建保持諸如步進操作的類型(步進進入、步進離開、步進通過、步進在調用棧上的位置等)等有關步進的狀態(tài)的對象。在204,向步進管理器通知該新的步進操作??梢詣?chuàng)建保持諸如步進操作的類型(步進進入、步進離開、步進通過、及步進在調用棧上的位置等)等有關步進的狀態(tài)的對象。在206,步進管理器將該新步進操作通知傳遞給每一運行時實例。在208,每一個被通知的運行時調試器實例可以執(zhí)行預步進設置動作。預步進設置動作可以包括但不限于發(fā)起捕獲處理程序發(fā)現(xiàn)通知、在已知的運行時被調試程序轉移處設置斷點、指定被調試程序轉移模塊等。
[0046]在210,步進管理器可以:執(zhí)行最高級或初始步進仲裁;按優(yōu)先級次序向每一運行時調試器實例詢問被調試程序當前是否正在該運行時調試器實例的運行時內執(zhí)行。當指令指針指向調用棧的屬于運行時調試器的區(qū)域時,被調試程序當前正在那個運行時調試器內執(zhí)行。在212,當前控制運行時調試器被選擇。在214,步進管理器向所有其他運行時調試器通知該新的控制運行時調試器(即,當前控制運行時)。通知使得其他運行時能夠充當當前控制運行時對特定運行時執(zhí)行特殊處理。在216,當前控制運行時調試器開始步進該進程。在218,在步進期間或當前棧幀改變的任何時候遇到的每一調用指令處,當前控制運行時調試器檢查以查看指令指針是否抵達另一運行時調試器所擁有的轉移模塊?;蛘撸硪贿\行時調試器可以在斷點被命中或在另一調試事件發(fā)生時,檢測其運行時內的轉移。
[0047]在218,響應于確定沒有轉移是可能的,則處理在224繼續(xù),在224,步進被控制運行時調試器完成。當步進操作在224完成時,在226當前控制運行時調試器向步進管理器通知該步進完成了。在228,步進管理器向所有其他運行時調試器通知步進被完成。在230,調試器用戶界面接收步進完成通知,并進入中斷模式。然而,如果在218確定轉移是可能的,則步進仲裁被請求,并且處理返回220。在步進仲裁期間,步進管理器按優(yōu)先級次序向每一運行時調試器詢問該運行時是否聲明該位置。如果沒有其他運行時調試器聲明該位置,則在224當前控制運行時調試器使步進結束。然而,如果在222步進管理器確定運行時轉移已發(fā)生,則處理在214繼續(xù)。
[0048]運行時調試器實例還可以直接使用斷點、異常或另一調試事件來檢測其運行時內的轉移。如果轉移發(fā)生,則運行時調試器實例可以針對通過步進管理器的控制而詢問當前控制運行時調試器。如果當前控制運行時調試器實例同意,則步進控制被給予該新的運行時調試器實例??梢韵蚱渌\行時調試器實例通知控制運行時調試器時發(fā)生的改變。這個機制允許所有步進操作,包括步進進入、步進通過、和步進離開。將理解,(例如,如果某步進從某函數(shù)的結尾步進離開的話),該步進通過可以遇到一新的邊界模塊。類似地,當從當前幀步進離開時,可遇到新的邊界模塊。
[0049]在調試器中的檢查是基于調用棧幀的。在n路互操作調試中,每一運行時調試器實例負責展開其自己的調用棧幀。n路互操作調試器的每一運行時調試器可以將當前幀標識成其自己的,使得變量檢查可被路由到合適的運行時調試器實例。n路互操作架構可以提供一種供來自不同運行時調試器的各幀在整個調用棧完成后被回縫在一起的方式。還必須提供一種供“運行時粘合”幀對用戶隱藏的方式。
[0050]圖2b示出了根據(jù)此處所公開的主題的各方面的走查調用棧的方法250的示例。在252,調用棧窗口可以請求n路互操作調試器開始走查各幀。在254,可將該請求路由到棧提供器。在256,棧提供器可以按優(yōu)先級次序向每一運行時調試器實例詢問該運行時調試器實例是否擁有當前位置。將理解,每一幀是本機幀,而不管它所屬于的運行時調試器。因為在步進時,一個運行時調試器可以被構建在另一運行時調試器之上,因此對各運行時排定優(yōu)先級確保了由合適的運行時調試器來控制對調用棧的走查。將理解,盡管運行時可被構建在本機運行時之上,但也可能將運行時構建在諸如例如在解釋器以托管代碼來實現(xiàn)時存在的較高級運行時之上。
[0051]在258,運行時調試器聲明位置,并在260請求來自調用棧的幀,直到當前幀不屬于該運行時調試器為止。在262,響應于檢測到不屬于該運行時的幀,向棧提供器指示“運行時結束”值。在264,運行時向棧提供器通知調用棧中該運行時的代碼再次開始(如果如此的話)的位置。這防止另一運行時展開不屬于它的調用棧的部分。為了理解這可如何發(fā)生,假設沒有向棧提供器通知棧轉移點。假設托管展開器在托管到本機轉移點處停止。即使存在回到托管代碼的另一轉移點,本機運行時仍將繼續(xù)展開調用棧,直到整個棧已被處理。這由于所有代碼最終是本機代碼而發(fā)生。
[0052]類似地,由于解釋器是用托管代碼來實現(xiàn)的,因此即使棧應該由解釋器來展開,從托管代碼到經解釋的代碼的轉移仍可由托管運行時調試器來展開。相反,根據(jù)在此公開的主題的各方面,由于棧提供器知道每一轉移點,因此棧提供器可以按優(yōu)先級次序向每一運行時調制器詢問該運行時調試器是否愿意處理下一個調用棧幀。當運行時調試器聲明了幀時,該聲明運行時調試器被給予對該展開的控制。一旦所有幀已被展開,將各調用棧幀過濾掉。即,每一運行時調試器被給予隱藏運行時粘合代碼或完全改變幀的內容的機會。最后,調用棧中的每一幀由匹配有問題的幀的語言表達式評估器來格式化。
[0053]在互操作調試被執(zhí)行時,一個運行時調試器中拋出的異??梢栽谟诹硪贿\行時調試器上運行的代碼中的捕獲處理程序中被捕獲。如果步進操作在異常被拋出時發(fā)生,則該步進通常被停止。支持異常的運行時調試器可被告知一異常何時被其運行時調試器使用該運行時調試器的異常處理程序發(fā)現(xiàn)通知捕獲。圖2c示出了根據(jù)此處所公開的主題的各方面的用于處理異常的方法270的示例。在272,步進操作開始。在274,作為響應,步進管理器向所有運行時調試器通知該步進操作已開始。在276,響應于該通知,每一運行時調試器實例可啟用其捕獲處理程序發(fā)現(xiàn)通知。異??梢员粡漠斍安竭M幀調用的幀拋出,并可以被某一幀在展開已經過步進幀之前被捕獲。根據(jù)此處所公開的主題的各方面,該幀的幀基數(shù)可用于檢測這樣的實例。幀基數(shù)為在針對該幀的任何棧操作發(fā)生之前棧指針的值。在其中調用棧以向下的方向增長的n路互操作調試系統(tǒng)中,與調用棧上較低處的調用相比,調用棧上較高處的調用將具有更小的幀基數(shù)。即,如果函數(shù)a調用函數(shù)b,函數(shù)b本身調用函數(shù)C,則調用棧將表現(xiàn)為:
[0054]c
[0055]b
[0056]a
[0057]c的幀基數(shù)將比b的幀基數(shù)小,b的幀基數(shù)將比a的幀基數(shù)小。
[0058]如果運行時的捕獲處理程序發(fā)現(xiàn)通知在步進完成之前激發(fā),則運行時調試器可以將當前棧幀的幀基數(shù)與該步進已開始時的棧幀的幀基數(shù)進行比較。如果當前棧幀的幀基數(shù)比開始幀的幀基數(shù)小,則異常被拋出并有被當前步進的幀調用的幀捕獲,并且可被忽略。然而,如果幀基數(shù)大于或等于該步進時刻的幀基數(shù),則異常已被轉移經過該步進的點,并且該步進操作可被認為已完成。將理解,包括但不限于CLR的某些運行時使用另一運行時的異常模型來實現(xiàn)各異常。通常,托管異常被構建在本機異常之上,但存在其他可能性。使用另一運行時的異常模型的任何運行時可以在步進處理程序發(fā)現(xiàn)通知被激發(fā)之后發(fā)起步進仲裁。例如,假設(在CLR上運行的)函數(shù)A調用函數(shù)B (本機代碼)。如果函數(shù)B拋出一異常,則本機運行時實例和托管運行時實例兩者都將接收它們的處理程序發(fā)現(xiàn)通知(可能在不同的時刻)。然而,由于目標處理程序實際上是托管代碼,因此本機運行時實例應該允許托管運行時結束該步進。邏輯上,對這個的實現(xiàn)看上去像這個在CLR中。
[0059]Try
[0060]{
[0061]調用本機代碼
[0062]Catch(native filter)
[0063]{
[0064]調用托管捕獲處理程序
[0065]}
[0066]如果在步進經過本機代碼時,異常被拋出,則可在本機捕獲塊處向運行時實例發(fā)送捕獲處理程序發(fā)現(xiàn)通知。不論何時捕獲處理程序發(fā)現(xiàn)通知激發(fā),步進仲裁都可以被執(zhí)行。如果該位置沒有被聲明,則捕獲塊在本機代碼中,并且步進結束。如果另一運行時調試器聲明了該位置,則聲明運行時調試器可結束步進。將理解,此處在n路交互式調試器的上下文中描述的機制還可被應用于用于通用的可擴展性模型,以用于在調試器中步進。例如,當被調試程序中正在使用改變調試行為的技術時,步進仲裁和轉移模塊可被該技術使用。例如,COMRPC步進可以調用可以檢測RPC轉移并可以使得在途中的步進操作在RPC調用的目標處結束的插件組件。
[0067]合適的計算環(huán)境的示例
[0068]為了提供有關本文所公開主題的各方面的上下文,圖3以及以下討論旨在提供其中可以實現(xiàn)本文所公開主題的各實施例的合適計算環(huán)境510的簡要概括描述。盡管本文所公開的主題是在諸如程序模塊等由一個或多個計算機或其他計算設備執(zhí)行的計算機可執(zhí)行指令的通用上下文中描述的,但本領域技術人員將認識到,本文所公開的主題的各部分還能夠結合其他程序模塊和/或硬件和軟件的組合來實現(xiàn)。通常,程序模塊包括執(zhí)行特定任務或實現(xiàn)特定數(shù)據(jù)類型的例程、程序、對象、物理人為產物、數(shù)據(jù)結構等。通常,程序模塊的功能可在各個實施例中按需進行組合或分布。計算環(huán)境510只是合適的操作環(huán)境的一個示例,并且不旨在對此處所公開的主題的使用范圍或功能提出任何限制。
[0069]參考圖3,描述了計算機512形式的計算設備。計算機512可包括處理單元514、系統(tǒng)存儲器516和系統(tǒng)總線518。處理單元514可以是各種可用處理器中的任何一種。也可以使用雙微處理器及其他多處理器體系結構作為處理單元514。系統(tǒng)存儲器516可包括易失性存儲器520和非易失性存儲器522。非易失性存儲器522可包括只讀存儲器(ROM)、可編程ROM (PROM)、電可編程ROM (EPROM)或閃存。易失性存儲器520可包括可充當外高速緩沖存儲器的隨機存取存儲器(RAM)。系統(tǒng)總線518將包括系統(tǒng)存儲器516的系統(tǒng)物理人為產物耦合到處理單元514。系統(tǒng)總線518可以是幾種類型的總線結構中的任何一種,包括存儲器總線、存儲控制器、外圍總線、外總線或局部總線,并且可以使用各種可用總線體系結構中的任一種。
[0070]計算機512通常包括各種計算機可讀介質,諸如易失性和非易失性介質、可移動和不可移動介質。計算機存儲介質可以通過用于存儲諸如計算機可讀指令、數(shù)據(jù)結構、程序模塊或其它數(shù)據(jù)等信息的任何方法或技術來實現(xiàn)。計算機存儲介質包括但不限于,RAM、ROM、EEPR0M、閃存或其它存儲器技術、⑶ROM、數(shù)字多功能盤(DVD)或其它光盤存儲、磁盒、磁帶、磁盤存儲或其它磁存儲設備、或可以用來儲存所期望的信息并可由計算機512訪問的任何其他瞬態(tài)或非瞬態(tài)介質。
[0071]將理解,圖3描述了可充當用戶與計算機資源之間的媒介的軟件。該軟件可以包括可存儲在盤存儲524上的操作系統(tǒng)528,該操作系統(tǒng)可分配計算機系統(tǒng)512的資源。盤存儲524可以是通過諸如接口 526等不可移動存儲器接口連接到系統(tǒng)總線518的硬盤驅動器。系統(tǒng)應用程序530利用由操作系統(tǒng)528通過存儲在系統(tǒng)存儲器516或者存儲在盤存儲524上的程序模塊532和程序數(shù)據(jù)534對資源的管理??梢岳斫?,計算機可用各種操作系統(tǒng)或操作系統(tǒng)的組合來實現(xiàn)。
[0072]用戶可通過輸入設備536向計算機512輸入命令或信息。輸入設備536包括但不限于定點設備,諸如鼠標、跟蹤球、指示筆、觸摸墊、鍵盤、話筒等。這些及其他輸入設備通過系統(tǒng)總線518經由接口端口 538連接到處理單元514。接口端口 538可表示串行端口、并行端口、通用串行總線(USB)等。輸出設備540可與輸入設備使用相同類型的端口。提供輸出適配器542以舉例說明存在像監(jiān)視器、揚聲器、以及打印機的需要特定適配器的一些輸出設備540。輸出適配器542包括但不限于,在輸出設備540和系統(tǒng)總線518之間提供連接的視頻卡和聲卡。其他設備和/或系統(tǒng)和/或設備,諸如遠程計算機544,可提供輸入和輸出兩種能力。
[0073]計算機512可以使用到諸如遠程計算機544之類的一個或多個遠程計算機的邏輯連接來在聯(lián)網環(huán)境中操作。遠程計算機544可以是個人計算機、服務器、路由器、網絡PC、對等設備或其他常見的網絡節(jié)點,并且通常包括許多或所有以上相對于計算機512所描述的元件,但在圖3中僅示出了存儲器存儲設備546。遠程計算機544可經由通信連接550邏輯地連接。網絡接口 548涵蓋諸如局域網(LAN)和廣域網(WAN)這樣的通信網絡,但也可包括其他網絡。通信連接550是指用來將網絡接口 548連接到總線518的硬件/軟件。連接550可以在計算機512內或外并且包括諸如調制解調器(電話、電纜、DSL和無線)和ISDN適配器、以太網卡等內和外技術。[0074]可以理解,所示網絡連接僅是示例,并且可以使用在計算機之間建立通信鏈路的其他手段。本領域的普通技術人員可以理解,計算機512或其他客戶機設備可作為計算機網絡的一部分來部署。在這一點上,本文所公開的主題涉及具有任意數(shù)量的存儲器或存儲單元以及在任意數(shù)量的存儲單元或卷上發(fā)生的任意數(shù)量的應用和進程的任何計算機系統(tǒng)。本文所公開的主題的各方面可應用于具有部署在網絡環(huán)境中的具有遠程或本地存儲的服務器計算機和客戶計算機的環(huán)境。本文所公開的主題的各方面也可應用于具有編程語言功能、解釋和執(zhí)行能力的獨立計算設備。
[0075]圖4示出集成開發(fā)環(huán)境(IDE)600和通用語言運行時環(huán)境602。IDE600可允許用戶(例如,開發(fā)者、程序員、設計者、編碼者等)在計算機系統(tǒng)中設計、編碼、編譯、測試、運行、編輯、調試或構建程序、程序集、網站、web應用和web服務。軟件程序可包括用一個或多個源代碼語言(例如,Visual Basic> Visual J#、C++、C#、J#、Java Script、APL、COBOL、Pascal、Eiffel、Haskell、ML、Oberon、Perl、Python、Scheme、和 Smalltalk 等)創(chuàng)建的源代碼(組件610)。IDE600可提供本機代碼開發(fā)環(huán)境,或者可提供在虛擬機上運行的托管代碼開發(fā),或者可提供其組合。IDE600可提供使用.NET框架的托管代碼開發(fā)環(huán)境。可使用語言專用源編譯器620從源代碼組件610和本機代碼組件611創(chuàng)建中間語言組件650,并且在執(zhí)行應用時使用中間語言編譯器660 (例如,即時(JIT)編譯器)從中間語言組件650創(chuàng)建本機代碼組件611 (例如,機器可執(zhí)行指令)。即,當IL應用被執(zhí)行時,其在被執(zhí)行的同時被編譯成適合正在其上執(zhí)行它的平臺的合適機器語言,藉此使代碼能跨若干平臺便攜。替代地,在其他實施例中,程序可被編譯成適合其目標平臺的本機代碼機器語言(未示出)。
[0076]用戶可根據(jù)已知軟件編程技術以及與特定源語言相關聯(lián)的特定邏輯和句法規(guī)則經由IDE600中的用戶接口 640和源代碼編輯器651來創(chuàng)建和/或編輯源代碼組件。此后,源代碼組件610可經由源編譯器620被編譯,藉此可創(chuàng)建該程序的中間語言表示,諸如匯編630。匯編630可包括中間語言組件650和元數(shù)據(jù)642。
[0077]應用設計可以能夠在部署前被確認。
[0078]本文所述的各種技術可結合硬件或軟件,或在適當時以其組合來實現(xiàn)。由此,本文所公開的方法和裝置或其特定方面或部分可采取包含在諸如軟盤、CD-ROM、硬盤驅動器或任何其他機器可讀存儲介質等有形介質中的程序代碼(即,指令)的形式,其中當程序代碼被加載到諸如計算機等機器內并由其執(zhí)行時,該機器成為用于實現(xiàn)本文所公開的主題的各方面的裝置。如此出所用的,術語“機器可讀介質”應被用來排除提供(即存儲和/或傳輸)任何形式的傳播信號的任何機制。在程序代碼在可編程計算機上執(zhí)行的情況下,計算設備通常將包括處理器、該處理器可讀的存儲介質(包括易失性和非易失性的存儲器和/或存儲元件)、至少一個輸入設備、以及至少一個輸出設備??衫缤ㄟ^使用數(shù)據(jù)處理API等來利用域專用編程模型各方面的創(chuàng)建和/或實現(xiàn)的一個或多個程序可用高級過程語言或面向對象的編程語言來實現(xiàn)以與計算機系統(tǒng)通信。然而,如果需要,該程序可以用匯編語言或機器語言來實現(xiàn)。在任何情形中,語言可以是編譯語言或解釋語言,且與硬件實現(xiàn)相結合。
[0079]盡管用結構特征和/或方法動作專用的語言描述了本主題,但可以理解,所附權利要求書中定義的主題不必限于上述具體特征或動作。更確切而言,上述具體特征和動作是作為實現(xiàn)權利要求的示例形式公開的。
【權利要求】
1.一種系統(tǒng),包括: 計算設備的處理器和存儲器;以及 n路互操作調試器,該n路互操作調試器包括被配置成使得所述計算設備的處理器互操作地調試在單個被調試程序進程中執(zhí)行的與n路互操作調試器兼容的多個運行時被調試程序的多個模塊,所述n路互操作調試器提供所述單個被調試程序進程的整體視圖,所述n路互操作調試器包括: 步進管理器模塊,所述步進管理器模塊包括所述多個運行時被調試程序的通信信道,所述步進管理器1旲塊執(zhí)行包括以下的最聞級步進仲裁: 按優(yōu)先級次序聯(lián)系所述多個運行時被調試程序中的至少一個; 從所述多個運行時被調試程序中聲明對當前調試指令的所有權的所聯(lián)系的運行時被調試程序接收響應,該聲明運行時被調試程序包括當前控制運行時; 向所述多個運行時被調試程序通知該當前控制運行時;以及 調試監(jiān)視器模塊,所述調試監(jiān)視器模炔基于所述n路互操作調試器和所述多個運行時被調試程序之間通用協(xié)議將調試事件路由到相應的運行時調試器。
2.如權利要求1所述的系統(tǒng),其特征在于,所述步進管理器模塊通過以下步驟為所述調試操作選擇當前控制運行時: 按優(yōu)先級次序聯(lián)系所述多個運行時被調試程序中的至少一個; 從所述多個運行時被調試程序中聲明對當前調試指令的所有權的所聯(lián)系的運行時被調試程序接收響應,該聲明運行時被調試程序包括當前控制運行時;以及向所述多個運行時被調試程序通知該當前控制運行時。
3.如權利要求1所述的系統(tǒng),其特征在于,所述多個運行時被調試程序中的至少一個是虛擬機運行時被調試程序、解釋運行時被調試程序或本機運行時被調試程序。
4.如權利要求1所述的系統(tǒng),其特征在于,調試操作包括: 將被調試程序代碼運行從一個運行時被調試程序步進到另一調試運行時; 在多個運行時被調試程序中設置斷點; 檢測來自多個運行時被調試程序的值; 執(zhí)行包括來自所述多個運行時被調試程序的代碼的調用棧。
5.一種方法,包括: 由在處理器上執(zhí)行的n路互操作調試模塊接收來自在單個調試進程中執(zhí)行的多個運行時被調試程序中的一個的調試通信,所述調試通信符合被所述多個運行時被調試程序共享的協(xié)議,其中所述多個運行時被調試程序包括:不執(zhí)行調試代碼的運行時、檢測到從一個運行時被調試程序到另一運行時被調試程序的轉移的運行時以及檢測到在其他被調試程序運行時中拋出的各異常的運行時; 通過按優(yōu)先級次序聯(lián)系所述多個運行時被調試程序中的至少一個來確定包括所述多個運行時被調試程序中的一個運行時被調試程序的當前控制運行時;以及 向所述多個運行時被調試程序中的至少一個通知所確定的當前控制運行時。
6.如權利要求5所述的方法,其特征在于,所述運行時被調試程序中的至少一個包括虛擬機運行時、解釋器運行時或本機運行時。
7.如權利要求5所述的方法,其特征在于,在一個運行時被調試程序中拋出的異常被在所述多個運行時中的另一運行時被調試程序中捕獲。
8.如權利要求5所述的方法,其特征在于,所述單個進程的調用棧包括來自所述多個運行時被調試程序的各幀。
9.如權利要求5所述的方法,其特征在于,各運行時被調試程序之間的轉移被檢測到。
10.一種包括當執(zhí)行時使計算設備的至少一個處理器執(zhí)行下列操作的計算機可執(zhí)行指令的計算機可讀存儲介質: 由在所述至少一個處理器上執(zhí)行的n路互操作調試模塊接收來自在單個調試進程中執(zhí)行的多個運行時被調試程序中的一個的調試通信,所述調試通信符合被所述多個運行時被調試程序共享的協(xié)議,其中所述多個運行時被調試程序包括:不執(zhí)行調試代碼的運行時、檢測到從一個運行時被調試程序到另一運行時被調試程序的轉移的運行時,以及檢測到在其他被調試程序運行時中拋出的各異常的運行時; 通過按優(yōu)先級次序聯(lián)系所述多個運行時被調試程序中的至少一個來確定包括所述多個運行時被調試程序中的一個運行時被調試程序的當前控制運行時; 向所述多個運行時被調試程序中的至少一個通知所確定的當前控制運行時; 接收來自解釋器運行時被調試程序、本機運行時被調試程序或虛擬機運行時被調試程序的調試通信。
【文檔編號】G06F11/36GK103620561SQ201280030942
【公開日】2014年3月5日 申請日期:2012年6月6日 優(yōu)先權日:2011年6月24日
【發(fā)明者】J·M·戴維斯, G·B·米斯凱利 申請人:微軟公司