1 #define MAGIC_RANGE_DEBUG MAGIC_DEBUG_SET(0) 2 3 #include <magic_range.h> 4 5 /*===========================================================================* 6 * magic_range_is_shlib * 7 *===========================================================================*/ 8 PRIVATE int magic_range_is_shlib(void *addr, void **container) 9 { 10 /* 11 * NB!: This function requires the calling thread to already 12 * hold the DSODESC lock. 13 */ 14 int ret = 0; 15 struct _magic_sodesc *sodesc; 16 struct _magic_dsodesc *dsodesc; 17 18 /* First iterate through the SO descriptors. */ 19 MAGIC_SODESC_ITER(_magic_first_sodesc, sodesc, 20 /* First check the text range. */ 21 MAGIC_RANGE_DEBUG_ADDR(addr, sodesc->lib.text_range); 22 if (MAGIC_ADDR_IS_IN_RANGE(addr, sodesc->lib.text_range)) { 23 ret |= MAGIC_STATE_TEXT; 24 goto found_so; 25 } 26 /* Next check the data range. */ 27 MAGIC_RANGE_DEBUG_ADDR(addr, sodesc->lib.data_range); 28 if (MAGIC_ADDR_IS_IN_RANGE(addr, sodesc->lib.data_range)) { 29 ret |= MAGIC_STATE_DATA; 30 goto found_so; 31 } 32 ); 33 34 /* Next iterate through the DSO descriptors. */ 35 MAGIC_SODESC_ITER(_magic_first_dsodesc, dsodesc, 36 /* First check the text range. */ 37 MAGIC_RANGE_DEBUG_ADDR(addr, dsodesc->lib.text_range); 38 if (MAGIC_ADDR_IS_IN_RANGE(addr, dsodesc->lib.text_range)) { 39 ret |= MAGIC_STATE_TEXT; 40 goto found_dso; 41 } 42 /* Next check the data range. */ 43 MAGIC_RANGE_DEBUG_ADDR(addr, dsodesc->lib.data_range); 44 if (MAGIC_ADDR_IS_IN_RANGE(addr, dsodesc->lib.data_range)) { 45 ret |= MAGIC_STATE_DATA; 46 goto found_dso; 47 } 48 ); 49 50 51 out: 52 return ret; 53 found_so: 54 ret |= MAGIC_STATE_LIB | MAGIC_STATE_LIB_SO; 55 if (container != NULL) 56 *container = (void *)(sodesc); 57 goto out; 58 found_dso: 59 ret |= MAGIC_STATE_LIB | MAGIC_STATE_LIB_DSO; 60 if (container != NULL) { 61 *container = (void *)(dsodesc); 62 } 63 goto out; 64 65 } 66 67 /*===========================================================================* 68 * magic_range_is_data * 69 *===========================================================================*/ 70 PRIVATE INLINE int magic_range_is_data(void *addr) 71 { 72 MAGIC_RANGE_DEBUG_ADDR(addr, magic_data_range); 73 return MAGIC_ADDR_IS_IN_RANGE(addr, magic_data_range) ? MAGIC_STATE_DATA : 0; 74 } 75 76 /*===========================================================================* 77 * magic_range_is_text * 78 *===========================================================================*/ 79 PRIVATE INLINE int magic_range_is_text(void *addr) 80 { 81 MAGIC_RANGE_DEBUG_ADDR(addr, magic_text_range); 82 return MAGIC_ADDR_IS_IN_RANGE(addr, magic_text_range) ? MAGIC_STATE_TEXT : 0; 83 } 84 85 /*===========================================================================* 86 * magic_range_is_heap * 87 *===========================================================================*/ 88 PRIVATE INLINE int magic_range_is_heap(void *addr) 89 { 90 void* heap_range[2]; 91 MAGIC_RANGE_SET_MIN(heap_range, magic_heap_start); 92 MAGIC_RANGE_SET_MAX(heap_range, (char *)magic_heap_end + MAGIC_HEAP_GAP); 93 MAGIC_RANGE_DEBUG_ADDR(addr, heap_range); 94 return MAGIC_ADDR_IS_IN_RANGE(addr, heap_range) ? MAGIC_STATE_HEAP : 0; 95 } 96 97 /*===========================================================================* 98 * magic_range_is_stack * 99 *===========================================================================*/ 100 PUBLIC int magic_range_is_stack(void *addr) 101 { 102 /* 103 * NB!: This function requires the calling thread to already 104 * hold the DSENTRY lock. 105 */ 106 struct _magic_sentry *sentry; 107 int ret; 108 void *stack_range[2]; 109 110 MAGIC_RANGE_INIT(stack_range); 111 assert(_magic_first_stack_dsentry && _magic_last_stack_dsentry); 112 sentry = MAGIC_DSENTRY_TO_SENTRY(_magic_first_stack_dsentry); 113 MAGIC_RANGE_SET_MIN(stack_range, 114 (char *) MAGIC_DSENTRY_TO_SENTRY(_magic_last_stack_dsentry)->address - 115 MAGIC_STACK_GAP); 116 MAGIC_RANGE_SET_MAX(stack_range, 117 ((char *) sentry->address) + sentry->type->size - 1); 118 #if MAGIC_RANGE_ROUND_STACK 119 MAGIC_RANGE_PAGE_ROUND(stack_range); 120 #endif 121 MAGIC_RANGE_DEBUG_ADDR(addr, stack_range); 122 ret = MAGIC_ADDR_IS_IN_RANGE(addr, stack_range) ? MAGIC_STATE_STACK : 0; 123 124 return ret; 125 } 126 127 /*===========================================================================* 128 * magic_range_is_dsentry * 129 *===========================================================================*/ 130 PUBLIC int magic_range_is_dsentry(void *addr) 131 { 132 /* 133 * NB!: This function requires the calling thread to already 134 * hold the DSENTRY lock. 135 */ 136 int ret = 0; 137 void *start_address, *end_address; 138 struct _magic_dsentry *prev_dsentry, *dsentry; 139 struct _magic_sentry *sentry; 140 int region; 141 142 if(magic_update_dsentry_ranges) { 143 MAGIC_RANGE_INIT(magic_heap_range); 144 MAGIC_RANGE_INIT(magic_map_range); 145 MAGIC_RANGE_INIT(magic_shm_range); 146 MAGIC_RANGE_INIT(magic_stack_range); 147 MAGIC_DSENTRY_ALIVE_ITER(_magic_first_dsentry, prev_dsentry, dsentry, sentry, 148 start_address = sentry->address; 149 end_address = (void *) (((char *)sentry->address) + 150 sentry->type->size - 1); 151 region = MAGIC_STATE_REGION(sentry); 152 if(region & MAGIC_STATE_HEAP) { 153 MAGIC_RANGE_UPDATE(magic_heap_range, start_address, end_address); 154 } 155 else if(region & MAGIC_STATE_MAP) { 156 MAGIC_RANGE_UPDATE(magic_map_range, start_address, end_address); 157 } 158 else if(region & MAGIC_STATE_SHM) { 159 MAGIC_RANGE_UPDATE(magic_shm_range, start_address, end_address); 160 } 161 else if(region & MAGIC_STATE_STACK) { 162 MAGIC_RANGE_UPDATE(magic_stack_range, start_address, end_address); 163 } 164 ); 165 magic_update_dsentry_ranges = 0; 166 } 167 MAGIC_RANGE_DEBUG_ADDR(addr, magic_heap_range); 168 if(MAGIC_ADDR_IS_IN_RANGE(addr, magic_heap_range)) { 169 ret |= MAGIC_STATE_HEAP; 170 } 171 MAGIC_RANGE_DEBUG_ADDR(addr, magic_map_range); 172 if(MAGIC_ADDR_IS_IN_RANGE(addr, magic_map_range)) { 173 ret |= MAGIC_STATE_MAP; 174 } 175 MAGIC_RANGE_DEBUG_ADDR(addr, magic_shm_range); 176 if(MAGIC_ADDR_IS_IN_RANGE(addr, magic_shm_range)) { 177 ret |= MAGIC_STATE_SHM; 178 } 179 MAGIC_RANGE_DEBUG_ADDR(addr, magic_stack_range); 180 if(MAGIC_ADDR_IS_IN_RANGE(addr, magic_stack_range)) { 181 ret |= MAGIC_STATE_STACK; 182 } 183 184 return ret; 185 } 186 187 /*===========================================================================* 188 * magic_range_is_dfunction * 189 *===========================================================================*/ 190 PUBLIC int magic_range_is_dfunction(void *addr) 191 { 192 /* 193 * NB!: This function requires the calling thread to already 194 * hold the DFUNCTION lock. 195 */ 196 int ret = 0; 197 void *start_address; 198 struct _magic_dfunction* dfunction; 199 struct _magic_function* function; 200 int region; 201 202 if(magic_update_dfunction_ranges) { 203 MAGIC_RANGE_INIT(magic_dfunction_range); 204 MAGIC_DFUNCTION_FUNC_ITER(_magic_first_dfunction, dfunction, function, 205 start_address = function->address; 206 region = MAGIC_STATE_REGION(function); 207 assert(region & MAGIC_STATE_TEXT); 208 MAGIC_RANGE_UPDATE(magic_dfunction_range, start_address, start_address); 209 ); 210 magic_update_dfunction_ranges = 0; 211 } 212 MAGIC_RANGE_DEBUG_ADDR(addr, magic_dfunction_range); 213 if(MAGIC_ADDR_IS_IN_RANGE(addr, magic_dfunction_range)) { 214 ret |= MAGIC_STATE_TEXT; 215 } 216 217 return ret; 218 } 219 220 /*===========================================================================* 221 * magic_ranges_init * 222 *===========================================================================*/ 223 PUBLIC void magic_ranges_init(void) 224 { 225 int i,j; 226 void *start_address, *end_address; 227 const char* linker_vars[] = { MAGIC_LINKER_VAR_NAMES }; 228 229 /* Init sentry and data range. */ 230 MAGIC_RANGE_INIT(magic_data_range); 231 MAGIC_RANGE_INIT(magic_sentry_range); 232 for (i = 0 ; i < _magic_sentries_num ; i++) { 233 start_address = _magic_sentries[i].address; 234 end_address = (void *) (((char *)_magic_sentries[i].address)+_magic_sentries[i].type->size-1); 235 MAGIC_RANGE_UPDATE(magic_sentry_range, start_address, end_address); 236 j = 0; 237 while (linker_vars[j] && strcmp(linker_vars[j], _magic_sentries[i].name)) j++; 238 if (linker_vars[j] || MAGIC_STATE_FLAG(&_magic_sentries[i], MAGIC_STATE_THREAD_LOCAL) 239 || MAGIC_STATE_FLAG(&_magic_sentries[i], MAGIC_STATE_EXTERNAL)) { 240 continue; 241 } 242 MAGIC_RANGE_UPDATE(magic_data_range, start_address, end_address); 243 } 244 #if MAGIC_RANGE_ROUND_DATA 245 MAGIC_RANGE_PAGE_ROUND(magic_data_range); 246 #endif 247 248 /* Init function range. */ 249 MAGIC_RANGE_INIT(magic_function_range); 250 for (i = 0 ; i < _magic_functions_num ; i++) { 251 start_address = _magic_functions[i].address; 252 MAGIC_RANGE_UPDATE(magic_function_range, start_address, start_address); 253 } 254 255 /* Init text range. */ 256 #ifdef __MINIX 257 MAGIC_RANGE_SET(magic_text_range, MAGIC_TEXT_START, 258 MAGIC_TEXT_END ? MAGIC_TEXT_END : ((char *)magic_function_range[1])); 259 #else 260 MAGIC_RANGE_SET(magic_text_range, MAGIC_TEXT_START, 261 MAGIC_TEXT_END ? MAGIC_TEXT_END : ((char *)magic_data_range[0] - 1)); 262 #endif 263 #if MAGIC_RANGE_ROUND_TEXT 264 MAGIC_RANGE_PAGE_ROUND(magic_text_range); 265 #endif 266 267 /* Init heap start. */ 268 magic_heap_start = MAGIC_HEAP_START ? MAGIC_HEAP_START : ((char *)magic_data_range[1] + 1); 269 magic_heap_end = ((char *)sbrk(0)) - 1; 270 271 /* Defaults for other ranges. */ 272 MAGIC_RANGE_INIT(magic_heap_range); 273 MAGIC_RANGE_INIT(magic_map_range); 274 MAGIC_RANGE_INIT(magic_shm_range); 275 MAGIC_RANGE_INIT(magic_stack_range); 276 MAGIC_RANGE_INIT(magic_dfunction_range); 277 } 278 279 /*===========================================================================* 280 * magic_range_lookup_by_addr * 281 *===========================================================================*/ 282 PUBLIC int magic_range_lookup_by_addr(void *addr, void **container) 283 { 284 /* 285 * NB!: This function requires the calling thread to already 286 * hold the DSENTRY, DFUNCTION and DSODESC locks. 287 */ 288 int ret; 289 /* Constant ranges first. */ 290 if (magic_range_is_data(addr)) { 291 return MAGIC_STATE_DATA; 292 } 293 if (magic_range_is_text(addr)) { 294 return MAGIC_STATE_TEXT; 295 } 296 297 /* Non-dsentry ranges next. */ 298 if (magic_range_is_heap(addr)) { 299 return MAGIC_STATE_HEAP; 300 } 301 if (magic_range_is_stack(addr)) { 302 return MAGIC_STATE_STACK; 303 } 304 305 /* Shared library ranges. */ 306 #if 0 307 /* XXX: This kind of range isn't very accurate. */ 308 if (magic_range_is_dfunction(addr)) { 309 return MAGIC_STATE_LIB | MAGIC_STATE_TEXT; 310 } 311 #endif 312 313 if ((ret = magic_range_is_shlib(addr, container))) { 314 return ret; 315 } 316 317 /* Dsentry ranges last. */ 318 return magic_range_is_dsentry(addr); 319 } 320 321 322