1//===-- asan_debugging.cc -------------------------------------------------===// 2// 3// This file is distributed under the University of Illinois Open Source 4// License. See LICENSE.TXT for details. 5// 6//===----------------------------------------------------------------------===// 7// 8// This file is a part of AddressSanitizer, an address sanity checker. 9// 10// This file contains various functions that are generally useful to call when 11// using a debugger (LLDB, GDB). 12//===----------------------------------------------------------------------===// 13 14#include "asan_allocator.h" 15#include "asan_flags.h" 16#include "asan_internal.h" 17#include "asan_mapping.h" 18#include "asan_report.h" 19#include "asan_thread.h" 20 21namespace __asan { 22 23void GetInfoForStackVar(uptr addr, AddressDescription *descr, AsanThread *t) { 24 descr->name[0] = 0; 25 descr->region_address = 0; 26 descr->region_size = 0; 27 descr->region_kind = "stack"; 28 29 AsanThread::StackFrameAccess access; 30 if (!t->GetStackFrameAccessByAddr(addr, &access)) 31 return; 32 InternalMmapVector<StackVarDescr> vars(16); 33 if (!ParseFrameDescription(access.frame_descr, &vars)) { 34 return; 35 } 36 37 for (uptr i = 0; i < vars.size(); i++) { 38 if (access.offset <= vars[i].beg + vars[i].size) { 39 internal_strncat(descr->name, vars[i].name_pos, 40 Min(descr->name_size, vars[i].name_len)); 41 descr->region_address = addr - (access.offset - vars[i].beg); 42 descr->region_size = vars[i].size; 43 return; 44 } 45 } 46} 47 48void GetInfoForHeapAddress(uptr addr, AddressDescription *descr) { 49 AsanChunkView chunk = FindHeapChunkByAddress(addr); 50 51 descr->name[0] = 0; 52 descr->region_address = 0; 53 descr->region_size = 0; 54 55 if (!chunk.IsValid()) { 56 descr->region_kind = "heap-invalid"; 57 return; 58 } 59 60 descr->region_address = chunk.Beg(); 61 descr->region_size = chunk.UsedSize(); 62 descr->region_kind = "heap"; 63} 64 65void AsanLocateAddress(uptr addr, AddressDescription *descr) { 66 if (DescribeAddressIfShadow(addr, descr, /* print */ false)) { 67 return; 68 } 69 if (GetInfoForAddressIfGlobal(addr, descr)) { 70 return; 71 } 72 asanThreadRegistry().Lock(); 73 AsanThread *thread = FindThreadByStackAddress(addr); 74 asanThreadRegistry().Unlock(); 75 if (thread) { 76 GetInfoForStackVar(addr, descr, thread); 77 return; 78 } 79 GetInfoForHeapAddress(addr, descr); 80} 81 82uptr AsanGetStack(uptr addr, uptr *trace, uptr size, u32 *thread_id, 83 bool alloc_stack) { 84 AsanChunkView chunk = FindHeapChunkByAddress(addr); 85 if (!chunk.IsValid()) return 0; 86 87 StackTrace stack(nullptr, 0); 88 if (alloc_stack) { 89 if (chunk.AllocTid() == kInvalidTid) return 0; 90 stack = chunk.GetAllocStack(); 91 if (thread_id) *thread_id = chunk.AllocTid(); 92 } else { 93 if (chunk.FreeTid() == kInvalidTid) return 0; 94 stack = chunk.GetFreeStack(); 95 if (thread_id) *thread_id = chunk.FreeTid(); 96 } 97 98 if (trace && size) { 99 size = Min(size, Min(stack.size, kStackTraceMax)); 100 for (uptr i = 0; i < size; i++) 101 trace[i] = StackTrace::GetPreviousInstructionPc(stack.trace[i]); 102 103 return size; 104 } 105 106 return 0; 107} 108 109} // namespace __asan 110 111using namespace __asan; 112 113SANITIZER_INTERFACE_ATTRIBUTE 114const char *__asan_locate_address(uptr addr, char *name, uptr name_size, 115 uptr *region_address, uptr *region_size) { 116 AddressDescription descr = { name, name_size, 0, 0, 0 }; 117 AsanLocateAddress(addr, &descr); 118 if (region_address) *region_address = descr.region_address; 119 if (region_size) *region_size = descr.region_size; 120 return descr.region_kind; 121} 122 123SANITIZER_INTERFACE_ATTRIBUTE 124uptr __asan_get_alloc_stack(uptr addr, uptr *trace, uptr size, u32 *thread_id) { 125 return AsanGetStack(addr, trace, size, thread_id, /* alloc_stack */ true); 126} 127 128SANITIZER_INTERFACE_ATTRIBUTE 129uptr __asan_get_free_stack(uptr addr, uptr *trace, uptr size, u32 *thread_id) { 130 return AsanGetStack(addr, trace, size, thread_id, /* alloc_stack */ false); 131} 132 133SANITIZER_INTERFACE_ATTRIBUTE 134void __asan_get_shadow_mapping(uptr *shadow_scale, uptr *shadow_offset) { 135 if (shadow_scale) 136 *shadow_scale = SHADOW_SCALE; 137 if (shadow_offset) 138 *shadow_offset = SHADOW_OFFSET; 139} 140