<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/96401>96401</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [lldb] `finish` doesn't work well with sanitizer coverage and if-else-chains.
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          mvanotti
      </td>
    </tr>
</table>

<pre>
    I'm trying to run the debugger on a program that was compiled with `-fsanitize-coverage=bb,no-prune,trace-pc-guard`, and I want to step-out of all the calls to `__sanitizer_cov_trace_pc_guard`.

I've found that when I attempt to do a `finish` in the `else` case of an `if` with an `else if` clause, lldb gets confused.

See the following example:

```c++
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/random.h>

[[clang::noinline]] void foo(void) {
  uint64_t random_num = 0;
  ssize_t res = getrandom(&random_num, sizeof(random_num), 0);
  assert(res != -1);
 assert(static_cast<size_t>(res) == sizeof(random_num));

  if (random_num == UINT64_MAX) {
    __asm__ volatile("nop");
  } else if (random_num == 0) {
    __asm__ volatile("nop");
  } else if (random_num == 1) {
    __asm__ volatile("nop");
  } else {
 __asm__ volatile("pause");
  }
}

int main(void) {
 foo();
  fprintf(stderr,
          "If we are single-stepping, we should have a stop here on main.\n");
  return 0;
}

extern "C" [[clang::noinline]] void __sanitizer_cov_trace_pc_guard(uint32_t *) {
  // Do (almost) nothing!
  __asm__ volatile("pause");
}

extern "C" void __sanitizer_cov_trace_pc_guard_init(uint32_t *, uint32_t *) {}
```

Compiled with:

```
$ clang++ -Wall -Wextra -pedantic -std=c++17 -gdwarf-5 -O0 -fsanitize-coverage=bb,no-prune,trace-pc-guard    program.cc   -o program
```

Running it under lldb, single stepping, and calling `finish` each time we are in `__sanitizer_cov_trace_pc_guard`:

```
(lldb) target create "./program"
Current executable set to '/home/user/lldb-test/program' (x86_64).
(lldb) breakpoint set --file program.cc --line 21
Breakpoint 1: where = program`foo() + 369 at program.cc:21:5, address = 0x000000000002e631
(lldb) run
Process 3612485 launched: '/home/user/lldb-test/program' (x86_64)
Process 3612485 stopped
* thread #1, name = 'program', stop reason = breakpoint 1.1
    frame #0: 0x0000555555582631 program`foo() at program.cc:21:5
   18     } else if (random_num == 1) {
   19       __asm__ volatile("nop");
   20     } else {
-> 21       __asm__ volatile("pause");
   22     }
   23 }
   24  
(lldb) s
Process 3612485 stopped
* thread #1, name = 'program', stop reason = step in
    frame #0: 0x00005555555824a8 program`__sanitizer_cov_trace_pc_guard((null)=0x0000555555599b50) at program.cc:33:3
   30   }
   31  
   32   extern "C" [[clang::noinline]] void __sanitizer_cov_trace_pc_guard(uint32_t *) {
-> 33     // Do (almost) nothing!
   34     __asm__ volatile("pause");
 35   }
   36  
(lldb) finish
Process 3612485 stopped
* thread #1, name = 'program', stop reason = step out
    frame #0: 0x0000555555582641 program`foo() at program.cc:21:5
   18     } else if (random_num == 1) {
   19       __asm__ volatile("nop");
   20     } else {
-> 21       __asm__ volatile("pause");
   22     }
   23 }
   24  
(lldb) s
Process 3612485 stopped
* thread #1, name = 'program', stop reason = step in
    frame #0: 0x00005555555824a8 program`__sanitizer_cov_trace_pc_guard((null)=0x0000555555599b54) at program.cc:33:3
   30   }
   31  
   32   extern "C" [[clang::noinline]] void __sanitizer_cov_trace_pc_guard(uint32_t *) {
-> 33     // Do (almost) nothing!
   34     __asm__ volatile("pause");
 35   }
   36  
(lldb) finish
If we are single-stepping, we should have a stop here on main.
Process 3612485 exited with status = 0 (0x00000000) 
(lldb) 
```

The outcome is less than ideal: instead of executing until the end of `__sanitizer_cov_trace_pc_guard`, the program executes until the end of the program.

Here is a python script that replicates this behavior (this is how I initially observed the issue):

```python
#!/usr/bin/python3
import lldb
import os

def main():
  debugger = lldb.SBDebugger.Create()
 debugger.SetAsync(False)

  target_prog = './program'
  argv = []
  envp = []

  target = debugger.CreateTargetWithFileAndArch(
 target_prog, lldb.LLDB_ARCH_DEFAULT_64BIT
  )

  assert target.IsValid()

  bp = target.BreakpointCreateByName('main')
 error = lldb.SBError()

  process = target.Launch(
 debugger.GetListener(),
    argv,
    envp,
    None,
 None,
    None,
    os.getcwd(),
    0,  # launch_flags
 False,  # stop_at_entry
    error,
  )

  assert error.Success(), error
  traced_functions = set(['main', 'foo()'])

  while process.GetState() == lldb.eStateStopped:
    assert len(process.threads) == 1
    thread = process.threads[0]
    assert thread.IsValid()
 frames = thread.get_thread_frames()
    assert frames
    frame = frames[0]
    assert frame.IsValid()

    func_name = frame.function.name
    if func_name not in traced_functions:
 print(f'Stepping out of function {func_name}')
 thread.StepOutOfFrame(frame)
      continue
    print(f'Func {func_name:>10} | Location {os.path.basename(str(frame.line_entry.file)):>10}:{frame.line_entry.line:>3} | pc @ {hex(frame.pc)}')

    thread.StepInto()

if __name__ == '__main__':
  main()
```

Output:

```
Func       main | Location program.cc: 25 | pc @ 0x555555582688
Stepping out of function ::__sanitizer_cov_trace_pc_guard(uint32_t *)
Func       main | Location program.cc: 25 | pc @ 0x555555582694
Func       main | Location program.cc: 26 | pc @ 0x55555558269b
Func      foo() | Location program.cc:  8 | pc @ 0x5555555824c8
Stepping out of function ::__sanitizer_cov_trace_pc_guard(uint32_t *)
Func      foo() | Location program.cc:  9 | pc @ 0x5555555824d4
Func      foo() | Location program.cc: 10 | pc @ 0x5555555824dc
Stepping out of function __GI___getrandom
Func      foo() | Location program.cc: 10 | pc @ 0x5555555824ec
Func      foo() | Location program.cc: 11 | pc @ 0x5555555824f0
Stepping out of function ::__sanitizer_cov_trace_pc_guard(uint32_t *)
Func      foo() | Location program.cc: 11 | pc @ 0x55555558250b
Func      foo() | Location program.cc: 12 | pc @ 0x55555558253f
Stepping out of function ::__sanitizer_cov_trace_pc_guard(uint32_t *)
Func      foo() | Location program.cc: 12 | pc @ 0x55555558254f
Stepping out of function ::__sanitizer_cov_trace_pc_guard(uint32_t *)
Func      foo() | Location program.cc: 12 | pc @ 0x55555558256a
Func      foo() | Location program.cc: 14 | pc @ 0x55555558259e
Stepping out of function ::__sanitizer_cov_trace_pc_guard(uint32_t *)
Func      foo() | Location program.cc: 14 | pc @ 0x5555555825ae
Func      foo() | Location program.cc: 16 | pc @ 0x5555555825cf
Stepping out of function ::__sanitizer_cov_trace_pc_guard(uint32_t *)
Func      foo() | Location program.cc: 16 | pc @ 0x5555555825df
Func      foo() | Location program.cc: 18 | pc @ 0x555555582600
Stepping out of function ::__sanitizer_cov_trace_pc_guard(uint32_t *)
Func      foo() | Location program.cc: 18 | pc @ 0x555555582610
Func      foo() | Location program.cc: 21 | pc @ 0x555555582631
Stepping out of function ::__sanitizer_cov_trace_pc_guard(uint32_t *)
Func      foo() | Location program.cc: 21 | pc @ 0x555555582641
Stepping out of function ::__sanitizer_cov_trace_pc_guard(uint32_t *)
```

I haven't tried this with the `lldb` version at trunk yet, will report back once I do.

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsWl9z4jgS_zTKSxeULYOBhzwQGHZTNbdztZm9vTeXsNtYN0ZySTIk--mvWraxSSCTyc1uzVUtlSIgtX7qf-putRHWyp1CvGXTOzZd34jaFdrc7g9CaefkzVZnT7f3jM_24MyTVDtwGkytwBUIGW7r3Q4NaAUCKqN3RuzBFcLBUVhI9b6SJWZwlK4AFgej3AolnfwDR6k-oBE7ZNF6u2V8pfSoMrVCxlfOiBRHVTra1cJkLA4YX4FQGdzDUShHDFiH1UjXDnQOoiw9M6koS0uTLA6SpNvIJKk-JB4yqdKkgxyzYM2CZfNO4h0Qcl2rrOW-QAX3IJzDfeV3zDQIQs6lkrZgcQCy0QGLAywt0kgqLHqOFI3KnMa86M0AkUEzmpaitiQrlGW2hR060pbKa4vZGWsPiH6XXJelPpL68VHsqxJZtBzSkZb8X8r4Hf01ozySKi3rDIFFK2EtGjcuWPTh0rR1mVSvT-vXZku5vT79ZBnfGKEyvR8SNe_keXdpKdSOpIqWSktVSoVsumbTNRy0zCDXmvE5fWR8AWzWSghQS-XiSeKgQU9UvQcWrSFg0YnGWvkHEglaP7dD11AzPmc87leSRYhW54zPh8MLmgnof4_a6JMICZaHhDwKz2hOJNYJJ9MkFdaROjw7pAa_2EsUrWn9tc17zG53mcMZWYfw2_0vn-NJ8o_lv58pCiBJhN0nCRx0KZws0UvPla4Y5-eisdkaWne9vEvwZ4KH3wO8X395cdWcwJfLWzWfPvh3qRzshVQXfbDxzXOgvDJSudybPkNjGF_14jQvxvl9DkcEYRCsVLsSRxTYKql25G5HBFvousygEAcEAdbpCgo0SPGWuBmz6Uq9kMGgq40aHIBnsuCjQ6No-xXjHN50_L4SUPmcjmHEEweML5-Zj_EN4xtYa7K2KPfaOqJQ2hVe0rAjfLuhXpfoDRwnUkn3gu0VXBLjtFcXY4dbr4Y57lpQ7kLiBBo1-xANo98pdY1-x0dnBIwqzIRyMoWRdRmL1m0kD2cw2mVHYfLRFEafAnhPEiV3a9PzOE0BYKS776_I9mutFKUc6aBWGRqfrJoQSc4KQ2el_EwZmOjP0iSKtAAn99h5ulRvytBf0-W8YWYBTpgdOkgNCofkA2PGN51wnLdmqo1B5QAfMa2d2BL36BM74zPGN4XeI-Ob2qJhfEPQI4fkpz3SjNz3cR4n8YTxxfgFH1uD4kulKVIQ9GiUyxKHWh-N6FRB5-93PX3IoiXVHAZ9euq2jINTZAFymChegHADSBYtKe0sp94CWWbQNgkueAz6F8c4Cl-wa2rVjP3T6JTWRXHIJ_MplKJWaYEZ8fRO5VwGpvBVYdZxsgRXGBQZMB6FJIAS-0Z-xmc9sPc3CnwGhdXKEwxUHY7DPq7mxkPwiLynVcK0ec15HIUXNXtFox1oOG-C9TcnrXDRxvm3Jy_gwflmJ7wRiz4AD19FvJzRgPMOsx-Kzr9OAF74h_2zjUjRA6R6o_UmYj6w3lfTEeNzVZelV8X6DGqx2E6DS3aPIno7sRMFz5QWhZ2W6Asp9a9NpN4FoqgtHd6YUiGafKvHRNPngscX3KMN8H-Fj-javfWIT_4-4n8fcX_EJ38f8e95xP_ni8pFT8NH6br2EN2Q67Z6IZH7Esar6Dlzr5StnwukmJHqPYK0UNKOrhAKZIaiJMeTyjryaJ23BSFVrbVysukkofJTb6pS-cov6XpfDRzal2gDqrMOz8-kJmlBQPXkCq3ApkZWrulDGaxKmQoCdIW0sMVCHKQ2pCA_IC0U-gj3QPcZKcryCfTWojlg5neU1tbobX-5mm72PLVsyK2o0KM6b0u33U1D0J4Zua-0cc01YDig7RA8w7y7Kw93hr5dSEYmkPHD3bodG698_d6uaRZ09OMHdEv7pFLG5xtRWjyRdMjNHSAh_XaR6ewWMDv1bMzu0FD4dmc3jOpQvRg-B_fT2Tm3n_3M79IVG1niUmVLkxYkQrNywFXX6ht__Li-S5a_rn5O1h82y98-fk7iyd395_6u_EyypoPUQo3v7b9EKbOhljrCbSNAS9hfLhpO755-EftGu7PGNrNez2iMPjPKBxq4tEnVHuDBTh_9daEX-qSin9B9lNahwg5q2AIhQ5wNkAnOBn7R_iLbDpx_ezENANqOd-jSY3ZhN39OKe-0t5skL8WudVpoXaoloNiVCJegcuZpwF6jktXXDOXpxg91Sno6cdIu7xyKokiW5LVKndSqUadFR-TTu6GFVuTJfXuJz8g5n-98LNqLJm1Jan9wp5PUlS7esOgnHtr03p_LE_Ml0qHtkJq0P-xODq5aXU3QXFfP6Kd3weBo9S7spy-5cFMWtF7VUNG5aT4mzeQZfQ_aTj4vMKJ1N3OFGT_72nECIPMk6gxu3JlsTOM9qcwH1Eo7_2zgmZF7ffvOIOPznPHZQ5tGoX2Y0ZFTTXCCpEw9PK-tjmjtp9p9yjemOdt583-gJYBUKydVPWB2uP2mVun5VlTVfAgDKk_ZbAUfdSo6frQdV8IV462wqJodrTPdvmMqg5pTM859-bFoo3-LRx9ndy9offXkqaJu0yoFNgloywIfT_hVSnjnqnjuj14n98rplyaVOSRexCTp3JnxWZLQWUsSAu0PxCB7XS8zPtWuqt3rbSqv3-ZFmOcqPStNgU-HsgeP_aVm3obW677iS9FvLTu_I4eLybeDxVfBts_BBl2w64AwvwI4Sf8a_b2Ny8U1LrMXOnwTYBhcBUy_InaS_HSfJEn_MOz77o_p-wDDa4B58OPY8SqX0-B97hvya4BR_gOJfZXLyf8Fl7F4H-DkGuACfyCxr3Ip8H2A12L0NP2RrH2Vyyx_H-C1TBIHP1IEuspl-KL4eBMgvxbSTk-PfgSxr3M5-TO5vFgB3vt-F93UHDgjfctF2qad1f40yLdK4gAOaCzxIIiyVl_gia57KzjKsgSDvouyFekX0CpFuIdMt02im-w2yhbRQtzgbTgLF8Esivnkprid8Vhs54s5otiGIp1MMyHyHIN4Gi-m-RZv5C0P-CSIOQ9jPgsm48U042kaRlOxyMIgmLNJgHshy3FZHvZjbXY3vlt0u4gnQXhTii2W1v8sjHOFx66VxNl0fWNuac1oW-8smwSltM72KE660v-ezAs_XZ8_D8402kZlR22-wBHLsm0AdmaB7rG2f6gs8xGWFkdpIaSy45valLeFc5W_UPke6U66ot6OU733TycP3b9RZfR_MHWMbzzvlvFNI9vhlv83AAD__2HfV50">