<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/60807>60807</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[clang] wrong address/line mapping in debug info
</td>
</tr>
<tr>
<th>Labels</th>
<td>
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
dirk-raincode
</td>
</tr>
</table>
<pre>
I have the following C program that shows a problem in the mapping of addresses to their corresponding line number in the debug info produced by clang/llc.
The observable behavior is that in both lldb and gdb, the `next` command jumps back to a previous line even though it should go to the next C instruction.
```C
#include <stdint.h>
struct frame {
int8_t values[100]; // must be a byte type
};
struct locdesc {
int64_t value; // can be any type, but field must be present
int64_t *pointer; // types does not seem to matter, as long as its a pointer
};
static __thread int64_t *global_locdesc; // must be __thread
int main(void){
_Alignas(8) struct frame cast; // use _Alignas(8) to get rid of warning "cast from 'int8_t *' (aka 'signed char *') to 'int64_t *' (aka 'long *') increases required alignment from 1 to 8 [-Wcast-align]"
int64_t stuff;
int32_t thing; // type does not matter
((struct locdesc*)&cast.values[80])->pointer = &stuff;
thing = 2; // must be in between the other instructions
global_locdesc = ((int64_t*)&cast.values[88]);
return thing;
}
```
compiled with
```
$ make
clang -g -O0 -Weverything -pedantic -o main main.c
llvm-dwarfdump -a main > main.dwarf
```
And the corresponding debug session in lldb. We can see it is jumping back from line 21 to line 19, no variable used on these two lines have anything in common:
```
$ make debug.lldb
(lldb) command source cmds.dbg
Executing commands in '/home/dirk/tls2/cmds.dbg'.
(lldb) b main.c:19
Breakpoint 1: where = main`main + 15 at main.c:19:48, address = 0x000000000000113f
(lldb) r
Process 3257704 stopped
* thread #1, name = 'main', stop reason = breakpoint 1.1
frame #0: 0x000055555555513f main`main at main.c:19:48
16 int64_t stuff;
17 int32_t thing; // type does not matter
18
-> 19 ((struct locdesc*)&cast.values[80])->pointer = &stuff;
20
21 thing = 2; // must be in between the other instructions
22 global_locdesc = ((int64_t*)&cast.values[88]);
Process 3257704 launched: '/home/dirk/tls2/main' (x86_64)
(lldb) n
Process 3257704 stopped
* thread #1, name = 'main', stop reason = step over
frame #0: 0x0000555555555143 main`main at main.c:21:9
18
19 ((struct locdesc*)&cast.values[80])->pointer = &stuff;
20
-> 21 thing = 2; // must be in between the other instructions
22 global_locdesc = ((int64_t*)&cast.values[88]);
23
24 return thing;
(lldb) n
Process 3257704 stopped
* thread #1, name = 'main', stop reason = step over
frame #0: 0x000055555555514a main`main at main.c:19:40
16 int64_t stuff;
17 int32_t thing; // type does not matter
18
-> 19 ((struct locdesc*)&cast.values[80])->pointer = &stuff;
20
21 thing = 2; // must be in between the other instructions
22 global_locdesc = ((int64_t*)&cast.values[88]);
(lldb) n
Process 3257704 stopped
* thread #1, name = 'main', stop reason = step over
frame #0: 0x000055555555514e main`main at main.c:22:18
19 ((struct locdesc*)&cast.values[80])->pointer = &stuff;
20
21 thing = 2; // must be in between the other instructions
-> 22 global_locdesc = ((int64_t*)&cast.values[88]);
23
24 return thing;
25 }
(lldb)
```
and here's the gdb session for the record:
```
```
Both the .asm and dwarf dump show the problem:
```asm
.loc 0 19 48 prologue_end # main.c:19:48
movq %rax, -16(%rbp)
.loc 0 21 9 # main.c:21:9
movl $2, -116(%rbp)
.loc 0 19 40 # main.c:19:40
leaq -16(%rbp), %rax
.loc 0 22 18 # main.c:22:18
movq %rax, %fs:global_locdesc@TPOFF
.loc 0 24 10 # main.c:24:10
movl -116(%rbp), %eax
.loc 0 24 3 is_stmt 0 # main.c:24:3
```
```
Address Line Column File ISA Discriminator Flags
------------------ ------ ------ ------ --- ------------- -------------
0x0000000000001130 14 0 0 0 0 is_stmt
0x000000000000113f 19 48 0 0 0 is_stmt prologue_end
0x0000000000001143 21 9 0 0 0 is_stmt
0x000000000000114a 19 40 0 0 0 is_stmt
0x000000000000114e 22 18 0 0 0 is_stmt
0x0000000000001157 24 10 0 0 0 is_stmt
0x000000000000115a 24 3 0 0 0
0x000000000000115c 24 3 0 0 0 end_sequence
```
I can also see the problem when editing the llvm ir generated by clang to remove the `optnone` from the main function, and optionally remove the `thread_local` attribute on the global variable. See other.ll in the attached zip file.
Running on Linux with version 15.0.7 of llvm/clang
```
[dirk@leonard tls2]$ clang --version
clang version 15.0.7 (https://github.com/llvm/llvm-project.git 8dfdcc7b7bf66834a761bd8de445840ef68e4d1a)
Target: x86_64-unknown-linux-gnu
Thread model: posix
```
[reproducer.zip](https://github.com/llvm/llvm-project/files/10754548/reproducer.zip)
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzMWV2P26jX_zTMzVEiG9uJczEX89JIlR5pV89W6uUIm2ObHQwu4MzMfvq_ADuT13a7aruL2kliOL_zwuF3ADNrRasQb0lxT4rHGza6TptbLszzwjChas3xptL87fYjdGyH4DqERkupX4Rq4QEGo1vDenAdc2A7_WKB-YeVxB6ECuN7Ngx-tG6AcW7QWrTgtO8TBmptDNpBK-7HSKEQ1NhXaGZxjtXYglCN9sB8rJFD9Qa1ZKoldCtlvSTJI0nuPnUIurJodqySCBV2bCe0AWGjeUJBpV0HUvIKmOLQ8orQh6CErBKFr46sEqh13_veP8d-sFCx-tkb673CndCjjTbiDr15emw7EMH1UXJo9eQYeDR4AKGsM2PthFaTldPfVRL_PUy_aSZULUeOQLIH67hQbtmR7EPsBgCI3yIcNIb1CGR9P_cL5conBzsmR7SkuE-ThBSPJLsHQreEbqEfrYMKgUH15hDc24CT6rUfNuEcKZG65mjrEzWrfNZzgF4zFcDVW0SmD1CNDhqBku9VDwYtKneKRejdoIVyaA4APYoFrtGC0g4sYu9D2zPnx9EHYBakVq3_FC5k3YRx7tRB8JgTNTw9uc4g44cWtFJXTD5NLl-I2yx0OItCOeiZUISWOy04oZuDUD3dSdEqZgktS0I3cDRzNbPuQMlo8Wy809CiAyO4XzkvzCi_QAilXhYao3sgdD3NO6F3hK6B0JI9M_88rGsOdcfM1DlhRpnZ7WOhEND30ULVBplfrQa_jMIgB-Zt7FFNBqQesQRS3C8-e7MWod8nHqWn02zd2DQHkyKUy-iTA9cJ1Z7M_PvETxN-EHTwBhNaHidpsHpD6MqbsdwvgzKsArpZkOzDlCBAskcgdHVsz4wdrAlD6IUk8BSC7gUxUpN2XeCp_Rq3E8xxNk0avdFTMK5ZW0ZrL6QugEE3GrUP13ueHxNK_FnrfhASObwI18HFIYTm0LPniQUCncKihcVvCSw-4w7NW4zFYkDOlF83Cx2yPfxZ1lFOyl2_4C_MNHzsB1iwOIRkH-Kw0HVZf_h7p3gI5XEZiJxv0VqhlY-65-wlfMZANBbRc66wgaP9-MDSISMDOdOQl-FruvFkoTTsmBGhLowWOegwgRbBvcSBNtY3piavhQqFQCuSnVL2cfiirUtv4NxRhh90sy8lVo-mRqh7bpe8auO4D69Yj87rmoZZrzQsvW2neyR06-swoVsnLSV0uxen6-WZqmqelewu3cTee4PsOSQ9pCS7g5cODYZcDJy1SuJM0XtIC2DuCCC7y8vAsrFgB6nkNTloaZo1Z1ZMC_V3o2svldFivU5ysE4PA87USe9g4l9CszRMTyhmYZGsI5-u_WMvBp6BtAq91YFDy_R9hUzFkGaJdzOaWcwtzZojfy85OiOlKw93lbEgXc_938lcXnZS45kI0k0A-hlEBgA0ef-aBkU_htUAKA1wP4reTvNEslHVHXI_jV9ZCFOKeJ2v5epplXvM01RUPzUVrcMB9O5gfr-RhXl2NQupX52bs0TxX39JmoSM_G8nikfM3r_mAfxyQfzvZgD7Bg_Nq_bnsdAv46CfxUA_OK3-tWT5Rqbgda6gPl1-NUP84GmMhPNvMYTvLuB947zPga_sUv0mzu-e_MEquNbyar89bbQJzwzW2vCr-8VLuPfadUF2yWwf7iTCfhnCXtp2-iV0Tvcp78jHgMz27xzk21Lq2n8mPj3y0stL3Y74hIrDQSM0u74XCq3Xuy9xZGHYq8_sRboK81OYatjH7FwxTWFzjH9S5WZ4GeFzGsEvoh_7k8C1dsGf5FihRPblzAX6MPt3zRkKafn3tJ6uzytRJLRoLMlObx3y5NPvv223Z27THNK_6TbNvQHJhTifBTfagV_xO4cMhH2yrndwpv9cbfaVTD95eDedKw7a__njGsCDlmOvYCuk__Xxjzt4FLY2oheKOW1gK1k788hZg2sfcGnY1CLY2ekmOpxGJpndT8L_BOawXJFtomwk57y8LHu0Li8D5VmQnMgXNt9jRM6OjDhy4LAl34DBaEKk67T8hzBF3LRMxJz-U2sKdggD2VFArojU10WONaPiTxa_jKhq_EoqfwyXEExaHW4iDhjaH7EVIBfhWO87pNz1IAy0qNAwd3B1DU6DwV5Pl-pklejBKa2QrJJ4lRHvzoWCZlShfIYDueKgB_-LSfl2ghA3J55OmPQwzDkjqtHhdN8xVdv9XcgS_sCpTC-lnC_cmXPMn8LgLzFAIyQe3Vz__6jCRaRWfsWOr_GGaYcm1MK0WCbLNegmeE7oNl7TXwxmcR-OdXkiUStmOITjnS_r-RSixWLCPbyjOlFFaNk5N3g2jbuRVrhurJa17sPbgd38sRiM_hNrt2yFg5I3vK7X1bpqVqsyy9l6lVa85JjnRZkn2KxKzHnK9kXoEzMtOr9bi0fOxaielX5RC-mDsGjVOI2L-8Nec5R-9KCteL3mv8HpjYZZ_iWG4Pp3OkPo1s-QJXSbJusiL_KS0O0J7uzDDb_N-CbbsBu8TVfrVZGnRb6-6W43VcFonWQN5ol3vGSbFUvXSYI02dAyvRG3NKFZQtNVsik2yXqZY02rYkOLrMkTXq1JnmDPhFx645batDfC2hFvV0mZrG8kq1Da-SWTuQ0eVGNr_eQL6-y7mBNOhtdRMXGKR3gx4Zo_Fgzvvq8T8zsloQ7eD92MRt5-d_yCoR442Pq_AAAA__-SqaE4">