forked from OSchip/llvm-project
[ASan] Introduce the dump_instruction_bytes flag to print the faulting instruction upon SIGSEGV
When dump_instruction_bytes=1 and the instruction pointer doesn't point to the zero page, ASan prints 16 bytes starting at the instruction point. llvm-svn: 218243
This commit is contained in:
parent
6da8a243f9
commit
1aba330e52
|
@ -65,6 +65,7 @@ struct Flags {
|
|||
int detect_invalid_pointer_pairs;
|
||||
bool detect_container_overflow;
|
||||
int detect_odr_violation;
|
||||
bool dump_instruction_bytes;
|
||||
};
|
||||
|
||||
extern Flags asan_flags_dont_use_directly;
|
||||
|
|
|
@ -86,15 +86,24 @@ class Decorator: public __sanitizer::SanitizerCommonDecorator {
|
|||
}
|
||||
}
|
||||
const char *EndShadowByte() { return Default(); }
|
||||
const char *MemoryByte() { return Magenta(); }
|
||||
const char *EndMemoryByte() { return Default(); }
|
||||
};
|
||||
|
||||
// ---------------------- Helper functions ----------------------- {{{1
|
||||
|
||||
static void PrintShadowByte(InternalScopedString *str, const char *before,
|
||||
u8 byte, const char *after = "\n") {
|
||||
static void PrintMemoryByte(InternalScopedString *str, const char *before,
|
||||
u8 byte, bool in_shadow, const char *after = "\n") {
|
||||
Decorator d;
|
||||
str->append("%s%s%x%x%s%s", before, d.ShadowByte(byte), byte >> 4, byte & 15,
|
||||
d.EndShadowByte(), after);
|
||||
str->append("%s%s%x%x%s%s", before,
|
||||
in_shadow ? d.ShadowByte(byte) : d.MemoryByte(),
|
||||
byte >> 4, byte & 15,
|
||||
in_shadow ? d.EndShadowByte() : d.EndMemoryByte(), after);
|
||||
}
|
||||
|
||||
static void PrintShadowByte(InternalScopedString *str, const char *before,
|
||||
u8 byte, const char *after = "\n") {
|
||||
PrintMemoryByte(str, before, byte, /*in_shadow*/true, after);
|
||||
}
|
||||
|
||||
static void PrintShadowBytes(InternalScopedString *str, const char *before,
|
||||
|
@ -149,6 +158,22 @@ static void PrintLegend(InternalScopedString *str) {
|
|||
PrintShadowByte(str, " ASan internal: ", kAsanInternalHeapMagic);
|
||||
}
|
||||
|
||||
void MaybeDumpInstructionBytes(uptr pc) {
|
||||
if (!flags()->dump_instruction_bytes || (pc < GetPageSizeCached()))
|
||||
return;
|
||||
InternalScopedString str(1024);
|
||||
str.append("First 16 instruction bytes at pc: ");
|
||||
if (IsAccessibleMemoryRange(pc, 16)) {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
PrintMemoryByte(&str, "", ((u8 *)pc)[i], /*in_shadow*/false, " ");
|
||||
}
|
||||
str.append("\n");
|
||||
} else {
|
||||
str.append("unaccessible\n");
|
||||
}
|
||||
Report("%s", str.data());
|
||||
}
|
||||
|
||||
static void PrintShadowMemoryForAddress(uptr addr) {
|
||||
if (!AddrIsInMem(addr)) return;
|
||||
uptr shadow_addr = MemToShadow(addr);
|
||||
|
@ -636,6 +661,7 @@ void ReportSIGSEGV(const char *description, uptr pc, uptr sp, uptr bp,
|
|||
Printf("%s", d.EndWarning());
|
||||
GET_STACK_TRACE_SIGNAL(pc, bp, context);
|
||||
stack.Print();
|
||||
MaybeDumpInstructionBytes(pc);
|
||||
Printf("AddressSanitizer can not provide additional info.\n");
|
||||
ReportErrorSummary("SEGV", &stack);
|
||||
}
|
||||
|
|
|
@ -230,6 +230,9 @@ static void ParseFlagsFromString(Flags *f, const char *str) {
|
|||
"If >=2, detect violation of One-Definition-Rule (ODR); "
|
||||
"If ==1, detect ODR-violation only if the two variables "
|
||||
"have different sizes");
|
||||
|
||||
ParseFlag(str, &f->dump_instruction_bytes, "dump_instruction_bytes",
|
||||
"If true, dump 16 bytes starting at the instruction that caused SEGV");
|
||||
}
|
||||
|
||||
void InitializeFlags(Flags *f, const char *env) {
|
||||
|
@ -283,6 +286,7 @@ void InitializeFlags(Flags *f, const char *env) {
|
|||
f->detect_invalid_pointer_pairs = 0;
|
||||
f->detect_container_overflow = true;
|
||||
f->detect_odr_violation = 2;
|
||||
f->dump_instruction_bytes = false;
|
||||
|
||||
// Override from compile definition.
|
||||
ParseFlagsFromString(f, MaybeUseAsanDefaultOptionsCompileDefinition());
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
// Check that ASan prints the faulting instruction bytes on
|
||||
// dump_instruction_bytes=1
|
||||
// RUN: %clangxx_asan %s -o %t
|
||||
// RUN: env ASAN_OPTIONS=dump_instruction_bytes=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-DUMP
|
||||
// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NODUMP
|
||||
|
||||
int main() {
|
||||
#if defined(__x86_64__)
|
||||
asm("movq $0, %rax");
|
||||
asm("movl $0xcafebabe, 0x0(%rax)");
|
||||
#elif defined(i386)
|
||||
asm("movl $0, %eax");
|
||||
asm("movl $0xcafebabe, 0x0(%eax)");
|
||||
#endif
|
||||
// CHECK-DUMP: First 16 instruction bytes at pc: c7 00 be ba fe ca
|
||||
// CHECK-NODUMP-NOT: First 16 instruction bytes
|
||||
return 0;
|
||||
}
|
||||
|
||||
// XFAIL: arm
|
Loading…
Reference in New Issue