cisco-open / llvm-crash-analyzer

llvm crash analysis
Apache License 2.0
40 stars 17 forks source link

Missing frame from the backtrace #33

Open niktesic opened 1 year ago

niktesic commented 1 year ago

Crash Analyzer runs Taint Analysis on each function from the backtrace, so it depends on LLDB's ability to populate backtrace with proper frames.

Please, consider a backtrace like in the example below: (from llvm-crash-analyzer/test/Analysis/missing-frame.test)

#0 set()
#1 missing()
#2 main()

If function set() is called from missing() via tail call (JMP instruction), that means that the frame for function missing() is not preserved on the stack (return PC and FramePointer). Modern debuggers, like GDB and LLDB (from D50478), can reconstruct missing frames, and create artificial ones, based on the call site information (from DWARF - example below). So, debugger can determine which function is called from main() at the particular PC, and match it to the corresponding DW_TAG_subprogram DIE.

0x0000011e:     DW_TAG_GNU_call_site
                  DW_AT_abstract_origin (0x0000012c "missing")
                  DW_AT_low_pc  (0x00000000004005b3)

If function missing() is called from main() via indirect call, generated call site information in DWARF, doesn't point to the DW_TAG_subprogram DIE, since call target is not known at the compile time. Debugger needs to determine call target at the runtime, by evaluating expression from DW_AT_GNU_call_site_target.

0x000000e5:     DW_TAG_GNU_call_site
                  DW_AT_GNU_call_site_target    (DW_OP_reg0 RAX)
                  DW_AT_low_pc  (0x0000000000400575)

However, in most cases, the expression which determines call target (usually just register, like in the example above), cannot be evaluated. In the presented example, value of register $rax is not available at that program point. Additionally, applying some other optimizations and call mechanisms can cause complete absence of DW_TAG_GNU_call_site for missing() call site in the main() function.

To sum up, without one frame from the backtrace, if it changes the location of the tainted value, which is expected, llvm-crash-analyzer cannot perform correct Taint Analysis.

To support creation of artificial frames in the presented case, it is needed to have:

  1. Compiler which is able to generate DW_TAG_GNU_call_site DIEs for (all) indirect call sites. This is not supported in some special cases.
  2. Compiler which could provide entry value expression describing call site target, like it is done for entry values of function parameters.
  3. Debugger which could evaluate indirect call target address and use it to match corresponding DW_TAG_subprogram DIE.