Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix echoBinSafe failure from #10559 #10576

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
329 changes: 45 additions & 284 deletions lib/system.nim

Large diffs are not rendered by default.

21 changes: 13 additions & 8 deletions lib/system/ansi_c.nim
Original file line number Diff line number Diff line change
Expand Up @@ -111,22 +111,27 @@ type c_sighandler_t = proc (a: cint) {.noconv.}
proc c_signal(sign: cint, handler: proc (a: cint) {.noconv.}): c_sighandler_t {.
importc: "signal", header: "<signal.h>", discardable.}

proc c_fprintf(f: File, frmt: cstring): cint {.
type
CFile {.importc: "FILE", header: "<stdio.h>",
incompletestruct.} = object
CFileStar* = ptr CFile ## The type representing a file handle.

var
cstderr* {.importc: "stderr", header: "<stdio.h>".}: CFileStar
cstdout* {.importc: "stdout", header: "<stdio.h>".}: CFileStar

proc c_fprintf(f: CFileStar, frmt: cstring): cint {.
importc: "fprintf", header: "<stdio.h>", varargs, discardable.}
proc c_printf(frmt: cstring): cint {.
importc: "printf", header: "<stdio.h>", varargs, discardable.}

proc c_fputs(c: cstring, f: CFileStar): cint {.
importc: "fputs", header: "<stdio.h>", discardable.}

proc c_sprintf(buf, frmt: cstring): cint {.
importc: "sprintf", header: "<stdio.h>", varargs, noSideEffect.}
# we use it only in a way that cannot lead to security issues

when defined(windows):
proc c_fileno(f: File): cint {.
importc: "_fileno", header: "<stdio.h>".}
else:
proc c_fileno(f: File): cint {.
importc: "fileno", header: "<fcntl.h>".}

proc c_malloc(size: csize): pointer {.
importc: "malloc", header: "<stdlib.h>".}
proc c_free(p: pointer) {.
Expand Down
32 changes: 16 additions & 16 deletions lib/system/dyncalls.nim
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ const

proc nimLoadLibraryError(path: string) =
# carefully written to avoid memory allocation:
stderr.rawWrite("could not load: ")
stderr.rawWrite(path)
stderr.rawWrite("\n")
cstderr.rawWrite("could not load: ")
cstderr.rawWrite(path)
cstderr.rawWrite("\n")
when not defined(nimDebugDlOpen) and not defined(windows):
stderr.rawWrite("compile with -d:nimDebugDlOpen for more information\n")
cstderr.rawWrite("compile with -d:nimDebugDlOpen for more information\n")
when defined(windows) and defined(guiapp):
# Because console output is not shown in GUI apps, display error as message box:
const prefix = "could not load: "
Expand All @@ -35,9 +35,9 @@ proc nimLoadLibraryError(path: string) =

proc procAddrError(name: cstring) {.noinline.} =
# carefully written to avoid memory allocation:
stderr.rawWrite("could not import: ")
stderr.rawWrite(name)
stderr.rawWrite("\n")
cstderr.rawWrite("could not import: ")
cstderr.rawWrite(name)
cstderr.rawWrite("\n")
quit(1)

# this code was inspired from Lua's source code:
Expand Down Expand Up @@ -79,8 +79,8 @@ when defined(posix):
when defined(nimDebugDlOpen):
let error = dlerror()
if error != nil:
stderr.rawWrite(error)
stderr.rawWrite("\n")
cstderr.rawWrite(error)
cstderr.rawWrite("\n")

proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr =
result = dlsym(lib, name)
Expand Down Expand Up @@ -162,20 +162,20 @@ elif defined(genode):

elif defined(nintendoswitch):
proc nimUnloadLibrary(lib: LibHandle) =
stderr.rawWrite("nimUnLoadLibrary not implemented")
stderr.rawWrite("\n")
cstderr.rawWrite("nimUnLoadLibrary not implemented")
cstderr.rawWrite("\n")
quit(1)

proc nimLoadLibrary(path: string): LibHandle =
stderr.rawWrite("nimLoadLibrary not implemented")
stderr.rawWrite("\n")
cstderr.rawWrite("nimLoadLibrary not implemented")
cstderr.rawWrite("\n")
quit(1)


proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr =
stderr.rawWrite("nimGetProAddr not implemented")
stderr.rawWrite(name)
stderr.rawWrite("\n")
cstderr.rawWrite("nimGetProAddr not implemented")
cstderr.rawWrite(name)
cstderr.rawWrite("\n")
quit(1)

else:
Expand Down
153 changes: 88 additions & 65 deletions lib/system/endb.nim
Original file line number Diff line number Diff line change
Expand Up @@ -76,29 +76,52 @@ proc `==`(a, b: StaticStr): bool =
proc `==`(a: StaticStr, b: cstring): bool =
result = c_strcmp(unsafeAddr a.data, b) == 0

proc write(f: File, s: StaticStr) =
proc write(f: CFileStar, s: cstring) = c_fputs(s, f)
proc writeLine(f: CFileStar, s: cstring) =
c_fputs(s, f)
c_fputs("\n", f)

proc write(f: CFileStar, s: StaticStr) =
write(f, cstring(unsafeAddr s.data))

proc write(f: CFileStar, i: int) =
when sizeof(int) == 8:
discard c_fprintf(f, "%lld", i)
else:
discard c_fprintf(f, "%ld", i)

proc close(f: CFileStar): cint {.
importc: "fclose", header: "<stdio.h>", discardable.}

proc c_fgetc(stream: CFileStar): cint {.
importc: "fgetc", header: "<stdio.h>".}
proc c_ungetc(c: cint, f: CFileStar): cint {.
importc: "ungetc", header: "<stdio.h>", discardable.}

var
cstdin* {.importc: "stdin", header: "<stdio.h>".}: CFileStar

proc listBreakPoints() =
write(stdout, EndbBeg)
write(stdout, "| Breakpoints:\n")
write(cstdout, EndbBeg)
write(cstdout, "| Breakpoints:\n")
for b in listBreakpoints():
write(stdout, abs(b.low))
write(cstdout, abs(b.low))
if b.high != b.low:
write(stdout, "..")
write(stdout, abs(b.high))
write(stdout, " ")
write(stdout, b.filename)
write(cstdout, "..")
write(cstdout, abs(b.high))
write(cstdout, " ")
write(cstdout, b.filename)
if b.isActive:
write(stdout, " [disabled]\n")
write(cstdout, " [disabled]\n")
else:
write(stdout, "\n")
write(stdout, EndbEnd)
write(cstdout, "\n")
write(cstdout, EndbEnd)

proc openAppend(filename: cstring): CFileStar =
proc fopen(filename, mode: cstring): CFileStar {.importc: "fopen", header: "<stdio.h>".}

proc openAppend(filename: cstring): File =
var p: pointer = fopen(filename, "ab")
if p != nil:
result = cast[File](p)
result = fopen(filename, "ab")
if result != nil:
write(result, "----------------------------------------\n")

proc dbgRepr(p: pointer, typ: PNimType): string =
Expand All @@ -112,12 +135,12 @@ proc dbgRepr(p: pointer, typ: PNimType): string =
# dec(recGcLock)
deinitReprClosure(cl)

proc writeVariable(stream: File, slot: VarSlot) =
proc writeVariable(stream: CFileStar, slot: VarSlot) =
write(stream, slot.name)
write(stream, " = ")
writeLine(stream, dbgRepr(slot.address, slot.typ))

proc listFrame(stream: File, f: PFrame) =
proc listFrame(stream: CFileStar, f: PFrame) =
write(stream, EndbBeg)
write(stream, "| Frame (")
write(stream, f.len)
Expand All @@ -126,7 +149,7 @@ proc listFrame(stream: File, f: PFrame) =
writeLine(stream, getLocal(f, i).name)
write(stream, EndbEnd)

proc listLocals(stream: File, f: PFrame) =
proc listLocals(stream: CFileStar, f: PFrame) =
write(stream, EndbBeg)
write(stream, "| Frame (")
write(stream, f.len)
Expand All @@ -135,7 +158,7 @@ proc listLocals(stream: File, f: PFrame) =
writeVariable(stream, getLocal(f, i))
write(stream, EndbEnd)

proc listGlobals(stream: File) =
proc listGlobals(stream: CFileStar) =
write(stream, EndbBeg)
write(stream, "| Globals:\n")
for i in 0 .. getGlobalLen()-1:
Expand All @@ -145,10 +168,10 @@ proc listGlobals(stream: File) =
proc debugOut(msg: cstring) =
# the *** *** markers are for easy recognition of debugger
# output for external frontends.
write(stdout, EndbBeg)
write(stdout, "| ")
write(stdout, msg)
write(stdout, EndbEnd)
write(cstdout, EndbBeg)
write(cstdout, "| ")
write(cstdout, msg)
write(cstdout, EndbEnd)

proc dbgFatal(msg: cstring) =
debugOut(msg)
Expand All @@ -157,20 +180,20 @@ proc dbgFatal(msg: cstring) =

proc dbgShowCurrentProc(dbgFramePointer: PFrame) =
if dbgFramePointer != nil:
write(stdout, "*** endb| now in proc: ")
write(stdout, dbgFramePointer.procname)
write(stdout, " ***\n")
write(cstdout, "*** endb| now in proc: ")
write(cstdout, dbgFramePointer.procname)
write(cstdout, " ***\n")
else:
write(stdout, "*** endb| (proc name not available) ***\n")
write(cstdout, "*** endb| (proc name not available) ***\n")

proc dbgShowExecutionPoint() =
write(stdout, "*** endb| ")
write(stdout, framePtr.filename)
write(stdout, "(")
write(stdout, framePtr.line)
write(stdout, ") ")
write(stdout, framePtr.procname)
write(stdout, " ***\n")
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
Expand Down Expand Up @@ -279,7 +302,7 @@ proc breakpointToggle(s: cstring, start: int) =
if not b.isNil: b.flip
else: debugOut("[Warning] unknown breakpoint ")

proc dbgEvaluate(stream: File, s: cstring, start: int, f: PFrame) =
proc dbgEvaluate(stream: CFileStar, s: cstring, start: int, f: PFrame) =
var dbgTemp: StaticStr
var i = scanWord(s, dbgTemp, start)
while s[i] in {' ', '\t'}: inc(i)
Expand Down Expand Up @@ -315,8 +338,8 @@ 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 stdout:
listFrame(stdout, currFrame)
# just write it to cstdout:
listFrame(cstdout, currFrame)
else:
var stream = openAppend(addr dbgTemp.data)
if stream == nil:
Expand All @@ -325,7 +348,7 @@ proc dbgStackFrame(s: cstring, start: int, currFrame: PFrame) =
listFrame(stream, currFrame)
close(stream)

proc readLine(f: File, line: var StaticStr): bool =
proc readLine(f: CFileStar, line: var StaticStr): bool =
while true:
var c = c_fgetc(f)
if c < 0'i32:
Expand All @@ -340,16 +363,16 @@ proc readLine(f: File, line: var StaticStr): bool =
result = true

proc listFilenames() =
write(stdout, EndbBeg)
write(stdout, "| Files:\n")
write(cstdout, EndbBeg)
write(cstdout, "| Files:\n")
var i = 0
while true:
let x = dbgFilenames[i]
if x.isNil: break
write(stdout, x)
write(stdout, "\n")
write(cstdout, x)
write(cstdout, "\n")
inc i
write(stdout, EndbEnd)
write(cstdout, EndbEnd)

proc dbgWriteStackTrace(f: PFrame)
proc commandPrompt() =
Expand All @@ -361,10 +384,10 @@ proc commandPrompt() =
dbgTemp: StaticStr

while again:
write(stdout, "*** endb| >>")
write(cstdout, "*** endb| >>")
let oldLen = dbgUser.len
dbgUser.len = 0
if not readLine(stdin, dbgUser): break
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)
Expand Down Expand Up @@ -398,7 +421,7 @@ proc commandPrompt() =
prevState = dbgState
prevSkipFrame = dbgSkipToFrame
dbgState = dbSkipCurrent
dbgEvaluate(stdout, addr dbgUser.data, i, dbgFramePtr)
dbgEvaluate(cstdout, addr dbgUser.data, i, dbgFramePtr)
dbgState = prevState
dbgSkipToFrame = prevSkipFrame
elif ?"o" or ?"out":
Expand All @@ -412,15 +435,15 @@ proc commandPrompt() =
prevState = dbgState
prevSkipFrame = dbgSkipToFrame
dbgState = dbSkipCurrent
listLocals(stdout, dbgFramePtr)
listLocals(cstdout, dbgFramePtr)
dbgState = prevState
dbgSkipToFrame = prevSkipFrame
elif ?"g" or ?"globals":
var
prevState = dbgState
prevSkipFrame = dbgSkipToFrame
dbgState = dbSkipCurrent
listGlobals(stdout)
listGlobals(cstdout)
dbgState = prevState
dbgSkipToFrame = prevSkipFrame
elif ?"u" or ?"up":
Expand Down Expand Up @@ -501,29 +524,29 @@ proc dbgWriteStackTrace(f: PFrame) =
b = b.prev
for j in countdown(i-1, 0):
if tempFrames[j] == nil:
write(stdout, "(")
write(stdout, skipped)
write(stdout, " calls omitted) ...")
write(cstdout, "(")
write(cstdout, skipped)
write(cstdout, " calls omitted) ...")
else:
write(stdout, tempFrames[j].filename)
write(cstdout, tempFrames[j].filename)
if tempFrames[j].line > 0:
write(stdout, '(')
write(stdout, tempFrames[j].line)
write(stdout, ')')
write(stdout, ' ')
write(stdout, tempFrames[j].procname)
write(stdout, "\n")
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(stdout, "*** endb| reached ")
write(stdout, framePtr.filename)
write(stdout, "(")
write(stdout, framePtr.line)
write(stdout, ") ")
write(stdout, framePtr.procname)
write(stdout, " ***\n")
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.} =
Expand Down