Skip to content

Commit

Permalink
Merge pull request #74 from JuliaDebug/sp/better-stackframe-printing
Browse files Browse the repository at this point in the history
Improve stackframe printing
  • Loading branch information
pfitzseb authored May 19, 2022
2 parents 8f21816 + 522b636 commit 50d65d4
Show file tree
Hide file tree
Showing 12 changed files with 84 additions and 136 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
*.jl.*.cov
*.jl.mem
*.out
Manifest.toml
4 changes: 3 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ uuid = "5903a43b-9cc3-4c30-8d17-598619ec4e9b"
version = "1.3.1"

[deps]
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[compat]
julia = "1.1"

[extras]
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
TerminalRegressionTests = "98bfdc55-cc95-5876-a49a-74609291cbe0"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[targets]
test = ["Random", "Test", "TerminalRegressionTests"]
32 changes: 16 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ julia> function f(x)
f (generic function with 1 method)

julia> f([1,2,3])
Infiltrating f(x::Vector{Int64}) at REPL[7]:5:
Infiltrating f(x::Vector{Int64})
at REPL[10]:5

infil> ?
Code entered is evaluated in the current functions module. Note that you cannot change local
Expand All @@ -86,20 +87,16 @@ infil> 0//0
ERROR: ArgumentError: invalid rational: zero(Int64)//zero(Int64)
Stacktrace:
[1] __throw_rational_argerror_zero(T::Type)
@ Base ./rational.jl:31
@ Base ./rational.jl:32
[2] Rational{Int64}(num::Int64, den::Int64)
@ Base ./rational.jl:33
@ Base ./rational.jl:34
[3] Rational
@ ./rational.jl:38 [inlined]
@ ./rational.jl:39 [inlined]
[4] //(n::Int64, d::Int64)
@ Base ./rational.jl:61
@ Base ./rational.jl:62
[5] top-level scope
@ none:1

infil> intermediate = copy(out) # assigned (or `@exfiltrate`d) variables can be accessed from the safehouse
1-element Vector{Any}:
2

infil> @toggle
Disabled infiltration at this infiltration point.

Expand All @@ -108,12 +105,13 @@ Enabled infiltration at this infiltration point.

infil> @continue

Infiltrating f(x::Vector{Int64}) at REPL[7]:5:
Infiltrating f(x::Vector{Int64})
at REPL[10]:5

infil> @locals
- out::Vector{Any} = Any[2, 4]
- i::Int64 = 2
- x::Vector{Int64} = [1, 2, 3]
infil> intermediate = copy(out)
2-element Vector{Any}:
2
4

infil> @exfiltrate intermediate x
Exfiltrating 2 local variables into the safehouse.
Expand All @@ -126,15 +124,17 @@ infil> @exit
6

julia> safehouse.intermediate
1-element Vector{Any}:
2-element Vector{Any}:
2
4

julia> @withstore begin
x = 23
x .* intermediate
end
1-element Vector{Int64}:
2-element Vector{Int64}:
46
92
```

# Related projects
Expand Down
79 changes: 64 additions & 15 deletions src/Infiltrator.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module Infiltrator

using REPL, UUIDs, InteractiveUtils
using REPL.LineEdit: getproperty
using REPL
using REPL.LineEdit

export @infiltrate, @exfiltrate, @withstore, safehouse, exfiltrated
Expand Down Expand Up @@ -210,7 +210,7 @@ function start_prompt(mod, locals, file, fileline;

trace = stacktrace()
start = something(findlast(x -> x.func === Symbol("start_prompt"), trace), 0) + 2
last = something(findfirst(x -> x.func === Symbol("top-level scope"), trace),
last = something(findfirst(x -> x.func === StackTraces.top_level_scope_sym, trace),
length(trace))
trace = trace[start:last]

Expand All @@ -228,7 +228,8 @@ function start_prompt(mod, locals, file, fileline;
if nostack
println(io, "Infiltrating <unknown>:")
else
println(io, "Infiltrating $(trace[1]):")
print(io, "Infiltrating ")
print_verbose_stackframe(io, trace[1])
end
else
println(io, "Infiltrating top-level frame:")
Expand Down Expand Up @@ -257,14 +258,6 @@ function show_help(io)
""")
end

function show_trace(io, trace, nostack)
for (i, frame) in enumerate(trace)
nostack && i > 1 && break
println(io, "[", i, "] ", frame)
end
println(io)
end

function strlimit(str, limit = 30)
strwidth = 0
for (i, c) in enumerate(str)
Expand Down Expand Up @@ -399,7 +392,7 @@ function debugprompt(mod, locals, trace, terminal, repl, nostack = false; file,
LineEdit.reset_state(s)
return true
elseif sline == "@trace"
show_trace(io, trace, nostack)
print_verbose_stacktrace(io, trace, nostack ? 0 : 100)
LineEdit.reset_state(s)
return true
elseif startswith(sline, "@locals")
Expand All @@ -425,7 +418,12 @@ function debugprompt(mod, locals, trace, terminal, repl, nostack = false; file,
elseif sline == "@exit"
setfield!(store, :exiting, true)
if !REPL_HOOKED[]
println(io, "Revert the effect of this with `Infiltrator.end_session!()` or you will not be able to enter a new session!")
printstyled(
io,
">> Restore infiltration capabilities with `Infiltrator.end_session!()` or you will not be able to enter a new session!\n";
color=:red,
bold=true
)
end
LineEdit.transition(s, :abort)
LineEdit.reset_state(s)
Expand Down Expand Up @@ -523,6 +521,57 @@ function get_module_names(m::Module, get_names = all_names)
out
end

function print_verbose_stacktrace(io, st, limit = 100)
len = length(st)
for (i, sf) in enumerate(st)
if i > limit
limit > 0 && println(io, "\n<< omitted $(len - limit) stack frames >>")
break
end

print_verbose_stackframe(io, sf, i, len)
end
println(io)
end

function print_verbose_stackframe(io, sf::StackTraces.StackFrame, i, len)
num_padding = ceil(Int, log10(len))
padding = num_padding + 3
print(io, "[", lpad(i, num_padding), "] ")
print_verbose_stackframe(io, sf, padding)
end

function print_verbose_stackframe(io, sf::StackTraces.StackFrame, padding = 2)
Base.StackTraces.show_spec_linfo(IOContext(io, :backtrace=>true), sf)
println(io)

sf.func == StackTraces.top_level_scope_sym && return

print(io, ' '^padding)
printstyled(io, "at ", color=:light_black)

file, line = string(sf.file), sf.line
file = fixup_stdlib_path(file)
file = something(Base.find_source_file(file), file)
printstyled(io, normpath(file), ":", line, '\n', color=:light_black)
end

# https://github.com/JuliaLang/julia/blob/1fb28ad8768cfdc077e968df7adf5716ae8eb9ab/base/methodshow.jl#L134-L148
function fixup_stdlib_path(path::String)
BUILD_STDLIB_PATH = isdefined(Sys, :BUILD_STDLIB_PATH) ?
Sys.BUILD_STDLIB_PATH :
dirname(abspath(joinpath(String((@which uuid1()).file), "..", "..", "..")))

STDLIB = Sys.STDLIB::String
if BUILD_STDLIB_PATH != STDLIB
# BUILD_STDLIB_PATH gets defined in sysinfo.jl
npath = normpath(path)
npath′ = replace(npath, normpath(BUILD_STDLIB_PATH) => normpath(STDLIB))
return npath == npath′ ? path : npath′
end
return path
end

function all_names(m)
symbols = Set(Symbol[])
seen = Set(Module[])
Expand Down Expand Up @@ -584,12 +633,12 @@ function find_first_topelevel_scope(bt::Vector{<:Union{Base.InterpreterIP,Ptr{Cv
linetable = linfo.linetable
if isa(linetable, Vector) && length(linetable) 1
lin = first(linetable)
if isa(lin, Core.LineInfoNode) && lin.method === Symbol("top-level scope")
if isa(lin, Core.LineInfoNode) && lin.method === StackTraces.top_level_scope_sym
return true
end
end
else
return frame.func === Symbol("top-level scope")
return frame.func === StackTraces.top_level_scope_sym
end
end
ind === nothing || return i
Expand Down
20 changes: 0 additions & 20 deletions test/Julia_f_1.1.multiout
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@
| 1.5 this needs to be manually cleared with `Infiltrator.end_session!()`).
|
|infil> @trace
|[1] f(::Int64) at runtests.jl:7
|
|infil>
--------------------------------------------------
Expand Down Expand Up @@ -109,7 +108,6 @@
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|BBBBBBBCCCCCC
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|BBBBBBB
++++++++++++++++++++++++++++++++++++++++++++++++++
Expand Down Expand Up @@ -137,7 +135,6 @@
| 1.5 this needs to be manually cleared with `Infiltrator.end_session!()`).
|
|infil> @trace
|[1] f(::Int64) at runtests.jl:7
|
|infil> @locals
|- y::Array{Int64,1} = [1, 2, 3]
Expand Down Expand Up @@ -169,7 +166,6 @@
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|BBBBBBBCCCCCC
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|BBBBBBBCCCCCCC
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
Expand Down Expand Up @@ -201,7 +197,6 @@
| 1.5 this needs to be manually cleared with `Infiltrator.end_session!()`).
|
|infil> @trace
|[1] f(::Int64) at runtests.jl:7
|
|infil> @locals
|- y::Array{Int64,1} = [1, 2, 3]
Expand Down Expand Up @@ -239,7 +234,6 @@
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|BBBBBBBCCCCCC
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|BBBBBBBCCCCCCC
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
Expand Down Expand Up @@ -277,7 +271,6 @@
| 1.5 this needs to be manually cleared with `Infiltrator.end_session!()`).
|
|infil> @trace
|[1] f(::Int64) at runtests.jl:7
|
|infil> @locals
|- y::Array{Int64,1} = [1, 2, 3]
Expand Down Expand Up @@ -320,7 +313,6 @@
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|BBBBBBBCCCCCC
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|BBBBBBBCCCCCCC
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
Expand Down Expand Up @@ -363,7 +355,6 @@
| 1.5 this needs to be manually cleared with `Infiltrator.end_session!()`).
|
|infil> @trace
|[1] f(::Int64) at runtests.jl:7
|
|infil> @locals
|- y::Array{Int64,1} = [1, 2, 3]
Expand Down Expand Up @@ -409,7 +400,6 @@
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|BBBBBBBCCCCCC
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|BBBBBBBCCCCCCC
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
Expand Down Expand Up @@ -455,7 +445,6 @@
| 1.5 this needs to be manually cleared with `Infiltrator.end_session!()`).
|
|infil> @trace
|[1] f(::Int64) at runtests.jl:7
|
|infil> @locals
|- y::Array{Int64,1} = [1, 2, 3]
Expand Down Expand Up @@ -504,7 +493,6 @@
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|BBBBBBBCCCCCC
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|BBBBBBBCCCCCCC
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
Expand Down Expand Up @@ -553,7 +541,6 @@
| 1.5 this needs to be manually cleared with `Infiltrator.end_session!()`).
|
|infil> @trace
|[1] f(::Int64) at runtests.jl:7
|
|infil> @locals
|- y::Array{Int64,1} = [1, 2, 3]
Expand Down Expand Up @@ -605,7 +592,6 @@
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|BBBBBBBCCCCCC
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|BBBBBBBCCCCCCC
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
Expand Down Expand Up @@ -657,7 +643,6 @@
| 1.5 this needs to be manually cleared with `Infiltrator.end_session!()`).
|
|infil> @trace
|[1] f(::Int64) at runtests.jl:7
|
|infil> @locals
|- y::Array{Int64,1} = [1, 2, 3]
Expand Down Expand Up @@ -712,7 +697,6 @@
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|BBBBBBBCCCCCC
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|BBBBBBBCCCCCCC
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
Expand Down Expand Up @@ -767,7 +751,6 @@
| 1.5 this needs to be manually cleared with `Infiltrator.end_session!()`).
|
|infil> @trace
|[1] f(::Int64) at runtests.jl:7
|
|infil> @locals
|- y::Array{Int64,1} = [1, 2, 3]
Expand Down Expand Up @@ -825,7 +808,6 @@
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|BBBBBBBCCCCCC
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|BBBBBBBCCCCCCC
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
Expand Down Expand Up @@ -883,7 +865,6 @@
| 1.5 this needs to be manually cleared with `Infiltrator.end_session!()`).
|
|infil> @trace
|[1] f(::Int64) at runtests.jl:7
|
|infil> @locals
|- y::Array{Int64,1} = [1, 2, 3]
Expand Down Expand Up @@ -944,7 +925,6 @@
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|BBBBBBBCCCCCC
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|BBBBBBBCCCCCCC
|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
Expand Down
Loading

0 comments on commit 50d65d4

Please sign in to comment.