[Bug gdb/34416] New: Incorrect loss of sign in 64-bit multiply (e.g.: DW_OP_mul in DWARF evaluation)

wmessmer at microsoft dot com via Gdb-prs <[email protected]>
Newsgroups gmane.comp.gdb.bugs.discuss
Message-ID <[email protected]/bugzilla/>
https://sourceware.org/bugzilla/show_bug.cgi?id=34416

            Bug ID: 34416
           Summary: Incorrect loss of sign in 64-bit multiply (e.g.:
                    DW_OP_mul in DWARF evaluation)
           Product: gdb
           Version: HEAD
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: gdb
          Assignee: unassigned at sourceware dot org
          Reporter: wmessmer at microsoft dot com
  Target Milestone: ---

Created attachment 16853
  --> https://sourceware.org/bugzilla/attachment.cgi?id=16853&action=edit
Zip of repro binary / core dump / test source

I was debugging some copilot generated test code intended utilize/fill APX
registers on the HEAD of GDB (with the APX support patch set) to compare
against WinDbg's handling of APX on Linux.  In any case, GDB and WinDbg were
showing different values for some of the local variables in the test. 
Unfortunately, copilot had generated code where the test core dump was
collected after the APX registers were reused and all of the variables ended up
as long DWARF expressions.

In tracking this down via observation & copilot, it would appear that GDB is
mishandling DW_OP_mul with signed values where the result of the multiplication
spills over 64-bits.

You can see this in the EE of GDB directly:

(gdb) print (long long)0x2000000000000001 * (long long)-8
$1 = 8

For the more problematic version (the variable), please see the attached
binary/source/core dump:


(gdb) break apx_leaf
Breakpoint 1 at 0x1060: file main.cpp, line 81.
(gdb) run
Starting program: /home/wmessmer/test/APX_WSL/apx_test
Breakpoint 1, apx_leaf (a=a@entry=15529827852863206509,
b=b@entry=17326333736759811083, c=c@entry=9017087056300321936,
    d=d@entry=9975881037687807339) at main.cpp:81
81          uint64_t v00 = mix64(a, 0x716F6F7200000000ULL);
(gdb) disassem apx_leaf
Dump of assembler code for function apx_leaf(uint64_t, uint64_t, uint64_t,
uint64_t):

...

   0x0000555555555571 <+1297>:  mov    %rax,%r22
   0x0000555555555575 <+1301>:  ror    $0x13,%r22
   0x000055555555557a <+1306>:  xor    %r22,%r21
   0x000055555555557e <+1310>:  add    %r21,%rdx

...

(gdb) break *0x000055555555557a
Breakpoint 2 at 0x55555555557a: file main.cpp, line 118.
(gdb) cont
Continuing.

Breakpoint 2, 0x000055555555557a in apx_leaf (a=a@entry=15529827852863206509,
b=b@entry=17326333736759811083,
    c=c@entry=9017087056300321936, d=d@entry=9975881037687807339) at
main.cpp:118
118         uint64_t w07 = rotr64(tag, 19) ^ v07;
(gdb) print v07
$1 = 16568925713597422312
(gdb) set output-radix 16
Output radix now set to decimal 16, hex 10, octal 20.
(gdb) print v07
$2 = 0xe5f0a6268ccf5ae8
(gdb) info address v07
Symbol "v07" is multi-location:
  Base address 0x1284  Range 0x555555555284-0x55555555557e: a variable in $
  Range 0x55555555557e-0x55555555563d: a complex DWARF expression:
     0: DW_OP_entry_value
       2: DW_OP_reg4 [$rsi]
     3: DW_OP_plus_uconst 8173874384117694471
    13: DW_OP_entry_value
      15: DW_OP_reg4 [$rsi]
    16: DW_OP_plus_uconst 8173874384117694471
    26: DW_OP_lit17
    27: DW_OP_shr
    28: DW_OP_xor
    29: DW_OP_consts -49064778989728563
    39: DW_OP_mul
    40: DW_OP_entry_value
      42: DW_OP_reg4 [$rsi]
    43: DW_OP_plus_uconst 8173874384117694471
    53: DW_OP_entry_value
      55: DW_OP_reg4 [$rsi]
    56: DW_OP_plus_uconst 8173874384117694471
    66: DW_OP_lit17
    67: DW_OP_shr
    68: DW_OP_xor
    69: DW_OP_consts -49064778989728563
    79: DW_OP_mul
    80: DW_OP_lit31
    81: DW_OP_shr
    82: DW_OP_xor
    83: DW_OP_consts -4265267296055464877
    93: DW_OP_mul
    94: DW_OP_entry_value
      96: DW_OP_reg4 [$rsi]
    97: DW_OP_plus_uconst 8173874384117694471
   107: DW_OP_entry_value
     109: DW_OP_reg4 [$rsi]
   110: DW_OP_plus_uconst 8173874384117694471
   120: DW_OP_lit17
   121: DW_OP_shr
   122: DW_OP_xor
   123: DW_OP_consts -49064778989728563
   133: DW_OP_mul
   134: DW_OP_entry_value
     136: DW_OP_reg4 [$rsi]
   137: DW_OP_plus_uconst 8173874384117694471
   147: DW_OP_entry_value
     149: DW_OP_reg4 [$rsi]
   150: DW_OP_plus_uconst 8173874384117694471
   160: DW_OP_lit17
   161: DW_OP_shr
   162: DW_OP_xor
   163: DW_OP_consts -49064778989728563
   173: DW_OP_mul
   174: DW_OP_lit31
   175: DW_OP_shr
   176: DW_OP_xor
   177: DW_OP_consts -4265267296055464877
   187: DW_OP_mul
   188: DW_OP_const1u 32
   190: DW_OP_shr
   191: DW_OP_xor
   192: DW_OP_stack_value

.
(gdb) ni
0x000055555555557e      137                                    w05 + w06 + w07
+ w08 + w09 +
(gdb) print v07
$3 = 0x3cf688b6bf336197

At the point where the two loclist locations for v07 diverge (from a simple r21
to a way more complex DWARF expression), you'll note that GDB is printing two
very different values for v07's value:

0xe5f0a6268ccf5ae8 (in r21)
0x3cf688b6bf336197 (the result of DWARF evaluation)

The value hasn't changed....  if you look at the operations in the complex
DWARF expression GCC emitted here, you'll note that the same problem as that
print is occuring.  The signed DW_OP_mul is ending up as a * |b| and not (a *
b) because of this.

The attached ZIP should contain source / binary / core dump for the copilot
generated test which was erroneous for what I wanted but repro'd this
particular problem.  The variable DIE in question is 0x11ac in apx_test.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.