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_flags.h"
16 #include "asan_internal.h"
17 #include "asan_mapping.h"
18 #include "asan_report.h"
19 #include "asan_thread.h"
23 void GetInfoForStackVar(uptr addr
, AddressDescription
*descr
, AsanThread
*t
) {
25 descr
->region_address
= 0;
26 descr
->region_size
= 0;
27 descr
->region_kind
= "stack";
29 AsanThread::StackFrameAccess access
;
30 if (!t
->GetStackFrameAccessByAddr(addr
, &access
))
32 InternalMmapVector
<StackVarDescr
> vars(16);
33 if (!ParseFrameDescription(access
.frame_descr
, &vars
)) {
37 for (uptr i
= 0; i
< vars
.size(); i
++) {
38 if (access
.offset
<= vars
[i
].beg
+ vars
[i
].size
) {
39 internal_strncat(descr
->name
, vars
[i
].name_pos
,
40 Min(descr
->name_size
, vars
[i
].name_len
));
41 descr
->region_address
= addr
- (access
.offset
- vars
[i
].beg
);
42 descr
->region_size
= vars
[i
].size
;
48 void GetInfoForHeapAddress(uptr addr
, AddressDescription
*descr
) {
49 AsanChunkView chunk
= FindHeapChunkByAddress(addr
);
52 descr
->region_address
= 0;
53 descr
->region_size
= 0;
55 if (!chunk
.IsValid()) {
56 descr
->region_kind
= "heap-invalid";
60 descr
->region_address
= chunk
.Beg();
61 descr
->region_size
= chunk
.UsedSize();
62 descr
->region_kind
= "heap";
65 void AsanLocateAddress(uptr addr
, AddressDescription
*descr
) {
66 if (DescribeAddressIfShadow(addr
, descr
, /* print */ false)) {
69 if (GetInfoForAddressIfGlobal(addr
, descr
)) {
72 asanThreadRegistry().Lock();
73 AsanThread
*thread
= FindThreadByStackAddress(addr
);
74 asanThreadRegistry().Unlock();
76 GetInfoForStackVar(addr
, descr
, thread
);
79 GetInfoForHeapAddress(addr
, descr
);
82 static uptr
AsanGetStack(uptr addr
, uptr
*trace
, u32 size
, u32
*thread_id
,
84 AsanChunkView chunk
= FindHeapChunkByAddress(addr
);
85 if (!chunk
.IsValid()) return 0;
87 StackTrace
stack(nullptr, 0);
89 if (chunk
.AllocTid() == kInvalidTid
) return 0;
90 stack
= chunk
.GetAllocStack();
91 if (thread_id
) *thread_id
= chunk
.AllocTid();
93 if (chunk
.FreeTid() == kInvalidTid
) return 0;
94 stack
= chunk
.GetFreeStack();
95 if (thread_id
) *thread_id
= chunk
.FreeTid();
99 size
= Min(size
, Min(stack
.size
, kStackTraceMax
));
100 for (uptr i
= 0; i
< size
; i
++)
101 trace
[i
] = StackTrace::GetPreviousInstructionPc(stack
.trace
[i
]);
109 } // namespace __asan
111 using namespace __asan
;
113 SANITIZER_INTERFACE_ATTRIBUTE
114 const char *__asan_locate_address(uptr addr
, char *name
, uptr name_size
,
115 uptr
*region_address
, uptr
*region_size
) {
116 AddressDescription descr
= { name
, name_size
, 0, 0, nullptr };
117 AsanLocateAddress(addr
, &descr
);
118 if (region_address
) *region_address
= descr
.region_address
;
119 if (region_size
) *region_size
= descr
.region_size
;
120 return descr
.region_kind
;
123 SANITIZER_INTERFACE_ATTRIBUTE
124 uptr
__asan_get_alloc_stack(uptr addr
, uptr
*trace
, uptr size
, u32
*thread_id
) {
125 return AsanGetStack(addr
, trace
, size
, thread_id
, /* alloc_stack */ true);
128 SANITIZER_INTERFACE_ATTRIBUTE
129 uptr
__asan_get_free_stack(uptr addr
, uptr
*trace
, uptr size
, u32
*thread_id
) {
130 return AsanGetStack(addr
, trace
, size
, thread_id
, /* alloc_stack */ false);
133 SANITIZER_INTERFACE_ATTRIBUTE
134 void __asan_get_shadow_mapping(uptr
*shadow_scale
, uptr
*shadow_offset
) {
136 *shadow_scale
= SHADOW_SCALE
;
138 *shadow_offset
= SHADOW_OFFSET
;