mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-12 13:50:06 +02:00
* Fixed breakpoints at programstart and initialization code
git-svn-id: trunk@10364 -
This commit is contained in:
parent
ff4f81d112
commit
6b96e74f9a
@ -103,6 +103,8 @@ type
|
|||||||
private
|
private
|
||||||
FCommandQueue: TStringList;
|
FCommandQueue: TStringList;
|
||||||
|
|
||||||
|
FMainAddr: TDbgPtr;
|
||||||
|
FBreakAtMain: TDBGBreakPoint;
|
||||||
FBreakErrorBreakID: Integer;
|
FBreakErrorBreakID: Integer;
|
||||||
FRunErrorBreakID: Integer;
|
FRunErrorBreakID: Integer;
|
||||||
FExceptionBreakID: Integer;
|
FExceptionBreakID: Integer;
|
||||||
@ -139,6 +141,7 @@ type
|
|||||||
function FindBreakpoint(const ABreakpoint: Integer): TDBGBreakPoint;
|
function FindBreakpoint(const ABreakpoint: Integer): TDBGBreakPoint;
|
||||||
function GetClassName(const AClass: TDBGPtr): String; overload;
|
function GetClassName(const AClass: TDBGPtr): String; overload;
|
||||||
function GetClassName(const AExpression: String; const AValues: array of const): String; overload;
|
function GetClassName(const AExpression: String; const AValues: array of const): String; overload;
|
||||||
|
function GetFrame(const AIndex: Integer): String;
|
||||||
function GetInstanceClassName(const AInstance: TDBGPtr): String; overload;
|
function GetInstanceClassName(const AInstance: TDBGPtr): String; overload;
|
||||||
function GetInstanceClassName(const AExpression: String; const AValues: array of const): String; overload;
|
function GetInstanceClassName(const AExpression: String; const AValues: array of const): String; overload;
|
||||||
function GetText(const ALocation: TDBGPtr): String; overload;
|
function GetText(const ALocation: TDBGPtr): String; overload;
|
||||||
@ -152,6 +155,8 @@ type
|
|||||||
function ProcessResult(var AResult: TGDBMIExecResult): Boolean;
|
function ProcessResult(var AResult: TGDBMIExecResult): Boolean;
|
||||||
function ProcessRunning(var AStoppedParams: String): Boolean;
|
function ProcessRunning(var AStoppedParams: String): Boolean;
|
||||||
function ProcessStopped(const AParams: String; const AIgnoreSigIntState: Boolean): Boolean;
|
function ProcessStopped(const AParams: String; const AIgnoreSigIntState: Boolean): Boolean;
|
||||||
|
procedure ProcessFrame(const AFrame: String = '');
|
||||||
|
|
||||||
// All ExecuteCommand functions are wrappers for the real (full) implementation
|
// All ExecuteCommand functions are wrappers for the real (full) implementation
|
||||||
// ExecuteCommandFull is never called directly
|
// ExecuteCommandFull is never called directly
|
||||||
function ExecuteCommand(const ACommand: String; const AFlags: TGDBMICmdFlags): Boolean; overload;
|
function ExecuteCommand(const ACommand: String; const AFlags: TGDBMICmdFlags): Boolean; overload;
|
||||||
@ -1121,6 +1126,24 @@ begin
|
|||||||
if e=0 then ;
|
if e=0 then ;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TGDBMIDebugger.GetFrame(const AIndex: Integer): String;
|
||||||
|
var
|
||||||
|
R: TGDBMIExecResult;
|
||||||
|
S: String;
|
||||||
|
List: TStringList;
|
||||||
|
begin
|
||||||
|
Result := '';
|
||||||
|
if ExecuteCommand('-stack-list-frames %d %d', [AIndex, AIndex], [cfIgnoreError], R)
|
||||||
|
then begin
|
||||||
|
List := CreateMIValueList(R);
|
||||||
|
S := List.Values['stack'];
|
||||||
|
List.Free;
|
||||||
|
List := CreateMIValueList(S);
|
||||||
|
Result := List.Values['frame'];
|
||||||
|
List.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function TGDBMIDebugger.GetIntValue(const AExpression: String; const AValues: array of const): Integer;
|
function TGDBMIDebugger.GetIntValue(const AExpression: String; const AValues: array of const): Integer;
|
||||||
var
|
var
|
||||||
e: Integer;
|
e: Integer;
|
||||||
@ -1454,6 +1477,32 @@ begin
|
|||||||
mtInformation, [mbOK], 0);
|
mtInformation, [mbOK], 0);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TGDBMIDebugger.ProcessFrame(const AFrame: String);
|
||||||
|
var
|
||||||
|
S: String;
|
||||||
|
e: Integer;
|
||||||
|
Frame: TStringList;
|
||||||
|
Location: TDBGLocationRec;
|
||||||
|
begin
|
||||||
|
// Do we have a frame ?
|
||||||
|
if AFrame = ''
|
||||||
|
then S := GetFrame(0)
|
||||||
|
else S := AFrame;
|
||||||
|
|
||||||
|
Frame := CreateMIValueList(S);
|
||||||
|
|
||||||
|
Location.Address := 0;
|
||||||
|
Val(Frame.Values['addr'], Location.Address, e);
|
||||||
|
if e=0 then ;
|
||||||
|
Location.FuncName := Frame.Values['func'];
|
||||||
|
Location.SrcFile := Frame.Values['file'];
|
||||||
|
Location.SrcLine := StrToIntDef(Frame.Values['line'], -1);
|
||||||
|
|
||||||
|
Frame.Free;
|
||||||
|
|
||||||
|
DoCurrent(Location);
|
||||||
|
end;
|
||||||
|
|
||||||
function TGDBMIDebugger.ProcessResult(var AResult: TGDBMIExecResult): Boolean;
|
function TGDBMIDebugger.ProcessResult(var AResult: TGDBMIExecResult): Boolean;
|
||||||
|
|
||||||
function DoResultRecord(Line: String): Boolean;
|
function DoResultRecord(Line: String): Boolean;
|
||||||
@ -1658,50 +1707,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function TGDBMIDebugger.ProcessStopped(const AParams: String; const AIgnoreSigIntState: Boolean): Boolean;
|
function TGDBMIDebugger.ProcessStopped(const AParams: String; const AIgnoreSigIntState: Boolean): Boolean;
|
||||||
function GetFrame(const AIndex: Integer): String;
|
|
||||||
var
|
|
||||||
R: TGDBMIExecResult;
|
|
||||||
S: String;
|
|
||||||
List: TStringList;
|
|
||||||
begin
|
|
||||||
Result := '';
|
|
||||||
if ExecuteCommand('-stack-list-frames %d %d', [AIndex, AIndex], [cfIgnoreError], R)
|
|
||||||
then begin
|
|
||||||
List := CreateMIValueList(R);
|
|
||||||
S := List.Values['stack'];
|
|
||||||
List.Free;
|
|
||||||
List := CreateMIValueList(S);
|
|
||||||
Result := List.Values['frame'];
|
|
||||||
List.Free;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure ProcessFrame(const AFrame: String);
|
|
||||||
var
|
|
||||||
S: String;
|
|
||||||
e: Integer;
|
|
||||||
Frame: TStringList;
|
|
||||||
Location: TDBGLocationRec;
|
|
||||||
begin
|
|
||||||
// Do we have a frame ?
|
|
||||||
if AFrame = ''
|
|
||||||
then S := GetFrame(0)
|
|
||||||
else S := AFrame;
|
|
||||||
|
|
||||||
Frame := CreateMIValueList(S);
|
|
||||||
|
|
||||||
Location.Address := 0;
|
|
||||||
Val(Frame.Values['addr'], Location.Address, e);
|
|
||||||
if e=0 then ;
|
|
||||||
Location.FuncName := Frame.Values['func'];
|
|
||||||
Location.SrcFile := Frame.Values['file'];
|
|
||||||
Location.SrcLine := StrToIntDef(Frame.Values['line'], -1);
|
|
||||||
|
|
||||||
Frame.Free;
|
|
||||||
|
|
||||||
DoCurrent(Location);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function GetLocation: TDBGLocationRec;
|
function GetLocation: TDBGLocationRec;
|
||||||
var
|
var
|
||||||
R: TGDBMIExecResult;
|
R: TGDBMIExecResult;
|
||||||
@ -2078,12 +2083,43 @@ function TGDBMIDebugger.StartDebugging(const AContinueCommand: String): Boolean;
|
|||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function SetTempMainBreak: Boolean;
|
||||||
|
var
|
||||||
|
R: TGDBMIExecResult;
|
||||||
|
S: String;
|
||||||
|
ResultList, BkptList: TStringList;
|
||||||
|
begin
|
||||||
|
// Try to retrieve the address of main. Setting a break on main is past initialization
|
||||||
|
if ExecuteCommand('info address main', [cfNoMICommand, cfIgnoreError], R)
|
||||||
|
and (R.State <> dsError)
|
||||||
|
then begin
|
||||||
|
S := GetPart('at address ', '.', R.Values);
|
||||||
|
if S <> ''
|
||||||
|
then begin
|
||||||
|
FMainAddr := StrToIntDef(S, 0);
|
||||||
|
ExecuteCommand('-break-insert -t *' + S, [cfIgnoreError], R);
|
||||||
|
Result := R.State <> dsError;
|
||||||
|
if Result then Exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
ExecuteCommand('-break-insert -t main', [cfIgnoreError], R);
|
||||||
|
Result := R.State <> dsError;
|
||||||
|
if not Result then Exit;
|
||||||
|
|
||||||
|
ResultList := CreateMIValueList(R);
|
||||||
|
BkptList := CreateMIValueList(ResultList.Values['bkpt']);
|
||||||
|
FMainAddr := StrToIntDef(BkptList.Values['addr'], 0);
|
||||||
|
BkptList.Free;
|
||||||
|
ResultList.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
R: TGDBMIExecResult;
|
R: TGDBMIExecResult;
|
||||||
S, FileType, EntryPoint: String;
|
S, FileType, EntryPoint: String;
|
||||||
List: TStringList;
|
List: TStringList;
|
||||||
TargetPIDPart: String;
|
TargetPIDPart: String;
|
||||||
TempInstalled: Boolean;
|
TempInstalled, CanContinue: Boolean;
|
||||||
begin
|
begin
|
||||||
if not (State in [dsStop])
|
if not (State in [dsStop])
|
||||||
then begin
|
then begin
|
||||||
@ -2107,8 +2143,7 @@ begin
|
|||||||
then begin
|
then begin
|
||||||
// Make sure we are talking pascal
|
// Make sure we are talking pascal
|
||||||
ExecuteCommand('-gdb-set language pascal', []);
|
ExecuteCommand('-gdb-set language pascal', []);
|
||||||
ExecuteCommand('-break-insert -t main', [], [cfIgnoreError], R);
|
TempInstalled := SetTempMainBreak;
|
||||||
TempInstalled := R.State <> dsError;
|
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
DebugLn('TGDBMIDebugger.StartDebugging Note: Target has no symbols');
|
DebugLn('TGDBMIDebugger.StartDebugging Note: Target has no symbols');
|
||||||
@ -2153,11 +2188,12 @@ begin
|
|||||||
|
|
||||||
SetTargetInfo(FileType);
|
SetTargetInfo(FileType);
|
||||||
|
|
||||||
if not TempInstalled and (Length(EntryPoint) > 0)
|
if not TempInstalled and (EntryPoint <> '')
|
||||||
then begin
|
then begin
|
||||||
// We could not set our initial break to get info and allow stepping
|
// We could not set our initial break to get info and allow stepping
|
||||||
// Try it with the program entry point
|
// Try it with the program entry point
|
||||||
ExecuteCommand('-break-insert -t *%d', [StrToIntDef(EntryPoint, 0)], [cfIgnoreError], R);
|
FMainAddr := StrToIntDef(EntryPoint, 0);
|
||||||
|
ExecuteCommand('-break-insert -t *' + EntryPoint, [cfIgnoreError], R);
|
||||||
TempInstalled := R.State <> dsError;
|
TempInstalled := R.State <> dsError;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2195,11 +2231,21 @@ begin
|
|||||||
if R.State = dsNone
|
if R.State = dsNone
|
||||||
then begin
|
then begin
|
||||||
SetState(dsInit);
|
SetState(dsInit);
|
||||||
if AContinueCommand <> ''
|
if FBreakAtMain <> nil
|
||||||
|
then begin
|
||||||
|
CanContinue := False;
|
||||||
|
TGDBMIBreakPoint(FBreakAtMain).Hit(CanContinue);
|
||||||
|
end
|
||||||
|
else CanContinue := True;
|
||||||
|
|
||||||
|
if CanContinue and (AContinueCommand <> '')
|
||||||
then Result := ExecuteCommand(AContinueCommand, [])
|
then Result := ExecuteCommand(AContinueCommand, [])
|
||||||
else SetState(dsPause);
|
else SetState(dsPause);
|
||||||
end
|
end
|
||||||
else SetState(R.State);
|
else SetState(R.State);
|
||||||
|
|
||||||
|
if State = dsPause
|
||||||
|
then ProcessFrame;
|
||||||
|
|
||||||
Result := True;
|
Result := True;
|
||||||
end;
|
end;
|
||||||
@ -2286,6 +2332,16 @@ begin
|
|||||||
else SetValid(vsInvalid);
|
else SetValid(vsInvalid);
|
||||||
UpdateExpression;
|
UpdateExpression;
|
||||||
UpdateEnable;
|
UpdateEnable;
|
||||||
|
|
||||||
|
if (FBreakID <> 0)
|
||||||
|
and Enabled
|
||||||
|
and (TGDBMIDebugger(Debugger).FBreakAtMain = nil)
|
||||||
|
then begin
|
||||||
|
// Check if this BP is at the same location as the temp break
|
||||||
|
if StrToIntDef(BkptList.Values['addr'], 0) = TGDBMIDebugger(Debugger).FMainAddr
|
||||||
|
then TGDBMIDebugger(Debugger).FBreakAtMain := Self;
|
||||||
|
end;
|
||||||
|
|
||||||
ResultList.Free;
|
ResultList.Free;
|
||||||
BkptList.Free;
|
BkptList.Free;
|
||||||
finally
|
finally
|
||||||
|
Loading…
Reference in New Issue
Block a user