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

Metadata missing from inlined frames in backtraces #41031

Closed
c42f opened this issue May 31, 2021 · 4 comments · Fixed by #41099
Closed

Metadata missing from inlined frames in backtraces #41031

c42f opened this issue May 31, 2021 · 4 comments · Fixed by #41099

Comments

@c42f
Copy link
Member

c42f commented May 31, 2021

Having the parent Module and other method metadata available for each frame in a backtrace is quite useful for pretty printing, but we're currently missing it for inlined frames. For example:

julia> bar() = backtrace()
julia> foo() = bar()

julia> st = stacktrace(foo())
15-element Vector{Base.StackTraces.StackFrame}:
 bar at REPL[10]:1 [inlined]
 foo() at REPL[11]:1
 top-level scope at REPL[13]:1
...

For the foo frame, the linfo field contains the MethodInstance which in turn can be traced back to the Method using st[2].linfo.def to get the Module or other desired metadata. However, for the bar frame we just get nothing here.

julia> dump(st[1])
Base.StackTraces.StackFrame
  func: Symbol bar
  file: Symbol ./REPL[10]
  line: Int64 1
  linfo: Nothing nothing
  from_c: Bool false
  inlined: Bool true
  pointer: UInt64 0x00007f832223b37c

julia> dump(st[2])
Base.StackTraces.StackFrame
  func: Symbol foo
  file: Symbol ./REPL[11]
  line: Int64 1
  linfo: Core.MethodInstance
    def: Method
      name: Symbol foo
      module: Module Main
      file: Symbol REPL[11]
      line: Int32 1
    [.....]
  from_c: Bool false
  inlined: Bool false
  pointer: UInt64 0x00007f832223b37c

A place to start looking is inside the lookup code at

frame->linfo = NULL; // TODO: if (new_frames[n_frames - 1].linfo) frame->linfo = lookup(func_name in linfo)?

As suggested there, we should have the MethodInstance (or a CodeInfo thunk for toplevel code... IIRC) for the parent non-inlined frame in new_frames[n_frames-1]. So if we made sure that contained sufficient information about inlined methods we could fill in linfo in some way from there.

See also #33065 (comment)

@BioTurboNick
Copy link
Contributor

BioTurboNick commented Jun 2, 2021

I poked around a little bit. I noticed there's a linetable field that contains stack frame information; and inlining.jl places information on inlined frames into a vector linetable. I'm not sure if they aren't removed at some point.

Is there a point at which the linetable is finalized and could be inspected on the Julia side?

jl_print_bt_entry_codeloc uses it to obtain information on each frame from its CodeInfo block (unwrapping MethodInstances to get it), and seems to include inlined stack frames. But not sure where this code is used, suggests in an interpreter? The function used when Julia has a segfault is jl_print_native_codeloc, but it just uses the information provided by jl_getFunctionInfo, which is what we're trying to change.

I'd like to determine if this linetable contains inlined frame information, and then figure out how to access it if so. Perhaps linfo for the parent non-inlined frame could just contain the pointers to do that lookup?

Update: Found out I can inspect linetable at the end of run_passes. It does contain module information for the inlined frames. At a minimum, could scan the table for the matching function name, file name, and line number?

@c42f
Copy link
Member Author

c42f commented Jun 2, 2021

At a minimum, could scan the table for the matching function name, file name, and line number?

Sounds great if it's reliable. Getting module information would be useful, but it would be even better if we could trace back to the Method. as this would allow things like #35371 to work reliably for inline frames (not that I'm sure that PR will be merged. It seemed controversial...)

@BioTurboNick
Copy link
Contributor

I have a partial solution.

image

Now I just need to get it not to segfault when trying to display the function name and signature.

@c42f
Copy link
Member Author

c42f commented Apr 26, 2023

Awesome to see this fixed. Thanks so much @BioTurboNick :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants