196 |aDebugger proc debugAction| |
196 |aDebugger proc debugAction| |
197 |
197 |
198 StepInterruptPending := nil. |
198 StepInterruptPending := nil. |
199 proc := Processor activeProcess. |
199 proc := Processor activeProcess. |
200 |
200 |
201 debugAction := [ |
201 "/ ignore halts & breakpoints while setting up the debugger |
202 aDebugger := self new. |
202 "/ to avoid recursive debugging ... |
203 aDebugger notNil ifTrue:[ |
203 ControlInterrupt handle:[:ex | |
204 Error handle:[:ex | |
204 ex parameter == #doNotCatchInDebugger. |
205 'DebugView [error]: error in debugger startup - shut down debugger' errorPrintCR. |
205 |
206 'DebugView [error]: Exception:' , ex description infoPrintCR. |
206 ex parameter printCR. |
207 ex return |
207 'DebugView [info]: breakpoint in debugger ignored [enterUncond.]' infoPrintCR. |
208 ] do:[ |
208 ex proceed |
209 aDebugger mayProceed:mayProceed. |
209 ] do:[ |
210 aDebugger setLabelFor:aString in:proc. |
210 aDebugger := self new. |
211 aDebugger enter:aContext select:nil. |
211 aDebugger notNil ifTrue:[ |
212 ] |
212 Error handle:[:ex | |
|
213 'DebugView [error]: error in debugger startup - shut down debugger' errorPrintCR. |
|
214 'DebugView [error]: Exception:' , ex description infoPrintCR. |
|
215 ex return |
|
216 ] do:[ |
|
217 aDebugger mayProceed:mayProceed. |
|
218 aDebugger setLabelFor:aString in:proc. |
|
219 aDebugger enter:aContext select:nil. |
|
220 ] |
|
221 ] ifFalse:[ |
|
222 'DebugView [error]: cannot open debugger' errorPrintCR. |
|
223 'DebugView [error]: Exception: ' errorPrint. aString errorPrintCR. |
|
224 mayProceed ifTrue:[ |
|
225 (Dialog confirm:'Error/Breakpoint cought.\\Press Continue or Abort.' withCRs |
|
226 yesLabel:'Continue' noLabel:'Abort') |
|
227 ifTrue:[ |
|
228 ^ nil |
|
229 ]. |
213 ] ifFalse:[ |
230 ] ifFalse:[ |
214 'DebugView [error]: cannot open debugger' errorPrintCR. |
231 self information:'Error cought.\\Press OK to abort the operation.' withCRs. |
215 'DebugView [error]: Exception: ' errorPrint. aString errorPrintCR. |
232 ]. |
216 mayProceed ifTrue:[ |
233 AbortSignal raise. |
217 (Dialog confirm:'Error/Breakpoint cought.\\Press Continue or Abort.' withCRs |
234 ] |
218 yesLabel:'Continue' noLabel:'Abort') |
|
219 ifTrue:[ |
|
220 ^ nil |
|
221 ]. |
|
222 ] ifFalse:[ |
|
223 self information:'Error cought.\\Press OK to abort the operation.' withCRs. |
|
224 ]. |
|
225 AbortSignal raise. |
|
226 ^ nil. |
|
227 ] |
|
228 ]. |
|
229 |
|
230 "/ ignore breakpoints while setting up the debugger |
|
231 "/ to avoid recursive debugging ... |
|
232 |
|
233 ControlInterrupt notNil ifTrue:[ |
|
234 ControlInterrupt handle:[:ex | |
|
235 'DebugView [info]: breakpoint in debugger ignored' infoPrintCR. |
|
236 ex proceed |
|
237 ] do:debugAction |
|
238 ] ifFalse:[ |
|
239 debugAction value |
|
240 ]. |
235 ]. |
241 ^ nil |
236 ^ nil |
242 |
237 |
243 "nil halt" |
238 "nil halt" |
244 |
239 |
245 "Modified: / 31.10.2001 / 09:39:14 / cg" |
240 "Modified: / 16.11.2001 / 17:15:48 / cg" |
246 ! |
241 ! |
247 |
242 |
248 new |
243 new |
249 "return a new DebugView. |
244 "return a new DebugView. |
250 - return a cached debugger if it already exists. |
245 - return a cached debugger if it already exists. |
917 get the walkback list; clear inspectors if we did not come here by single stepping) |
931 get the walkback list; clear inspectors if we did not come here by single stepping) |
918 " |
932 " |
919 self setContext:aContext releaseInspectors:(exitAction ~~ #step). |
933 self setContext:aContext releaseInspectors:(exitAction ~~ #step). |
920 "/'after setContext; first is ' print. |
934 "/'after setContext; first is ' print. |
921 "/(contextArray at:1 ifAbsent:nil) printCR. |
935 "/(contextArray at:1 ifAbsent:nil) printCR. |
|
936 self setInitialSelectionOnEntry:initialSelectionOrNil context:aContext. |
|
937 |
|
938 m := contextView middleButtonMenu. |
|
939 m notNil ifTrue:[ |
|
940 self updateMenuItems. |
|
941 |
|
942 (inspecting or:[AbortOperationRequest isHandled]) ifTrue:[ |
|
943 abortButton enable. |
|
944 m enable:#doAbort. |
|
945 ] ifFalse:[ |
|
946 abortButton disable. |
|
947 m disable:#doAbort. |
|
948 ]. |
|
949 exclusive ifTrue:[ |
|
950 terminateButton disable. |
|
951 m disable:#doTerminate. |
|
952 ] ifFalse:[ |
|
953 terminateButton enable. |
|
954 m enable:#doTerminate. |
|
955 ] |
|
956 ]. |
|
957 |
|
958 mayProceed == false ifTrue:[ |
|
959 continueButton disable. |
|
960 m notNil ifTrue:[m disable:#doContinue]. |
|
961 ] ifFalse:[ |
|
962 continueButton enable. |
|
963 m notNil ifTrue:[m enable:#doContinue] |
|
964 ]. |
|
965 |
|
966 " |
|
967 If this is a new debugger, do a realize. |
|
968 Otherwise, its probably better to do a map, which shows the |
|
969 view at the previous position, without a need for the user to set the |
|
970 position again |
|
971 " |
|
972 iAmNew ifFalse:[ |
|
973 self remap. |
|
974 ] ifTrue:[ |
|
975 self realize. |
|
976 ]. |
|
977 |
|
978 exclusive ifTrue:[ |
|
979 self showError:' |
|
980 Debugging system process `' , (inspectedProcess nameOrId) printString , '''. |
|
981 |
|
982 This is a modal debugger - all event processing is stopped.. |
|
983 Therefore, you cannot interact with other views or |
|
984 open any other tools while this debugger is active. |
|
985 |
|
986 Also, there is no event processing (redraw) for other views.' |
|
987 ]. |
|
988 |
|
989 self raise. |
|
990 |
|
991 canContinue := true. |
|
992 exitAction := nil. |
|
993 |
|
994 "/ enter private event handling loop. This is left (and we come back here again) |
|
995 "/ when any button was pressed which requires continuation of the debuggee or |
|
996 "/ closedown of the debugger. |
|
997 [self controlLoop] valueOnUnwindDo:[ |
|
998 windowGroup notNil ifTrue:[ |
|
999 windowGroup setProcess:nil. |
|
1000 ]. |
|
1001 self destroy |
|
1002 ]. |
|
1003 |
|
1004 "/ release all context stuff. |
|
1005 "/ This is required to avoid keeping references to the debuggees objects |
|
1006 "/ forever. (since the debugger is reused for faster startup next time) |
|
1007 contextArray := nil. |
|
1008 contextView contents:nil. |
|
1009 |
|
1010 codeView acceptAction:nil. |
|
1011 codeView doItAction:nil. |
|
1012 |
|
1013 (exitAction ~~ #step) ifTrue:[ |
|
1014 lastSelectionInReceiverInspector := receiverInspector selectedKeyName. |
|
1015 lastSelectionInContextInspector := contextInspector selectedKeyName. |
|
1016 receiverInspector release. |
|
1017 contextInspector release. |
|
1018 |
|
1019 self unmap. |
|
1020 device flush. |
|
1021 |
|
1022 self cacheMyself. |
|
1023 |
|
1024 (exitAction == #abort) ifTrue:[ |
|
1025 self exit_abort. |
|
1026 ]. |
|
1027 |
|
1028 (exitAction == #return) ifTrue:[ |
|
1029 self exit_return. |
|
1030 ]. |
|
1031 |
|
1032 (exitAction == #restart) ifTrue:[ |
|
1033 self exit_restart. |
|
1034 ]. |
|
1035 |
|
1036 (exitAction == #quickTerminate) ifTrue:[ |
|
1037 self exit_quickTerminate. |
|
1038 ]. |
|
1039 |
|
1040 (exitAction == #terminate) ifTrue:[ |
|
1041 self exit_terminate. |
|
1042 ] |
|
1043 ]. |
|
1044 |
|
1045 selectedContext := actualContext := firstContext := nil. |
|
1046 |
|
1047 "/ restore the previous pointer grab |
|
1048 grabber notNil ifTrue:[ |
|
1049 device grabPointerInView:grabber. |
|
1050 grabber := nil. |
|
1051 ]. |
|
1052 |
|
1053 (exitAction == #step) ifTrue:[ |
|
1054 " |
|
1055 schedule another stepInterrupt |
|
1056 - must enter myself into the collection of open debuggers, |
|
1057 in case the stepping process comes back again via a halt or signal |
|
1058 before the step is finished. In this case, the stepping debugger should |
|
1059 come up (instead of a new one) |
|
1060 - must flush caches since optimized methods not always |
|
1061 look for pending interrupts |
|
1062 " |
|
1063 |
|
1064 "/ |
|
1065 "/ also must care for stepping into a return |
|
1066 "/ |
|
1067 steppedContext notNil ifTrue:[ |
|
1068 Processor activeProcess forceInterruptOnReturnOf:steppedContext. |
|
1069 ]. |
|
1070 |
|
1071 OpenDebuggers isNil ifTrue:[ |
|
1072 OpenDebuggers := WeakArray with:self |
|
1073 ] ifFalse:[ |
|
1074 (OpenDebuggers includes:self) ifFalse:[ |
|
1075 idx := OpenDebuggers identityIndexOf:nil. |
|
1076 idx == 0 ifTrue:[ |
|
1077 idx := OpenDebuggers identityIndexOf:0 |
|
1078 ]. |
|
1079 idx ~~ 0 ifTrue:[ |
|
1080 OpenDebuggers at:idx put:self |
|
1081 ] ifFalse:[ |
|
1082 OpenDebuggers := OpenDebuggers copyWith:self |
|
1083 ] |
|
1084 ] |
|
1085 ]. |
|
1086 self label:'single stepping - please wait ...'. |
|
1087 stepping := true. |
|
1088 |
|
1089 ObjectMemory stepInterruptHandler:self. |
|
1090 Processor activeProcess stepInterruptHandler:self. |
|
1091 ObjectMemory flushCaches. |
|
1092 |
|
1093 Context singleStepInterruptRequest isHandled ifTrue:[ |
|
1094 "bigStep" steppedContextLineno notNil ifTrue:[ |
|
1095 Context singleStepInterruptRequest raiseWith:#next |
|
1096 ] ifFalse:[ |
|
1097 Context singleStepInterruptRequest raiseWith:#step |
|
1098 ] |
|
1099 ] ifFalse:[ |
|
1100 "/ see if we came here through an interrupt-action |
|
1101 "/ (i.e. aProcess interruptWith:...) |
|
1102 |
|
1103 enteredByInterrupt := false. |
|
1104 con := thisContext findNextContextWithSelector:#timerInterrupt or:#ioInterrupt or:nil. |
|
1105 [enteredByInterrupt not |
|
1106 and:[con notNil |
|
1107 and:[con ~~ aContext]]] whileTrue:[ |
|
1108 ((sel := con selector) == #timerInterrupt |
|
1109 or:[sel == #ioInterrupt]) ifTrue:[ |
|
1110 enteredByInterrupt := true. |
|
1111 ] ifFalse:[ |
|
1112 con := con findNextContextWithSelector:#timerInterrupt or:#ioInterrupt or:nil. |
|
1113 ]. |
|
1114 ]. |
|
1115 |
|
1116 ObjectMemory flushInlineCaches. |
|
1117 |
|
1118 DebuggingDebugger == true ifTrue:[ |
|
1119 enteredByInterrupt printCR. |
|
1120 ]. |
|
1121 enteredByInterrupt ifTrue:[ |
|
1122 "/ dont want to step through all intermediate |
|
1123 "/ (scheduler-) contexts; place a return-trap on the |
|
1124 "/ one right below the interesting one |
|
1125 |
|
1126 "/ 'special unwind return' printCR. |
|
1127 con unwindThenDo:[ |
|
1128 Processor activeProcess stepInterruptHandler:self. |
|
1129 ObjectMemory stepInterruptHandler:self. |
|
1130 InStepInterrupt := nil. |
|
1131 StepInterruptPending := 1. |
|
1132 InterruptPending := 1]. |
|
1133 ] ifFalse:[ |
|
1134 "/ 'normal step return' printCR. |
|
1135 skipLineNr ~~ #return ifTrue:[ |
|
1136 StepInterruptPending := 1. |
|
1137 InterruptPending := 1. |
|
1138 ] ifFalse:[ |
|
1139 "/ 'step for return' printCR. |
|
1140 ] |
|
1141 ]. |
|
1142 InStepInterrupt := nil |
|
1143 ] |
|
1144 ] ifFalse:[ |
|
1145 OpenDebuggers notNil ifTrue:[ |
|
1146 idx := OpenDebuggers identityIndexOf:self. |
|
1147 idx ~~ 0 ifTrue:[ |
|
1148 OpenDebuggers at:idx put:nil |
|
1149 ] |
|
1150 ]. |
|
1151 self cacheMyself. |
|
1152 ] |
|
1153 |
|
1154 "Modified: / 17.4.1997 / 13:01:32 / stefan" |
|
1155 "Created: / 30.10.1997 / 21:08:18 / cg" |
|
1156 "Modified: / 13.10.1998 / 19:56:59 / ps" |
|
1157 "Modified: / 16.11.2001 / 17:40:03 / cg" |
|
1158 ! |
|
1159 |
|
1160 exit_abort |
|
1161 " |
|
1162 have to catch errors occuring in unwind-blocks |
|
1163 " |
|
1164 ErrorSignal handle:[:ex | |
|
1165 'DebugView [info]: ignored error while unwinding: ' infoPrint. |
|
1166 ex errorString infoPrintCR. |
|
1167 |
|
1168 ex proceed |
|
1169 ] do:[ |
|
1170 AbortOperationRequest raise. |
|
1171 ]. |
|
1172 'DebugView [warning]: abort failed' errorPrintCR |
|
1173 |
|
1174 "Created: / 16.11.2001 / 17:20:45 / cg" |
|
1175 "Modified: / 16.11.2001 / 17:38:28 / cg" |
|
1176 ! |
|
1177 |
|
1178 exit_quickTerminate |
|
1179 Processor activeProcess terminateNoSignal |
|
1180 |
|
1181 "Created: / 16.11.2001 / 17:23:51 / cg" |
|
1182 "Modified: / 16.11.2001 / 17:24:55 / cg" |
|
1183 ! |
|
1184 |
|
1185 exit_restart |
|
1186 |con| |
|
1187 |
|
1188 selectedContext notNil ifTrue:[ |
|
1189 con := selectedContext. |
|
1190 " |
|
1191 have to catch errors occuring in unwind-blocks |
|
1192 " |
|
1193 Object errorSignal handle:[:ex | |
|
1194 'DebugView [info]: ignored error while unwinding: ' infoPrint. |
|
1195 ex errorString infoPrintCR. |
|
1196 ex proceed |
|
1197 ] do:[ |
|
1198 con unwindAndRestart. |
|
1199 ]. |
|
1200 'DebugView [warning]: cannot restart selected context' errorPrintCR |
|
1201 ] |
|
1202 |
|
1203 "Created: / 16.11.2001 / 17:23:17 / cg" |
|
1204 "Modified: / 16.11.2001 / 17:24:59 / cg" |
|
1205 ! |
|
1206 |
|
1207 exit_return |
|
1208 |con retVal| |
|
1209 |
|
1210 selectedContext notNil ifTrue:[ |
|
1211 " |
|
1212 if there is a selection in the codeView, |
|
1213 evaluate it and use the result as return value |
|
1214 " |
|
1215 "/ disabled for now, there is almost always a selection (the current line) |
|
1216 "/ and that is syntactically incorrect ... |
|
1217 "/ ... leading to a popup warning from the codeView |
|
1218 "/ |
|
1219 "/ codeView hasSelection ifTrue:[ |
|
1220 "/ Object errorSignal handle:[:ex | |
|
1221 "/ 'DebugView [warning]: error - returning nil' errorPrintCR. |
|
1222 "/ retVal := nil. |
|
1223 "/ ex return |
|
1224 "/ ] do:[ |
|
1225 "/ |s| |
|
1226 "/ |
|
1227 "/ s := codeView selection asString. |
|
1228 "/ retVal := codeView doItAction value:s. |
|
1229 "/ ]. |
|
1230 "/ ]. |
|
1231 |
|
1232 con := selectedContext. |
|
1233 " |
|
1234 have to catch errors occuring in unwind-blocks |
|
1235 " |
|
1236 Object errorSignal handle:[:ex | |
|
1237 'DebugView [info]: ignored error while unwinding: ' infoPrint. |
|
1238 ex errorString infoPrintCR. |
|
1239 ex proceed |
|
1240 ] do:[ |
|
1241 con unwind:retVal. |
|
1242 ]. |
|
1243 'DebugView [warning]: cannot return from selected context' errorPrintCR |
|
1244 ] |
|
1245 |
|
1246 "Created: / 16.11.2001 / 17:22:24 / cg" |
|
1247 "Modified: / 16.11.2001 / 17:25:03 / cg" |
|
1248 ! |
|
1249 |
|
1250 exit_terminate |
|
1251 |
|
1252 " |
|
1253 have to catch errors occuring in unwind-blocks |
|
1254 " |
|
1255 Object errorSignal handle:[:ex | |
|
1256 'DebugView [info]: ignored error while unwinding: ' infoPrint. |
|
1257 ex errorString infoPrintCR. |
|
1258 ex proceed |
|
1259 ] do:[ |
|
1260 Processor activeProcess terminate. |
|
1261 ]. |
|
1262 'DebugView [warning]: cannot terminate process' errorPrintCR |
|
1263 |
|
1264 "Created: / 16.11.2001 / 17:24:20 / cg" |
|
1265 "Modified: / 16.11.2001 / 17:25:09 / cg" |
|
1266 ! |
|
1267 |
|
1268 openOn:aProcess |
|
1269 "enter the debugger on a process - |
|
1270 in this case, we are just inspecting the context chain of the process, |
|
1271 not running on top of the debugged process, but as a separate |
|
1272 one. (think of it as an inspector showing more detail, and offering |
|
1273 some more control operations)" |
|
1274 |
|
1275 |bpanel dummy w| |
|
1276 |
|
1277 verboseBacktrace := VerboseBacktraceDefault ? false. |
|
1278 |
|
1279 busy := true. |
|
1280 bigStep := false. |
|
1281 stepHow := nil. |
|
1282 inspecting := true. |
|
1283 inspectedProcess := aProcess. |
|
1284 nChainShown := InitialNCHAINShown. |
|
1285 |
|
1286 bpanel := abortButton superView. |
|
1287 bpanel ignoreInvisibleComponents:true. |
|
1288 |
|
1289 "/ get the max size & freeze button |
|
1290 continueButton label:(resources at:'continue'). |
|
1291 w := continueButton preferredExtent x. |
|
1292 continueButton label:(resources at:'stop'). |
|
1293 w := w max:(continueButton preferredExtent x). |
|
1294 continueButton preferredExtent:(w @ continueButton preferredExtent y). |
|
1295 |
|
1296 aProcess state == #run ifTrue:[ |
|
1297 device hasColors ifTrue:[ |
|
1298 continueButton foregroundColor:Color red darkened. |
|
1299 ]. |
|
1300 continueButton label:(resources at:'stop'). |
|
1301 continueButton action:[self doStop]. |
|
1302 ] ifFalse:[ |
|
1303 device hasColors ifTrue:[ |
|
1304 continueButton foregroundColor:Color green darkened darkened. |
|
1305 ]. |
|
1306 continueButton label:(resources at:'continue'). |
|
1307 continueButton action:[self doContinue]. |
|
1308 ]. |
|
1309 |
|
1310 returnButton disable. |
|
1311 restartButton disable. |
|
1312 |
|
1313 dummy := View extent:(10 @ 5) in:bpanel. |
|
1314 dummy borderWidth:0; level:0. |
|
1315 |
|
1316 "/ stepButton destroy. |
|
1317 "/ sendButton destroy. |
|
1318 |
|
1319 updateButton := Button |
|
1320 label:(resources at:'update') |
|
1321 action:[self updateContext] |
|
1322 in:bpanel. |
|
1323 monitorToggle := Toggle in:bpanel. |
|
1324 monitorToggle label:(resources at:'monitor'). |
|
1325 monitorToggle pressAction:[self autoUpdateOn]. |
|
1326 monitorToggle releaseAction:[self autoUpdateOff]. |
|
1327 |
|
1328 "can only look into process - context chain is not active" |
|
1329 canContinue := true. |
|
1330 |
|
1331 terminateButton enable. |
|
1332 abortButton enable. |
|
1333 |
|
1334 sendButton disable; beInvisible. |
|
1335 stepButton disable; beInvisible. |
|
1336 nextButton disable; beInvisible. |
|
1337 nextOverButton notNil ifTrue:[nextOverButton disable; beInvisible]. |
|
1338 nextOutButton notNil ifTrue:[nextOutButton disable; beInvisible]. |
|
1339 |
|
1340 aProcess isNil ifTrue:[ |
|
1341 terminateButton disable. |
|
1342 abortButton disable. |
|
1343 continueButton disable. |
|
1344 returnButton disable. |
|
1345 restartButton disable. |
|
1346 ] ifFalse:[ |
|
1347 (aProcess suspendedContext isNil |
|
1348 or:[aProcess isSystemProcess]) ifTrue:[ |
|
1349 terminateButton disable. |
|
1350 ]. |
|
1351 |
|
1352 self setContextSkippingInterruptContexts:aProcess suspendedContext. |
|
1353 |
|
1354 catchBlock := [ |
|
1355 catchBlock := nil. |
|
1356 contextArray := nil. |
|
1357 selectedContext := actualContext := firstContext := nil. |
|
1358 steppedContext := wrapperContext := nil. |
|
1359 |
|
1360 (exitAction == #terminate) ifTrue:[ |
|
1361 aProcess terminate. |
|
1362 ]. |
|
1363 (exitAction == #quickTerminate) ifTrue:[ |
|
1364 aProcess terminateNoSignal. |
|
1365 ]. |
|
1366 super destroy |
|
1367 ]. |
|
1368 ]. |
|
1369 self open |
|
1370 |
|
1371 "Modified: 20.3.1997 / 16:53:56 / cg" |
|
1372 "Modified: 17.4.1997 / 13:01:57 / stefan" |
|
1373 ! |
|
1374 |
|
1375 setInitialSelectionOnEntry:initialSelectionOrNil context:aContext |
|
1376 |selection con1 con2 h| |
922 |
1377 |
923 initialSelectionOrNil notNil ifTrue:[ |
1378 initialSelectionOrNil notNil ifTrue:[ |
924 selection := initialSelectionOrNil |
1379 selection := initialSelectionOrNil |
925 ] ifFalse:[ |
1380 ] ifFalse:[ |
926 " |
1381 " |
993 selection > 1 ifTrue:[ |
1448 selection > 1 ifTrue:[ |
994 contextView scrollToLine:(selection - 1) |
1449 contextView scrollToLine:(selection - 1) |
995 ] |
1450 ] |
996 ]. |
1451 ]. |
997 |
1452 |
998 m := contextView middleButtonMenu. |
1453 "Created: / 16.11.2001 / 17:28:07 / cg" |
999 m notNil ifTrue:[ |
1454 ! |
1000 self updateMenuItems. |
1455 |
1001 |
1456 turnOffAllButtons |
1002 (inspecting or:[Object abortSignal isHandled]) ifTrue:[ |
1457 terminateButton turnOffWithoutRedraw. |
1003 abortButton enable. |
1458 continueButton turnOffWithoutRedraw. |
1004 m enable:#doAbort. |
1459 returnButton turnOffWithoutRedraw. |
1005 ] ifFalse:[ |
1460 restartButton turnOffWithoutRedraw. |
1006 abortButton disable. |
1461 abortButton turnOffWithoutRedraw. |
1007 m disable:#doAbort. |
1462 nextButton turnOffWithoutRedraw. |
1008 ]. |
1463 stepButton turnOffWithoutRedraw. |
1009 exclusive ifTrue:[ |
1464 sendButton turnOffWithoutRedraw. |
1010 terminateButton disable. |
1465 |
1011 m disable:#doTerminate. |
1466 "Created: / 16.11.2001 / 17:36:18 / cg" |
1012 ] ifFalse:[ |
|
1013 terminateButton enable. |
|
1014 m enable:#doTerminate. |
|
1015 ] |
|
1016 ]. |
|
1017 |
|
1018 mayProceed == false ifTrue:[ |
|
1019 continueButton disable. |
|
1020 m notNil ifTrue:[m disable:#doContinue]. |
|
1021 ] ifFalse:[ |
|
1022 continueButton enable. |
|
1023 m notNil ifTrue:[m enable:#doContinue] |
|
1024 ]. |
|
1025 |
|
1026 " |
|
1027 If this is a new debugger, do a realize. |
|
1028 Otherwise, its probably better to do a map, which shows the |
|
1029 view at the previous position, without a need for the user to set the |
|
1030 position again |
|
1031 " |
|
1032 iAmNew ifFalse:[ |
|
1033 self remap. |
|
1034 ] ifTrue:[ |
|
1035 self realize. |
|
1036 ]. |
|
1037 "/ self realizeAllSubViews. |
|
1038 |
|
1039 exclusive ifTrue:[ |
|
1040 self showError:' |
|
1041 Debugging system process `' , (inspectedProcess nameOrId) printString , '''. |
|
1042 |
|
1043 This is a modal debugger - all event processing is stopped.. |
|
1044 Therefore, you cannot interact with other views or |
|
1045 open any other tools while this debugger is active. |
|
1046 |
|
1047 Also, there is no event processing (redraw) for other views.' |
|
1048 ]. |
|
1049 |
|
1050 "/ |
|
1051 "/ bring us to the top |
|
1052 "/ |
|
1053 self raise. |
|
1054 |
|
1055 "/ |
|
1056 "/ wait until realized ... |
|
1057 "/ - kludge; I have (currently) no idea, why this is needed ... |
|
1058 "/ |
|
1059 "/ Object haltSignal handle:[:ex | |
|
1060 "/ 'DebugView [info]: halt in debugger ignored' infoPrintCR. |
|
1061 "/ ex proceed. |
|
1062 "/ ] do:[ |
|
1063 "/ windowGroup eventLoopWhile:[self shown not] onLeave:[]. |
|
1064 "/ self withAllSubViewsDo:[:v | v invalidate]. |
|
1065 "/ ]. |
|
1066 |
|
1067 canContinue := true. |
|
1068 exitAction := nil. |
|
1069 |
|
1070 " |
|
1071 enter private event handling loop. This is left (and we come back here again) |
|
1072 when any button was pressed which requires continuation of the debuggee or |
|
1073 closedown of the debugger. |
|
1074 " |
|
1075 |
|
1076 [self controlLoop] valueOnUnwindDo:[ |
|
1077 windowGroup notNil ifTrue:[ |
|
1078 windowGroup setProcess:nil. |
|
1079 ]. |
|
1080 self destroy |
|
1081 ]. |
|
1082 |
|
1083 " |
|
1084 release all context stuff. |
|
1085 This is required to avoid keeping references to the debuggees objects |
|
1086 forever. (since the debugger is reused for faster startup next time) |
|
1087 " |
|
1088 contextArray := nil. |
|
1089 contextView contents:nil. |
|
1090 |
|
1091 codeView acceptAction:nil. |
|
1092 codeView doItAction:nil. |
|
1093 "/ codeView contents:nil. |
|
1094 |
|
1095 (exitAction ~~ #step) ifTrue:[ |
|
1096 lastSelectionInReceiverInspector := receiverInspector selectedKeyName. |
|
1097 lastSelectionInContextInspector := contextInspector selectedKeyName. |
|
1098 receiverInspector release. |
|
1099 contextInspector release. |
|
1100 |
|
1101 self unmap. |
|
1102 device flush. |
|
1103 |
|
1104 (exitAction == #abort) ifTrue:[ |
|
1105 self cacheMyself. |
|
1106 |
|
1107 " |
|
1108 have to catch errors occuring in unwind-blocks |
|
1109 " |
|
1110 ErrorSignal handle:[:ex | |
|
1111 'DebugView [info]: ignored error while unwinding: ' infoPrint. |
|
1112 ex errorString infoPrintCR. |
|
1113 |
|
1114 ex proceed |
|
1115 ] do:[ |
|
1116 Object abortSignal raise. |
|
1117 ]. |
|
1118 'DebugView [warning]: abort failed' errorPrintCR |
|
1119 ]. |
|
1120 |
|
1121 (exitAction == #return) ifTrue:[ |
|
1122 selectedContext notNil ifTrue:[ |
|
1123 " |
|
1124 if there is a selection in the codeView, |
|
1125 evaluate it and use the result as return value |
|
1126 " |
|
1127 "/ disabled for now, there is almost always a selection (the current line) |
|
1128 "/ and that is syntactically incorrect ... |
|
1129 "/ ... leading to a popup warning from the codeView |
|
1130 "/ |
|
1131 "/ codeView hasSelection ifTrue:[ |
|
1132 "/ Object errorSignal handle:[:ex | |
|
1133 "/ 'DebugView [warning]: error - returning nil' errorPrintCR. |
|
1134 "/ retval := nil. |
|
1135 "/ ex return |
|
1136 "/ ] do:[ |
|
1137 "/ |s| |
|
1138 "/ |
|
1139 "/ s := codeView selection asString. |
|
1140 "/ retval := codeView doItAction value:s. |
|
1141 "/ ]. |
|
1142 "/ ]. |
|
1143 |
|
1144 con := selectedContext. |
|
1145 self cacheMyself. |
|
1146 " |
|
1147 have to catch errors occuring in unwind-blocks |
|
1148 " |
|
1149 Object errorSignal handle:[:ex | |
|
1150 'DebugView [info]: ignored error while unwinding: ' infoPrint. |
|
1151 ex errorString infoPrintCR. |
|
1152 ex proceed |
|
1153 ] do:[ |
|
1154 con unwind:retval. |
|
1155 ]. |
|
1156 'DebugView [warning]: cannot return from selected context' errorPrintCR |
|
1157 ] |
|
1158 ]. |
|
1159 |
|
1160 (exitAction == #restart) ifTrue:[ |
|
1161 selectedContext notNil ifTrue:[ |
|
1162 con := selectedContext. |
|
1163 self cacheMyself. |
|
1164 " |
|
1165 have to catch errors occuring in unwind-blocks |
|
1166 " |
|
1167 Object errorSignal handle:[:ex | |
|
1168 'DebugView [info]: ignored error while unwinding: ' infoPrint. |
|
1169 ex errorString infoPrintCR. |
|
1170 ex proceed |
|
1171 ] do:[ |
|
1172 con unwindAndRestart. |
|
1173 ]. |
|
1174 'DebugView [warning]: cannot restart selected context' errorPrintCR |
|
1175 ] |
|
1176 ]. |
|
1177 |
|
1178 (exitAction == #quickTerminate) ifTrue:[ |
|
1179 self cacheMyself. |
|
1180 Processor activeProcess terminateNoSignal |
|
1181 ]. |
|
1182 |
|
1183 (exitAction == #terminate) ifTrue:[ |
|
1184 self cacheMyself. |
|
1185 " |
|
1186 have to catch errors occuring in unwind-blocks |
|
1187 " |
|
1188 Object errorSignal handle:[:ex | |
|
1189 'DebugView [info]: ignored error while unwinding: ' infoPrint. |
|
1190 ex errorString infoPrintCR. |
|
1191 ex proceed |
|
1192 ] do:[ |
|
1193 Processor activeProcess terminate. |
|
1194 ]. |
|
1195 'DebugView [warning]: cannot terminate process' errorPrintCR |
|
1196 ] |
|
1197 ]. |
|
1198 |
|
1199 selectedContext := actualContext := firstContext := nil. |
|
1200 |
|
1201 "/ restore the previous pointer grab |
|
1202 grabber notNil ifTrue:[ |
|
1203 device grabPointerInView:grabber. |
|
1204 grabber := nil. |
|
1205 ]. |
|
1206 |
|
1207 (exitAction == #step) ifTrue:[ |
|
1208 " |
|
1209 schedule another stepInterrupt |
|
1210 - must enter myself into the collection of open debuggers, |
|
1211 in case the stepping process comes back again via a halt or signal |
|
1212 before the step is finished. In this case, the stepping debugger should |
|
1213 come up (instead of a new one) |
|
1214 - must flush caches since optimized methods not always |
|
1215 look for pending interrupts |
|
1216 " |
|
1217 |
|
1218 "/ |
|
1219 "/ also must care for stepping into a return |
|
1220 "/ |
|
1221 steppedContext notNil ifTrue:[ |
|
1222 Processor activeProcess forceInterruptOnReturnOf:steppedContext. |
|
1223 ]. |
|
1224 |
|
1225 OpenDebuggers isNil ifTrue:[ |
|
1226 OpenDebuggers := WeakArray with:self |
|
1227 ] ifFalse:[ |
|
1228 (OpenDebuggers includes:self) ifFalse:[ |
|
1229 idx := OpenDebuggers identityIndexOf:nil. |
|
1230 idx == 0 ifTrue:[ |
|
1231 idx := OpenDebuggers identityIndexOf:0 |
|
1232 ]. |
|
1233 idx ~~ 0 ifTrue:[ |
|
1234 OpenDebuggers at:idx put:self |
|
1235 ] ifFalse:[ |
|
1236 OpenDebuggers := OpenDebuggers copyWith:self |
|
1237 ] |
|
1238 ] |
|
1239 ]. |
|
1240 self label:'single stepping - please wait ...'. |
|
1241 stepping := true. |
|
1242 |
|
1243 ObjectMemory stepInterruptHandler:self. |
|
1244 Processor activeProcess stepInterruptHandler:self. |
|
1245 ObjectMemory flushCaches. |
|
1246 |
|
1247 Context singleStepInterruptRequest isHandled ifTrue:[ |
|
1248 "bigStep" steppedContextLineno notNil ifTrue:[ |
|
1249 Context singleStepInterruptRequest raiseWith:#next |
|
1250 ] ifFalse:[ |
|
1251 Context singleStepInterruptRequest raiseWith:#step |
|
1252 ] |
|
1253 ] ifFalse:[ |
|
1254 "/ see if we came here through an interrupt-action |
|
1255 "/ (i.e. aProcess interruptWith:...) |
|
1256 |
|
1257 enteredByInterrupt := false. |
|
1258 con := thisContext findNextContextWithSelector:#timerInterrupt or:#ioInterrupt or:nil. |
|
1259 [enteredByInterrupt not |
|
1260 and:[con notNil |
|
1261 and:[con ~~ aContext]]] whileTrue:[ |
|
1262 ((sel := con selector) == #timerInterrupt |
|
1263 or:[sel == #ioInterrupt]) ifTrue:[ |
|
1264 enteredByInterrupt := true. |
|
1265 ] ifFalse:[ |
|
1266 con := con findNextContextWithSelector:#timerInterrupt or:#ioInterrupt or:nil. |
|
1267 ]. |
|
1268 ]. |
|
1269 |
|
1270 ObjectMemory flushInlineCaches. |
|
1271 |
|
1272 DebuggingDebugger == true ifTrue:[ |
|
1273 enteredByInterrupt printCR. |
|
1274 ]. |
|
1275 enteredByInterrupt ifTrue:[ |
|
1276 "/ dont want to step through all intermediate |
|
1277 "/ (scheduler-) contexts; place a return-trap on the |
|
1278 "/ one right below the interesting one |
|
1279 |
|
1280 "/ 'special unwind return' printCR. |
|
1281 con unwindThenDo:[ |
|
1282 Processor activeProcess stepInterruptHandler:self. |
|
1283 ObjectMemory stepInterruptHandler:self. |
|
1284 InStepInterrupt := nil. |
|
1285 StepInterruptPending := 1. |
|
1286 InterruptPending := 1]. |
|
1287 ] ifFalse:[ |
|
1288 "/ 'normal step return' printCR. |
|
1289 skipLineNr ~~ #return ifTrue:[ |
|
1290 StepInterruptPending := 1. |
|
1291 InterruptPending := 1. |
|
1292 ] ifFalse:[ |
|
1293 "/ 'step for return' printCR. |
|
1294 ] |
|
1295 ]. |
|
1296 InStepInterrupt := nil |
|
1297 ] |
|
1298 ] ifFalse:[ |
|
1299 OpenDebuggers notNil ifTrue:[ |
|
1300 idx := OpenDebuggers identityIndexOf:self. |
|
1301 idx ~~ 0 ifTrue:[ |
|
1302 OpenDebuggers at:idx put:nil |
|
1303 ] |
|
1304 ]. |
|
1305 self cacheMyself. |
|
1306 ] |
|
1307 |
|
1308 "Modified: / 17.4.1997 / 13:01:32 / stefan" |
|
1309 "Created: / 30.10.1997 / 21:08:18 / cg" |
|
1310 "Modified: / 13.10.1998 / 19:56:59 / ps" |
|
1311 "Modified: / 16.11.2001 / 15:59:32 / cg" |
|
1312 ! |
|
1313 |
|
1314 openOn:aProcess |
|
1315 "enter the debugger on a process - |
|
1316 in this case, we are just inspecting the context chain of the process, |
|
1317 not running on top of the debugged process, but as a separate |
|
1318 one. (think of it as an inspector showing more detail, and offering |
|
1319 some more control operations)" |
|
1320 |
|
1321 |bpanel dummy w| |
|
1322 |
|
1323 verboseBacktrace := VerboseBacktraceDefault ? false. |
|
1324 |
|
1325 busy := true. |
|
1326 bigStep := false. |
|
1327 stepHow := nil. |
|
1328 inspecting := true. |
|
1329 inspectedProcess := aProcess. |
|
1330 nChainShown := InitialNCHAINShown. |
|
1331 |
|
1332 bpanel := abortButton superView. |
|
1333 bpanel ignoreInvisibleComponents:true. |
|
1334 |
|
1335 "/ get the max size & freeze button |
|
1336 continueButton label:(resources at:'continue'). |
|
1337 w := continueButton preferredExtent x. |
|
1338 continueButton label:(resources at:'stop'). |
|
1339 w := w max:(continueButton preferredExtent x). |
|
1340 continueButton preferredExtent:(w @ continueButton preferredExtent y). |
|
1341 |
|
1342 aProcess state == #run ifTrue:[ |
|
1343 device hasColors ifTrue:[ |
|
1344 continueButton foregroundColor:Color red darkened. |
|
1345 ]. |
|
1346 continueButton label:(resources at:'stop'). |
|
1347 continueButton action:[self doStop]. |
|
1348 ] ifFalse:[ |
|
1349 device hasColors ifTrue:[ |
|
1350 continueButton foregroundColor:Color green darkened darkened. |
|
1351 ]. |
|
1352 continueButton label:(resources at:'continue'). |
|
1353 continueButton action:[self doContinue]. |
|
1354 ]. |
|
1355 |
|
1356 returnButton disable. |
|
1357 restartButton disable. |
|
1358 |
|
1359 dummy := View extent:(10 @ 5) in:bpanel. |
|
1360 dummy borderWidth:0; level:0. |
|
1361 |
|
1362 "/ stepButton destroy. |
|
1363 "/ sendButton destroy. |
|
1364 |
|
1365 updateButton := Button |
|
1366 label:(resources at:'update') |
|
1367 action:[self updateContext] |
|
1368 in:bpanel. |
|
1369 monitorToggle := Toggle in:bpanel. |
|
1370 monitorToggle label:(resources at:'monitor'). |
|
1371 monitorToggle pressAction:[self autoUpdateOn]. |
|
1372 monitorToggle releaseAction:[self autoUpdateOff]. |
|
1373 |
|
1374 "can only look into process - context chain is not active" |
|
1375 canContinue := true. |
|
1376 |
|
1377 terminateButton enable. |
|
1378 abortButton enable. |
|
1379 |
|
1380 sendButton disable; beInvisible. |
|
1381 stepButton disable; beInvisible. |
|
1382 nextButton disable; beInvisible. |
|
1383 nextOverButton notNil ifTrue:[nextOverButton disable; beInvisible]. |
|
1384 nextOutButton notNil ifTrue:[nextOutButton disable; beInvisible]. |
|
1385 |
|
1386 aProcess isNil ifTrue:[ |
|
1387 terminateButton disable. |
|
1388 abortButton disable. |
|
1389 continueButton disable. |
|
1390 returnButton disable. |
|
1391 restartButton disable. |
|
1392 ] ifFalse:[ |
|
1393 (aProcess suspendedContext isNil |
|
1394 or:[aProcess isSystemProcess]) ifTrue:[ |
|
1395 terminateButton disable. |
|
1396 ]. |
|
1397 |
|
1398 self setContextSkippingInterruptContexts:aProcess suspendedContext. |
|
1399 |
|
1400 catchBlock := [ |
|
1401 catchBlock := nil. |
|
1402 contextArray := nil. |
|
1403 selectedContext := actualContext := firstContext := nil. |
|
1404 steppedContext := wrapperContext := nil. |
|
1405 |
|
1406 (exitAction == #terminate) ifTrue:[ |
|
1407 aProcess terminate. |
|
1408 ]. |
|
1409 (exitAction == #quickTerminate) ifTrue:[ |
|
1410 aProcess terminateNoSignal. |
|
1411 ]. |
|
1412 super destroy |
|
1413 ]. |
|
1414 ]. |
|
1415 self open |
|
1416 |
|
1417 "Modified: 20.3.1997 / 16:53:56 / cg" |
|
1418 "Modified: 17.4.1997 / 13:01:57 / stefan" |
|
1419 ! ! |
1467 ! ! |
1420 |
1468 |
1421 !DebugView methodsFor:'help'! |
1469 !DebugView methodsFor:'help'! |
1422 |
1470 |
1423 helpTextFor:aComponent |
1471 helpTextFor:aComponent |