<html>
<head>
<base href="https://bugs.llvm.org/">
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW - -fsanitize-coverage=trace-cmp passes parameters incorrectly"
href="https://bugs.llvm.org/show_bug.cgi?id=33732">33732</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>-fsanitize-coverage=trace-cmp passes parameters incorrectly
</td>
</tr>
<tr>
<th>Product</th>
<td>clang
</td>
</tr>
<tr>
<th>Version</th>
<td>trunk
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>Linux
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>enhancement
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>-New Bugs
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedclangbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>glider@google.com
</td>
</tr>
<tr>
<th>CC</th>
<td>dvyukov@google.com, kcc@google.com, llvm-bugs@lists.llvm.org
</td>
</tr></table>
<p>
<div>
<pre>Consider the following program:
==========dummy.ii================
char *_copy_from_user(void *to, const void *from, unsigned n);
long dev_write(struct file *filep, const char *buffer) {
char s[16];
_copy_from_user(s, buffer, 1);
if (s[0] == 's')
return 1;
return 0;
}
==================================
When compiled as follows:
$ clang -O2 -fsanitize-coverage=trace-pc -fsanitize-coverage=trace-cmp -x c
dummy.ii -c -o dummy.o -w
it produces the following assembly:
$ objdump -dr dummy.o
dummy.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <dev_write>:
0: 53 push %rbx
1: 48 83 ec 10 sub $0x10,%rsp
5: 48 89 f3 mov %rsi,%rbx
8: e8 00 00 00 00 callq d <dev_write+0xd>
9: R_X86_64_PC32 __sanitizer_cov_trace_pc-0x4
d: 48 89 e7 mov %rsp,%rdi
10: ba 01 00 00 00 mov $0x1,%edx
15: 48 89 de mov %rbx,%rsi
18: e8 00 00 00 00 callq 1d <dev_write+0x1d>
19: R_X86_64_PC32 _copy_from_user-0x4
1d: 8b 1c 24 mov (%rsp),%ebx
20: be 73 00 00 00 mov $0x73,%esi
25: 89 df mov %ebx,%edi
27: e8 00 00 00 00 callq 2c <dev_write+0x2c>
28: R_X86_64_PC32 __sanitizer_cov_trace_cmp1-0x4
2c: 31 c0 xor %eax,%eax
2e: 80 fb 73 cmp $0x73,%bl
31: 0f 94 c0 sete %al
34: 48 83 c4 10 add $0x10,%rsp
38: 5b pop %rbx
39: c3 retq
Note that the first parameter to __sanitizer_cov_trace_cmp1() is a 4-byte value
taken directly from the stack, despite __sanitizer_cov_trace_cmp1() expects a
1-byte value.
This looks like a violation of the x86_64 ABI, which mandates that byte-sized
arguments are extended (in this case zero-extended) to the full register.
If I change the s[] size to, say, 1, Clang generates correct code:
d: 48 8d 7c 24 0f lea 0xf(%rsp),%rdi
12: ba 01 00 00 00 mov $0x1,%edx
17: 48 89 de mov %rbx,%rsi
1a: e8 00 00 00 00 callq 1f <dev_write+0x1f>
1b: R_X86_64_PC32 _copy_from_user-0x4
1f: 0f b6 5c 24 0f movzbl 0xf(%rsp),%ebx
24: be 73 00 00 00 mov $0x73,%esi
29: 89 df mov %ebx,%edi
2b: e8 00 00 00 00 callq 30 <dev_write+0x30>
2c: R_X86_64_PC32 __sanitizer_cov_trace_cmp1-0x4</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>