| 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 | |