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