FpDebug, LazDebuggerFp: fix last frame in stack list / allow evaluate more frames

git-svn-id: trunk@60335 -
This commit is contained in:
martin 2019-02-04 18:26:11 +00:00
parent 2c784a8bf2
commit dac68e42e2
2 changed files with 67 additions and 25 deletions

View File

@ -1708,47 +1708,76 @@ end;
procedure TDbgThread.PrepareCallStackEntryList(AFrameRequired: Integer);
const
MaxFrames = 25;
MAX_FRAMES = 50000; // safety net
var
Address, Frame, LastFrame: QWord;
Size, Count: integer;
Size, CountNeeded, IP, BP: integer;
AnEntry: TDbgCallstackEntry;
R: TDbgRegisterValue;
nIP, nBP: String;
NextIdx: LongInt;
begin
// TODO: use AFrameRequired // check if already partly done
if FCallStackEntryList = nil then
FCallStackEntryList := TDbgCallstackEntryList.Create;
if (AFrameRequired >= 0) and (AFrameRequired < FCallStackEntryList.Count) then
exit;
// TODO: remove, using AFrameRequired
if FCallStackEntryList.Count > 0 then exit; // already done
Address := GetInstructionPointerRegisterValue;
Frame := GetStackBasePointerRegisterValue;
Size := sizeof(pointer); // TODO: Context.AddressSize
case FProcess.Mode of
dm32: begin
Size := 4;
IP := 8; // Dwarf Reg Num EIP
BP := 5; // EBP
nIP := 'eip';
nBP := 'ebp';
end;
dm64: begin
Size := 8;
IP := 16; // Dwarf Reg Num RIP
BP := 6; // RBP
nIP := 'rip';
nBP := 'rbp';
end;
else assert(False, 'unknown address size for stack')
end;
FCallStackEntryList.FreeObjects:=true;
AnEntry := TDbgCallstackEntry.create(Self, 0, Frame, Address);
// Top level entry needs no registerlist / same as GetRegisterValueList
FCallStackEntryList.Add(AnEntry);
if FCallStackEntryList.Count > 0 then begin
AnEntry := FCallStackEntryList[FCallStackEntryList.Count - 1];
R := AnEntry.RegisterValueList.FindRegisterByDwarfIndex(IP);
if R = nil then exit;
Address := R.NumValue;
R := AnEntry.RegisterValueList.FindRegisterByDwarfIndex(BP);
if R = nil then exit;
Frame := R.NumValue;
end
else begin
Address := GetInstructionPointerRegisterValue;
Frame := GetStackBasePointerRegisterValue;
AnEntry := TDbgCallstackEntry.create(Self, 0, Frame, Address);
// Top level entry needs no registerlist / same as GetRegisterValueList
FCallStackEntryList.Add(AnEntry);
end;
NextIdx := FCallStackEntryList.Count;
if AFrameRequired < 0 then
AFrameRequired := MaxInt;
CountNeeded := AFrameRequired - FCallStackEntryList.Count;
LastFrame := 0;
Count := MaxFrames;
while (Frame <> 0) and (Frame > LastFrame) do
while (CountNeeded > 0) and (Frame <> 0) and (Frame > LastFrame) do
begin
LastFrame := Frame;
if not Process.ReadData(Frame + Size, Size, Address) or (Address = 0) then Break;
if not Process.ReadData(Frame, Size, Frame) then Break;
AnEntry := TDbgCallstackEntry.create(Self, MaxFrames+1-Count, Frame, Address);
if Process.Mode=dm32 then begin
AnEntry.RegisterValueList.DbgRegisterAutoCreate['eip'].SetValue(Address, IntToStr(Address),Size,8);
AnEntry.RegisterValueList.DbgRegisterAutoCreate['ebp'].SetValue(Frame, IntToStr(Frame),Size,5);
end
else begin
AnEntry.RegisterValueList.DbgRegisterAutoCreate['rip'].SetValue(Address, IntToStr(Address),Size,16);
AnEntry.RegisterValueList.DbgRegisterAutoCreate['rbp'].SetValue(Frame, IntToStr(Frame),Size,6);
end;
AnEntry := TDbgCallstackEntry.create(Self, NextIdx, Frame, Address);
AnEntry.RegisterValueList.DbgRegisterAutoCreate[nIP].SetValue(Address, IntToStr(Address),Size, IP);
AnEntry.RegisterValueList.DbgRegisterAutoCreate[nBP].SetValue(Frame, IntToStr(Frame),Size, BP);
FCallStackEntryList.Add(AnEntry);
Dec(count);
if Count <= 0 then Break;
Dec(CountNeeded);
inc(NextIdx);
If (NextIdx > MAX_FRAMES) then
break;
end;
end;

View File

@ -223,6 +223,8 @@ type
constructor Create(const ADebugger: TDebuggerIntf);
destructor Destroy; override;
procedure RequestCount(ACallstack: TCallStackBase); override;
procedure RequestAtLeastCount(ACallstack: TCallStackBase;
ARequiredMinCount: Integer); override;
procedure RequestEntries(ACallstack: TCallStackBase); override;
procedure RequestCurrent(ACallstack: TCallStackBase); override;
procedure UpdateCurrentIndex; override;
@ -589,6 +591,12 @@ begin
end;
procedure TFPCallStackSupplier.RequestCount(ACallstack: TCallStackBase);
begin
RequestAtLeastCount(ACallstack, -1);
end;
procedure TFPCallStackSupplier.RequestAtLeastCount(ACallstack: TCallStackBase;
ARequiredMinCount: Integer);
var
ThreadCallStack: TDbgCallstackEntryList;
begin
@ -597,7 +605,7 @@ begin
ACallstack.SetCountValidity(ddsInvalid);
exit;
end;
TFpDebugDebugger(Debugger).PrepareCallStackEntryList;
TFpDebugDebugger(Debugger).PrepareCallStackEntryList(ARequiredMinCount);
ThreadCallStack := TFpDebugDebugger(Debugger).FDbgController.CurrentThread.CallStackEntryList;
if ThreadCallStack = nil then
exit;
@ -608,9 +616,14 @@ begin
ACallstack.SetHasAtLeastCountInfo(ddsInvalid);
end
else
if (ARequiredMinCount < 0) or (ThreadCallStack.Count < ARequiredMinCount) then
begin
ACallstack.Count := ThreadCallStack.Count;
ACallstack.SetCountValidity(ddsValid);
end
else
begin
ACallstack.SetHasAtLeastCountInfo(ddsValid, ThreadCallStack.Count);
end;
end;
@ -644,7 +657,7 @@ begin
AController := FpDebugger.FDbgController;
OldContext := FpDebugger.FMemManager.DefaultContext;
while (not IT.EOM) and (TCallStackEntry(It.DataPtr^).Index < ACallstack.HighestUnknown)
while (not IT.EOM) and (TCallStackEntry(It.DataPtr^).Index <= ACallstack.HighestUnknown)
do begin
e := TCallStackEntry(It.DataPtr^);
if e.Validity = ddsRequested then