Search code examples
swiftxcodeexceptionlldb

bypassing exc_breakpoint crash to continue program execution


During testing my iOS app, (it's a workout app), the app crashed (EXC_BREAKPOINT) as it was trying to save the workout data.

The crash was an index out of range issue whereby the array count is 1 lesser than the workout seconds. (I should have started the seconds counter from 1 instead of 0)

 for i in 0...seconds {
        let data = "\(i),\(dataArray.powerGenY[i-1]),\(dataArray.powerGenYAlt[i-1])\n"
        
        do {
          try data.appendToURL(fileURL: fileURL)
        }
        catch {
          print("Could not write data to file")
        }
      }

anyways, the error dropped me to LLDB. Is there any way I an Use LLDB to bypass this error and continue execution?


Solution

  • Having worked out for a hour, I wasn't prepared to have this crash take my data along with it. Since the crashed dropped me into LLDB, I wanted to see if there's any way to salvage the data by stepping over / bypassing / changing the value of i so that the program execution can continue.

    Initially I tried

    (lldb) po i = 3327
    error: <EXPR>:3:1: error: cannot assign to value: 'i' is immutable
    i = 3327
    ^
    

    but it won't let me change the value (I is immutable)

    Then I tried thread jump -l 1 but it spewed some error about not the code execution outside of current function.

    (lldb) th j -l 29
    error: CSVExport.swift:29 is outside the current function.
    

    Finally, going thru this site https://www.inovex.de/blog/lldb-patch-your-code-with-breakpoints/ and trying a few things. The one that helped was thread jump

    thread return

    The mentioned disadvantage of thread jump can be avoided by using a different technique to change control flow behaviour. Instead of manipulating the affected lines of code directly the idea is to manipulate other parts of the program which in turn results in the desired behaviour. For the given example this means changing the return value of can_pass() from 0 to 1. Which, of course, can be done through LLDB. The command to use is thread just like before, but this time with the subcommand return to prematurely return from a stack frame, thereby short-circuiting its execution.

    Executing thread return 1 did the trick. This returned true (1) to the index out of range issue and then continued the execution to the next line of code.