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