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

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: 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') | src/IceASanInstrumentation.cpp » ('J')
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
51 #define ACCESS_LOAD (0)
52 #define ACCESS_STORE (1)
48 53
49 #if DEBUG 54 #if DEBUG
50 #define DUMP(args...) \ 55 #define DUMP(args...) \
51 do { \ 56 do { \
52 printf(args); \ 57 printf(args); \
53 } while (false); 58 } while (false);
54 #else // !DEBUG 59 #else // !DEBUG
55 #define DUMP(args...) 60 #define DUMP(args...)
56 #endif // DEBUG 61 #endif // DEBUG
57 62
58 static char *shadow_offset = NULL; 63 static char *shadow_offset = NULL;
59 64
60 static void __asan_error(char *, int); 65 static bool __asan_check(char *, int);
61 static void __asan_check(char *, int); 66 static void __asan_error(char *, int, int);
62 static void __asan_get_redzones(char *, char **, char **); 67 static void __asan_get_redzones(char *, char **, char **);
63 68
64 void __asan_init(int, void **, int *); 69 void __asan_init(int, void **, int *);
65 void __asan_check_load(char *, int); 70 void __asan_check_load(char *, int);
66 void __asan_check_store(char *, int); 71 void __asan_check_store(char *, int);
67 void *__asan_malloc(size_t); 72 void *__asan_malloc(size_t);
68 void *__asan_calloc(size_t, size_t); 73 void *__asan_calloc(size_t, size_t);
69 void *__asan_realloc(char *, size_t); 74 void *__asan_realloc(char *, size_t);
70 void __asan_free(char *); 75 void __asan_free(char *);
71 void __asan_poison(char *, int); 76 void __asan_poison(char *, int, char);
72 void __asan_unpoison(char *, int); 77 void __asan_unpoison(char *, int);
73 78
74 static void __asan_error(char *ptr, int size) { 79 static void __asan_error(char *ptr, int size, int access) {
75 fprintf(stderr, "Illegal access of %d bytes at %p\n", size, ptr); 80 char *shadow_addr = MEM2SHADOW(ptr);
81 char shadow_val = *shadow_addr;
82 if (shadow_val > 0)
83 shadow_val = *(shadow_addr + 1);
84 char *accesstype = NULL;
85 switch (access) {
Karl 2016/08/04 14:42:24 Why not use a global array with these values, and
Jim Stichnoth 2016/08/04 14:55:09 That sounds appealing, but note that it will proba
tlively 2016/08/04 17:58:22 Done.
86 case ACCESS_LOAD:
87 accesstype = "load from";
88 break;
89 case ACCESS_STORE:
90 accesstype = "store to";
91 break;
92 }
93 assert(accesstype != NULL);
94 char *memtype = NULL;
95 switch (shadow_val) {
Karl 2016/08/04 14:42:24 Similar here, replace with something like: memtyp
tlively 2016/08/04 17:58:22 Done.
96 case STACK_POISON_VAL:
97 memtype = "stack";
98 break;
99 case HEAP_POISON_VAL:
100 memtype = "heap";
101 break;
102 case GLOBAL_POISON_VAL:
103 memtype = "global";
104 break;
105 }
106 assert(memtype != NULL);
107 fprintf(stderr, "Illegal %d byte %s %s object at %p\n", size, accesstype,
108 memtype, ptr);
76 abort(); 109 abort();
77 } 110 }
78 111
79 // check only the first byte of each word unless strict 112 // check only the first byte of each word unless strict
80 static void __asan_check(char *ptr, int size) { 113 static bool __asan_check(char *ptr, int size) {
81 assert(size == 1 || size == 2 || size == 4 || size == 8); 114 assert(size == 1 || size == 2 || size == 4 || size == 8);
82 char *shadow_addr = (char *)MEM2SHADOW(ptr); 115 char *shadow_addr = (char *)MEM2SHADOW(ptr);
116 char shadow_val = *shadow_addr;
83 DUMP("check %d bytes at %p: %p + %d (%d)\n", size, ptr, shadow_addr, 117 DUMP("check %d bytes at %p: %p + %d (%d)\n", size, ptr, shadow_addr,
84 (uintptr_t)ptr % SHADOW_SCALE, *shadow_addr); 118 (uintptr_t)ptr % SHADOW_SCALE, shadow_val);
85 if (size == SHADOW_SCALE) { 119 if (size == SHADOW_SCALE) {
86 if (*shadow_addr != 0) 120 return shadow_val == 0;
87 __asan_error(ptr, size);
88 return;
89 } 121 }
90 if (*shadow_addr != 0 && (char)SHADOW_OFFSET(ptr) + size > *shadow_addr) 122 return shadow_val == 0 || (char)SHADOW_OFFSET(ptr) + size <= shadow_val;
91 __asan_error(ptr, size);
92 } 123 }
93 124
94 static void __asan_get_redzones(char *ptr, char **left, char **right) { 125 static void __asan_get_redzones(char *ptr, char **left, char **right) {
95 char *rz_left = ptr - RZ_SIZE; 126 char *rz_left = ptr - RZ_SIZE;
96 char *rz_right = *(char **)rz_left; 127 char *rz_right = *(char **)rz_left;
97 if (left != NULL) 128 if (left != NULL)
98 *left = rz_left; 129 *left = rz_left;
99 if (right != NULL) 130 if (right != NULL)
100 *right = rz_right; 131 *right = rz_right;
101 } 132 }
102 133
103 void __asan_check_load(char *ptr, int size) { 134 void __asan_check_load(char *ptr, int size) {
104 // aligned single word accesses may be widened single byte accesses, but for 135 // aligned single word accesses may be widened single byte accesses, but for
105 // all else use strict check 136 // all else use strict check
106 if (size == WORD_SIZE && (uintptr_t)ptr % WORD_SIZE == 0) 137 int check_size =
107 size = 1; 138 (size == WORD_SIZE && (uintptr_t)ptr % WORD_SIZE == 0) ? 1 : size;
108 __asan_check(ptr, size); 139 if (!__asan_check(ptr, check_size))
140 __asan_error(ptr, size, ACCESS_LOAD);
109 } 141 }
110 142
111 void __asan_check_store(char *ptr, int size) { 143 void __asan_check_store(char *ptr, int size) {
112 // stores may never be partially out of bounds so use strict check 144 // stores may never be partially out of bounds so use strict check
113 bool strict = true; 145 if (!__asan_check(ptr, size))
114 __asan_check(ptr, size); 146 __asan_error(ptr, size, ACCESS_STORE);
115 } 147 }
116 148
117 void __asan_init(int n_rzs, void **rzs, int *rz_sizes) { 149 void __asan_init(int n_rzs, void **rzs, int *rz_sizes) {
118 // ensure the redzones are large enough to hold metadata 150 // ensure the redzones are large enough to hold metadata
119 assert(RZ_SIZE >= sizeof(void *) && RZ_SIZE >= sizeof(size_t)); 151 assert(RZ_SIZE >= sizeof(void *) && RZ_SIZE >= sizeof(size_t));
120 assert(shadow_offset == NULL); 152 assert(shadow_offset == NULL);
121 size_t length = (IS_32_BIT) ? SHADOW_LENGTH_32 : SHADOW_LENGTH_64; 153 size_t length = (IS_32_BIT) ? SHADOW_LENGTH_32 : SHADOW_LENGTH_64;
122 int prot = PROT_READ | PROT_WRITE; 154 int prot = PROT_READ | PROT_WRITE;
123 int flags = MAP_PRIVATE | MAP_ANONYMOUS; 155 int flags = MAP_PRIVATE | MAP_ANONYMOUS;
124 int fd = -1; 156 int fd = -1;
125 off_t offset = 0; 157 off_t offset = 0;
126 shadow_offset = mmap((void *)length, length, prot, flags, fd, offset); 158 shadow_offset = mmap((void *)length, length, prot, flags, fd, offset);
127 if (shadow_offset == NULL) 159 if (shadow_offset == NULL)
128 fprintf(stderr, "unable to allocate shadow memory\n"); 160 fprintf(stderr, "unable to allocate shadow memory\n");
129 else 161 else
130 DUMP("set up shadow memory at %p\n", shadow_offset); 162 DUMP("set up shadow memory at %p\n", shadow_offset);
131 if (mprotect(MEM2SHADOW(shadow_offset), length >> SHADOW_SCALE_LOG2, 163 if (mprotect(MEM2SHADOW(shadow_offset), length >> SHADOW_SCALE_LOG2,
132 PROT_NONE)) 164 PROT_NONE))
133 fprintf(stderr, "could not protect bad region\n"); 165 fprintf(stderr, "could not protect bad region\n");
134 else 166 else
135 DUMP("protected bad region\n"); 167 DUMP("protected bad region\n");
136 168
137 // poison global redzones 169 // poison global redzones
138 DUMP("poisioning %d global redzones\n", n_rzs); 170 DUMP("poisioning %d global redzones\n", n_rzs);
139 for (int i = 0; i < n_rzs; i++) { 171 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]); 172 DUMP("(%d) poisoning redzone of size %d at %p\n", i, rz_sizes[i], rzs[i]);
141 __asan_poison(rzs[i], rz_sizes[i]); 173 __asan_poison(rzs[i], rz_sizes[i], GLOBAL_POISON_VAL);
142 } 174 }
143 } 175 }
144 176
145 void *__asan_malloc(size_t size) { 177 void *__asan_malloc(size_t size) {
146 DUMP("malloc() called with size %d\n", size); 178 DUMP("malloc() called with size %d\n", size);
147 size_t padding = 179 size_t padding =
148 (IS_SHADOW_ALIGNED(size)) ? 0 : SHADOW_SCALE - SHADOW_OFFSET(size); 180 (IS_SHADOW_ALIGNED(size)) ? 0 : SHADOW_SCALE - SHADOW_OFFSET(size);
149 size_t rz_left_size = RZ_SIZE; 181 size_t rz_left_size = RZ_SIZE;
150 size_t rz_right_size = RZ_SIZE + padding; 182 size_t rz_right_size = RZ_SIZE + padding;
151 void *rz_left; 183 void *rz_left;
152 int err = posix_memalign(&rz_left, SHADOW_SCALE, 184 int err = posix_memalign(&rz_left, SHADOW_SCALE,
153 rz_left_size + size + rz_right_size); 185 rz_left_size + size + rz_right_size);
154 if (err != 0) { 186 if (err != 0) {
155 assert(err == ENOMEM); 187 assert(err == ENOMEM);
156 return NULL; 188 return NULL;
157 } 189 }
158 void *ret = rz_left + rz_left_size; 190 void *ret = rz_left + rz_left_size;
159 void *rz_right = ret + size; 191 void *rz_right = ret + size;
160 __asan_poison(rz_left, rz_left_size); 192 __asan_poison(rz_left, rz_left_size, HEAP_POISON_VAL);
161 __asan_poison(rz_right, rz_right_size); 193 __asan_poison(rz_right, rz_right_size, HEAP_POISON_VAL);
162 // record size and location data so we can find it again 194 // record size and location data so we can find it again
163 *(void **)rz_left = rz_right; 195 *(void **)rz_left = rz_right;
164 *(size_t *)rz_right = rz_right_size; 196 *(size_t *)rz_right = rz_right_size;
165 assert((uintptr_t)ret % 8 == 0); 197 assert((uintptr_t)ret % 8 == 0);
166 return ret; 198 return ret;
167 } 199 }
168 200
169 void *__asan_calloc(size_t nmemb, size_t size) { 201 void *__asan_calloc(size_t nmemb, size_t size) {
170 size_t alloc_size = nmemb * size; 202 size_t alloc_size = nmemb * size;
171 void *ret = __asan_malloc(alloc_size); 203 void *ret = __asan_malloc(alloc_size);
(...skipping 25 matching lines...) Expand all
197 void __asan_free(char *ptr) { 229 void __asan_free(char *ptr) {
198 DUMP("free() called on %p\n", ptr); 230 DUMP("free() called on %p\n", ptr);
199 char *rz_left, *rz_right; 231 char *rz_left, *rz_right;
200 __asan_get_redzones(ptr, &rz_left, &rz_right); 232 __asan_get_redzones(ptr, &rz_left, &rz_right);
201 size_t rz_right_size = *(size_t *)rz_right; 233 size_t rz_right_size = *(size_t *)rz_right;
202 __asan_unpoison(rz_left, RZ_SIZE); 234 __asan_unpoison(rz_left, RZ_SIZE);
203 __asan_unpoison(rz_right, rz_right_size); 235 __asan_unpoison(rz_right, rz_right_size);
204 free(rz_left); 236 free(rz_left);
205 } 237 }
206 238
207 void __asan_poison(char *ptr, int size) { 239 void __asan_poison(char *ptr, int size, char poison_val) {
208 char *end = ptr + size; 240 char *end = ptr + size;
209 assert(IS_SHADOW_ALIGNED(end)); 241 assert(IS_SHADOW_ALIGNED(end));
210 // redzones should be no greater than RZ_SIZE + RZ_SIZE-1 for alignment 242 // redzones should be no greater than RZ_SIZE + RZ_SIZE-1 for alignment
211 assert(size < 2 * RZ_SIZE); 243 assert(size < 2 * RZ_SIZE);
212 DUMP("poison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr), 244 DUMP("poison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr),
213 MEM2SHADOW(end)); 245 MEM2SHADOW(end));
214 size_t offset = SHADOW_OFFSET(ptr); 246 size_t offset = SHADOW_OFFSET(ptr);
215 *(char *)MEM2SHADOW(ptr) = (offset == 0) ? POISON_VAL : offset; 247 *(char *)MEM2SHADOW(ptr) = (offset == 0) ? poison_val : offset;
216 ptr += SHADOW_OFFSET(size); 248 ptr += SHADOW_OFFSET(size);
217 assert(IS_SHADOW_ALIGNED(ptr)); 249 assert(IS_SHADOW_ALIGNED(ptr));
218 for (; ptr != end; ptr += SHADOW_SCALE) { 250 int len = (end - ptr) >> SHADOW_SCALE_LOG2;
219 *(char *)MEM2SHADOW(ptr) = POISON_VAL; 251 memset(MEM2SHADOW(ptr), poison_val, len);
220 }
221 } 252 }
222 253
223 void __asan_unpoison(char *ptr, int size) { 254 void __asan_unpoison(char *ptr, int size) {
224 char *end = ptr + size; 255 char *end = ptr + size;
225 assert(IS_SHADOW_ALIGNED(end)); 256 assert(IS_SHADOW_ALIGNED(end));
226 assert(size < 2 * RZ_SIZE); 257 assert(size < 2 * RZ_SIZE);
227 DUMP("unpoison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr), 258 DUMP("unpoison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr),
228 MEM2SHADOW(end)); 259 MEM2SHADOW(end));
229 *(char *)MEM2SHADOW(ptr) = 0; 260 *(char *)MEM2SHADOW(ptr) = 0;
230 ptr += SHADOW_OFFSET(size); 261 ptr += SHADOW_OFFSET(size);
231 assert(IS_SHADOW_ALIGNED(ptr)); 262 assert(IS_SHADOW_ALIGNED(ptr));
232 for (; ptr != end; ptr += SHADOW_SCALE) { 263 memset(MEM2SHADOW(ptr), 0, (end - ptr) >> SHADOW_SCALE_LOG2);
233 *(char *)MEM2SHADOW(ptr) = 0;
234 }
235 } 264 }
OLDNEW
« no previous file with comments | « no previous file | src/IceASanInstrumentation.cpp » ('j') | src/IceASanInstrumentation.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698