1 | // XFAIL:* |
2 | //// Suboptimal coverage, see description below. |
3 | |
4 | // REQUIRES: lldb |
5 | // UNSUPPORTED: system-windows |
6 | // RUN: %clang -std=gnu11 -O3 -glldb %s -o %t |
7 | // RUN: %dexter --fail-lt 1.0 -w --debugger lldb --binary %t -- %s |
8 | |
9 | //// Adapted from https://bugs.llvm.org/show_bug.cgi?id=34136#c1 |
10 | //// LowerDbgDeclare has since been updated to look through bitcasts. We still |
11 | //// get suboptimal coverage at the beginning of 'main' though. For each local, |
12 | //// LowerDbgDeclare inserts a dbg.value and a dbg.value+DW_OP_deref before the |
13 | //// store (after the call to 'getint') and the call to 'alias' respectively. |
14 | //// The first dbg.value describes the result of the 'getint' call, eventually |
15 | //// becoming a register location. The second points back into the stack |
16 | //// home. There is a gap in the coverage between the quickly clobbered register |
17 | //// location and the stack location, even though the stack location is valid |
18 | //// during that gap. For x86 we end up with this code at the start of main: |
19 | //// 00000000004004b0 <main>: |
20 | //// 4004b0: sub rsp,0x18 |
21 | //// 4004b4: mov edi,0x5 |
22 | //// 4004b9: call 400480 <getint> |
23 | //// 4004be: mov DWORD PTR [rsp+0x14],eax |
24 | //// 4004c2: mov edi,0x5 |
25 | //// 4004c7: call 400480 <getint> |
26 | //// 4004cc: mov DWORD PTR [rsp+0x10],eax |
27 | //// 4004d0: mov edi,0x5 |
28 | //// 4004d5: call 400480 <getint> |
29 | //// 4004da: mov DWORD PTR [rsp+0xc],eax |
30 | //// ... |
31 | //// With these variable locations: |
32 | //// DW_TAG_variable |
33 | //// DW_AT_location (0x00000000: |
34 | //// [0x00000000004004be, 0x00000000004004cc): DW_OP_reg0 RAX |
35 | //// [0x00000000004004de, 0x0000000000400503): DW_OP_breg7 RSP+20) |
36 | //// DW_AT_name ("x") |
37 | //// ... |
38 | //// DW_TAG_variable |
39 | //// DW_AT_location (0x00000037: |
40 | //// [0x00000000004004cc, 0x00000000004004da): DW_OP_reg0 RAX |
41 | //// [0x00000000004004e8, 0x0000000000400503): DW_OP_breg7 RSP+16) |
42 | //// DW_AT_name ("y") |
43 | //// ... |
44 | //// DW_TAG_variable |
45 | //// DW_AT_location (0x0000006e: |
46 | //// [0x00000000004004da, 0x00000000004004e8): DW_OP_reg0 RAX |
47 | //// [0x00000000004004f2, 0x0000000000400503): DW_OP_breg7 RSP+12) |
48 | //// DW_AT_name ("z") |
49 | //// ... |
50 | |
51 | char g = 1; |
52 | int five = 5; |
53 | __attribute__((__noinline__)) |
54 | int getint(int x) { |
55 | g = x - 4; |
56 | return x * g; |
57 | } |
58 | |
59 | __attribute__((__noinline__)) |
60 | void alias(char* c) { |
61 | g = *c; |
62 | *c = (char)five; |
63 | } |
64 | |
65 | int main() { |
66 | int x = getint(x: 5); |
67 | int y = getint(x: 5); // DexLabel('s1') |
68 | int z = getint(x: 5); // DexLabel('s2') |
69 | alias(c: (char*)&x); // DexLabel('s3') |
70 | alias(c: (char*)&y); |
71 | alias(c: (char*)&z); |
72 | return 0; // DexLabel('s4') |
73 | } |
74 | |
75 | // DexExpectWatchValue('x', '5', from_line=ref('s1'), to_line=ref('s4')) |
76 | // DexExpectWatchValue('y', '5', from_line=ref('s2'), to_line=ref('s4')) |
77 | // DexExpectWatchValue('z', '5', from_line=ref('s3'), to_line=ref('s4')) |
78 | |