1 //===-- asan_debugging.cc -------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is a part of AddressSanitizer, an address sanity checker.
12 // This file contains various functions that are generally useful to call when
13 // using a debugger (LLDB, GDB).
14 //===----------------------------------------------------------------------===//
16 #include "asan_allocator.h"
17 #include "asan_descriptions.h"
18 #include "asan_flags.h"
19 #include "asan_internal.h"
20 #include "asan_mapping.h"
21 #include "asan_report.h"
22 #include "asan_thread.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
®ion_address
, uptr
®ion_size
) {
30 InternalMmapVector
<StackVarDescr
> vars(16);
31 if (!ParseFrameDescription(frame_descr
, &vars
)) {
35 for (uptr i
= 0; i
< vars
.size(); i
++) {
36 if (offset
<= vars
[i
].beg
+ vars
[i
].size
) {
37 // We use name_len + 1 because strlcpy will guarantee a \0 at the end, so
38 // if we're limiting the copy due to name_len, we add 1 to ensure we copy
39 // the whole name and then terminate with '\0'.
40 internal_strlcpy(name
, vars
[i
].name_pos
,
41 Min(name_size
, vars
[i
].name_len
+ 1));
42 region_address
= addr
- (offset
- vars
[i
].beg
);
43 region_size
= vars
[i
].size
;
49 uptr
AsanGetStack(uptr addr
, uptr
*trace
, u32 size
, u32
*thread_id
,
51 AsanChunkView chunk
= FindHeapChunkByAddress(addr
);
52 if (!chunk
.IsValid()) return 0;
54 StackTrace
stack(nullptr, 0);
56 if (chunk
.AllocTid() == kInvalidTid
) return 0;
57 stack
= chunk
.GetAllocStack();
58 if (thread_id
) *thread_id
= chunk
.AllocTid();
60 if (chunk
.FreeTid() == kInvalidTid
) return 0;
61 stack
= chunk
.GetFreeStack();
62 if (thread_id
) *thread_id
= chunk
.FreeTid();
66 size
= Min(size
, Min(stack
.size
, kStackTraceMax
));
67 for (uptr i
= 0; i
< size
; i
++)
68 trace
[i
] = StackTrace::GetPreviousInstructionPc(stack
.trace
[i
]);
78 SANITIZER_INTERFACE_ATTRIBUTE
79 const char *__asan_locate_address(uptr addr
, char *name
, uptr name_size
,
80 uptr
*region_address_ptr
,
81 uptr
*region_size_ptr
) {
82 AddressDescription
descr(addr
);
83 uptr region_address
= 0;
85 const char *region_kind
= nullptr;
86 if (name
&& name_size
> 0) name
[0] = 0;
88 if (auto shadow
= descr
.AsShadow()) {
89 // region_{address,size} are already 0
90 switch (shadow
->kind
) {
92 region_kind
= "low shadow";
95 region_kind
= "shadow gap";
98 region_kind
= "high shadow";
101 } else if (auto heap
= descr
.AsHeap()) {
102 region_kind
= "heap";
103 region_address
= heap
->chunk_access
.chunk_begin
;
104 region_size
= heap
->chunk_access
.chunk_size
;
105 } else if (auto stack
= descr
.AsStack()) {
106 region_kind
= "stack";
107 if (!stack
->frame_descr
) {
108 // region_{address,size} are already 0
110 FindInfoForStackVar(addr
, stack
->frame_descr
, stack
->offset
, name
,
111 name_size
, region_address
, region_size
);
113 } else if (auto global
= descr
.AsGlobal()) {
114 region_kind
= "global";
115 auto &g
= global
->globals
[0];
116 internal_strlcpy(name
, g
.name
, name_size
);
117 region_address
= g
.beg
;
118 region_size
= g
.size
;
120 // region_{address,size} are already 0
121 region_kind
= "heap-invalid";
125 if (region_address_ptr
) *region_address_ptr
= region_address
;
126 if (region_size_ptr
) *region_size_ptr
= region_size
;
130 SANITIZER_INTERFACE_ATTRIBUTE
131 uptr
__asan_get_alloc_stack(uptr addr
, uptr
*trace
, uptr size
, u32
*thread_id
) {
132 return AsanGetStack(addr
, trace
, size
, thread_id
, /* alloc_stack */ true);
135 SANITIZER_INTERFACE_ATTRIBUTE
136 uptr
__asan_get_free_stack(uptr addr
, uptr
*trace
, uptr size
, u32
*thread_id
) {
137 return AsanGetStack(addr
, trace
, size
, thread_id
, /* alloc_stack */ false);
140 SANITIZER_INTERFACE_ATTRIBUTE
141 void __asan_get_shadow_mapping(uptr
*shadow_scale
, uptr
*shadow_offset
) {
143 *shadow_scale
= SHADOW_SCALE
;
145 *shadow_offset
= SHADOW_OFFSET
;