diff options
-rw-r--r-- | compiler/ccgstmts.nim | 26 | ||||
-rw-r--r-- | compiler/cgen.nim | 45 | ||||
-rw-r--r-- | compiler/cgendata.nim | 2 | ||||
-rw-r--r-- | compiler/commands.nim | 24 | ||||
-rw-r--r-- | compiler/jsgen.nim | 6 | ||||
-rw-r--r-- | compiler/options.nim | 1 | ||||
-rw-r--r-- | compiler/pragmas.nim | 15 | ||||
-rw-r--r-- | compiler/wordrecg.nim | 8 | ||||
-rw-r--r-- | doc/endb.rst | 203 | ||||
-rw-r--r-- | lib/system.nim | 7 | ||||
-rw-r--r-- | lib/system/debugger.nim | 303 | ||||
-rw-r--r-- | lib/system/endb.nim | 579 | ||||
-rw-r--r-- | lib/system/excpt.nim | 12 | ||||
-rw-r--r-- | tests/gc/gcleak4.nim | 2 | ||||
-rw-r--r-- | tests/misc/thallo.nim | 1 | ||||
-rw-r--r-- | tests/objects/tobjects_various.nim | 1 |
16 files changed, 19 insertions, 1216 deletions
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index bfd053f2d..ffeeb0db9 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -1161,36 +1161,10 @@ proc genEmit(p: BProc, t: PNode) = genLineDir(p, t) line(p, cpsStmts, s) -proc genBreakPoint(p: BProc, t: PNode) = - var name: string - if optEndb in p.options: - if t.kind == nkExprColonExpr: - assert(t.sons[1].kind in {nkStrLit..nkTripleStrLit}) - name = normalize(t.sons[1].strVal) - else: - inc(p.module.g.breakPointId) - name = "bp" & $p.module.g.breakPointId - genLineDir(p, t) # BUGFIX - appcg(p.module, p.module.g.breakpoints, - "#dbgRegisterBreakpoint($1, (NCSTRING)$2, (NCSTRING)$3);$n", [ - toLinenumber(t.info), makeCString(toFilename(p.config, t.info)), - makeCString(name)]) - -proc genWatchpoint(p: BProc, n: PNode) = - if optEndb notin p.options: return - var a: TLoc - initLocExpr(p, n.sons[1], a) - let typ = skipTypes(n.sons[1].typ, abstractVarRange) - lineCg(p, cpsStmts, "#dbgRegisterWatchpoint($1, (NCSTRING)$2, $3);$n", - [addrLoc(p.config, a), makeCString(renderTree(n.sons[1])), - genTypeInfo(p.module, typ, n.info)]) - proc genPragma(p: BProc, n: PNode) = for it in n.sons: case whichPragma(it) of wEmit: genEmit(p, it) - of wBreakpoint: genBreakPoint(p, it) - of wWatchPoint: genWatchpoint(p, it) of wInjectStmt: var p = newProc(nil, p.module) p.options = p.options - {optLineTrace, optStackTrace} diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 033003485..6e79b2d7b 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -264,13 +264,7 @@ proc genLineDir(p: BProc, t: PNode) = if optEmbedOrigSrc in p.config.globalOptions: add(p.s(cpsStmts), ~"//" & sourceLine(p.config, t.info) & "\L") genCLineDir(p.s(cpsStmts), toFullPath(p.config, t.info), line, p.config) - if ({optStackTrace, optEndb} * p.options == {optStackTrace, optEndb}) and - (p.prc == nil or sfPure notin p.prc.flags): - if freshLineInfo(p, t.info): - linefmt(p, cpsStmts, "#endb($1, $2);$N", - [line, makeCString(toFilename(p.config, t.info))]) - elif ({optLineTrace, optStackTrace} * p.options == - {optLineTrace, optStackTrace}) and + if ({optLineTrace, optStackTrace} * p.options == {optLineTrace, optStackTrace}) and (p.prc == nil or sfPure notin p.prc.flags) and t.info.fileIndex != InvalidFileIdx: if freshLineInfo(p, t.info): linefmt(p, cpsStmts, "nimln_($1, $2);$n", @@ -479,19 +473,6 @@ proc deinitGCFrame(p: BProc): Rope = result = ropecg(p.module, "if (((NU)&GCFRAME_) < 4096) #nimGCFrame(&GCFRAME_);$n", []) -proc localDebugInfo(p: BProc, s: PSym, retType: PType) = - if {optStackTrace, optEndb} * p.options != {optStackTrace, optEndb}: return - # XXX work around a bug: No type information for open arrays possible: - if skipTypes(s.typ, abstractVar).kind in {tyOpenArray, tyVarargs}: return - var a = "&" & s.loc.r - if s.kind == skParam and ccgIntroducedPtr(p.config, s, retType): a = s.loc.r - lineF(p, cpsInit, - "FR_.s[$1].address = (void*)$3; FR_.s[$1].typ = $4; FR_.s[$1].name = $2;$n", - [p.maxFrameLen.rope, makeCString(normalize(s.name.s)), a, - genTypeInfo(p.module, s.loc.t, s.info)]) - inc(p.maxFrameLen) - inc p.blocks[p.blocks.len-1].frameLen - proc localVarDecl(p: BProc; n: PNode): Rope = let s = n.sym if s.loc.k == locNone: @@ -515,7 +496,6 @@ proc assignLocalVar(p: BProc, n: PNode) = let nl = if optLineDir in p.config.options: "" else: "\L" let decl = localVarDecl(p, n) & ";" & nl line(p, cpsLocals, decl) - localDebugInfo(p, n.sym, nil) include ccgthreadvars @@ -562,17 +542,10 @@ proc assignGlobalVar(p: BProc, n: PNode) = if p.withinLoop > 0: # fixes tests/run/tzeroarray: resetLoc(p, s.loc) - if p.module.module.options * {optStackTrace, optEndb} == - {optStackTrace, optEndb}: - appcg(p.module, p.module.s[cfsDebugInit], - "#dbgRegisterGlobal($1, &$2, $3);$n", - [makeCString(normalize(s.owner.name.s & '.' & s.name.s)), - s.loc.r, genTypeInfo(p.module, s.typ, n.info)]) proc assignParam(p: BProc, s: PSym, retType: PType) = assert(s.loc.r != nil) scopeMangledParam(p, s) - localDebugInfo(p, s, retType) proc fillProcLoc(m: BModule; n: PNode) = let sym = n.sym @@ -689,7 +662,7 @@ proc loadDynamicLib(m: BModule, lib: PLib) = [loadlib, genStringLiteral(m, lib.path)]) else: var p = newProc(nil, m) - p.options = p.options - {optStackTrace, optEndb} + p.options = p.options - {optStackTrace} var dest: TLoc initLoc(dest, locTemp, lib.path, OnStack) dest.r = getTempName(m) @@ -1318,7 +1291,6 @@ proc genMainProc(m: BModule) = PreMainBody = "$N" & "void PreMainInner(void) {$N" & "$2" & - "$3" & "}$N$N" & PosixCmdLine & "void PreMain(void) {$N" & @@ -1408,17 +1380,11 @@ proc genMainProc(m: BModule) = elif m.config.target.targetOS == osGenode: m.includeHeader("<libc/component.h>") - if optEndb in m.config.options: - for i in 0..<m.config.m.fileInfos.len: - m.g.breakpoints.addf("dbgRegisterFilename($1);$N", - [m.config.m.fileInfos[i].projPath.string.makeCString]) - let initStackBottomCall = if m.config.target.targetOS == osStandalone or m.config.selectedGC == gcNone: "".rope else: ropecg(m, "\t#initStackBottomWith((void *)&inner);$N", []) inc(m.labels) - appcg(m, m.s[cfsProcs], PreMainBody, [ - m.g.mainDatInit, m.g.breakpoints, m.g.otherModsInit]) + appcg(m, m.s[cfsProcs], PreMainBody, [m.g.mainDatInit, m.g.otherModsInit]) if m.config.target.targetOS == osWindows and m.config.globalOptions * {optGenGuiApp, optGenDynLib} != {}: @@ -2024,11 +1990,6 @@ proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode = if emulatedThreadVars(m.config) and m.config.target.targetOS != osStandalone: discard cgsym(m, "initThreadVarsEmulation") - if m.g.breakpoints != nil: - discard cgsym(m, "dbgRegisterBreakpoint") - if optEndb in m.config.options: - discard cgsym(m, "dbgRegisterFilename") - if m.g.forwardedProcs.len == 0: incl m.flags, objHasKidsValid let disp = generateMethodDispatchers(graph) diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim index 47b0f23ec..0035931f0 100644 --- a/compiler/cgendata.nim +++ b/compiler/cgendata.nim @@ -117,8 +117,6 @@ type modulesClosed*: seq[BModule] # list of the same compiled modules, but in the order they were closed forwardedProcs*: seq[PSym] # proc:s that did not yet have a body generatedHeader*: BModule - breakPointId*: int - breakpoints*: Rope # later the breakpoints are inserted into the main proc typeInfoMarker*: TypeCacheWithOwner config*: ConfigRef graph*: ModuleGraph diff --git a/compiler/commands.nim b/compiler/commands.nim index 662df9c84..5b6f3ac0f 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -266,7 +266,7 @@ proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool of "threadanalysis": result = contains(conf.globalOptions, optThreadAnalysis) of "stacktrace": result = contains(conf.options, optStackTrace) of "linetrace": result = contains(conf.options, optLineTrace) - of "debugger": result = contains(conf.options, optEndb) + of "debugger": result = contains(conf.globalOptions, optCDebug) of "profiler": result = contains(conf.options, optProfiler) of "memtracker": result = contains(conf.options, optMemTracker) of "checks", "x": result = conf.options * ChecksOptions == ChecksOptions @@ -473,24 +473,18 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; of "linetrace": processOnOffSwitch(conf, {optLineTrace}, arg, pass, info) of "debugger": case arg.normalize - of "on", "endb": - conf.options.incl optEndb - defineSymbol(conf.symbols, "endb") - of "off": - conf.options.excl optEndb - undefSymbol(conf.symbols, "endb") - of "native", "gdb": - incl(conf.globalOptions, optCDebug) - conf.options = conf.options + {optLineDir} - {optEndb} + of "on", "native", "gdb": + conf.globalOptions.incl optCDebug + conf.options.incl optLineDir #defineSymbol(conf.symbols, "nimTypeNames") # type names are used in gdb pretty printing - undefSymbol(conf.symbols, "endb") + of "off": + conf.globalOptions.excl optCDebug else: - localError(conf, info, "expected endb|gdb but found " & arg) + localError(conf, info, "expected native|gdb|on|off but found " & arg) of "g": # alias for --debugger:native - incl(conf.globalOptions, optCDebug) - conf.options = conf.options + {optLineDir} - {optEndb} + conf.globalOptions.incl optCDebug + conf.options.incl optLineDir #defineSymbol(conf.symbols, "nimTypeNames") # type names are used in gdb pretty printing - undefSymbol(conf.symbols, "endb") of "profiler": processOnOffSwitch(conf, {optProfiler}, arg, pass, info) if optProfiler in conf.options: defineSymbol(conf.symbols, "profiler") diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 5391a451b..107fa2b28 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -658,11 +658,7 @@ proc genLineDir(p: PProc, n: PNode) = if optLineDir in p.options: lineF(p, "// line $2 \"$1\"$n", [rope(toFilename(p.config, n.info)), rope(line)]) - if {optStackTrace, optEndb} * p.options == {optStackTrace, optEndb} and - ((p.prc == nil) or sfPure notin p.prc.flags): - useMagic(p, "endb") - lineF(p, "endb($1);$n", [rope(line)]) - elif hasFrameInfo(p): + if hasFrameInfo(p): lineF(p, "F.line = $1;$n", [rope(line)]) proc genWhileStmt(p: PProc, n: PNode) = diff --git a/compiler/options.nim b/compiler/options.nim index 8b5ade727..1b9bbb38f 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -30,7 +30,6 @@ type # please make sure we have under 32 options optAssert, optLineDir, optWarns, optHints, optOptimizeSpeed, optOptimizeSize, optStackTrace, # stack tracing support optLineTrace, # line tracing support (includes stack tracing) - optEndb, # embedded debugger optByRef, # use pass by ref for objects # (for interfacing with C) optProfiler, # profiler turned on diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 000066b8e..3de12cfa9 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -44,7 +44,7 @@ const wWarnings, wHints, wLineDir, wStackTrace, wLineTrace, wOptimization, wHint, wWarning, wError, wFatal, wDefine, wUndef, wCompile, wLink, wLinksys, wPure, wPush, wPop, - wBreakpoint, wWatchPoint, wPassl, wPassc, + wPassl, wPassc, wDeadCodeElimUnused, # deprecated, always on wDeprecated, wFloatChecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll, @@ -345,7 +345,7 @@ proc pragmaToOptions(w: TSpecialWord): TOptions {.inline.} = of wLineDir: {optLineDir} of wStackTrace: {optStackTrace} of wLineTrace: {optLineTrace} - of wDebugger: {optEndb} + of wDebugger: {optNone} of wProfiler: {optProfiler, optMemTracker} of wMemTracker: {optMemTracker} of wByRef: {optByRef} @@ -513,15 +513,6 @@ proc processLink(c: PContext, n: PNode) = extccomp.addExternalFileToLink(c.config, found) recordPragma(c, n, "link", found.string) -proc pragmaBreakpoint(c: PContext, n: PNode) = - discard getOptionalStr(c, n, "") - -proc pragmaWatchpoint(c: PContext, n: PNode) = - if n.kind in nkPragmaCallKinds and n.len == 2: - n.sons[1] = c.semExpr(c, n.sons[1]) - else: - invalidPragma(c, n) - proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode = case n.sons[1].kind of nkStrLit, nkRStrLit, nkTripleStrLit: @@ -996,8 +987,6 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, let s = expectStrLit(c, it) extccomp.addCompileOption(c.config, s) recordPragma(c, it, "passc", s) - of wBreakpoint: pragmaBreakpoint(c, it) - of wWatchPoint: pragmaWatchpoint(c, it) of wPush: processPush(c, n, i + 1) result = true diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim index 837ce4268..62b26adf3 100644 --- a/compiler/wordrecg.nim +++ b/compiler/wordrecg.nim @@ -48,7 +48,7 @@ type wCompilerProc, wCore, wProcVar, wBase, wUsed, wFatal, wError, wWarning, wHint, wLine, wPush, wPop, wDefine, wUndef, wLineDir, wStackTrace, wLineTrace, wLink, wCompile, - wLinksys, wDeprecated, wVarargs, wCallconv, wBreakpoint, wDebugger, + wLinksys, wDeprecated, wVarargs, wCallconv, wDebugger, wNimcall, wStdcall, wCdecl, wSafecall, wSyscall, wInline, wNoInline, wFastcall, wClosure, wNoconv, wOn, wOff, wChecks, wRangeChecks, wBoundChecks, wOverflowChecks, wNilChecks, @@ -62,8 +62,7 @@ type wCompileTime, wNoInit, wPassc, wPassl, wBorrow, wDiscardable, wFieldChecks, - wWatchPoint, wSubsChar, - wAcyclic, wShallow, wUnroll, wLinearScanEnd, wComputedGoto, + wSubsChar, wAcyclic, wShallow, wUnroll, wLinearScanEnd, wComputedGoto, wInjectStmt, wExperimental, wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit, wAsmNoStackFrame, @@ -138,7 +137,7 @@ const "fatal", "error", "warning", "hint", "line", "push", "pop", "define", "undef", "linedir", "stacktrace", "linetrace", "link", "compile", "linksys", "deprecated", "varargs", - "callconv", "breakpoint", "debugger", "nimcall", "stdcall", + "callconv", "debugger", "nimcall", "stdcall", "cdecl", "safecall", "syscall", "inline", "noinline", "fastcall", "closure", "noconv", "on", "off", "checks", "rangechecks", "boundchecks", "overflowchecks", "nilchecks", @@ -152,7 +151,6 @@ const "pragma", "compiletime", "noinit", "passc", "passl", "borrow", "discardable", "fieldchecks", - "watchpoint", "subschar", "acyclic", "shallow", "unroll", "linearscanend", "computedgoto", "injectstmt", "experimental", "write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit", diff --git a/doc/endb.rst b/doc/endb.rst deleted file mode 100644 index 90bb964ba..000000000 --- a/doc/endb.rst +++ /dev/null @@ -1,203 +0,0 @@ -============================================== - Embedded Nim Debugger (ENDB) User Guide -============================================== - -:Author: Andreas Rumpf -:Version: |nimversion| - -.. contents:: - -**WARNING**: ENDB is not maintained anymore! Please help if you're interested -in this tool. - -Nim comes with a platform independent debugger - -the Embedded Nim Debugger (ENDB). The debugger is -*embedded* into your executable if it has been -compiled with the ``--debugger:on`` command line option. -This also defines the conditional symbol ``ENDB`` for you. - -Note: You must not compile your program with the ``--app:gui`` -command line option because then there would be no console -available for the debugger. - -If you start your program the debugger will immediately show -a prompt on the console. You can now enter a command. The next sections -deal with the possible commands. As usual in Nim in all commands -underscores and case do not matter. Optional components of a command -are listed in brackets ``[...]`` here. - - -General Commands -================ - -``h``, ``help`` - Display a quick reference of the possible commands. - -``q``, ``quit`` - Quit the debugger and the program. - -<ENTER> - (Without any typed command) repeat the previous debugger command. - If there is no previous command, ``step_into`` is assumed. - -Executing Commands -================== - -``s``, ``step_into`` - Single step, stepping into routine calls. - -``n``, ``step_over`` - Single step, without stepping into routine calls. - -``f``, ``skip_current`` - Continue execution until the current routine finishes. - -``c``, ``continue`` - Continue execution until the next breakpoint. - -``i``, ``ignore`` - Continue execution, ignore all breakpoints. This effectively quits - the debugger and runs the program until it finishes. - - -Breakpoint Commands -=================== - -``b``, ``setbreak`` [fromline [toline]] [file] - Set a new breakpoint for the given file - and line numbers. If no file is given, the current execution point's - filename is used. If the filename has no extension, ``.nim`` is - appended for your convenience. - If no line numbers are given, the current execution point's - line is used. If both ``fromline`` and ``toline`` are given the - breakpoint contains a line number range. Some examples if it is still - unclear: - - * ``b 12 15 thallo`` creates a breakpoint that - will be triggered if the instruction pointer reaches one of the - lines 12-15 in the file ``thallo.nim``. - * ``b 12 thallo`` creates a breakpoint that - will be triggered if the instruction pointer reaches the - line 12 in the file ``thallo.nim``. - * ``b 12`` creates a breakpoint that - will be triggered if the instruction pointer reaches the - line 12 in the current file. - * ``b`` creates a breakpoint that - will be triggered if the instruction pointer reaches the - current line in the current file again. - -``breakpoints`` - Display the entire breakpoint list. - -``disable`` <identifier> - Disable a breakpoint. It remains disabled until you turn it on again - with the ``enable`` command. - -``enable`` <identifier> - Enable a breakpoint. - -Often it happens when debugging that you keep retyping the breakpoints again -and again because they are lost when you restart your program. This is not -necessary: A special pragma has been defined for this: - - -The ``breakpoint`` pragma -------------------------- - -The ``breakpoint`` pragma is syntactically a statement. It can be used -to mark the *following line* as a breakpoint: - -.. code-block:: Nim - write("1") - {.breakpoint: "before_write_2".} - write("2") - -The name of the breakpoint here is ``before_write_2``. Of course the -breakpoint's name is optional - the compiler will generate one for you -if you leave it out. - -Code for the ``breakpoint`` pragma is only generated if the debugger -is turned on, so you don't need to remove it from your source code after -debugging. - - -The ``watchpoint`` pragma -------------------------- - -The ``watchpoint`` pragma is syntactically a statement. It can be used -to mark a location as a watchpoint: - -.. code-block:: Nim - var a: array[0..20, int] - - {.watchpoint: a[3].} - for i in 0 .. 20: a[i] = i - -ENDB then writes a stack trace whenever the content of the location ``a[3]`` -changes. The current implementation only tracks a hash value of the location's -contents and so locations that are not word sized may encounter false -negatives in very rare cases. - -Code for the ``watchpoint`` pragma is only generated if the debugger -is turned on, so you don't need to remove it from your source code after -debugging. - -Due to the primitive implementation watchpoints are even slower than -breakpoints: After *every* executed Nim code line it is checked whether the -location changed. - - -Data Display Commands -===================== - -``e``, ``eval`` <exp> - Evaluate the expression <exp>. Note that ENDB has no full-blown expression - evaluator built-in. So expressions are limited: - - * To display global variables prefix their names with their - owning module: ``nim1.globalVar`` - * To display local variables or parameters just type in - their name: ``localVar``. If you want to inspect variables that are not - in the current stack frame, use the ``up`` or ``down`` command. - - Unfortunately, only inspecting variables is possible at the moment. Maybe - a future version will implement a full-blown Nim expression evaluator, - but this is not easy to do and would bloat the debugger's code. - - Since displaying the whole data structures is often not needed and - painfully slow, the debugger uses a *maximal display depth* concept for - displaying. - - You can alter the maximal display depth with the ``maxdisplay`` - command. - -``maxdisplay`` <natural> - Sets the maximal display depth to the given integer value. A value of 0 - means there is no maximal display depth. Default is 3. - -``o``, ``out`` <filename> <exp> - Evaluate the expression <exp> and store its string representation into a - file named <filename>. If the file does not exist, it will be created, - otherwise it will be opened for appending. - -``w``, ``where`` - Display the current execution point. - -``u``, ``up`` - Go up in the call stack. - -``d``, ``down`` - Go down in the call stack. - -``stackframe`` [file] - Displays the content of the current stack frame in ``stdout`` or - appends it to the file, depending on whether a file is given. - -``callstack`` - Display the entire call stack (but not its content). - -``l``, ``locals`` - Display the available local variables in the current stack frame. - -``g``, ``globals`` - Display all the global variables that are available for inspection. diff --git a/lib/system.nim b/lib/system.nim index 6d43d672a..16a5e03fe 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -3639,10 +3639,6 @@ when not defined(JS): #and not defined(nimscript): if result == 0: result = x.len - y.len - when not defined(nimscript) and hostOS != "standalone": - when defined(endb): - proc endbStep() - when declared(newSeq): proc cstringArrayToSeq*(a: cstringArray, len: Natural): seq[string] = ## Converts a ``cstringArray`` to a ``seq[string]``. `a` is supposed to be @@ -3816,9 +3812,6 @@ when not defined(JS): #and not defined(nimscript): currException = exc {.push stack_trace: off, profiler:off.} - when defined(endb) and not defined(nimscript): - include "system/debugger" - when (defined(profiler) or defined(memProfiler)) and not defined(nimscript): include "system/profiler" {.pop.} # stacktrace diff --git a/lib/system/debugger.nim b/lib/system/debugger.nim deleted file mode 100644 index fd0ae2399..000000000 --- a/lib/system/debugger.nim +++ /dev/null @@ -1,303 +0,0 @@ -# -# -# Nim's Runtime Library -# (c) Copyright 2013 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -## This file implements basic features for any debugger. - -type - VarSlot* {.compilerproc, final.} = object ## a slot in a frame - address*: pointer ## the variable's address - typ*: PNimType ## the variable's type - name*: cstring ## the variable's name; for globals this is "module.name" - - PExtendedFrame = ptr ExtendedFrame - ExtendedFrame = object # If the debugger is enabled the compiler - # provides an extended frame. Of course - # only slots that are - # needed are allocated and not 10_000, - # except for the global data description. - f: TFrame - slots: array[0..10_000, VarSlot] - -var - dbgGlobalData: ExtendedFrame # this reserves much space, but - # for now it is the most practical way - -proc dbgRegisterGlobal(name: cstring, address: pointer, - typ: PNimType) {.compilerproc.} = - let i = dbgGlobalData.f.len - if i >= high(dbgGlobalData.slots): - #debugOut("[Warning] cannot register global ") - return - dbgGlobalData.slots[i].name = name - dbgGlobalData.slots[i].typ = typ - dbgGlobalData.slots[i].address = address - inc(dbgGlobalData.f.len) - -proc getLocal*(frame: PFrame; slot: int): VarSlot {.inline.} = - ## retrieves the meta data for the local variable at `slot`. CAUTION: An - ## invalid `slot` value causes a corruption! - result = cast[PExtendedFrame](frame).slots[slot] - -proc getGlobalLen*(): int {.inline.} = - ## gets the number of registered globals. - result = dbgGlobalData.f.len - -proc getGlobal*(slot: int): VarSlot {.inline.} = - ## retrieves the meta data for the global variable at `slot`. CAUTION: An - ## invalid `slot` value causes a corruption! - result = dbgGlobalData.slots[slot] - -# ------------------- breakpoint support ------------------------------------ - -type - Breakpoint* = object ## represents a break point - low*, high*: int ## range from low to high; if disabled - ## both low and high are set to their negative values - filename*: cstring ## the filename of the breakpoint - -var - dbgBP: array[0..127, Breakpoint] # breakpoints - dbgBPlen: int - dbgBPbloom: int64 # we use a bloom filter to speed up breakpoint checking - - dbgFilenames*: array[0..300, cstring] ## registered filenames; - ## 'nil' terminated - dbgFilenameLen: int - -proc dbgRegisterFilename(filename: cstring) {.compilerproc.} = - # XXX we could check for duplicates here for DLL support - dbgFilenames[dbgFilenameLen] = filename - inc dbgFilenameLen - -proc dbgRegisterBreakpoint(line: int, - filename, name: cstring) {.compilerproc.} = - let x = dbgBPlen - if x >= high(dbgBP): - #debugOut("[Warning] cannot register breakpoint") - return - inc(dbgBPlen) - dbgBP[x].filename = filename - dbgBP[x].low = line - dbgBP[x].high = line - dbgBPbloom = dbgBPbloom or line - -proc addBreakpoint*(filename: cstring, lo, hi: int): bool = - let x = dbgBPlen - if x >= high(dbgBP): return false - inc(dbgBPlen) - result = true - dbgBP[x].filename = filename - dbgBP[x].low = lo - dbgBP[x].high = hi - for line in lo..hi: dbgBPbloom = dbgBPbloom or line - -const - FileSystemCaseInsensitive = defined(windows) or defined(dos) or defined(os2) - -proc fileMatches(c, bp: cstring): bool = - # bp = breakpoint filename - # c = current filename - # we consider it a match if bp is a suffix of c - # and the character for the suffix does not exist or - # is one of: \ / : - # depending on the OS case does not matter! - var blen: int = bp.len - var clen: int = c.len - if blen > clen: return false - # check for \ / : - if clen-blen-1 >= 0 and c[clen-blen-1] notin {'\\', '/', ':'}: - return false - var i = 0 - while i < blen: - var x = bp[i] - var y = c[i+clen-blen] - when FileSystemCaseInsensitive: - if x >= 'A' and x <= 'Z': x = chr(ord(x) - ord('A') + ord('a')) - if y >= 'A' and y <= 'Z': y = chr(ord(y) - ord('A') + ord('a')) - if x != y: return false - inc(i) - return true - -proc canonFilename*(filename: cstring): cstring = - ## returns 'nil' if the filename cannot be found. - for i in 0 .. dbgFilenameLen-1: - result = dbgFilenames[i] - if fileMatches(result, filename): return result - result = nil - -iterator listBreakpoints*(): ptr Breakpoint = - ## lists all breakpoints. - for i in 0..dbgBPlen-1: yield addr(dbgBP[i]) - -proc isActive*(b: ptr Breakpoint): bool = b.low > 0 -proc flip*(b: ptr Breakpoint) = - ## enables or disables 'b' depending on its current state. - b.low = -b.low; b.high = -b.high - -proc checkBreakpoints*(filename: cstring, line: int): ptr Breakpoint = - ## in which breakpoint (if any) we are. - if (dbgBPbloom and line) != line: return nil - for b in listBreakpoints(): - if line >= b.low and line <= b.high and filename == b.filename: return b - -# ------------------- watchpoint support ------------------------------------ - -type - Hash = int - Watchpoint {.pure, final.} = object - name: cstring - address: pointer - typ: PNimType - oldValue: Hash - -var - watchpoints: array[0..99, Watchpoint] - watchpointsLen: int - -proc `!&`(h: Hash, val: int): Hash {.inline.} = - result = h +% val - result = result +% result shl 10 - result = result xor (result shr 6) - -proc `!$`(h: Hash): Hash {.inline.} = - result = h +% h shl 3 - result = result xor (result shr 11) - result = result +% result shl 15 - -proc hash(data: pointer, size: int): Hash = - var h: Hash = 0 - var p = cast[cstring](data) - var i = 0 - var s = size - while s > 0: - h = h !& ord(p[i]) - inc(i) - dec(s) - result = !$h - -proc hashGcHeader(data: pointer): Hash = - const headerSize = sizeof(int)*2 - result = hash(cast[pointer](cast[int](data) -% headerSize), headerSize) - -proc genericHashAux(dest: pointer, mt: PNimType, shallow: bool, - h: Hash): Hash -proc genericHashAux(dest: pointer, n: ptr TNimNode, shallow: bool, - h: Hash): Hash = - var d = cast[ByteAddress](dest) - case n.kind - of nkSlot: - result = genericHashAux(cast[pointer](d +% n.offset), n.typ, shallow, h) - of nkList: - result = h - for i in 0..n.len-1: - result = result !& genericHashAux(dest, n.sons[i], shallow, result) - of nkCase: - result = h !& hash(cast[pointer](d +% n.offset), n.typ.size) - var m = selectBranch(dest, n) - if m != nil: result = genericHashAux(dest, m, shallow, result) - of nkNone: sysAssert(false, "genericHashAux") - -proc genericHashAux(dest: pointer, mt: PNimType, shallow: bool, - h: Hash): Hash = - sysAssert(mt != nil, "genericHashAux 2") - case mt.kind - of tyString: - var x = cast[PPointer](dest)[] - result = h - if x != nil: - let s = cast[NimString](x) - when defined(trackGcHeaders): - result = result !& hashGcHeader(x) - else: - result = result !& hash(x, s.len) - of tySequence: - var x = cast[PPointer](dest) - var dst = cast[ByteAddress](cast[PPointer](dest)[]) - result = h - if dst != 0: - when defined(trackGcHeaders): - result = result !& hashGcHeader(cast[PPointer](dest)[]) - else: - for i in 0..cast[PGenericSeq](dst).len-1: - result = result !& genericHashAux( - cast[pointer](dst +% i*% mt.base.size +% GenericSeqSize), - mt.base, shallow, result) - of tyObject, tyTuple: - # we don't need to copy m_type field for tyObject, as they are equal anyway - result = genericHashAux(dest, mt.node, shallow, h) - of tyArray, tyArrayConstr: - let d = cast[ByteAddress](dest) - result = h - for i in 0..(mt.size div mt.base.size)-1: - result = result !& genericHashAux(cast[pointer](d +% i*% mt.base.size), - mt.base, shallow, result) - of tyRef: - when defined(trackGcHeaders): - var s = cast[PPointer](dest)[] - if s != nil: - result = result !& hashGcHeader(s) - else: - if shallow: - result = h !& hash(dest, mt.size) - else: - result = h - var s = cast[PPointer](dest)[] - if s != nil: - result = result !& genericHashAux(s, mt.base, shallow, result) - else: - result = h !& hash(dest, mt.size) # hash raw bits - -proc genericHash(dest: pointer, mt: PNimType): int = - result = genericHashAux(dest, mt, false, 0) - -proc dbgRegisterWatchpoint(address: pointer, name: cstring, - typ: PNimType) {.compilerproc.} = - let L = watchPointsLen - for i in 0 .. pred(L): - if watchPoints[i].name == name: - # address may have changed: - watchPoints[i].address = address - return - if L >= watchPoints.high: - #debugOut("[Warning] cannot register watchpoint") - return - watchPoints[L].name = name - watchPoints[L].address = address - watchPoints[L].typ = typ - watchPoints[L].oldValue = genericHash(address, typ) - inc watchPointsLen - -proc dbgUnregisterWatchpoints*() = - watchPointsLen = 0 - -var - dbgLineHook*: proc () {.nimcall.} - ## set this variable to provide a procedure that should be called before - ## each executed instruction. This should only be used by debuggers! - ## Only code compiled with the ``debugger:on`` switch calls this hook. - - dbgWatchpointHook*: proc (watchpointName: cstring) {.nimcall.} - -proc checkWatchpoints = - let L = watchPointsLen - for i in 0 .. pred(L): - let newHash = genericHash(watchPoints[i].address, watchPoints[i].typ) - if newHash != watchPoints[i].oldValue: - dbgWatchpointHook(watchPoints[i].name) - watchPoints[i].oldValue = newHash - -proc endb(line: int, file: cstring) {.compilerproc, noinline.} = - # This proc is called before every Nim code line! - if framePtr == nil: return - if dbgWatchpointHook != nil: checkWatchpoints() - framePtr.line = line # this is done here for smaller code size! - framePtr.filename = file - if dbgLineHook != nil: dbgLineHook() - -include "system/endb" diff --git a/lib/system/endb.nim b/lib/system/endb.nim deleted file mode 100644 index 6c99f8d12..000000000 --- a/lib/system/endb.nim +++ /dev/null @@ -1,579 +0,0 @@ -# -# -# Nim's Runtime Library -# (c) Copyright 2013 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -# This file implements the embedded debugger that can be linked -# with the application. Mostly we do not use dynamic memory here as that -# would interfere with the GC and trigger ON/OFF errors if the -# user program corrupts memory. Unfortunately, for dispaying -# variables we use the ``system.repr()`` proc which uses Nim -# strings and thus allocates memory from the heap. Pity, but -# I do not want to implement ``repr()`` twice. - -const - EndbBeg = "*** endb" - EndbEnd = "***\n" - -type - StaticStr = object - len: int - data: array[0..100, char] - - BreakpointFilename = object - b: ptr Breakpoint - filename: StaticStr - - DbgState = enum - dbOff, # debugger is turned off - dbStepInto, # debugger is in tracing mode - dbStepOver, - dbSkipCurrent, - dbQuiting, # debugger wants to quit - dbBreakpoints # debugger is only interested in breakpoints - -var - dbgUser: StaticStr # buffer for user input; first command is ``step_into`` - # needs to be global cause we store the last command - # in it - dbgState: DbgState # state of debugger - dbgSkipToFrame: PFrame # frame to be skipped to - - maxDisplayRecDepth: int = 5 # do not display too much data! - - brkPoints: array[0..127, BreakpointFilename] - -proc setLen(s: var StaticStr, newLen=0) = - s.len = newLen - s.data[newLen] = '\0' - -proc add(s: var StaticStr, c: char) = - if s.len < high(s.data)-1: - s.data[s.len] = c - s.data[s.len+1] = '\0' - inc s.len - -proc add(s: var StaticStr, c: cstring) = - var i = 0 - while c[i] != '\0': - add s, c[i] - inc i - -proc assign(s: var StaticStr, c: cstring) = - setLen(s) - add s, c - -proc `==`(a, b: StaticStr): bool = - if a.len == b.len: - for i in 0 .. a.len-1: - if a.data[i] != b.data[i]: return false - return true - -proc `==`(a: StaticStr, b: cstring): bool = - result = c_strcmp(unsafeAddr a.data, b) == 0 - -proc write(f: CFilePtr, s: cstring) = c_fputs(s, f) -proc writeLine(f: CFilePtr, s: cstring) = - c_fputs(s, f) - c_fputs("\n", f) - -proc write(f: CFilePtr, s: StaticStr) = - write(f, cstring(unsafeAddr s.data)) - -proc write(f: CFilePtr, i: int) = - when sizeof(int) == 8: - discard c_fprintf(f, "%lld", i) - else: - discard c_fprintf(f, "%ld", i) - -proc close(f: CFilePtr): cint {. - importc: "fclose", header: "<stdio.h>", discardable.} - -proc c_fgetc(stream: CFilePtr): cint {. - importc: "fgetc", header: "<stdio.h>".} -proc c_ungetc(c: cint, f: CFilePtr): cint {. - importc: "ungetc", header: "<stdio.h>", discardable.} - -var - cstdin* {.importc: "stdin", header: "<stdio.h>".}: CFilePtr - -proc listBreakPoints() = - write(cstdout, EndbBeg) - write(cstdout, "| Breakpoints:\n") - for b in listBreakpoints(): - write(cstdout, abs(b.low)) - if b.high != b.low: - write(cstdout, "..") - write(cstdout, abs(b.high)) - write(cstdout, " ") - write(cstdout, b.filename) - if b.isActive: - write(cstdout, " [disabled]\n") - else: - write(cstdout, "\n") - write(cstdout, EndbEnd) - -proc openAppend(filename: cstring): CFilePtr = - proc fopen(filename, mode: cstring): CFilePtr {.importc: "fopen", header: "<stdio.h>".} - - result = fopen(filename, "ab") - if result != nil: - write(result, "----------------------------------------\n") - -proc dbgRepr(p: pointer, typ: PNimType): string = - var cl: ReprClosure - initReprClosure(cl) - cl.recDepth = maxDisplayRecDepth - # locks for the GC turned out to be a bad idea... - # inc(recGcLock) - result = "" - reprAux(result, p, typ, cl) - # dec(recGcLock) - deinitReprClosure(cl) - -proc writeVariable(stream: CFilePtr, slot: VarSlot) = - write(stream, slot.name) - write(stream, " = ") - writeLine(stream, dbgRepr(slot.address, slot.typ)) - -proc listFrame(stream: CFilePtr, f: PFrame) = - write(stream, EndbBeg) - write(stream, "| Frame (") - write(stream, f.len) - write(stream, " slots):\n") - for i in 0 .. f.len-1: - writeLine(stream, getLocal(f, i).name) - write(stream, EndbEnd) - -proc listLocals(stream: CFilePtr, f: PFrame) = - write(stream, EndbBeg) - write(stream, "| Frame (") - write(stream, f.len) - write(stream, " slots):\n") - for i in 0 .. f.len-1: - writeVariable(stream, getLocal(f, i)) - write(stream, EndbEnd) - -proc listGlobals(stream: CFilePtr) = - write(stream, EndbBeg) - write(stream, "| Globals:\n") - for i in 0 .. getGlobalLen()-1: - writeLine(stream, getGlobal(i).name) - write(stream, EndbEnd) - -proc debugOut(msg: cstring) = - # the *** *** markers are for easy recognition of debugger - # output for external frontends. - write(cstdout, EndbBeg) - write(cstdout, "| ") - write(cstdout, msg) - write(cstdout, EndbEnd) - -proc dbgFatal(msg: cstring) = - debugOut(msg) - dbgAborting = true # the debugger wants to abort - quit(1) - -proc dbgShowCurrentProc(dbgFramePointer: PFrame) = - if dbgFramePointer != nil: - write(cstdout, "*** endb| now in proc: ") - write(cstdout, dbgFramePointer.procname) - write(cstdout, " ***\n") - else: - write(cstdout, "*** endb| (proc name not available) ***\n") - -proc dbgShowExecutionPoint() = - write(cstdout, "*** endb| ") - write(cstdout, framePtr.filename) - write(cstdout, "(") - write(cstdout, framePtr.line) - write(cstdout, ") ") - write(cstdout, framePtr.procname) - write(cstdout, " ***\n") - -proc scanAndAppendWord(src: cstring, a: var StaticStr, start: int): int = - result = start - # skip whitespace: - while src[result] in {'\t', ' '}: inc(result) - while true: - case src[result] - of 'a'..'z', '0'..'9': add(a, src[result]) - of '_': discard # just skip it - of 'A'..'Z': add(a, chr(ord(src[result]) - ord('A') + ord('a'))) - else: break - inc(result) - -proc scanWord(src: cstring, a: var StaticStr, start: int): int = - setlen(a) - result = scanAndAppendWord(src, a, start) - -proc scanFilename(src: cstring, a: var StaticStr, start: int): int = - result = start - setLen a - while src[result] in {'\t', ' '}: inc(result) - while src[result] notin {'\t', ' ', '\0'}: - add(a, src[result]) - inc(result) - -proc scanNumber(src: cstring, a: var int, start: int): int = - result = start - a = 0 - while src[result] in {'\t', ' '}: inc(result) - while true: - case src[result] - of '0'..'9': a = a * 10 + ord(src[result]) - ord('0') - of '_': discard # skip underscores (nice for long line numbers) - else: break - inc(result) - -proc dbgHelp() = - debugOut(""" -list of commands (see the manual for further help): - GENERAL -h, help display this help message -q, quit quit the debugger and the program -<ENTER> repeat the previous debugger command - EXECUTING -s, step single step, stepping into routine calls -n, next single step, without stepping into routine calls -f, skipcurrent continue execution until the current routine finishes -c, continue, r, run continue execution until the next breakpoint -i, ignore continue execution, ignore all breakpoints - BREAKPOINTS -b, break [fromline [toline]] [file] - set a new breakpoint for line and file - if line or file are omitted the current one is used -breakpoints display the entire breakpoint list -toggle fromline [file] enable or disable a breakpoint -filenames list all valid filenames - DATA DISPLAY -e, eval <expr> evaluate the expression <expr> -o, out <file> <expr> evaluate <expr> and write it to <file> -w, where display the current execution point -stackframe [file] display current stack frame [and write it to file] -u, up go up in the call stack -d, down go down in the call stack -bt, backtrace display the entire call stack -l, locals display available local variables -g, globals display available global variables -maxdisplay <integer> set the display's recursion maximum -""") - -proc invalidCommand() = - debugOut("[Warning] invalid command ignored (type 'h' for help) ") - -proc hasExt(s: cstring): bool = - # returns true if s has a filename extension - var i = 0 - while s[i] != '\0': - if s[i] == '.': return true - inc i - -proc parseBreakpoint(s: cstring, start: int): Breakpoint = - var dbgTemp: StaticStr - var i = scanNumber(s, result.low, start) - if result.low == 0: result.low = framePtr.line - i = scanNumber(s, result.high, i) - if result.high == 0: result.high = result.low - i = scanFilename(s, dbgTemp, i) - if dbgTemp.len != 0: - if not hasExt(addr dbgTemp.data): add(dbgTemp, ".nim") - result.filename = canonFilename(addr dbgTemp.data) - if result.filename.isNil: - debugOut("[Warning] no breakpoint could be set; unknown filename ") - return - else: - result.filename = framePtr.filename - -proc createBreakPoint(s: cstring, start: int) = - let br = parseBreakpoint(s, start) - if not br.filename.isNil: - if not addBreakpoint(br.filename, br.low, br.high): - debugOut("[Warning] no breakpoint could be set; out of breakpoint space ") - -proc breakpointToggle(s: cstring, start: int) = - var a = parseBreakpoint(s, start) - if not a.filename.isNil: - var b = checkBreakpoints(a.filename, a.low) - if not b.isNil: b.flip - else: debugOut("[Warning] unknown breakpoint ") - -proc dbgEvaluate(stream: CFilePtr, s: cstring, start: int, f: PFrame) = - var dbgTemp: StaticStr - var i = scanWord(s, dbgTemp, start) - while s[i] in {' ', '\t'}: inc(i) - var v: VarSlot - if s[i] == '.': - inc(i) - add(dbgTemp, '.') - i = scanAndAppendWord(s, dbgTemp, i) - for i in 0 .. getGlobalLen()-1: - let v = getGlobal(i) - if c_strcmp(v.name, addr dbgTemp.data) == 0: - writeVariable(stream, v) - else: - for i in 0 .. f.len-1: - let v = getLocal(f, i) - if c_strcmp(v.name, addr dbgTemp.data) == 0: - writeVariable(stream, v) - -proc dbgOut(s: cstring, start: int, currFrame: PFrame) = - var dbgTemp: StaticStr - var i = scanFilename(s, dbgTemp, start) - if dbgTemp.len == 0: - invalidCommand() - return - var stream = openAppend(addr dbgTemp.data) - if stream == nil: - debugOut("[Warning] could not open or create file ") - return - dbgEvaluate(stream, s, i, currFrame) - close(stream) - -proc dbgStackFrame(s: cstring, start: int, currFrame: PFrame) = - var dbgTemp: StaticStr - var i = scanFilename(s, dbgTemp, start) - if dbgTemp.len == 0: - # just write it to cstdout: - listFrame(cstdout, currFrame) - else: - var stream = openAppend(addr dbgTemp.data) - if stream == nil: - debugOut("[Warning] could not open or create file ") - return - listFrame(stream, currFrame) - close(stream) - -proc readLine(f: CFilePtr, line: var StaticStr): bool = - while true: - var c = c_fgetc(f) - if c < 0'i32: - if line.len > 0: break - else: return false - if c == 10'i32: break # LF - if c == 13'i32: # CR - c = c_fgetc(f) # is the next char LF? - if c != 10'i32: discard c_ungetc(c, f) # no, put the character back - break - add line, chr(int(c)) - result = true - -proc listFilenames() = - write(cstdout, EndbBeg) - write(cstdout, "| Files:\n") - var i = 0 - while true: - let x = dbgFilenames[i] - if x.isNil: break - write(cstdout, x) - write(cstdout, "\n") - inc i - write(cstdout, EndbEnd) - -proc dbgWriteStackTrace(f: PFrame) -proc commandPrompt() = - # if we return from this routine, user code executes again - var - again = true - dbgFramePtr = framePtr # for going down and up the stack - dbgDown = 0 # how often we did go down - dbgTemp: StaticStr - - while again: - write(cstdout, "*** endb| >>") - let oldLen = dbgUser.len - dbgUser.len = 0 - if not readLine(cstdin, dbgUser): break - if dbgUser.len == 0: dbgUser.len = oldLen - # now look what we have to do: - var i = scanWord(addr dbgUser.data, dbgTemp, 0) - template `?`(x: untyped): untyped = dbgTemp == cstring(x) - if ?"s" or ?"step": - dbgState = dbStepInto - again = false - elif ?"n" or ?"next": - dbgState = dbStepOver - dbgSkipToFrame = framePtr - again = false - elif ?"f" or ?"skipcurrent": - dbgState = dbSkipCurrent - dbgSkipToFrame = framePtr.prev - again = false - elif ?"c" or ?"continue" or ?"r" or ?"run": - dbgState = dbBreakpoints - again = false - elif ?"i" or ?"ignore": - dbgState = dbOff - again = false - elif ?"h" or ?"help": - dbgHelp() - elif ?"q" or ?"quit": - dbgState = dbQuiting - dbgAborting = true - again = false - quit(1) # BUGFIX: quit with error code > 0 - elif ?"e" or ?"eval": - var - prevState = dbgState - prevSkipFrame = dbgSkipToFrame - dbgState = dbSkipCurrent - dbgEvaluate(cstdout, addr dbgUser.data, i, dbgFramePtr) - dbgState = prevState - dbgSkipToFrame = prevSkipFrame - elif ?"o" or ?"out": - dbgOut(addr dbgUser.data, i, dbgFramePtr) - elif ?"stackframe": - dbgStackFrame(addr dbgUser.data, i, dbgFramePtr) - elif ?"w" or ?"where": - dbgShowExecutionPoint() - elif ?"l" or ?"locals": - var - prevState = dbgState - prevSkipFrame = dbgSkipToFrame - dbgState = dbSkipCurrent - listLocals(cstdout, dbgFramePtr) - dbgState = prevState - dbgSkipToFrame = prevSkipFrame - elif ?"g" or ?"globals": - var - prevState = dbgState - prevSkipFrame = dbgSkipToFrame - dbgState = dbSkipCurrent - listGlobals(cstdout) - dbgState = prevState - dbgSkipToFrame = prevSkipFrame - elif ?"u" or ?"up": - if dbgDown <= 0: - debugOut("[Warning] cannot go up any further ") - else: - dbgFramePtr = framePtr - for j in 0 .. dbgDown-2: # BUGFIX - dbgFramePtr = dbgFramePtr.prev - dec(dbgDown) - dbgShowCurrentProc(dbgFramePtr) - elif ?"d" or ?"down": - if dbgFramePtr != nil: - inc(dbgDown) - dbgFramePtr = dbgFramePtr.prev - dbgShowCurrentProc(dbgFramePtr) - else: - debugOut("[Warning] cannot go down any further ") - elif ?"bt" or ?"backtrace": - dbgWriteStackTrace(framePtr) - elif ?"b" or ?"break": - createBreakPoint(addr dbgUser.data, i) - elif ?"breakpoints": - listBreakPoints() - elif ?"toggle": - breakpointToggle(addr dbgUser.data, i) - elif ?"filenames": - listFilenames() - elif ?"maxdisplay": - var parsed: int - i = scanNumber(addr dbgUser.data, parsed, i) - if dbgUser.data[i-1] in {'0'..'9'}: - if parsed == 0: maxDisplayRecDepth = -1 - else: maxDisplayRecDepth = parsed - else: - invalidCommand() - else: invalidCommand() - -proc endbStep() = - # we get into here if an unhandled exception has been raised - # XXX: do not allow the user to run the program any further? - # XXX: BUG: the frame is lost here! - dbgShowExecutionPoint() - commandPrompt() - -proc dbgWriteStackTrace(f: PFrame) = - const - firstCalls = 32 - var - it = f - i = 0 - total = 0 - tempFrames: array[0..127, PFrame] - # setup long head: - while it != nil and i <= high(tempFrames)-firstCalls: - tempFrames[i] = it - inc(i) - inc(total) - it = it.prev - # go up the stack to count 'total': - var b = it - while it != nil: - inc(total) - it = it.prev - var skipped = 0 - if total > len(tempFrames): - # skip N - skipped = total-i-firstCalls+1 - for j in 1..skipped: - if b != nil: b = b.prev - # create '...' entry: - tempFrames[i] = nil - inc(i) - # setup short tail: - while b != nil and i <= high(tempFrames): - tempFrames[i] = b - inc(i) - b = b.prev - for j in countdown(i-1, 0): - if tempFrames[j] == nil: - write(cstdout, "(") - write(cstdout, skipped) - write(cstdout, " calls omitted) ...") - else: - write(cstdout, tempFrames[j].filename) - if tempFrames[j].line > 0: - write(cstdout, "(") - write(cstdout, tempFrames[j].line) - write(cstdout, ")") - write(cstdout, " ") - write(cstdout, tempFrames[j].procname) - write(cstdout, "\n") - -proc checkForBreakpoint = - let b = checkBreakpoints(framePtr.filename, framePtr.line) - if b != nil: - write(cstdout, "*** endb| reached ") - write(cstdout, framePtr.filename) - write(cstdout, "(") - write(cstdout, framePtr.line) - write(cstdout, ") ") - write(cstdout, framePtr.procname) - write(cstdout, " ***\n") - commandPrompt() - -proc lineHookImpl() {.nimcall.} = - case dbgState - of dbStepInto: - # we really want the command prompt here: - dbgShowExecutionPoint() - commandPrompt() - of dbSkipCurrent, dbStepOver: # skip current routine - if framePtr == dbgSkipToFrame: - dbgShowExecutionPoint() - commandPrompt() - else: - # breakpoints are wanted though (I guess) - checkForBreakpoint() - of dbBreakpoints: - # debugger is only interested in breakpoints - checkForBreakpoint() - else: discard - -proc watchpointHookImpl(name: cstring) {.nimcall.} = - dbgWriteStackTrace(framePtr) - debugOut(name) - -proc initDebugger {.inline.} = - dbgState = dbStepInto - dbgUser.len = 1 - dbgUser.data[0] = 's' - dbgWatchpointHook = watchpointHookImpl - dbgLineHook = lineHookImpl diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim index 0898ad0fd..1eb4cedc8 100644 --- a/lib/system/excpt.nim +++ b/lib/system/excpt.nim @@ -38,10 +38,7 @@ proc showErrorMessage(data: cstring) {.gcsafe.} = writeToStdErr(data) proc quitOrDebug() {.inline.} = - when defined(endb): - endbStep() # call the debugger - else: - quit(1) + quit(1) proc chckIndx(i, a, b: int): int {.inline, compilerproc, benign.} proc chckRange(i, a, b: int): int {.inline, compilerproc, benign.} @@ -469,10 +466,6 @@ proc nimFrame(s: PFrame) {.compilerRtl, inl.} = framePtr = s if s.calldepth == nimCallDepthLimit: callDepthLimitReached() -when defined(endb): - var - dbgAborting: bool # whether the debugger wants to abort - when defined(cpp) and appType != "lib" and not defined(js) and not defined(nimscript) and hostOS != "standalone" and not defined(noCppExceptions): @@ -515,8 +508,6 @@ when not defined(noSignalHandler) and not defined(useNimRtl): elif s == SIGSEGV: action("SIGSEGV: Illegal storage access. (Attempt to read from nil?)\n") elif s == SIGABRT: - when defined(endb): - if dbgAborting: return # the debugger wants to abort action("SIGABRT: Abnormal termination.\n") elif s == SIGFPE: action("SIGFPE: Arithmetic error.\n") elif s == SIGILL: action("SIGILL: Illegal operation.\n") @@ -546,7 +537,6 @@ when not defined(noSignalHandler) and not defined(useNimRtl): msg = y processSignal(sign, asgn) showErrorMessage(msg) - when defined(endb): dbgAborting = true quit(1) # always quit when SIGABRT proc registerSignalHandler() = diff --git a/tests/gc/gcleak4.nim b/tests/gc/gcleak4.nim index e9b17e557..35b8ce112 100644 --- a/tests/gc/gcleak4.nim +++ b/tests/gc/gcleak4.nim @@ -27,13 +27,11 @@ method eval(e: ref TPlusExpr): int = proc newLit(x: int): ref TLiteral = new(result) - {.watchpoint: result.} result.x = x result.op1 = $getOccupiedMem() proc newPlus(a, b: ref TExpr): ref TPlusExpr = new(result) - {.watchpoint: result.} result.a = a result.b = b result.op2 = $getOccupiedMem() diff --git a/tests/misc/thallo.nim b/tests/misc/thallo.nim index f61ce2ef2..8dac56023 100644 --- a/tests/misc/thallo.nim +++ b/tests/misc/thallo.nim @@ -48,7 +48,6 @@ echo(["a", "b", "c", "d"].len) for x in items(["What's", "your", "name", "?", ]): echo(x) var `name` = readLine(stdin) -{.breakpoint.} echo("Hi " & thallo.name & "!\n") debug(name) diff --git a/tests/objects/tobjects_various.nim b/tests/objects/tobjects_various.nim index a6c4628af..315193de9 100644 --- a/tests/objects/tobjects_various.nim +++ b/tests/objects/tobjects_various.nim @@ -17,7 +17,6 @@ block tobject2: z: int # added a field proc getPoint( p: var TPoint2d) = - {.breakpoint.} writeLine(stdout, p.x) var p: TPoint3d |