Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(201)

Side by Side Diff: runtime/szrt_asan.c

Issue 2211733002: Subzero: Improved quality of ASan error messages (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Replaced switch statements with table lookups Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/IceASanInstrumentation.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 //===- subzero/runtime/szrt_asan.c - AddressSanitizer Runtime -----*- C -*-===// 1 //===- subzero/runtime/szrt_asan.c - AddressSanitizer Runtime -----*- C -*-===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 /// 9 ///
10 /// \file 10 /// \file
(...skipping 26 matching lines...) Expand all
37 #define WORD_SIZE (sizeof(uint32_t)) 37 #define WORD_SIZE (sizeof(uint32_t))
38 #define IS_32_BIT (sizeof(void *) == WORD_SIZE) 38 #define IS_32_BIT (sizeof(void *) == WORD_SIZE)
39 39
40 #define SHADOW_OFFSET(p) ((uintptr_t)(p) % SHADOW_SCALE) 40 #define SHADOW_OFFSET(p) ((uintptr_t)(p) % SHADOW_SCALE)
41 #define IS_SHADOW_ALIGNED(p) (SHADOW_OFFSET(p) == 0) 41 #define IS_SHADOW_ALIGNED(p) (SHADOW_OFFSET(p) == 0)
42 42
43 #define MEM2SHADOW(p) (((uintptr_t)(p) >> SHADOW_SCALE_LOG2) + shadow_offset) 43 #define MEM2SHADOW(p) (((uintptr_t)(p) >> SHADOW_SCALE_LOG2) + shadow_offset)
44 #define SHADOW2MEM(p) \ 44 #define SHADOW2MEM(p) \
45 ((uintptr_t)((char *)(p)-shadow_offset) << SHADOW_SCALE_LOG2) 45 ((uintptr_t)((char *)(p)-shadow_offset) << SHADOW_SCALE_LOG2)
46 46
47 #define POISON_VAL (-1) 47 #define STACK_POISON_VAL ((char)-1)
48 #define HEAP_POISON_VAL ((char)-2)
49 #define GLOBAL_POISON_VAL ((char)-3)
50 #define MEMTYPE_INDEX(x) (-1 - (x))
51 static const char *memtype_names[] = {"stack", "heap", "global"};
52
53 #define ACCESS_LOAD (0)
54 #define ACCESS_STORE (1)
55 static const char *access_names[] = {"load from", "store to"};
48 56
49 #if DEBUG 57 #if DEBUG
50 #define DUMP(args...) \ 58 #define DUMP(args...) \
51 do { \ 59 do { \
52 printf(args); \ 60 printf(args); \
53 } while (false); 61 } while (false);
54 #else // !DEBUG 62 #else // !DEBUG
55 #define DUMP(args...) 63 #define DUMP(args...)
56 #endif // DEBUG 64 #endif // DEBUG
57 65
58 static char *shadow_offset = NULL; 66 static char *shadow_offset = NULL;
59 67
60 static void __asan_error(char *, int); 68 static bool __asan_check(char *, int);
61 static void __asan_check(char *, int); 69 static void __asan_error(char *, int, int);
62 static void __asan_get_redzones(char *, char **, char **); 70 static void __asan_get_redzones(char *, char **, char **);
63 71
64 void __asan_init(int, void **, int *); 72 void __asan_init(int, void **, int *);
65 void __asan_check_load(char *, int); 73 void __asan_check_load(char *, int);
66 void __asan_check_store(char *, int); 74 void __asan_check_store(char *, int);
67 void *__asan_malloc(size_t); 75 void *__asan_malloc(size_t);
68 void *__asan_calloc(size_t, size_t); 76 void *__asan_calloc(size_t, size_t);
69 void *__asan_realloc(char *, size_t); 77 void *__asan_realloc(char *, size_t);
70 void __asan_free(char *); 78 void __asan_free(char *);
71 void __asan_poison(char *, int); 79 void __asan_poison(char *, int, char);
72 void __asan_unpoison(char *, int); 80 void __asan_unpoison(char *, int);
73 81
74 static void __asan_error(char *ptr, int size) { 82 static void __asan_error(char *ptr, int size, int access) {
75 fprintf(stderr, "Illegal access of %d bytes at %p\n", size, ptr); 83 char *shadow_addr = MEM2SHADOW(ptr);
84 char shadow_val = *shadow_addr;
85 if (shadow_val > 0)
86 shadow_val = *(shadow_addr + 1);
87 assert(access == ACCESS_LOAD || access == ACCESS_STORE);
88 const char *access_name = access_names[access];
89 assert(shadow_val == STACK_POISON_VAL || shadow_val == HEAP_POISON_VAL ||
90 shadow_val == GLOBAL_POISON_VAL);
91 const char *memtype = memtype_names[MEMTYPE_INDEX(shadow_val)];
92 fprintf(stderr, "Illegal %d byte %s %s object at %p\n", size, access_name,
93 memtype, ptr);
76 abort(); 94 abort();
77 } 95 }
78 96
79 // check only the first byte of each word unless strict 97 // check only the first byte of each word unless strict
80 static void __asan_check(char *ptr, int size) { 98 static bool __asan_check(char *ptr, int size) {
81 assert(size == 1 || size == 2 || size == 4 || size == 8); 99 assert(size == 1 || size == 2 || size == 4 || size == 8);
82 char *shadow_addr = (char *)MEM2SHADOW(ptr); 100 char *shadow_addr = (char *)MEM2SHADOW(ptr);
101 char shadow_val = *shadow_addr;
83 DUMP("check %d bytes at %p: %p + %d (%d)\n", size, ptr, shadow_addr, 102 DUMP("check %d bytes at %p: %p + %d (%d)\n", size, ptr, shadow_addr,
84 (uintptr_t)ptr % SHADOW_SCALE, *shadow_addr); 103 (uintptr_t)ptr % SHADOW_SCALE, shadow_val);
85 if (size == SHADOW_SCALE) { 104 if (size == SHADOW_SCALE) {
86 if (*shadow_addr != 0) 105 return shadow_val == 0;
87 __asan_error(ptr, size);
88 return;
89 } 106 }
90 if (*shadow_addr != 0 && (char)SHADOW_OFFSET(ptr) + size > *shadow_addr) 107 return shadow_val == 0 || (char)SHADOW_OFFSET(ptr) + size <= shadow_val;
91 __asan_error(ptr, size);
92 } 108 }
93 109
94 static void __asan_get_redzones(char *ptr, char **left, char **right) { 110 static void __asan_get_redzones(char *ptr, char **left, char **right) {
95 char *rz_left = ptr - RZ_SIZE; 111 char *rz_left = ptr - RZ_SIZE;
96 char *rz_right = *(char **)rz_left; 112 char *rz_right = *(char **)rz_left;
97 if (left != NULL) 113 if (left != NULL)
98 *left = rz_left; 114 *left = rz_left;
99 if (right != NULL) 115 if (right != NULL)
100 *right = rz_right; 116 *right = rz_right;
101 } 117 }
102 118
103 void __asan_check_load(char *ptr, int size) { 119 void __asan_check_load(char *ptr, int size) {
104 // aligned single word accesses may be widened single byte accesses, but for 120 // aligned single word accesses may be widened single byte accesses, but for
105 // all else use strict check 121 // all else use strict check
106 if (size == WORD_SIZE && (uintptr_t)ptr % WORD_SIZE == 0) 122 int check_size =
107 size = 1; 123 (size == WORD_SIZE && (uintptr_t)ptr % WORD_SIZE == 0) ? 1 : size;
108 __asan_check(ptr, size); 124 if (!__asan_check(ptr, check_size))
125 __asan_error(ptr, size, ACCESS_LOAD);
109 } 126 }
110 127
111 void __asan_check_store(char *ptr, int size) { 128 void __asan_check_store(char *ptr, int size) {
112 // stores may never be partially out of bounds so use strict check 129 // stores may never be partially out of bounds so use strict check
113 bool strict = true; 130 if (!__asan_check(ptr, size))
114 __asan_check(ptr, size); 131 __asan_error(ptr, size, ACCESS_STORE);
115 } 132 }
116 133
117 void __asan_init(int n_rzs, void **rzs, int *rz_sizes) { 134 void __asan_init(int n_rzs, void **rzs, int *rz_sizes) {
118 // ensure the redzones are large enough to hold metadata 135 // ensure the redzones are large enough to hold metadata
119 assert(RZ_SIZE >= sizeof(void *) && RZ_SIZE >= sizeof(size_t)); 136 assert(RZ_SIZE >= sizeof(void *) && RZ_SIZE >= sizeof(size_t));
120 assert(shadow_offset == NULL); 137 assert(shadow_offset == NULL);
121 size_t length = (IS_32_BIT) ? SHADOW_LENGTH_32 : SHADOW_LENGTH_64; 138 size_t length = (IS_32_BIT) ? SHADOW_LENGTH_32 : SHADOW_LENGTH_64;
122 int prot = PROT_READ | PROT_WRITE; 139 int prot = PROT_READ | PROT_WRITE;
123 int flags = MAP_PRIVATE | MAP_ANONYMOUS; 140 int flags = MAP_PRIVATE | MAP_ANONYMOUS;
124 int fd = -1; 141 int fd = -1;
125 off_t offset = 0; 142 off_t offset = 0;
126 shadow_offset = mmap((void *)length, length, prot, flags, fd, offset); 143 shadow_offset = mmap((void *)length, length, prot, flags, fd, offset);
127 if (shadow_offset == NULL) 144 if (shadow_offset == NULL)
128 fprintf(stderr, "unable to allocate shadow memory\n"); 145 fprintf(stderr, "unable to allocate shadow memory\n");
129 else 146 else
130 DUMP("set up shadow memory at %p\n", shadow_offset); 147 DUMP("set up shadow memory at %p\n", shadow_offset);
131 if (mprotect(MEM2SHADOW(shadow_offset), length >> SHADOW_SCALE_LOG2, 148 if (mprotect(MEM2SHADOW(shadow_offset), length >> SHADOW_SCALE_LOG2,
132 PROT_NONE)) 149 PROT_NONE))
133 fprintf(stderr, "could not protect bad region\n"); 150 fprintf(stderr, "could not protect bad region\n");
134 else 151 else
135 DUMP("protected bad region\n"); 152 DUMP("protected bad region\n");
136 153
137 // poison global redzones 154 // poison global redzones
138 DUMP("poisioning %d global redzones\n", n_rzs); 155 DUMP("poisioning %d global redzones\n", n_rzs);
139 for (int i = 0; i < n_rzs; i++) { 156 for (int i = 0; i < n_rzs; i++) {
140 DUMP("(%d) poisoning redzone of size %d at %p\n", i, rz_sizes[i], rzs[i]); 157 DUMP("(%d) poisoning redzone of size %d at %p\n", i, rz_sizes[i], rzs[i]);
141 __asan_poison(rzs[i], rz_sizes[i]); 158 __asan_poison(rzs[i], rz_sizes[i], GLOBAL_POISON_VAL);
142 } 159 }
143 } 160 }
144 161
145 void *__asan_malloc(size_t size) { 162 void *__asan_malloc(size_t size) {
146 DUMP("malloc() called with size %d\n", size); 163 DUMP("malloc() called with size %d\n", size);
147 size_t padding = 164 size_t padding =
148 (IS_SHADOW_ALIGNED(size)) ? 0 : SHADOW_SCALE - SHADOW_OFFSET(size); 165 (IS_SHADOW_ALIGNED(size)) ? 0 : SHADOW_SCALE - SHADOW_OFFSET(size);
149 size_t rz_left_size = RZ_SIZE; 166 size_t rz_left_size = RZ_SIZE;
150 size_t rz_right_size = RZ_SIZE + padding; 167 size_t rz_right_size = RZ_SIZE + padding;
151 void *rz_left; 168 void *rz_left;
152 int err = posix_memalign(&rz_left, SHADOW_SCALE, 169 int err = posix_memalign(&rz_left, SHADOW_SCALE,
153 rz_left_size + size + rz_right_size); 170 rz_left_size + size + rz_right_size);
154 if (err != 0) { 171 if (err != 0) {
155 assert(err == ENOMEM); 172 assert(err == ENOMEM);
156 return NULL; 173 return NULL;
157 } 174 }
158 void *ret = rz_left + rz_left_size; 175 void *ret = rz_left + rz_left_size;
159 void *rz_right = ret + size; 176 void *rz_right = ret + size;
160 __asan_poison(rz_left, rz_left_size); 177 __asan_poison(rz_left, rz_left_size, HEAP_POISON_VAL);
161 __asan_poison(rz_right, rz_right_size); 178 __asan_poison(rz_right, rz_right_size, HEAP_POISON_VAL);
162 // record size and location data so we can find it again 179 // record size and location data so we can find it again
163 *(void **)rz_left = rz_right; 180 *(void **)rz_left = rz_right;
164 *(size_t *)rz_right = rz_right_size; 181 *(size_t *)rz_right = rz_right_size;
165 assert((uintptr_t)ret % 8 == 0); 182 assert((uintptr_t)ret % 8 == 0);
166 return ret; 183 return ret;
167 } 184 }
168 185
169 void *__asan_calloc(size_t nmemb, size_t size) { 186 void *__asan_calloc(size_t nmemb, size_t size) {
170 size_t alloc_size = nmemb * size; 187 size_t alloc_size = nmemb * size;
171 void *ret = __asan_malloc(alloc_size); 188 void *ret = __asan_malloc(alloc_size);
(...skipping 25 matching lines...) Expand all
197 void __asan_free(char *ptr) { 214 void __asan_free(char *ptr) {
198 DUMP("free() called on %p\n", ptr); 215 DUMP("free() called on %p\n", ptr);
199 char *rz_left, *rz_right; 216 char *rz_left, *rz_right;
200 __asan_get_redzones(ptr, &rz_left, &rz_right); 217 __asan_get_redzones(ptr, &rz_left, &rz_right);
201 size_t rz_right_size = *(size_t *)rz_right; 218 size_t rz_right_size = *(size_t *)rz_right;
202 __asan_unpoison(rz_left, RZ_SIZE); 219 __asan_unpoison(rz_left, RZ_SIZE);
203 __asan_unpoison(rz_right, rz_right_size); 220 __asan_unpoison(rz_right, rz_right_size);
204 free(rz_left); 221 free(rz_left);
205 } 222 }
206 223
207 void __asan_poison(char *ptr, int size) { 224 void __asan_poison(char *ptr, int size, char poison_val) {
208 char *end = ptr + size; 225 char *end = ptr + size;
209 assert(IS_SHADOW_ALIGNED(end)); 226 assert(IS_SHADOW_ALIGNED(end));
210 // redzones should be no greater than RZ_SIZE + RZ_SIZE-1 for alignment 227 // redzones should be no greater than RZ_SIZE + RZ_SIZE-1 for alignment
211 assert(size < 2 * RZ_SIZE); 228 assert(size < 2 * RZ_SIZE);
212 DUMP("poison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr), 229 DUMP("poison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr),
213 MEM2SHADOW(end)); 230 MEM2SHADOW(end));
214 size_t offset = SHADOW_OFFSET(ptr); 231 size_t offset = SHADOW_OFFSET(ptr);
215 *(char *)MEM2SHADOW(ptr) = (offset == 0) ? POISON_VAL : offset; 232 *(char *)MEM2SHADOW(ptr) = (offset == 0) ? poison_val : offset;
216 ptr += SHADOW_OFFSET(size); 233 ptr += SHADOW_OFFSET(size);
217 assert(IS_SHADOW_ALIGNED(ptr)); 234 assert(IS_SHADOW_ALIGNED(ptr));
218 for (; ptr != end; ptr += SHADOW_SCALE) { 235 int len = (end - ptr) >> SHADOW_SCALE_LOG2;
219 *(char *)MEM2SHADOW(ptr) = POISON_VAL; 236 memset(MEM2SHADOW(ptr), poison_val, len);
220 }
221 } 237 }
222 238
223 void __asan_unpoison(char *ptr, int size) { 239 void __asan_unpoison(char *ptr, int size) {
224 char *end = ptr + size; 240 char *end = ptr + size;
225 assert(IS_SHADOW_ALIGNED(end)); 241 assert(IS_SHADOW_ALIGNED(end));
226 assert(size < 2 * RZ_SIZE); 242 assert(size < 2 * RZ_SIZE);
227 DUMP("unpoison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr), 243 DUMP("unpoison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr),
228 MEM2SHADOW(end)); 244 MEM2SHADOW(end));
229 *(char *)MEM2SHADOW(ptr) = 0; 245 *(char *)MEM2SHADOW(ptr) = 0;
230 ptr += SHADOW_OFFSET(size); 246 ptr += SHADOW_OFFSET(size);
231 assert(IS_SHADOW_ALIGNED(ptr)); 247 assert(IS_SHADOW_ALIGNED(ptr));
232 for (; ptr != end; ptr += SHADOW_SCALE) { 248 memset(MEM2SHADOW(ptr), 0, (end - ptr) >> SHADOW_SCALE_LOG2);
233 *(char *)MEM2SHADOW(ptr) = 0;
234 }
235 } 249 }
OLDNEW
« no previous file with comments | « no previous file | src/IceASanInstrumentation.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698