📄 fastmm_fulldebugmode.dpr
字号:
end;
end
else
begin
{If the return address is invalid it implies this stack frame is
invalid after all.}
LNextFrame := LStackTop;
end;
end
else
begin
{The return address is bad - this is not a valid stack frame}
LNextFrame := LStackTop;
end;
end
else
begin
{This is not a valid stack frame}
LNextFrame := LStackTop;
end;
{Do not check intermediate entries if there are still frames to skip}
if ASkipFrames <> 0 then
begin
Dec(ASkipFrames);
end
else
begin
{Check all stack entries up to the next stack frame}
LStackAddress := LCurrentFrame + 8;
while (AMaxDepth > 0)
and (LStackAddress < LNextFrame) do
begin
{Get the return address}
LReturnAddress := PCardinal(LStackAddress)^;
{Is this a valid call site?}
if IsValidCallSite(LReturnAddress) then
begin
AReturnAddresses^ := LReturnAddress;
Inc(AReturnAddresses);
Dec(AMaxDepth);
end;
{Check the next stack address}
Inc(LStackAddress, 4);
end;
end;
{Do the next stack frame}
LCurrentFrame := LNextFrame;
end;
{Clear the remaining dwords}
while (AMaxDepth > 0) do
begin
AReturnAddresses^ := 0;
Inc(AReturnAddresses);
Dec(AMaxDepth);
end;
{Restore the last Windows error code, since a VirtualQuery call may have
modified it.}
SetLastError(LLastOSError);
end
else
begin
{Exception handling is not available - do a frame based stack trace}
GetFrameBasedStackTrace(AReturnAddresses, AMaxDepth, ASkipFrames);
end;
end;
{-----------------------------Stack Trace Logging----------------------------}
{Gets the textual representation of the stack trace into ABuffer and returns
a pointer to the position just after the last character.}
{$ifdef JCLDebug}
{Converts a cardinal to a hexadecimal string at the buffer location, returning
the new buffer position.}
function CardinalToHexBuf(ACardinal: integer; ABuffer: PChar): PChar;
asm
{On entry:
eax = ACardinal
edx = ABuffer}
push ebx
push edi
{Save ACardinal in ebx}
mov ebx, eax
{Get a pointer to the first character in edi}
mov edi, edx
{Get the number in ecx as well}
mov ecx, eax
{Keep the low nibbles in ebx and the high nibbles in ecx}
and ebx, $0f0f0f0f
and ecx, $f0f0f0f0
{Swap the bytes into the right order}
ror ebx, 16
ror ecx, 20
{Get nibble 7}
movzx eax, ch
mov dl, ch
mov al, byte ptr HexTable[eax]
mov [edi], al
cmp dl, 1
sbb edi, -1
{Get nibble 6}
movzx eax, bh
or dl, bh
mov al, byte ptr HexTable[eax]
mov [edi], al
cmp dl, 1
sbb edi, -1
{Get nibble 5}
movzx eax, cl
or dl, cl
mov al, byte ptr HexTable[eax]
mov [edi], al
cmp dl, 1
sbb edi, -1
{Get nibble 4}
movzx eax, bl
or dl, bl
mov al, byte ptr HexTable[eax]
mov [edi], al
cmp dl, 1
sbb edi, -1
{Rotate ecx and ebx so we get access to the rest}
shr ebx, 16
shr ecx, 16
{Get nibble 3}
movzx eax, ch
or dl, ch
mov al, byte ptr HexTable[eax]
mov [edi], al
cmp dl, 1
sbb edi, -1
{Get nibble 2}
movzx eax, bh
or dl, bh
mov al, byte ptr HexTable[eax]
mov [edi], al
cmp dl, 1
sbb edi, -1
{Get nibble 1}
movzx eax, cl
or dl, cl
mov al, byte ptr HexTable[eax]
mov [edi], al
cmp dl, 1
sbb edi, -1
{Get nibble 0}
movzx eax, bl
mov al, byte ptr HexTable[eax]
mov [edi], al
{Return a pointer to the end of the string}
lea eax, [edi + 1]
{Restore registers}
pop edi
pop ebx
end;
function LogStackTrace(AReturnAddresses: PCardinal;
AMaxDepth: Cardinal; ABuffer: PChar): PChar;
var
LInd, LAddress: Cardinal;
LNumChars: Integer;
LInfo: TJCLLocationInfo;
LTempStr: string;
begin
Result := ABuffer;
for LInd := 0 to AMaxDepth - 1 do
begin
LAddress := AReturnAddresses^;
if LAddress = 0 then
exit;
Result^ := #13;
Inc(Result);
Result^ := #10;
Inc(Result);
Result := CardinalToHexBuf(LAddress, Result);
{Get location info for the caller (at least one byte before the return
address).}
GetLocationInfo(Pointer(Cardinal(LAddress) - 1), LInfo);
{Build the result string}
LTempStr := ' ';
if LInfo.SourceName <> '' then
LTempStr := LTempStr + '[' + LInfo.SourceName + ']';
if LInfo.UnitName <> '' then
LTempStr := LTempStr + '[' + LInfo.UnitName + ']';
if LInfo.ProcedureName <> '' then
LTempStr := LTempStr + '[' + LInfo.ProcedureName + ']';
if LInfo.LineNumber <> 0 then
LTempStr := LTempStr + '[' + IntToStr(LInfo.LineNumber) + ']';
{Return the result}
if length(LTempStr) < 256 then
LNumChars := length(LTempStr)
else
LNumChars := 255;
StrLCopy(Result, PChar(LTempStr), LNumChars);
Inc(Result, LNumChars);
{Next address}
Inc(AReturnAddresses);
end;
end;
{$endif}
{$ifdef madExcept}
function LogStackTrace(AReturnAddresses: PCardinal;
AMaxDepth: Cardinal; ABuffer: PChar): PChar;
begin
{Needs madExcept 2.7i or madExcept 3.0a or a newer build}
Result := madStackTrace.FastMM_LogStackTrace(
AReturnAddresses,
AMaxDepth,
ABuffer,
{madExcept stack trace fine tuning}
false, //hide items which have no line number information?
true, //show relative address offset to procedure entrypoint?
true, //show relative line number offset to procedure entry point?
false //skip special noise reduction processing?
);
end;
{$endif}
{$ifdef EurekaLog}
function LogStackTrace(AReturnAddresses: PCardinal; AMaxDepth: Cardinal; ABuffer: PChar): PChar;
begin
{Needs EurekaLog 5.0.5 or a newer build}
Result := ExceptionLog.FastMM_LogStackTrace(
AReturnAddresses, AMaxDepth, ABuffer,
{EurekaLog stack trace fine tuning}
False, // Show the DLLs functions call. <--|
// |-- See the note below!
False, // Show the BPLs functions call. <--|
True // Show relative line no. offset to procedure start point.
);
// NOTE:
// -----
// With these values set both to "False", EurekaLog try to returns the best
// call-stack available.
//
// To do this EurekaLog execute the following points:
// --------------------------------------------------
// 1)...try to fill all call-stack items using only debug data with line no.
// 2)...if remains some empty call-stack items from the previous process (1),
// EurekaLog try to fill these with the BPLs functions calls;
// 3)...if remains some empty call-stack items from the previous process (2),
// EurekaLog try to fill these with the DLLs functions calls;
end;
{$endif}
{-----------------------------Exported Functions----------------------------}
exports
GetFrameBasedStackTrace,
GetRawStackTrace,
LogStackTrace;
begin
{$ifdef JCLDebug}
JclStackTrackingOptions := JclStackTrackingOptions + [stAllModules];
{$endif}
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -