* Dbg: Added debug expressions. Modyfied patch #16474 by Flavio Etrusco

* Dbg: Improved pascal to gdb string conversion, so valid gdb strings will 
       be used for breakpoint expresions and string modification
* Dbg: some cleanup

git-svn-id: trunk@25523 -
This commit is contained in:
marc 2010-05-19 23:28:46 +00:00
parent 9d580fed56
commit 07e6bb0f2b
3 changed files with 278 additions and 229 deletions

View File

@ -19,9 +19,9 @@ inherited BreakPropertyDlg: TBreakPropertyDlg
AnchorSideTop.Control = edtFilename
AnchorSideTop.Side = asrCenter
Left = 6
Height = 18
Height = 14
Top = 10
Width = 62
Width = 55
BorderSpacing.Around = 6
Caption = 'Filename:'
ParentColor = False
@ -31,21 +31,20 @@ inherited BreakPropertyDlg: TBreakPropertyDlg
AnchorSideTop.Control = edtLine
AnchorSideTop.Side = asrCenter
Left = 6
Height = 18
Top = 43
Width = 31
Height = 14
Top = 39
Width = 28
BorderSpacing.Around = 6
Caption = 'Line:'
ParentColor = False
end
object lblCondition: TLabel[2]
AnchorSideLeft.Control = Owner
AnchorSideTop.Control = edtCondition
AnchorSideTop.Side = asrCenter
Left = 6
Height = 18
Height = 14
Top = 76
Width = 65
Width = 58
BorderSpacing.Around = 6
Caption = 'Condition:'
ParentColor = False
@ -55,9 +54,9 @@ inherited BreakPropertyDlg: TBreakPropertyDlg
AnchorSideTop.Control = edtCounter
AnchorSideTop.Side = asrCenter
Left = 6
Height = 18
Height = 14
Top = 109
Width = 59
Width = 51
BorderSpacing.Around = 6
Caption = 'Hitcount:'
ParentColor = False
@ -67,9 +66,9 @@ inherited BreakPropertyDlg: TBreakPropertyDlg
AnchorSideTop.Control = cmbGroup
AnchorSideTop.Side = asrCenter
Left = 6
Height = 18
Top = 176
Width = 44
Height = 14
Top = 169
Width = 40
BorderSpacing.Around = 6
Caption = 'Group:'
ParentColor = False
@ -79,9 +78,9 @@ inherited BreakPropertyDlg: TBreakPropertyDlg
AnchorSideTop.Control = edtAutocontinueMS
AnchorSideTop.Side = asrCenter
Left = 6
Height = 18
Top = 142
Width = 124
Height = 14
Top = 138
Width = 109
BorderSpacing.Around = 6
Caption = 'Auto continue after'
ParentColor = False
@ -91,10 +90,10 @@ inherited BreakPropertyDlg: TBreakPropertyDlg
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = lblAutoContinue
AnchorSideTop.Side = asrCenter
Left = 208
Height = 18
Top = 142
Width = 31
Left = 193
Height = 14
Top = 138
Width = 27
BorderSpacing.Left = 6
Caption = '(ms)'
ParentColor = False
@ -105,58 +104,40 @@ inherited BreakPropertyDlg: TBreakPropertyDlg
AnchorSideTop.Control = edtCounter
AnchorSideTop.Side = asrBottom
AnchorSideRight.Side = asrBottom
Left = 142
Height = 27
Top = 138
Left = 127
Height = 23
Top = 134
Width = 60
BorderSpacing.Left = 6
BorderSpacing.Around = 6
TabOrder = 4
TabOrder = 3
Text = 'edtAutocontinueMS'
end
object edtCounter: TEdit[8]
AnchorSideLeft.Control = lblAutoContinue
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = edtCondition
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
Left = 142
Height = 27
Left = 127
Height = 23
Top = 105
Width = 295
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 6
BorderSpacing.Around = 6
TabOrder = 3
Text = 'edtCounter'
end
object edtCondition: TEdit[9]
AnchorSideLeft.Control = lblAutoContinue
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = edtLine
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
Left = 142
Height = 27
Top = 72
Width = 295
Width = 310
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 6
BorderSpacing.Around = 6
TabOrder = 2
Text = 'edtCondition'
Text = 'edtCounter'
end
object edtLine: TEdit[10]
object edtLine: TEdit[9]
AnchorSideLeft.Control = lblAutoContinue
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = edtFilename
AnchorSideTop.Side = asrBottom
AnchorSideRight.Side = asrBottom
Left = 142
Height = 27
Top = 39
Left = 127
Height = 23
Top = 35
Width = 60
BorderSpacing.Left = 6
BorderSpacing.Around = 6
@ -165,16 +146,16 @@ inherited BreakPropertyDlg: TBreakPropertyDlg
TabOrder = 1
Text = 'edtLine'
end
object edtFilename: TEdit[11]
object edtFilename: TEdit[10]
AnchorSideLeft.Control = lblAutoContinue
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = Owner
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
Left = 142
Height = 27
Left = 127
Height = 23
Top = 6
Width = 295
Width = 310
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 6
BorderSpacing.Around = 6
@ -183,48 +164,48 @@ inherited BreakPropertyDlg: TBreakPropertyDlg
TabOrder = 0
Text = 'edtFilename'
end
object cmbGroup: TComboBox[12]
object cmbGroup: TComboBox[11]
AnchorSideLeft.Control = lblAutoContinue
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = edtAutocontinueMS
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
Left = 142
Height = 29
Top = 171
Width = 295
Left = 127
Height = 27
Top = 163
Width = 310
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 6
BorderSpacing.Around = 6
ItemHeight = 0
TabOrder = 5
TabOrder = 4
Text = 'cmbGroup'
end
object gbActions: TGroupBox[13]
object gbActions: TGroupBox[12]
AnchorSideLeft.Control = Owner
AnchorSideTop.Control = cmbGroup
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
Left = 6
Height = 185
Top = 206
Height = 165
Top = 196
Width = 431
Anchors = [akTop, akLeft, akRight]
AutoSize = True
BorderSpacing.Around = 6
Caption = 'Actions'
ClientHeight = 166
ClientHeight = 150
ClientWidth = 427
TabOrder = 6
TabOrder = 5
object chkActionBreak: TCheckBox
AnchorSideLeft.Control = gbActions
AnchorSideTop.Control = gbActions
Left = 6
Height = 22
Top = 6
Width = 61
Width = 57
BorderSpacing.Around = 6
Caption = 'Break'
TabOrder = 0
@ -235,8 +216,8 @@ inherited BreakPropertyDlg: TBreakPropertyDlg
AnchorSideTop.Side = asrCenter
Left = 6
Height = 22
Top = 36
Width = 110
Top = 34
Width = 101
BorderSpacing.Around = 6
Caption = 'Enable goups'
TabOrder = 1
@ -247,8 +228,8 @@ inherited BreakPropertyDlg: TBreakPropertyDlg
AnchorSideTop.Side = asrCenter
Left = 6
Height = 22
Top = 69
Width = 119
Top = 63
Width = 110
BorderSpacing.Around = 6
Caption = 'Disable groups'
TabOrder = 2
@ -259,10 +240,10 @@ inherited BreakPropertyDlg: TBreakPropertyDlg
AnchorSideTop.Control = chkActionBreak
AnchorSideTop.Side = asrBottom
AnchorSideRight.Side = asrBottom
Left = 147
Height = 27
Left = 143
Height = 23
Top = 34
Width = 251
Width = 255
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 80
BorderSpacing.Top = 6
@ -280,10 +261,10 @@ inherited BreakPropertyDlg: TBreakPropertyDlg
AnchorSideTop.Control = edtEnableGroups
AnchorSideTop.Side = asrBottom
AnchorSideRight.Side = asrBottom
Left = 147
Height = 27
Top = 67
Width = 251
Left = 143
Height = 23
Top = 63
Width = 255
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 80
BorderSpacing.Top = 6
@ -301,8 +282,8 @@ inherited BreakPropertyDlg: TBreakPropertyDlg
AnchorSideTop.Side = asrCenter
Left = 6
Height = 22
Top = 102
Width = 123
Top = 92
Width = 114
BorderSpacing.Around = 6
Caption = 'Eval expression'
Enabled = False
@ -314,8 +295,8 @@ inherited BreakPropertyDlg: TBreakPropertyDlg
AnchorSideTop.Side = asrCenter
Left = 6
Height = 22
Top = 135
Width = 110
Top = 121
Width = 101
BorderSpacing.Around = 6
Caption = 'Log message'
Enabled = False
@ -328,10 +309,10 @@ inherited BreakPropertyDlg: TBreakPropertyDlg
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = gbActions
AnchorSideRight.Side = asrBottom
Left = 147
Height = 27
Top = 100
Width = 274
Left = 143
Height = 23
Top = 92
Width = 278
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 80
BorderSpacing.Top = 6
@ -347,10 +328,10 @@ inherited BreakPropertyDlg: TBreakPropertyDlg
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = gbActions
AnchorSideRight.Side = asrBottom
Left = 147
Height = 27
Top = 133
Width = 274
Left = 143
Height = 23
Top = 121
Width = 278
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 80
BorderSpacing.Top = 6
@ -360,17 +341,35 @@ inherited BreakPropertyDlg: TBreakPropertyDlg
TabOrder = 8
end
end
object ButtonPanel: TButtonPanel[14]
object ButtonPanel: TButtonPanel[13]
AnchorSideTop.Control = gbActions
AnchorSideTop.Side = asrBottom
AnchorSideRight.Side = asrBottom
Left = 6
Height = 32
Top = 397
Height = 62
Top = 367
Width = 431
Anchors = [akTop, akLeft, akRight, akBottom]
TabOrder = 7
TabOrder = 6
ShowButtons = [pbOK, pbCancel, pbHelp]
ShowBevel = False
end
object edtCondition: TComboBox[14]
AnchorSideLeft.Control = lblAutoContinue
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = edtLine
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
Left = 127
Height = 27
Top = 64
Width = 310
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 6
BorderSpacing.Around = 6
ItemHeight = 0
TabOrder = 7
Text = 'edtCondition'
end
end

View File

@ -7,7 +7,7 @@ interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
ExtCtrls, StdCtrls, Buttons, DebuggerDlg, Debugger, ButtonPanel, EditBtn,
BaseDebugManager, IDEContextHelpEdit, LazarusIDEStrConsts;
BaseDebugManager, IDEContextHelpEdit, LazarusIDEStrConsts, InputHistory;
type
@ -21,12 +21,12 @@ type
chkLogMessage: TCheckBox;
chkActionBreak: TCheckBox;
cmbGroup: TComboBox;
edtCondition: TComboBox;
edtEvalExpression: TEdit;
edtLogMessage: TEdit;
edtEnableGroups: TEditButton;
edtDisableGroups: TEditButton;
edtAutocontinueMS: TEdit;
edtCondition: TEdit;
edtCounter: TEdit;
edtFilename: TEdit;
edtLine: TEdit;
@ -105,6 +105,8 @@ begin
// if chkEvalExpression.Checked then Include(Actions, bpaEValExpression);
// if chkLogMessage.Checked then Include(Actions, bpaLogMessage);
FBreakpoint.Actions := Actions;
InputHistories.HistoryLists.GetList('BreakPointExpression', True).Add(edtCondition.Text);
end;
procedure TBreakPropertyDlg.DoEndUpdate;
@ -162,6 +164,7 @@ begin
chkDisableGroups.Caption := lisDisableGroup;
chkEvalExpression.Caption := lisEvalExpression;
chkLogMessage.Caption := lisLogMessage;
edtCondition.Items.Assign(InputHistories.HistoryLists.GetList('BreakPointExpression', True));
FBreakpoint := ABreakPoint;
FBreakpointsNotification := TIDEBreakPointsNotification.Create;

View File

@ -153,6 +153,7 @@ type
function GDBSourceAdress(const ASource: String; ALine, AColumn: Integer; out AAddr: TDbgPtr): Boolean;
procedure CallStackSetCurrent(AIndex: Integer);
function ConvertPascalExpression(var AExpression: String): Boolean;
// ---
procedure ClearSourceInfo;
procedure GDBStopCallback(const AResult: TGDBMIExecResult; const ATag: PtrInt);
@ -285,6 +286,7 @@ type
TGDBMIBreakPoint = class(TDBGBreakPoint)
private
FBreakID: Integer;
FParsedExpression: String;
procedure SetBreakPointCallback(const AResult: TGDBMIExecResult; const ATag: PtrInt);
procedure SetBreakPoint;
procedure ReleaseBreakPoint;
@ -2683,127 +2685,6 @@ begin
end;
function TGDBMIDebugger.GDBModify(const AExpression, ANewValue: String): Boolean;
function ConvertString(var AValue: String): Boolean;
var
R: String;
P: PChar;
InString, EndString, EndVal: Boolean;
CharVal: Byte;
n: Integer;
ValMode: Char;
begin
R := '"';
Instring := False;
EndString := False;
EndVal := False;
ValMode := #0;
CharVal := 0;
P := @AValue[1];
for n := 1 to Length(AVAlue) do
begin
if InString
then begin
case P^ of
'''': begin
InString := False;
EndString := True;
end;
#0..#31,
'"',
#128..#255: begin
R := R + '\' + OctStr(Ord(P^), 3);
end;
else
R := R + P^;
end;
Inc(P);
Continue;
end;
case P^ of
'''': begin
if EndString
then R := R + '\' + OctStr(Ord(''''), 3);
EndVal := True;
InString := True;
end;
'#': begin
if ValMode <> #0
then begin
if not (ValMode in ['h', 'd', 'o', 'b']) then Exit(False);
R := R + '\' + OctStr(CharVal, 3);
end;
CharVal := 0;
ValMode := 'D';
end;
'$', '&', '%': begin
if ValMode <> 'D' then Exit(False);
ValMode := P^;
end;
else
case ValMode of
'D', 'd': begin
case P^ of
'0'..'9': CharVal := CharVal * 10 + Ord(P^) - Ord('0');
else
Exit(False);
end;
ValMode := 'd';
end;
'$', 'h': begin
case P^ of
'0'..'9': CharVal := CharVal * 16 + Ord(P^) - Ord('0');
'a'..'f': CharVal := CharVal * 16 + Ord(P^) - Ord('a');
'A'..'F': CharVal := CharVal * 16 + Ord(P^) - Ord('A');
else
Exit(False);
end;
ValMode := 'h';
end;
'&', 'o': begin
case P^ of
'0'..'7': CharVal := CharVal * 8 + Ord(P^) - Ord('0');
else
Exit(False);
end;
ValMode := 'o';
end;
'%', 'b': begin
case P^ of
'0': CharVal := CharVal shl 1;
'1': CharVal := CharVal shl 1 or 1;
else
Exit(False);
end;
ValMode := 'o';
end;
else
Exit(False);
end;
end;
if EndVal
then begin
case Valmode of
#0:;
'h', 'd', 'o', 'b': begin
R := R + '\' + OctStr(CharVal, 3);
ValMode := #0;
end;
else
Exit(False);
end;
EndVal := False;
end;
EndString := False;
Inc(p);
end;
AValue := R + '"';
Result := True;
end;
var
R: TGDBMIExecResult;
S: String;
@ -2811,7 +2692,7 @@ begin
S := Trim(ANewValue);
if (S <> '') and (S[1] in ['''', '#'])
then begin
if not ConvertString(S) then Exit(False);
if not ConvertPascalExpression(S) then Exit(False);
end;
Result := ExecuteCommand('-gdb-set var %s := %s', [AExpression, S], [cfIgnoreError, cfExternal], R)
@ -4028,6 +3909,157 @@ begin
FSourceNames.Clear;
end;
function TGDBMIDebugger.ConvertPascalExpression(var AExpression: String): Boolean;
var
R: String;
P: PChar;
InString, WasString, IsText, ValIsChar: Boolean;
n: Integer;
ValMode: Char;
Value: QWord;
function AppendValue: Boolean;
var
S: String;
begin
if ValMode = #0 then Exit(True);
if not (ValMode in ['h', 'd', 'o', 'b']) then Exit(False);
if ValIsChar
then begin
if not IsText
then begin
R := R + '"';
IsText := True;
end;
R := R + '\' + OctStr(Value, 3);
ValIsChar := False;
end
else begin
if IsText
then begin
R := R + '"';
IsText := False;
end;
Str(Value, S);
R := R + S;
end;
Result := True;
ValMode := #0;
end;
begin
R := '';
Instring := False;
WasString := False;
IsText := False;
ValIsChar := False;
ValMode := #0;
Value := 0;
P := @AExpression[1];
for n := 1 to Length(AExpression) do
begin
if InString
then begin
case P^ of
'''': begin
InString := False;
// delay setting terminating ", more characters defined through # may follow
WasString := True;
end;
#0..#31,
'"', '\',
#128..#255: begin
R := R + '\' + OctStr(Ord(P^), 3);
end;
else
R := R + P^;
end;
Inc(P);
Continue;
end;
case P^ of
'''': begin
if WasString
then begin
R := R + '\' + OctStr(Ord(''''), 3)
end
else begin
if not AppendValue then Exit(False);
if not IsText
then R := R + '"';
end;
IsText := True;
InString := True;
end;
'#': begin
if not AppendValue then Exit(False);
Value := 0;
ValMode := 'D';
ValIsChar := True;
end;
'$', '&', '%': begin
if not (ValMode in [#0, 'D']) then Exit(False);
ValMode := P^;
end;
else
case ValMode of
'D', 'd': begin
case P^ of
'0'..'9': Value := Value * 10 + Ord(P^) - Ord('0');
else
Exit(False);
end;
ValMode := 'd';
end;
'$', 'h': begin
case P^ of
'0'..'9': Value := Value * 16 + Ord(P^) - Ord('0');
'a'..'f': Value := Value * 16 + Ord(P^) - Ord('a');
'A'..'F': Value := Value * 16 + Ord(P^) - Ord('A');
else
Exit(False);
end;
ValMode := 'h';
end;
'&', 'o': begin
case P^ of
'0'..'7': Value := Value * 8 + Ord(P^) - Ord('0');
else
Exit(False);
end;
ValMode := 'o';
end;
'%', 'b': begin
case P^ of
'0': Value := Value shl 1;
'1': Value := Value shl 1 or 1;
else
Exit(False);
end;
ValMode := 'b';
end;
else
if IsText
then begin
R := R + '"';
IsText := False;
end;
R := R + P^;
end;
end;
WasString := False;
Inc(p);
end;
if not AppendValue then Exit(False);
if IsText then R := R + '"';
AExpression := R;
Result := True;
end;
procedure TGDBMIDebugger.SelectStackFrame(AIndex: Integer);
begin
ExecuteCommand('-stack-select-frame %d', [AIndex], [cfIgnoreError]);
@ -4427,7 +4459,13 @@ begin
end;
procedure TGDBMIBreakPoint.DoExpressionChange;
var
S: String;
begin
S := Expression;
if TGDBMIDebugger(Debugger).ConvertPascalExpression(S)
then FParsedExpression := S
else FParsedExpression := Expression;
UpdateExpression;
inherited;
end;
@ -4474,14 +4512,18 @@ begin
ResultList := TGDBMINameValueList.Create(AResult, ['bkpt']);
FBreakID := StrToIntDef(ResultList.Values['number'], 0);
SetHitCount(StrToIntDef(ResultList.Values['times'], 0));
if FBreakID <> 0
then SetValid(vsValid)
else SetValid(vsInvalid);
UpdateExpression;
if FBreakID = 0
then begin
ResultList.Free;
SetValid(vsInvalid);
Exit;
end;
SetValid(vsValid);
if FParsedExpression <> '' then UpdateExpression;
UpdateEnable;
if (FBreakID <> 0)
and Enabled
if Enabled
and (TGDBMIDebugger(Debugger).FBreakAtMain = nil)
then begin
// Check if this BP is at the same location as the temp break
@ -4521,19 +4563,24 @@ const
// Use shortstring as fix for fpc 1.9.5 [2004/07/15]
CMD: array[Boolean] of ShortString = ('disable', 'enable');
begin
if (FBreakID = 0)
or (Debugger = nil)
then Exit;
if FBreakID = 0 then Exit;
if Debugger = nil then Exit;
if Debugger.State = dsRun
then TGDBMIDebugger(Debugger).GDBPause(True);
//writeln('TGDBMIBreakPoint.UpdateEnable Line=',Line,' Enabled=',Enabled,' InitialEnabled=',InitialEnabled);
TGDBMIDebugger(Debugger).ExecuteCommand('-break-%s %d',
[CMD[Enabled], FBreakID], []);
TGDBMIDebugger(Debugger).ExecuteCommand('-break-%s %d', [CMD[Enabled], FBreakID], []);
end;
procedure TGDBMIBreakPoint.UpdateExpression;
begin
if FBreakID = 0 then Exit;
if Debugger = nil then Exit;
if Debugger.State = dsRun
then TGDBMIDebugger(Debugger).GDBPause(True);
TGDBMIDebugger(Debugger).ExecuteCommand('-break-condition %d %s', [FBreakID, FParsedExpression], [cfIgnoreError, cfExternal]);
end;
{ =========================================================================== }