<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/54873>54873</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
-fsanitize-coverage produces incorrect debug info at function entry points
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
khuey
</td>
</tr>
</table>
<pre>
Consider the following function:
```c
int square(int i) {
return i * i;
}
```
Compiling with
```
Debian clang version 15.0.0-++20220411071831+e995526e661f-1~exp1~20220411071915.217
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/local/bin
```
The assembly looks like:
```asm
0000000000001130 <square>:
1130: 55 push %rbp
1131: 48 89 e5 mov %rsp,%rbp
1134: 89 7d fc mov %edi,-0x4(%rbp)
1137: 8b 45 fc mov -0x4(%rbp),%eax
113a: 0f af 45 fc imul -0x4(%rbp),%eax
113e: 5d pop %rbp
113f: c3 retq
```
The DWARF output from `dwarfdump -i` is:
```
<snip>
< 1><0x00000023> DW_TAG_subprogram
DW_AT_low_pc (indirect address, index 0x0): 0x00001130
DW_AT_high_pc <offset-from-lowpc>16
DW_AT_frame_base len 0x0001: 56: DW_OP_reg6
DW_AT_name (indirect string, index 0x3): square
DW_AT_decl_file 0x00000000
DW_AT_decl_line 0x00000001
DW_AT_prototyped yes
DW_AT_type 0x00000064<.debug_info+0x00000064>
DW_AT_external yes
< 2><0x00000032> DW_TAG_formal_parameter
DW_AT_location len 0x0002: 917c: DW_OP_fbreg -4
DW_AT_name (indirect string, index 0x6): i
DW_AT_decl_file 0x00000000
DW_AT_decl_line 0x00000001
DW_AT_type 0x00000064<.debug_info+0x00000064>
<snip>
```
And from `dwarfdump -l`
```
.debug_line: line number info for a single cu
Source lines (from CU-DIE at .debug_info offset 0x0000000c):
NS new statement, BB new basic block, ET end of text sequence
PE prologue end, EB epilogue begin
IS=val ISA number, DI=val discriminator value
<pc> [lno,col] NS BB ET PE EB IS= DI= uri: "filepath"
0x00001130 [ 1, 0] NS uri: "/build/coverage-test.c"
0x00001137 [ 2,10] NS PE
<snip>
```
Note that the debug_info declares the parameter is on the stack at -0x4(%rbp), not in the register specified in the ABI (this is normal for debug builds). The debug_line section specifies the prologue end is at 0x1137 (the PE marker) so that's where a debugger will place a breakpoint at function entry. Because that's after the value of %edi at function entry has been moved into the stack slot, everything will work as expected.
Now add `-fsanitize-coverage=trace-pc-guard` to the compiler arguments:
The assembly looks like:
```asm
000000000002d8c0 <square>:
2d8c0: 55 push %rbp
2d8c1: 48 89 e5 mov %rsp,%rbp
2d8c4: 48 83 ec 10 sub $0x10,%rsp
2d8c8: 89 7d f8 mov %edi,-0x8(%rbp)
2d8cb: 48 8d 3d be 72 01 00 lea 0x172be(%rip),%rdi # 44b90 <__TMC_END__>
2d8d2: e8 19 02 ff ff callq 1daf0 <__sanitizer_cov_trace_pc_guard>
2d8d7: 8b 7d f8 mov -0x8(%rbp),%edi
2d8da: 89 7d fc mov %edi,-0x4(%rbp)
2d8dd: 8b 45 fc mov -0x4(%rbp),%eax
2d8e0: 0f af 45 fc imul -0x4(%rbp),%eax
2d8e4: 48 83 c4 10 add $0x10,%rsp
2d8e8: 5d pop %rbp
2d8e9: c3 retq
2d8ea: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
```
Note that the compiler has inserted a call to __sanitizer_cov_trace_pc_guard, and a second stack slot for the original value of %edi at -0x8(%rbp).
The DWARF output from `dwarfdump -i` is:
```
<snip>
< 1><0x0000002b> DW_TAG_subprogram
DW_AT_low_pc (indirect address, index 0x0): 0x0002d8c0
DW_AT_high_pc <offset-from-lowpc>42
DW_AT_frame_base len 0x0001: 56: DW_OP_reg6
DW_AT_name (indirect string, index 0x3): square
DW_AT_decl_file 0x00000000
DW_AT_decl_line 0x00000001
DW_AT_prototyped yes
DW_AT_type 0x0000006c<.debug_info+0x0000006c>
DW_AT_external yes
< 2><0x0000003a> DW_TAG_formal_parameter
DW_AT_location len 0x0002: 917c: DW_OP_fbreg -4
DW_AT_name (indirect string, index 0x6): i
DW_AT_decl_file 0x00000000
DW_AT_decl_line 0x00000001
DW_AT_type 0x0000006c<.debug_info+0x0000006c>
<snip>
```
i.e. essentially unchanged, note that the DWARF still claims the variable lives at -0x4(%rbp).
The output from `dwarfdump -l`, however, is:
```
.debug_line: line number info for a single cu
Source lines (from CU-DIE at .debug_info offset 0x0000000c):
NS new statement, BB new basic block, ET end of text sequence
PE prologue end, EB epilogue begin
IS=val ISA number, DI=val discriminator value
<pc> [lno,col] NS BB ET PE EB IS= DI= uri: "filepath"
0x0002d8c0 [ 1, 0] NS uri: "/build/coverage-test.c"
0x0002d8cb [ 1, 0] NS PE
0x0002d8dd [ 2,10] NS
<snip>
```
The prologue end marker is now placed at 0x2d8cb, which is after the value of %rdi has been moved to the newly added stack slot -0x8(%rbp). But the DWARF still claims that value of `i` is in -0x4(%rbp), which is not initialized until 0x2d8dd. So a debugger will break at 0x2d8cb, read the value of `i` from -0x4(%rbp), and get a garbage value because that slot is not yet initialized.
This affects displaying the values of variables on function entry, including setting conditional breakpoints on them
(This issue was originally reported to me by @hsivonen in a Rust binary produced by cargo-fuzz.)
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJztWV1z4jgW_TXkRQXlL74eeAiQbOVhe7sm2ZpHSrZl0MZYbskOoX_9nivbYPORpHuyMztVTVEhWNLR1b1HV_eIUMX72UJlRsZCs2IjWKLSVO1ktmZJmUWFVFnPv-05y57T_B051TuqvsusYOZbybXoeRP6InvelPXG86qZ4aVFUeqMSdbzbtHs10298fIEsj3PQm1zmZIhO1lsLlpQfV2KUPKMRSlH3xehDWxm7nDgDJx-z5vj7Tme5wSu64zdie_igZhOh0NvJEYjN-m7vfGdeM3po9VxCgTPHVdTPHG9FgUcwV4no9Uo6OdRH6aVr_11VtZdNlrwmG1VLFLqmCsjX6umh8wUPE1FvJSamnrefWk0_qYq4ik-Q5m94YgnRIUbI7ZhumepUs-GpfJZXAsLN9vqidN6ua7vsJ6_qAPl3x1GU3yolQyrXsMhu_jKS7PBR88b6jDvDHaPg4MJm0yZOIPYqhdWDzZ5z1tcQAmOKIAYxyyJrqOIGDRb9J3XAKyrwbxpB2_cwgtZMLyOdwZj7RP8tYPHj3hOwnhyAVJuy_TDeKLl8viKy1XeeO3EWclxcORfHoxd940Gv82s5e-3v90zVRZ5WbBEqy1Dp3jHdRKX25z1Jb4yaY5sOwECpzKZE6Oa78y1_Fo4rxX3PB_fyaDl76un23-sTBnmWq013x5XdP5C59unFVLRKj8Lm000sdQiKhiPYy2MgYsZnolXhmnJ5XBPZYAl97sTbeR6cz4TVqGSxIiiT57pw5o8wmLc0fuACdYnViE3ot2Wiqwyy26Z4Yj-ov-_vq60WH8ANQPoeVvbH6bQyJltd_i1O-q9_-4csYjSVSLT7kRNNJ0PONMiID9eQXDfRwBBClXsc9HZGHth3h9Ko87bmslHyDKLQSzCcr2SWaJwGLSb7t7HF6-F0BlPu20H02gDeN0N4Hv1BjhsgUTpLU9XOSeSAO6tWY9bIeJ0HHfbDoTyKMRTdxwdKZWEIBXrBx9B_xlijWpiyY9M8EdY9Rm8-kx6XEl9l1LsbRZfyqrpsVt3VD03LZJcaxebldsQ1RnZg_JMM84MIgFPRnXt8ahKHQnb2VDM7ISLf_eXD3eMF6y1Hlals6PPoiqGbZPbfvnyyDKxQ-x5IbYiKyj887l9htQmIxaCls_09O6JCaxVJazADmFGfCtFFl1IN1_vGHZ3qtaloBF27JwJ1Hr2USjWTTXUHvXw2POXL9h1D4-3tUNo5PKhfhxLE2m5lRkv4CE8KcUhSjZnN0C94TzNENdFpNLecEkrxIJgPeyCHXaeCpaVWlblmke8zTmqUM-ra6vD0WIRgeuSOU6NeBxJ1V0pUyzzPlIoTvla9AthikF0jjVusDBq4TZYX-9-gG5fVCFQxiPoVMu34k5bB9nf2OeHvIODnSGj0DOEOHomtlwoXlimUNZX_ZBSpKGhJheRTCQydN1yO38g8hUbgOKd2RxnCWvtYNYPOKinA_Z0MM4S3AgrNA6QtZUtlhAgJ9paN9lZBEVsy_UzMWHKjLLr7nljw3YboVEzV1OsYetOpinLUx7RU2RF_pwrkiqAbFQOZin0fsDmIuKlEUcwnhS1NLKsIoZX9ef5aLbhBgRGSkZhaR1TqJZzTarsBhLgwR5ustIGhu2UhucNgwiBI0Q86EZ0RzUO5Y9-YngmC_ld9BsugaaFxrJIkKxxvMdUrdWTRlZAwXaIl5I2rznZ6J8gLLx4El0XFrb1Z4UFDf7jwoJQgi6Kz0TEXKeDgpq0QglAMaeGMV2YyZk-mVw35qBPJhf1CeGFXbNi5scgDxt7zHGZY-1LBacP2DT2QlEjyaOk0GBhk9c8nwVBOLXRWK2e_rlY3X1Zrlbtmgazxt5xVjFh7pQ5HksSeh9eEKUplIMb86RGa3inVyDeyjIOxfKqYtzJBF3Z9ZabzrxTyaRYdvD4J8pCwos_URYCTzifKAsJ74ytUXDKVsoH7G22isnPqksaPP1BdVkPa4VqNCJvuPBGQFx2mgVkKt8xVok06wmsvrLf_uMeovXhQ-6Q5ij5yswIjRSKNE8splT4DnuRj3lG_XEIKfxzTNX26KIZlJaoSXCWXTgATjk8OE2wf4K-Dv9KfV3l-M_V14H3S1-_i_B_qq-j6wIq-l_pa_5LX_9d9PWH6PGO1JEDMWDISShpJZL8nqEI3_BsLeJaq7ROhyr9moLqbCgguTV1Ka8lD1PSzC_CXJI9Z4n8egq3Yh4zb9SOSnsbwqsJ_ZfA__sI_ErdfI7AtxX_RaxG4DfdqLg7vwf4gUuAp1PxXKnkSpTvKh0cV3K60iEwZreR0caq7Ityl4TGibitVSaYgh2IKkF0aqezuojNyzd2JIw5Tjdy6qKIbhYuXUccjK3uJSSlAdR3MRIBYKtlxfGAPaqzSwAr_k_Wbn-46664NsHus0sWUMm4xjbjbM11iJjXY8PW7UHliNrKvehYepJdrN8TnAKGeI4A7ely4GCSIZualGVvbLr3DtWhEaVlTMOw_Qv6pHJWUieetu48mgufbafM9iZP1bWNwSJ2CHRT8yK2WuTK1tSIOA6xcM96gbMx8kVlIANCxNlvpSlYiP56T8yLSyIYOkZcr1U_Kb9_H8BxN_HMj6f-lN8UskjF7MJ9RjOaQh8pbQ_G6vbIJrfzG5dqTTelTmebosht2vXu8V7LYlOGA6gD-qE1fWk--pjhP4DFV7taVLb3w2Ay9m82Mz7FAT8c8cQLEt-NIiF8340hvf0g5kMe3KQ8FKmZYXdic1OOtBC00YfLGzmrfz723Ik7dIaDyWg4DJwJ504SxqFw4Tax5TIdkB0Dpdc3emZNwvoMGlNpCnNs5MbIdSaEnQ74vCw2Ss-eN6XY39iJZ9bw_wJK1o0i">