<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/125770>125770</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Differences in LLDB and GDB Behavior When Stepping Into Inline Functions Twice
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
edumoot
</td>
</tr>
</table>
<pre>
We found that:
- When debugging a binary compiled with -O3, -O2, or -O1, GDB only steps into the first instance of an inline function, while LLDB steps in twice.
- Additionally, GDB halts at line 25 and LLDB at line 26, even though neither line appears in the debug line table.
Steps to Reproduce:
1. Compile and debug the binary in LLVM 19.1.7 context.
```
$clang -g -O3 6.c -o 6_O3.out
$lldb
(lldb) file 6_O3.out
(lldb) b main
(lldb) r
* thread #1, name = '6_O3.out', stop reason = breakpoint 1.1
frame #0: 0x0000555555555130 6_O3.out`main [inlined] compute_result at 6.c:19:16
16 int32_t secondary_var = -9L;
17
18 global_counter = local_values[7];
-> 19 temp_var = global_array[1] % 0xFCL;
20 secondary_var &= (temp_var | (++global_value));
21 return global_union;
22 }
(lldb) s
* thread #1, name = '6_O3.out', stop reason = step in
frame #0: 0x0000555555555136 6_O3.out`main at 6.c:26:19
23
24 int main(void) {
25 int result0 = compute_result().f0;
-> 26 int result1 = compute_result().f1;
27 global_union.f0++;
28 return result0 == result1;
29 }
(lldb) s
* thread #1, name = '6_O3.out', stop reason = step in
frame #0: 0x0000555555555136 6_O3.out`main [inlined] compute_result at 6.c:19:16
16 int32_t secondary_var = -9L;
17
18 global_counter = local_values[7];
-> 19 temp_var = global_array[1] % 0xFCL;
20 secondary_var &= (temp_var | (++global_value));
21 return global_union;
22 }
(lldb) s
* thread #1, name = '6_O3.out', stop reason = step in
frame #0: 0x000055555555513c 6_O3.out`main [inlined] compute_result at 6.c:20:35
17
18 global_counter = local_values[7];
19 temp_var = global_array[1] % 0xFCL;
-> 20 secondary_var &= (temp_var | (++global_value));
21 return global_union;
22 }
23
(lldb) s
* thread #1, name = '6_O3.out', stop reason = step in
frame #0: 0x0000555555555136 6_O3.out`main at 6.c:26:19
23
24 int main(void) {
25 int result0 = compute_result().f0;
-> 26 int result1 = compute_result().f1;
27 global_union.f0++;
28 return result0 == result1;
29 }
```
2. Debug the binary using GDB 15.
```
$ gdb
GNU gdb (Ubuntu 15.0.50.20240403-0ubuntu1) 15.0.50.20240403-git
Copyright (C) 2024 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
(gdb) file 6_O3.out
(gdb) b main
(gdb) r
[...]
Breakpoint 1, main () at 6.c:25
25 int result0 = compute_result().f0;
(gdb) s
compute_result () at 6.c:19
19 temp_var = global_array[1] % 0xFCL;
(gdb) s
compute_result () at 6.c:20
20 secondary_var &= (temp_var | (++global_value));
(gdb) s
main () at 6.c:27
27 global_union.f0++;
(gdb) s
28 return result0 == result1;
```
3. cat 6.c
```
File: 6.c
01: #include <stdint.h>
02:
03: union U1 {
04: int8_t f0;
05: const int8_t f1;
06: };
07:
08: static uint16_t global_counter = 1UL;
09: static volatile uint32_t global_array[10] = {0UL};
10: static uint32_t global_value = 4294967286UL;
11: static union U1 global_union = {-2L};
12:
13: static union U1 compute_result(void) {
14: int8_t local_values[8] = {0xA0L};
15: int32_t temp_var = 0x5BF2D3F5L;
16: int32_t secondary_var = -9L;
17:
18: global_counter = local_values[7];
19: temp_var = global_array[1] % 0xFCL;
20: secondary_var &= (temp_var | (++global_value));
21: return global_union;
22: }
23:
24: int main(void) {
25: int result0 = compute_result().f0;
26: int result1 = compute_result().f1;
27: global_union.f0++;
28: return result0 == result1;
29: }
30:
```
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzUWN1u2zoSfhr6ZmCBpP4vfGHHx0UB7_Zgu9lzGdASLXGXJg2JcpK3Xwwl2YqdtmnaYrtBIFMi54cz3ww_SbStqoyUCxKvSLyeic7VtlnIsjtY62Y7Wz4v_pKwt50pwdXCkXAJhC7n8FctDZRy11WVMhUI2Ckjmmco7OGotCzhUbka5p9Cwu9g_onjj21g_onh6MN6BdboZ2idPLagjLPgagl71bQOlGmdMIUEuwdhQBmtjIR9ZwqnrEH5x1ppCdvtenXWAO5RFTLovVuWpcK1Quvn0V4ttGtBOPDaeAzClL2K87ME18qTNOBq21U1GKlcLZt-WhyPUjS9rVr2m-9nnNhpGRC6JHT52fvjLPxDHhtbdoUk4bKfAgBgAdz1IfL2eyWoboifMrDd_utvwPKABSkU1jj55AbdJKHDP10SHhVamArmFYYZkqCAuYXk4VMY2M4NAjzSutz5UeZHPIc9Gp-uu0zt4CCUefms8bdLcHUjRQmEhz6FRhwkkHANhKdnZTzFqdbZIzRStNb4FbtGiv8crTIOWMCGQOwbr4CHFDFFnyilNB7_WEgvHiYUnQISr3oklCRee5x1Tj40su20wxQmQUHCJcvxkvRGWAJAaI7mlHEhf3DQysKaUjTPDyfReO_m-ZaEq0Eg9QLDTXaWrrTdCf1Q2M442YtpWwj9cBK6ky2JVymJ172aOQn_AJb3sk4ejmdLgxbRNOKZxCuG-yA8Bvq0uUMfUAQNc3o2fOUuT_qIZxe96R3eE74ifDUY8E4RnuP_uDPOzjob6brGjN50BmvqvIz7_afrlxhoRzj9CAywUsGj61vJT26Sf84vRgCT3HsbTtLFIxwjyDyGeXayqkTnSTpuLp7CAXroUO_bSzj5gObBnk4yypNbWfYVWXaJaXqNIx9zVO-zNizk2XWGJg6incHmRW-PsV-erG8X622-_i-LFeDd9fq_K9ffBALFOyHAUV0Y_7yMouSP5LMv9t8jo-cW97uV99va8Vv78bua8S_uxvCj_fiKrY0EkAewvuZ8XYsUGjkqi4NbmgeVZ3Af_n6PIwTb_a4zrsPVNIhpwCmPaETDOe38BMMo30xWCsnenT0-N6qqHeq5w4W4ADaNlPDZ7t2jaCRskO-LkWx_NAV6tVWFNK2ED39uT6EP1BLQpw9_buEkm1ZZAyFyfC36Ir2rnTsi-eUbwjeV6QLbVIRvdK-oxYdHHdTuoEn4x4jqrPoiS61uSWo14ajxKggC7AN0uZowTtxC35A8FibYxa6Dl-9nBBfLWI1Xve3aji8PvLyzI32XMY6gwUv-k1rXS-uvBzJFm-m3q-qlLp69vbxuyykMoBg8eDm3URpfuYYZyvwrKw-VKXRXYn-8a12pjAvqHnWUDy-1NMSB9xvu2dCmaIQPB4BkDw5GCNB4nCis8S-t_fTgME281nQ4lWg6Gslw0DrhVAGdMo4lD-61A47dD0yH5hOJk9XCYWV0I0e6hhD1GMJMpyt6vz17wOiV4am0z7qXinge5UnKs2S0z9hUcIzONMujuTmfmBujysLXxG-qa3I4eKnrsF-d99l0l09LOhj2ovFE1G_yRcnRp3i14etwE4_7S67Xf4V2sjGPLBulvoeceMIL72sDninBz-MknI36vshHOB9BTJc8HHbOfWq-eK7zafjf3lF5civ2hgOdp1dpeK3t8Oxqp1_rNDy_7LnnQ1ftZ1YuwjIPczGTC5aGWUrTMItn9aIsZB6X-zINyzwvmMgjtktlFGY0CnkUJTO14JTHlNOIc5bwOChKWkRpFMVpmfJstyMRlQehdKD16YCn5Uy1bScXjMdpSmda7KRu_bc6zo18BD9LOCfxetYsUGi-66qWRFSr1rUXNU45LRdrtd_LRppCtv13pvXKf4RC5rGStTgp2_Qf9j47eTwiKflonIWP_Qe4zfABroV_PqpCzrpGL_CIby9nvHJ1twsKe8BjXp_Gn_mxsf-WhSN8413Go3_Y02nB_xsAAP__lyzEQw">