When i adding map files in 64 bit Delphi XE4 project (debug mode). Iv got some symbols like "_zn6", "_zn11" and etc. What the reason of it? In 32 bit project everything is good. If i chooses release mode then information is clear but very poor. Fragment of map file:
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
Here is JCL log sample (with x64 map files):
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 ?GetTotal@ColumnDesc@TablesManager@ProviderEngine@@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
These extra names are related to the different exception handling model on x64. On x86 exceptions are stack based. On x64 they are table based. This has consequences for how the compiler treats except
and finally
blocks.
In particular, the compiler/linker has to be able output an exception table that describes the exception handling code. As I understand it, the names that you see with $pdata$
and $unwind$
are created by the compiler when it processes except
and finally
blocks. These names are then used by the linker to create the exception table that is written to the executable output file. And the compiler generates such unspeakable names so that they don't clash with the true function names.
My guess is that you are seeing these names in your stack traces because the JCL stack walker code is not clever enough to decipher these names. If you were using madExcept, for instance, you would see the names that you were expecting.
So fundamentally, the problem is that JCL is lacking functionality.
There really is a huge difference between x86 and x64 structured exception handling. For instance, it is an interesting fact to note that the compiled code for a finally
block appears twice in an x64 executable. Consider this short program:
procedure Foo;
begin
end;
procedure Main;
begin
try
finally
Foo;
end;
end;
begin
Main;
end.
The compiler transforms Main
into:
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
Note the two calls to Foo
. The first one is normal execution. That is when there are no exceptions, and the finally
block is entered normally. The second call to Foo
deals with the case where an exception is active.
This second version of the finally block is actually compiled as a separate function. It has the name Project1.$pdata$_ZN8Project13FooEv
according to my map file.
0005:00000A50 Project1.$pdata$_ZN8Project13FooEv
It is called from the main exception handler, System._DelphiExceptionHandler
. And it really is a separate function as can be see by the fact that it ends with ret
. If I throw an exception inside the try/finally
to get this variant of code to run, the stack trace in the IDE looks like this:
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
So as you can see, the IDE is able to achieve what the JCL code cannot, and make sense of the table based exception handling.
Under x86 is looks quite different:
Project1.Main Project1.Project1 :7618336a kernel32.BaseThreadInitThunk + 0x12 :77be9f72 ntdll.RtlInitializeExceptionChain + 0x63 :77be9f45 ntdll.RtlInitializeExceptionChain + 0x36
So, these unspeakable names are all related to the management of table based exceptions. The behaviour is entirely to be expected.