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
;
30 if (!ParseFrameDescription(frame_descr
, &vars
)) {
34 for (uptr i
= 0; i
< vars
.size(); i
++) {
35 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(name
, vars
[i
].name_pos
,
40 Min(name_size
, vars
[i
].name_len
+ 1));
41 region_address
= addr
- (offset
- vars
[i
].beg
);
42 region_size
= vars
[i
].size
;
48 uptr
AsanGetStack(uptr addr
, uptr
*trace
, u32 size
, u32
*thread_id
,
50 AsanChunkView chunk
= FindHeapChunkByAddress(addr
);
51 if (!chunk
.IsValid()) return 0;
53 StackTrace
stack(nullptr, 0);
55 if (chunk
.AllocTid() == kInvalidTid
) return 0;
56 stack
= chunk
.GetAllocStack();
57 if (thread_id
) *thread_id
= chunk
.AllocTid();
59 if (chunk
.FreeTid() == kInvalidTid
) return 0;
60 stack
= chunk
.GetFreeStack();
61 if (thread_id
) *thread_id
= chunk
.FreeTid();
65 size
= Min(size
, Min(stack
.size
, kStackTraceMax
));
66 for (uptr i
= 0; i
< size
; i
++)
67 trace
[i
] = StackTrace::GetPreviousInstructionPc(stack
.trace
[i
]);
77 SANITIZER_INTERFACE_ATTRIBUTE
78 const char *__asan_locate_address(uptr addr
, char *name
, uptr name_size
,
79 uptr
*region_address_ptr
,
80 uptr
*region_size_ptr
) {
81 AddressDescription
descr(addr
);
82 uptr region_address
= 0;
84 const char *region_kind
= nullptr;
85 if (name
&& name_size
> 0) name
[0] = 0;
87 if (auto shadow
= descr
.AsShadow()) {
88 // region_{address,size} are already 0
89 switch (shadow
->kind
) {
91 region_kind
= "low shadow";
94 region_kind
= "shadow gap";
97 region_kind
= "high shadow";
100 } else if (auto heap
= descr
.AsHeap()) {
101 region_kind
= "heap";
102 region_address
= heap
->chunk_access
.chunk_begin
;
103 region_size
= heap
->chunk_access
.chunk_size
;
104 } else if (auto stack
= descr
.AsStack()) {
105 region_kind
= "stack";
106 if (!stack
->frame_descr
) {
107 // region_{address,size} are already 0
109 FindInfoForStackVar(addr
, stack
->frame_descr
, stack
->offset
, name
,
110 name_size
, region_address
, region_size
);
112 } else if (auto global
= descr
.AsGlobal()) {
113 region_kind
= "global";
114 auto &g
= global
->globals
[0];
115 internal_strlcpy(name
, g
.name
, name_size
);
116 region_address
= g
.beg
;
117 region_size
= g
.size
;
119 // region_{address,size} are already 0
120 region_kind
= "heap-invalid";
124 if (region_address_ptr
) *region_address_ptr
= region_address
;
125 if (region_size_ptr
) *region_size_ptr
= region_size
;
129 SANITIZER_INTERFACE_ATTRIBUTE
130 uptr
__asan_get_alloc_stack(uptr addr
, uptr
*trace
, uptr size
, u32
*thread_id
) {
131 return AsanGetStack(addr
, trace
, size
, thread_id
, /* alloc_stack */ true);
134 SANITIZER_INTERFACE_ATTRIBUTE
135 uptr
__asan_get_free_stack(uptr addr
, uptr
*trace
, uptr size
, u32
*thread_id
) {
136 return AsanGetStack(addr
, trace
, size
, thread_id
, /* alloc_stack */ false);
139 SANITIZER_INTERFACE_ATTRIBUTE
140 void __asan_get_shadow_mapping(uptr
*shadow_scale
, uptr
*shadow_offset
) {
142 *shadow_scale
= SHADOW_SCALE
;
144 *shadow_offset
= SHADOW_OFFSET
;