blob: 053eb51fffade80ddba6cd10d60c1326d47bda3f [file] [log] [blame]
Kuba Brecka58f44dc2014-07-15 17:33:23 +00001//===-- asan_debugging.cc -------------------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is a part of AddressSanitizer, an address sanity checker.
11//
12// This file contains various functions that are generally useful to call when
13// using a debugger (LLDB, GDB).
14//===----------------------------------------------------------------------===//
15
16#include "asan_allocator.h"
Filipe Cabecinhasf8a15c32016-08-15 19:30:21 +000017#include "asan_descriptions.h"
Kuba Brecka58f44dc2014-07-15 17:33:23 +000018#include "asan_flags.h"
19#include "asan_internal.h"
20#include "asan_mapping.h"
Kuba Brecka7e38e422014-09-26 19:15:32 +000021#include "asan_report.h"
Kuba Brecka58f44dc2014-07-15 17:33:23 +000022#include "asan_thread.h"
23
Filipe Cabecinhase86f80c2016-08-18 10:31:19 +000024namespace {
25using namespace __asan;
Kuba Brecka58f44dc2014-07-15 17:33:23 +000026
Filipe Cabecinhase86f80c2016-08-18 10:31:19 +000027void FindInfoForStackVar(uptr addr, const char *frame_descr, uptr offset,
28 AddressDescription *descr) {
Kuba Brecka7e38e422014-09-26 19:15:32 +000029 InternalMmapVector<StackVarDescr> vars(16);
Filipe Cabecinhase86f80c2016-08-18 10:31:19 +000030 if (!ParseFrameDescription(frame_descr, &vars)) {
Kuba Brecka7e38e422014-09-26 19:15:32 +000031 return;
32 }
33
34 for (uptr i = 0; i < vars.size(); i++) {
Filipe Cabecinhase86f80c2016-08-18 10:31:19 +000035 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(descr->name, vars[i].name_pos,
40 Min(descr->name_size, vars[i].name_len + 1));
41 descr->region_address = addr - (offset - vars[i].beg);
Kuba Brecka7e38e422014-09-26 19:15:32 +000042 descr->region_size = vars[i].size;
43 return;
44 }
45 }
46}
47
Kuba Brecka7e38e422014-09-26 19:15:32 +000048void AsanLocateAddress(uptr addr, AddressDescription *descr) {
Filipe Cabecinhasf8a15c32016-08-15 19:30:21 +000049 ShadowAddressDescription shadow_descr;
50 if (GetShadowAddressInformation(addr, &shadow_descr)) {
51 descr->region_kind = ShadowNames[shadow_descr.kind];
Kuba Brecka7e38e422014-09-26 19:15:32 +000052 return;
53 }
Filipe Cabecinhas41f41632016-08-17 19:52:12 +000054 GlobalAddressDescription global_descr;
55 if (GetGlobalAddressInformation(addr, &global_descr)) {
56 descr->region_kind = "global";
57 auto &g = global_descr.globals[0];
58 internal_strlcpy(descr->name, g.name, descr->name_size);
59 descr->region_address = g.beg;
60 descr->region_size = g.size;
Kuba Brecka7e38e422014-09-26 19:15:32 +000061 return;
62 }
Filipe Cabecinhase86f80c2016-08-18 10:31:19 +000063
64 StackAddressDescription stack_descr;
Kuba Brecka7e38e422014-09-26 19:15:32 +000065 asanThreadRegistry().Lock();
Filipe Cabecinhase86f80c2016-08-18 10:31:19 +000066 if (GetStackAddressInformation(addr, &stack_descr)) {
67 asanThreadRegistry().Unlock();
68 descr->region_kind = "stack";
69 if (!stack_descr.frame_descr) {
70 descr->name[0] = 0;
71 descr->region_address = 0;
72 descr->region_size = 0;
73 } else {
74 FindInfoForStackVar(addr, stack_descr.frame_descr, stack_descr.offset,
75 descr);
76 }
Kuba Brecka7e38e422014-09-26 19:15:32 +000077 return;
78 }
Filipe Cabecinhase86f80c2016-08-18 10:31:19 +000079 asanThreadRegistry().Unlock();
80
81 descr->name[0] = 0;
82 HeapAddressDescription heap_descr;
83 if (GetHeapAddressInformation(addr, 1, &heap_descr)) {
84 descr->region_address = heap_descr.chunk_access.chunk_begin;
85 descr->region_size = heap_descr.chunk_access.chunk_size;
86 descr->region_kind = "heap";
87 return;
88 }
89
90 descr->region_address = 0;
91 descr->region_size = 0;
92 descr->region_kind = "heap-invalid";
Kuba Brecka7e38e422014-09-26 19:15:32 +000093}
94
Filipe Cabecinhase86f80c2016-08-18 10:31:19 +000095uptr AsanGetStack(uptr addr, uptr *trace, u32 size, u32 *thread_id,
Evgeniy Stepanovd38af302015-01-22 13:33:16 +000096 bool alloc_stack) {
Kuba Brecka58f44dc2014-07-15 17:33:23 +000097 AsanChunkView chunk = FindHeapChunkByAddress(addr);
98 if (!chunk.IsValid()) return 0;
99
Alexey Samsonov9c859272014-10-26 03:35:14 +0000100 StackTrace stack(nullptr, 0);
Kuba Brecka58f44dc2014-07-15 17:33:23 +0000101 if (alloc_stack) {
102 if (chunk.AllocTid() == kInvalidTid) return 0;
Alexey Samsonov9c859272014-10-26 03:35:14 +0000103 stack = chunk.GetAllocStack();
Kuba Brecka58f44dc2014-07-15 17:33:23 +0000104 if (thread_id) *thread_id = chunk.AllocTid();
105 } else {
106 if (chunk.FreeTid() == kInvalidTid) return 0;
Alexey Samsonov9c859272014-10-26 03:35:14 +0000107 stack = chunk.GetFreeStack();
Kuba Brecka58f44dc2014-07-15 17:33:23 +0000108 if (thread_id) *thread_id = chunk.FreeTid();
109 }
110
111 if (trace && size) {
Alexey Samsonov9c859272014-10-26 03:35:14 +0000112 size = Min(size, Min(stack.size, kStackTraceMax));
Kuba Brecka58f44dc2014-07-15 17:33:23 +0000113 for (uptr i = 0; i < size; i++)
114 trace[i] = StackTrace::GetPreviousInstructionPc(stack.trace[i]);
115
116 return size;
117 }
118
119 return 0;
120}
121
Filipe Cabecinhase86f80c2016-08-18 10:31:19 +0000122} // namespace
Kuba Brecka58f44dc2014-07-15 17:33:23 +0000123
124SANITIZER_INTERFACE_ATTRIBUTE
Kuba Brecka7e38e422014-09-26 19:15:32 +0000125const char *__asan_locate_address(uptr addr, char *name, uptr name_size,
126 uptr *region_address, uptr *region_size) {
Vedant Kumar59ba7b82015-10-01 00:22:21 +0000127 AddressDescription descr = { name, name_size, 0, 0, nullptr };
Kuba Brecka7e38e422014-09-26 19:15:32 +0000128 AsanLocateAddress(addr, &descr);
129 if (region_address) *region_address = descr.region_address;
130 if (region_size) *region_size = descr.region_size;
131 return descr.region_kind;
132}
133
134SANITIZER_INTERFACE_ATTRIBUTE
Kuba Brecka58f44dc2014-07-15 17:33:23 +0000135uptr __asan_get_alloc_stack(uptr addr, uptr *trace, uptr size, u32 *thread_id) {
136 return AsanGetStack(addr, trace, size, thread_id, /* alloc_stack */ true);
137}
138
139SANITIZER_INTERFACE_ATTRIBUTE
140uptr __asan_get_free_stack(uptr addr, uptr *trace, uptr size, u32 *thread_id) {
141 return AsanGetStack(addr, trace, size, thread_id, /* alloc_stack */ false);
142}
143
144SANITIZER_INTERFACE_ATTRIBUTE
145void __asan_get_shadow_mapping(uptr *shadow_scale, uptr *shadow_offset) {
146 if (shadow_scale)
147 *shadow_scale = SHADOW_SCALE;
148 if (shadow_offset)
149 *shadow_offset = SHADOW_OFFSET;
150}