1 //===-- asan_debugging.cc -------------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is a part of AddressSanitizer, an address sanity checker.
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"
23 using namespace __asan
;
25 static 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(16);
29 if (!ParseFrameDescription(frame_descr
, &vars
)) {
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
;
47 uptr
AsanGetStack(uptr addr
, uptr
*trace
, u32 size
, u32
*thread_id
,
49 AsanChunkView chunk
= FindHeapChunkByAddress(addr
);
50 if (!chunk
.IsValid()) return 0;
52 StackTrace
stack(nullptr, 0);
54 if (chunk
.AllocTid() == kInvalidTid
) return 0;
55 stack
= chunk
.GetAllocStack();
56 if (thread_id
) *thread_id
= chunk
.AllocTid();
58 if (chunk
.FreeTid() == kInvalidTid
) return 0;
59 stack
= chunk
.GetFreeStack();
60 if (thread_id
) *thread_id
= chunk
.FreeTid();
64 size
= Min(size
, Min(stack
.size
, kStackTraceMax
));
65 for (uptr i
= 0; i
< size
; i
++)
66 trace
[i
] = StackTrace::GetPreviousInstructionPc(stack
.trace
[i
]);
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;
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
) {
90 region_kind
= "low shadow";
93 region_kind
= "shadow gap";
96 region_kind
= "high shadow";
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
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
;
118 // region_{address,size} are already 0
119 region_kind
= "heap-invalid";
123 if (region_address_ptr
) *region_address_ptr
= region_address
;
124 if (region_size_ptr
) *region_size_ptr
= region_size
;
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
) {
141 *shadow_scale
= SHADOW_SCALE
;
143 *shadow_offset
= SHADOW_OFFSET
;