2014-01-26 69 views
1

當我在64位Delphi XE4項目(調試模式)中添加映射文件時。我有一些像「_zn6」,「_zn11」等符號。究竟是什麼原因呢?在32位項目中一切都很好。如果我選擇釋放模式,那麼信息很清楚,但非常差。 片段映射文件:Delphi x64映射文件問題

0005:0000B970  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE6RemoveES5_ 
0005:0000B97C  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE10RemoveItemES5_NS_5Types10TDirectionE 
0005:0000B988  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE6DeleteEi 
0005:0000B994  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE11DeleteRangeEii 
0005:0000B9AC  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE7ExtractES5_ 
0005:0000B9B8  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE11ExtractItemES5_NS_5Types10TDirectionE 
0005:0000B9C4  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE8ExchangeEii 
0005:0000B9D0  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE4MoveEii 
0005:0000B9DC  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE5FirstEv 
0005:0000B9E8  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE4LastEv 
0005:0000B9F4  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE5ClearEv 
0005:0000BA00  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE6ExpandEv 
0005:0000BA0C  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE8ContainsES5_ 
0005:0000BA18  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE7IndexOfES5_ 
0005:0000BA24  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE11IndexOfItemES5_NS_5Types10TDirectionE 
0005:0000BA30  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE11LastIndexOfES5_ 
0005:0000BA3C  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE7ReverseEv 
0005:0000BA48  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE4SortEv 
0005:0000BA54  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE4SortENS_15DelphiInterfaceINS0_8Defaults12IComparer__1IS5_EEEE 
0005:0000BA60  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE12BinarySearchES5_Ri 
0005:0000BA6C  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE12BinarySearchES5_RiNS_15DelphiInterfaceINS0_8Defaults12IComparer__1IS5_EEEE 
0005:0000BA78  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE10TrimExcessEv 
0005:0000BA84  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE7ToArrayEv 
0005:0000BA90  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE13GetEnumeratorEv 
0005:0000BA9C  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE11TEnumeratorIE10GetCurrentEv 
0005:0000BAA8  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE11TEnumeratorIE12DoGetCurrentEv 
0005:0000BAB4  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE11TEnumeratorIE10DoMoveNextEv 
0005:0000BAC0  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE11TEnumeratorIEC3EPNS2_IS5_EE 
0005:0000BAD8  System.Rtti.$pdata$_ZN6System8Generics11Collections8TList__1IPNS_7Typinfo9TTypeInfoEE11TEnumeratorIE8MoveNextEv 

這裏是JCL日誌樣品(含64映射文件):

ERR (ThreadID=12E0 25.01.2014 23:06:28:098) - External exception E06D7363 
Exception class: EExternalException 
Exception address: 000007FEFD7DBCCD 
Stack list, generated 25.01.2014 23:06:27 
[000007FEFD7DBCCD] RaiseException + $3D 
[00000000775797A8] RtlRaiseException + $248 
[000007FEFD7DBCCD] RaiseException + $3D 
[000007FEEC70E92C] _CxxThrowException + $D4 
[000007FEECB88383] Unknown function at ?[email protected]@[email protected]@@QEBA_KXZ + $1BF3 
[000007FEECB7EB49] Unknown function at DllCanUnloadNow + $33F69 
[000007FEECB7B160] Unknown function at DllCanUnloadNow + $30580 
[000007FEECB7CC9D] Unknown function at DllCanUnloadNow + $320BD 
[00000000030F115D] ConnPool.GetSKRowset (Line 1220, "ConnPool.pas" + 25) + $27 
[00000000030F20B2] ConnPool._ZN8Connpool11TConnection9GetResultEN6System15DelphiInterfaceIN6Winapi6Adoint10_RecordsetEEEN11Definitions9TDCReturnENS1_3SetINS_16TRecordsetOptionELSA_0ELSA_2EEEPNS1_7TObjectEb (Line 1341, "ConnPool.pas" + 27) + $1B 
[00000000030EEFFF] ConnPool._ZN8Connpool11TConnection18InternalExecuteCmdEv (Line 974, "ConnPool.pas" + 134) + $0 
[00000000030EE56E] ConnPool._ZN8Connpool11TConnection7ExecuteEPNS_12TCmdExecArgsE (Line 801, "ConnPool.pas" + 8) + $0 
[00000000031C1B97] SKDS._ZN4Skds13TConfigReader7ExecCmdEiN6System13UnicodeStringES2_RKNS1_10OleVariantEPN8Connpool15TCmdExecOptionsEiNS6_9TTranModeEPS3_SA_i (Line 439, "SKDS.pas" + 65) + $0 
[00000000031AD053] Dataservice.DoSimpleCall (Line 3241, "Dataservice.pas" + 8) + $167 
[00000000031AD929] Dataservice._ZN11Dataservice12TDataservice10RunCommandEiN6System10WideStringES2_RKNS1_10OleVariantES5_RS3_ (Line 3336, "Dataservice.pas" + 44) + $0 
[000007FEFE2216D0] Unknown function at SetErrorInfo + $80 
[000007FEFE2224D2] DispCallFunc + $262 
[000007FEFE221DE1] Unknown function at SetErrorInfo + $791 
[0000000002F18242] System.Win.ComObj._ZN6System3Win6Comobj11TAutoObject6InvokeEiRK5_GUIDitPvS6_S6_S6_ + $82 
[000000000073407F] Invoker._ZN7Invoker9TKInvoker6InvokeEv (Line 177, "Invoker.pas" + 30) + $73 
[00000000007613A5] WorkerThread._ZN12Workerthread14TKWorkerThread17IntCallFromMemoryEN6System15DelphiInterfaceI7IStreamEEii (Line 426, "WorkerThread.pas" + 16) + $0 
[0000000000760728] WorkerThread._ZN12Workerthread14TKWorkerThread10WorkInvokeEN6System15DelphiInterfaceI7IStreamEES4_ (Line 391, "WorkerThread.pas" + 59) + $0 
[000000000075EEC1] WorkerThread.ProcessRequest (Line 195, "WorkerThread.pas" + 37) + $50 
[000000000075F36E] WorkerThread._ZN12Workerthread14TKWorkerThread11DoSomethingEv (Line 218, "WorkerThread.pas" + 4) + $8 
[0000000000737038] PoolableThread._ZN14Poolablethread16TKPoolableThread7ExecuteEv (Line 259, "PoolableThread.pas" + 17) + $E 
[000000000052C89B] System.Classes._ZN6System7Classes10ThreadProcEPNS0_7TThreadE + $3B 
[000000000040DACB] System._ZN6System13ThreadWrapperEPv + $3B 
[000000007735652D] BaseThreadInitThunk + $D 
[000000007758C521] RtlUserThreadStart + $21 
+0

您標記了錯誤的XE問題。你能解決這個問題嗎?看起來像是C++的名字。 –

+0

請向我們展示真實的地圖文件,而不是堆棧跟蹤。 –

+0

@FreeConsulting我做到了。 – Sibay

回答

3

這些額外的名稱都與在x64不同的異常處理模型。在x86上,異常是基於堆棧的。在x64上它們是table based。這會對編譯器如何處理exceptfinally塊產生影響。

特別是,編譯器/鏈接器必須能夠輸出描述異常處理代碼的異常表。據我瞭解,編號爲$pdata$$unwind$的編號在處理exceptfinally塊時由編譯器創建。鏈接器使用這些名稱創建寫入可執行輸出文件的異常表。編譯器會生成這些難以形容的名稱,以免它們與真正的函數名稱衝突。

我的猜測是你在棧跟蹤中看到了這些名字,因爲JCL stack walker代碼不夠聰明,無法破譯這些名字。例如,如果你使用madExcept,你會看到你期待的名字。

從根本上說,問題在於JCL缺乏功能。


x86和x64結構化異常處理之間確實存在巨大差異。例如,有趣的是,finally塊的編譯代碼在x64可執行文件中出現兩次。考慮這個短節目:

procedure Foo; 
begin 
end; 

procedure Main; 
begin 
    try 
    finally 
    Foo; 
    end; 
end; 

begin 
    Main; 
end. 

編譯器轉換成Main

 
Project1.dpr.8: begin 
0000000000409A30 55    push rbp 
0000000000409A31 4883EC30   sub rsp,$30 
0000000000409A35 488BEC   mov rbp,rsp 
0000000000409A38 48896D28   mov [rbp+$28],rbp 
Project1.dpr.9: try 
0000000000409A3C 90    nop 
Project1.dpr.11: Foo; 
0000000000409A3D 90    nop 
0000000000409A3E E8DDFFFFFF  call Foo 
Project1.dpr.13: end; 
0000000000409A43 488D6530   lea rsp,[rbp+$30] 
0000000000409A47 5D    pop rbp 
0000000000409A48 C3    ret 
0000000000409A49 488D8000000000 lea rax,[rax+$00000000] 
Project1.dpr.11: Foo; 
0000000000409A50 55    push rbp 
0000000000409A51 4883EC20   sub rsp,$20 
0000000000409A55 488BEC   mov rbp,rsp 
0000000000409A58 E8C3FFFFFF  call Foo 
0000000000409A5D 488D6520   lea rsp,[rbp+$20] 
0000000000409A61 5D    pop rbp 
0000000000409A62 C3    ret 

注意兩次調用Foo。第一個是正常執行。那就是當沒有例外,並且finally塊被正常輸入時。第二次致電Foo處理異常處於活動狀態的情況。

finally塊的第二個版本實際上被編譯爲一個單獨的函數。根據我的地圖文件,它的名稱爲Project1.$pdata$_ZN8Project13FooEv

 
0005:00000A50  Project1.$pdata$_ZN8Project13FooEv 

它從主異常處理程序,System._DelphiExceptionHandler調用。它確實是一個獨立的功能,因爲它以ret結尾。如果我扔try/finally內的異常來獲取代碼運行這個變體,在IDE中的堆棧跟蹤看起來是這樣的:

 
Project1.Main 
System._DelphiExceptionHandler($12FAB0,1244912,$12E820,$12E730) 
:00000000779F9DAD ; ntdll.dll 
:00000000779E8A4C ; ntdll.dll 
:00000000778E2D3E ; C:\Windows\system32\kernel32.dll 
System._DelphiExceptionHandler($12FAB0,1244976,$12F5C0,$12EF70) 
:00000000779F9D2D ; ntdll.dll 
:00000000779E91CF ; ntdll.dll 
:0000000077A21248 ; ntdll.dll 
:000007FEFDA7940D ; C:\Windows\system32\KERNELBASE.dll 
System._RaiseAtExcept(???,???) 
System._RaiseExcept(???) 
Project1.Main 

因此,大家可以看到,IDE能夠達到什麼樣的JCL代碼不能,並且理解基於表的異常處理。

在x86下是看起來相當不同:

 
Project1.Main 
Project1.Project1 
:7618336a kernel32.BaseThreadInitThunk + 0x12 
:77be9f72 ntdll.RtlInitializeExceptionChain + 0x63 
:77be9f45 ntdll.RtlInitializeExceptionChain + 0x36 

那麼,這些無法形容的名字都與基於表例外的管理。這種行爲完全是可以預料的。

+0

我建議用「unmangle」替換「解密」,這看起來還沒有在JCL中完全實現。 –