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_descriptions.h" 16#include "asan_flags.h" 17#include "asan_internal.h" 18#include "asan_mapping.h" 19#include "asan_report.h" 20#include "asan_thread.h" 21 22namespace { 23using namespace __asan; 24 25static void FindInfoForStackVar(uptr addr, const char *frame_descr, uptr offset, 26 char *name, uptr name_size, 27 uptr ®ion_address, uptr ®ion_size) { 28 InternalMmapVector<StackVarDescr> vars; 29 vars.reserve(16); 30 if (!ParseFrameDescription(frame_descr, &vars)) { 31 return; 32 } 33 34 for (uptr i = 0; i < vars.size(); i++) { 35 if (offset <= vars[i].beg + vars[i].size) { 36 // We use name_len + 1 because strlcpy will guarantee a \0 at the end, so 37 // if we're limiting the copy due to name_len, we add 1 to ensure we copy 38 // the whole name and then terminate with '\0'. 39 internal_strlcpy(name, vars[i].name_pos, 40 Min(name_size, vars[i].name_len + 1)); 41 region_address = addr - (offset - vars[i].beg); 42 region_size = vars[i].size; 43 return; 44 } 45 } 46} 47 48uptr AsanGetStack(uptr addr, uptr *trace, u32 size, u32 *thread_id, 49 bool alloc_stack) { 50 AsanChunkView chunk = FindHeapChunkByAddress(addr); 51 if (!chunk.IsValid()) return 0; 52 53 StackTrace stack(nullptr, 0); 54 if (alloc_stack) { 55 if (chunk.AllocTid() == kInvalidTid) return 0; 56 stack = chunk.GetAllocStack(); 57 if (thread_id) *thread_id = chunk.AllocTid(); 58 } else { 59 if (chunk.FreeTid() == kInvalidTid) return 0; 60 stack = chunk.GetFreeStack(); 61 if (thread_id) *thread_id = chunk.FreeTid(); 62 } 63 64 if (trace && size) { 65 size = Min(size, Min(stack.size, kStackTraceMax)); 66 for (uptr i = 0; i < size; i++) 67 trace[i] = StackTrace::GetPreviousInstructionPc(stack.trace[i]); 68 69 return size; 70 } 71 72 return 0; 73} 74 75} // namespace 76 77SANITIZER_INTERFACE_ATTRIBUTE 78const char *__asan_locate_address(uptr addr, char *name, uptr name_size, 79 uptr *region_address_ptr, 80 uptr *region_size_ptr) { 81 AddressDescription descr(addr); 82 uptr region_address = 0; 83 uptr region_size = 0; 84 const char *region_kind = nullptr; 85 if (name && name_size > 0) name[0] = 0; 86 87 if (auto shadow = descr.AsShadow()) { 88 // region_{address,size} are already 0 89 switch (shadow->kind) { 90 case kShadowKindLow: 91 region_kind = "low shadow"; 92 break; 93 case kShadowKindGap: 94 region_kind = "shadow gap"; 95 break; 96 case kShadowKindHigh: 97 region_kind = "high shadow"; 98 break; 99 } 100 } else if (auto heap = descr.AsHeap()) { 101 region_kind = "heap"; 102 region_address = heap->chunk_access.chunk_begin; 103 region_size = heap->chunk_access.chunk_size; 104 } else if (auto stack = descr.AsStack()) { 105 region_kind = "stack"; 106 if (!stack->frame_descr) { 107 // region_{address,size} are already 0 108 } else { 109 FindInfoForStackVar(addr, stack->frame_descr, stack->offset, name, 110 name_size, region_address, region_size); 111 } 112 } else if (auto global = descr.AsGlobal()) { 113 region_kind = "global"; 114 auto &g = global->globals[0]; 115 internal_strlcpy(name, g.name, name_size); 116 region_address = g.beg; 117 region_size = g.size; 118 } else { 119 // region_{address,size} are already 0 120 region_kind = "heap-invalid"; 121 } 122 123 CHECK(region_kind); 124 if (region_address_ptr) *region_address_ptr = region_address; 125 if (region_size_ptr) *region_size_ptr = region_size; 126 return region_kind; 127} 128 129SANITIZER_INTERFACE_ATTRIBUTE 130uptr __asan_get_alloc_stack(uptr addr, uptr *trace, uptr size, u32 *thread_id) { 131 return AsanGetStack(addr, trace, size, thread_id, /* alloc_stack */ true); 132} 133 134SANITIZER_INTERFACE_ATTRIBUTE 135uptr __asan_get_free_stack(uptr addr, uptr *trace, uptr size, u32 *thread_id) { 136 return AsanGetStack(addr, trace, size, thread_id, /* alloc_stack */ false); 137} 138 139SANITIZER_INTERFACE_ATTRIBUTE 140void __asan_get_shadow_mapping(uptr *shadow_scale, uptr *shadow_offset) { 141 if (shadow_scale) 142 *shadow_scale = SHADOW_SCALE; 143 if (shadow_offset) 144 *shadow_offset = SHADOW_OFFSET; 145} 146