[asan] Fix x86 asm instrumentation to preserve flags.
This change also enables asm instrumentation in asan tests that was accidentally disabled yearlier, and adds a sanity test for that. Patch by Yuri Gorshenin. llvm-svn: 209282
This commit is contained in:
		
							parent
							
								
									b9aa538db1
								
							
						
					
					
						commit
						687933f55d
					
				| 
						 | 
				
			
			@ -324,7 +324,7 @@ __sanitizer_sanitize_load16:
 | 
			
		|||
.globl __sanitizer_sanitize_store1
 | 
			
		||||
.type __sanitizer_sanitize_store1, @function
 | 
			
		||||
__sanitizer_sanitize_store1:
 | 
			
		||||
  subq $128, %rsp
 | 
			
		||||
  leaq -128(%rsp), %rsp
 | 
			
		||||
  pushq %rax
 | 
			
		||||
  pushq %rcx
 | 
			
		||||
  pushfq
 | 
			
		||||
| 
						 | 
				
			
			@ -347,14 +347,14 @@ __sanitizer_sanitize_store1:
 | 
			
		|||
  popfq
 | 
			
		||||
  popq %rcx
 | 
			
		||||
  popq %rax
 | 
			
		||||
  addq $128, %rsp
 | 
			
		||||
  leaq 128(%rsp), %rsp
 | 
			
		||||
  ret
 | 
			
		||||
// Sanitize 1-byte load. Takes one 8-byte address as an argument in %rdi,
 | 
			
		||||
// nothing is returned.
 | 
			
		||||
.globl __sanitizer_sanitize_load1
 | 
			
		||||
.type __sanitizer_sanitize_load1, @function
 | 
			
		||||
__sanitizer_sanitize_load1:
 | 
			
		||||
  subq $128, %rsp
 | 
			
		||||
  leaq -128(%rsp), %rsp
 | 
			
		||||
  pushq %rax
 | 
			
		||||
  pushq %rcx
 | 
			
		||||
  pushfq
 | 
			
		||||
| 
						 | 
				
			
			@ -377,14 +377,14 @@ __sanitizer_sanitize_load1:
 | 
			
		|||
  popfq
 | 
			
		||||
  popq %rcx
 | 
			
		||||
  popq %rax
 | 
			
		||||
  addq $128, %rsp
 | 
			
		||||
  leaq 128(%rsp), %rsp
 | 
			
		||||
  ret
 | 
			
		||||
// Sanitize 2-byte store. Takes one 8-byte address as an argument in %rdi,
 | 
			
		||||
// nothing is returned.
 | 
			
		||||
.globl __sanitizer_sanitize_store2
 | 
			
		||||
.type __sanitizer_sanitize_store2, @function
 | 
			
		||||
__sanitizer_sanitize_store2:
 | 
			
		||||
  subq $128, %rsp
 | 
			
		||||
  leaq -128(%rsp), %rsp
 | 
			
		||||
  pushq %rax
 | 
			
		||||
  pushq %rcx
 | 
			
		||||
  pushfq
 | 
			
		||||
| 
						 | 
				
			
			@ -408,14 +408,14 @@ __sanitizer_sanitize_store2:
 | 
			
		|||
  popfq
 | 
			
		||||
  popq %rcx
 | 
			
		||||
  popq %rax
 | 
			
		||||
  addq $128, %rsp
 | 
			
		||||
  leaq 128(%rsp), %rsp
 | 
			
		||||
  ret
 | 
			
		||||
// Sanitize 2-byte load. Takes one 8-byte address as an argument in %rdi,
 | 
			
		||||
// nothing is returned.
 | 
			
		||||
.globl __sanitizer_sanitize_load2
 | 
			
		||||
.type __sanitizer_sanitize_load2, @function
 | 
			
		||||
__sanitizer_sanitize_load2:
 | 
			
		||||
  subq $128, %rsp
 | 
			
		||||
  leaq -128(%rsp), %rsp
 | 
			
		||||
  pushq %rax
 | 
			
		||||
  pushq %rcx
 | 
			
		||||
  pushfq
 | 
			
		||||
| 
						 | 
				
			
			@ -439,14 +439,14 @@ __sanitizer_sanitize_load2:
 | 
			
		|||
  popfq
 | 
			
		||||
  popq %rcx
 | 
			
		||||
  popq %rax
 | 
			
		||||
  addq $128, %rsp
 | 
			
		||||
  leaq 128(%rsp), %rsp
 | 
			
		||||
  ret
 | 
			
		||||
// Sanitize 4-byte store. Takes one 8-byte address as an argument in %rdi,
 | 
			
		||||
// nothing is returned.
 | 
			
		||||
.globl __sanitizer_sanitize_store4
 | 
			
		||||
.type __sanitizer_sanitize_store4, @function
 | 
			
		||||
__sanitizer_sanitize_store4:
 | 
			
		||||
  subq $128, %rsp
 | 
			
		||||
  leaq -128(%rsp), %rsp
 | 
			
		||||
  pushq %rax
 | 
			
		||||
  pushq %rcx
 | 
			
		||||
  pushfq
 | 
			
		||||
| 
						 | 
				
			
			@ -470,14 +470,14 @@ __sanitizer_sanitize_store4:
 | 
			
		|||
  popfq
 | 
			
		||||
  popq %rcx
 | 
			
		||||
  popq %rax
 | 
			
		||||
  addq $128, %rsp
 | 
			
		||||
  leaq 128(%rsp), %rsp
 | 
			
		||||
  ret
 | 
			
		||||
// Sanitize 4-byte load. Takes one 8-byte address as an argument in %rdi,
 | 
			
		||||
// nothing is returned.
 | 
			
		||||
.globl __sanitizer_sanitize_load4
 | 
			
		||||
.type __sanitizer_sanitize_load4, @function
 | 
			
		||||
__sanitizer_sanitize_load4:
 | 
			
		||||
  subq $128, %rsp
 | 
			
		||||
  leaq -128(%rsp), %rsp
 | 
			
		||||
  pushq %rax
 | 
			
		||||
  pushq %rcx
 | 
			
		||||
  pushfq
 | 
			
		||||
| 
						 | 
				
			
			@ -501,14 +501,14 @@ __sanitizer_sanitize_load4:
 | 
			
		|||
  popfq
 | 
			
		||||
  popq %rcx
 | 
			
		||||
  popq %rax
 | 
			
		||||
  addq $128, %rsp
 | 
			
		||||
  leaq 128(%rsp), %rsp
 | 
			
		||||
  ret
 | 
			
		||||
// Sanitize 8-byte store. Takes one 8-byte address as an argument in %rdi,
 | 
			
		||||
// nothing is returned.
 | 
			
		||||
.globl __sanitizer_sanitize_store8
 | 
			
		||||
.type __sanitizer_sanitize_store8, @function
 | 
			
		||||
__sanitizer_sanitize_store8:
 | 
			
		||||
  subq $128, %rsp
 | 
			
		||||
  leaq -128(%rsp), %rsp
 | 
			
		||||
  pushq %rax
 | 
			
		||||
  pushfq
 | 
			
		||||
  movq %rdi, %rax
 | 
			
		||||
| 
						 | 
				
			
			@ -523,14 +523,14 @@ __sanitizer_sanitize_store8:
 | 
			
		|||
.sanitize_store8_done:
 | 
			
		||||
  popfq
 | 
			
		||||
  popq %rax
 | 
			
		||||
  addq $128, %rsp
 | 
			
		||||
  leaq 128(%rsp), %rsp
 | 
			
		||||
  ret
 | 
			
		||||
// Sanitize 8-byte load. Takes one 8-byte address as an argument in %rdi,
 | 
			
		||||
// nothing is returned.
 | 
			
		||||
.globl __sanitizer_sanitize_load8
 | 
			
		||||
.type __sanitizer_sanitize_load8, @function
 | 
			
		||||
__sanitizer_sanitize_load8:
 | 
			
		||||
  subq $128, %rsp
 | 
			
		||||
  leaq -128(%rsp), %rsp
 | 
			
		||||
  pushq %rax
 | 
			
		||||
  pushfq
 | 
			
		||||
  movq %rdi, %rax
 | 
			
		||||
| 
						 | 
				
			
			@ -545,14 +545,14 @@ __sanitizer_sanitize_load8:
 | 
			
		|||
.sanitize_load8_done:
 | 
			
		||||
  popfq
 | 
			
		||||
  popq %rax
 | 
			
		||||
  addq $128, %rsp
 | 
			
		||||
  leaq 128(%rsp), %rsp
 | 
			
		||||
  ret
 | 
			
		||||
// Sanitize 16-byte store. Takes one 8-byte address as an argument in %rdi,
 | 
			
		||||
// nothing is returned.
 | 
			
		||||
.globl __sanitizer_sanitize_store16
 | 
			
		||||
.type __sanitizer_sanitize_store16, @function
 | 
			
		||||
__sanitizer_sanitize_store16:
 | 
			
		||||
  subq $128, %rsp
 | 
			
		||||
  leaq -128(%rsp), %rsp
 | 
			
		||||
  pushq %rax
 | 
			
		||||
  pushfq
 | 
			
		||||
  movq %rdi, %rax
 | 
			
		||||
| 
						 | 
				
			
			@ -567,14 +567,14 @@ __sanitizer_sanitize_store16:
 | 
			
		|||
.sanitize_store16_done:
 | 
			
		||||
  popfq
 | 
			
		||||
  popq %rax
 | 
			
		||||
  addq $128, %rsp
 | 
			
		||||
  leaq 128(%rsp), %rsp
 | 
			
		||||
  ret
 | 
			
		||||
// Sanitize 16-byte load. Takes one 8-byte address as an argument in %rdi,
 | 
			
		||||
// nothing is returned.
 | 
			
		||||
.globl __sanitizer_sanitize_load16
 | 
			
		||||
.type __sanitizer_sanitize_load16, @function
 | 
			
		||||
__sanitizer_sanitize_load16:
 | 
			
		||||
  subq $128, %rsp
 | 
			
		||||
  leaq -128(%rsp), %rsp
 | 
			
		||||
  pushq %rax
 | 
			
		||||
  pushfq
 | 
			
		||||
  movq %rdi, %rax
 | 
			
		||||
| 
						 | 
				
			
			@ -589,7 +589,7 @@ __sanitizer_sanitize_load16:
 | 
			
		|||
.sanitize_load16_done:
 | 
			
		||||
  popfq
 | 
			
		||||
  popq %rax
 | 
			
		||||
  addq $128, %rsp
 | 
			
		||||
  leaq 128(%rsp), %rsp
 | 
			
		||||
  ret
 | 
			
		||||
#endif // defined(__x86_64__)
 | 
			
		||||
/* We do not need executable stack. */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -181,7 +181,7 @@ cat <<EOF
 | 
			
		|||
.globl $(func_name $at $as)
 | 
			
		||||
.type $(func_name $at $as), @function
 | 
			
		||||
$(func_name $at $as):
 | 
			
		||||
  subq \$128, %rsp
 | 
			
		||||
  leaq -128(%rsp), %rsp
 | 
			
		||||
  pushq %rax
 | 
			
		||||
  pushq %rcx
 | 
			
		||||
  pushfq
 | 
			
		||||
| 
						 | 
				
			
			@ -211,7 +211,7 @@ $(func_label $at $as):
 | 
			
		|||
  popfq
 | 
			
		||||
  popq %rcx
 | 
			
		||||
  popq %rax
 | 
			
		||||
  addq \$128, %rsp
 | 
			
		||||
  leaq 128(%rsp), %rsp
 | 
			
		||||
  ret
 | 
			
		||||
EOF
 | 
			
		||||
  done
 | 
			
		||||
| 
						 | 
				
			
			@ -228,7 +228,7 @@ cat <<EOF
 | 
			
		|||
.globl $(func_name $at $as)
 | 
			
		||||
.type $(func_name $at $as), @function
 | 
			
		||||
$(func_name $at $as):
 | 
			
		||||
  subq \$128, %rsp
 | 
			
		||||
  leaq -128(%rsp), %rsp
 | 
			
		||||
  pushq %rax
 | 
			
		||||
  pushfq
 | 
			
		||||
  movq %rdi, %rax
 | 
			
		||||
| 
						 | 
				
			
			@ -248,7 +248,7 @@ $(emit_call_report $at $as)
 | 
			
		|||
$(func_label $at $as):
 | 
			
		||||
  popfq
 | 
			
		||||
  popq %rax
 | 
			
		||||
  addq \$128, %rsp
 | 
			
		||||
  leaq 128(%rsp), %rsp
 | 
			
		||||
  ret
 | 
			
		||||
EOF
 | 
			
		||||
  done
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -60,6 +60,7 @@ set(ASAN_UNITTEST_INSTRUMENTED_CFLAGS
 | 
			
		|||
  ${ASAN_UNITTEST_COMMON_CFLAGS}
 | 
			
		||||
  -fsanitize=address
 | 
			
		||||
  "-fsanitize-blacklist=${ASAN_BLACKLIST_FILE}"
 | 
			
		||||
  -mllvm -asan-instrument-assembly
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
if(NOT MSVC)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -197,8 +197,25 @@ template<> void TestAsmRead<__m128i>(const char *DeathPattern) {
 | 
			
		|||
  delete [] buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
U4 AsmLoad(U4 *a) {
 | 
			
		||||
  U4 r;
 | 
			
		||||
  __asm__("movl (%[a]), %[r]  \n\t" : [r] "=r" (r) : [a] "r" (a) : "memory");
 | 
			
		||||
  return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AsmStore(U4 r, U4 *a) {
 | 
			
		||||
  __asm__("movl %[r], (%[a])  \n\t" : : [a] "r" (a), [r] "r" (r) : "memory");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // End of anonymous namespace
 | 
			
		||||
 | 
			
		||||
TEST(AddressSanitizer, asm_load_store) {
 | 
			
		||||
  U4* buf = new U4[2];
 | 
			
		||||
  EXPECT_DEATH(AsmLoad(&buf[3]), "READ of size 4");
 | 
			
		||||
  EXPECT_DEATH(AsmStore(0x1234, &buf[3]), "WRITE of size 4");
 | 
			
		||||
  delete [] buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(AddressSanitizer, asm_rw) {
 | 
			
		||||
  TestAsmWrite<U1>("WRITE of size 1");
 | 
			
		||||
  TestAsmWrite<U2>("WRITE of size 2");
 | 
			
		||||
| 
						 | 
				
			
			@ -213,6 +230,31 @@ TEST(AddressSanitizer, asm_rw) {
 | 
			
		|||
  TestAsmRead<__m128i>("READ of size 16");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(AddressSanitizer, asm_flags) {
 | 
			
		||||
  long magic = 0x1234;
 | 
			
		||||
  long r = 0x0;
 | 
			
		||||
 | 
			
		||||
#if defined(__x86_64__)
 | 
			
		||||
  __asm__("xorq %%rax, %%rax  \n\t"
 | 
			
		||||
          "movq (%[p]), %%rax \n\t"
 | 
			
		||||
          "sete %%al          \n\t"
 | 
			
		||||
          "movzbq %%al, %[r]  \n\t"
 | 
			
		||||
          : [r] "=r"(r)
 | 
			
		||||
          : [p] "r"(&magic)
 | 
			
		||||
          : "rax", "memory");
 | 
			
		||||
#else
 | 
			
		||||
  __asm__("xorl %%eax, %%eax  \n\t"
 | 
			
		||||
          "movl (%[p]), %%eax \n\t"
 | 
			
		||||
          "sete %%al          \n\t"
 | 
			
		||||
          "movzbl %%al, %[r]  \n\t"
 | 
			
		||||
          : [r] "=r"(r)
 | 
			
		||||
          : [p] "r"(&magic)
 | 
			
		||||
          : "eax", "memory");
 | 
			
		||||
#endif // defined(__x86_64__)
 | 
			
		||||
 | 
			
		||||
  ASSERT_EQ(0x1, r);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // defined(__x86_64__) || (defined(__i386__) && defined(__SSE2__))
 | 
			
		||||
 | 
			
		||||
#endif // defined(__linux__)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue