1 //===-- asan_debugging.cpp ------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file is a part of AddressSanitizer, an address sanity checker.
11 // This file contains various functions that are generally useful to call when
12 // using a debugger (LLDB, GDB).
13 //===----------------------------------------------------------------------===//
15 #include "asan_allocator.h"
16 #include "asan_descriptions.h"
17 #include "asan_flags.h"
18 #include "asan_internal.h"
19 #include "asan_mapping.h"
20 #include "asan_report.h"
21 #include "asan_thread.h"
22 #include "sanitizer_common/sanitizer_stackdepot.h"
25 using namespace __asan
;
27 static void FindInfoForStackVar(uptr addr
, const char *frame_descr
, uptr offset
,
28 char *name
, uptr name_size
,
29 uptr
*region_address
, uptr
*region_size
) {
30 InternalMmapVector
<StackVarDescr
> vars
;
32 if (!ParseFrameDescription(frame_descr
, &vars
)) {
36 for (uptr i
= 0; i
< vars
.size(); i
++) {
37 if (offset
<= vars
[i
].beg
+ vars
[i
].size
) {
38 // We use name_len + 1 because strlcpy will guarantee a \0 at the end, so
39 // if we're limiting the copy due to name_len, we add 1 to ensure we copy
40 // the whole name and then terminate with '\0'.
41 internal_strlcpy(name
, vars
[i
].name_pos
,
42 Min(name_size
, vars
[i
].name_len
+ 1));
43 *region_address
= addr
- (offset
- vars
[i
].beg
);
44 *region_size
= vars
[i
].size
;
50 uptr
AsanGetStack(uptr addr
, uptr
*trace
, u32 size
, u32
*thread_id
,
52 AsanChunkView chunk
= FindHeapChunkByAddress(addr
);
53 if (!chunk
.IsValid()) return 0;
55 StackTrace
stack(nullptr, 0);
57 if (chunk
.AllocTid() == kInvalidTid
) return 0;
58 stack
= StackDepotGet(chunk
.GetAllocStackId());
59 if (thread_id
) *thread_id
= chunk
.AllocTid();
61 if (chunk
.FreeTid() == kInvalidTid
) return 0;
62 stack
= StackDepotGet(chunk
.GetFreeStackId());
63 if (thread_id
) *thread_id
= chunk
.FreeTid();
67 size
= Min(size
, Min(stack
.size
, kStackTraceMax
));
68 for (uptr i
= 0; i
< size
; i
++)
69 trace
[i
] = StackTrace::GetPreviousInstructionPc(stack
.trace
[i
]);
79 SANITIZER_INTERFACE_ATTRIBUTE
80 const char *__asan_locate_address(uptr addr
, char *name
, uptr name_size
,
81 uptr
*region_address_ptr
,
82 uptr
*region_size_ptr
) {
83 AddressDescription
descr(addr
);
84 uptr region_address
= 0;
86 const char *region_kind
= nullptr;
87 if (name
&& name_size
> 0) name
[0] = 0;
89 if (auto shadow
= descr
.AsShadow()) {
90 // region_{address,size} are already 0
91 switch (shadow
->kind
) {
93 region_kind
= "low shadow";
96 region_kind
= "shadow gap";
99 region_kind
= "high shadow";
102 } else if (auto heap
= descr
.AsHeap()) {
103 region_kind
= "heap";
104 region_address
= heap
->chunk_access
.chunk_begin
;
105 region_size
= heap
->chunk_access
.chunk_size
;
106 } else if (auto stack
= descr
.AsStack()) {
107 region_kind
= "stack";
108 if (!stack
->frame_descr
) {
109 // region_{address,size} are already 0
111 FindInfoForStackVar(addr
, stack
->frame_descr
, stack
->offset
, name
,
112 name_size
, ®ion_address
, ®ion_size
);
114 } else if (auto global
= descr
.AsGlobal()) {
115 region_kind
= "global";
116 auto &g
= global
->globals
[0];
117 internal_strlcpy(name
, g
.name
, name_size
);
118 region_address
= g
.beg
;
119 region_size
= g
.size
;
121 // region_{address,size} are already 0
122 region_kind
= "heap-invalid";
126 if (region_address_ptr
) *region_address_ptr
= region_address
;
127 if (region_size_ptr
) *region_size_ptr
= region_size
;
131 SANITIZER_INTERFACE_ATTRIBUTE
132 uptr
__asan_get_alloc_stack(uptr addr
, uptr
*trace
, uptr size
, u32
*thread_id
) {
133 return AsanGetStack(addr
, trace
, size
, thread_id
, /* alloc_stack */ true);
136 SANITIZER_INTERFACE_ATTRIBUTE
137 uptr
__asan_get_free_stack(uptr addr
, uptr
*trace
, uptr size
, u32
*thread_id
) {
138 return AsanGetStack(addr
, trace
, size
, thread_id
, /* alloc_stack */ false);
141 SANITIZER_INTERFACE_ATTRIBUTE
142 void __asan_get_shadow_mapping(uptr
*shadow_scale
, uptr
*shadow_offset
) {
144 *shadow_scale
= ASAN_SHADOW_SCALE
;
146 *shadow_offset
= ASAN_SHADOW_OFFSET
;