1 #define MAGIC_RANGE_DEBUG MAGIC_DEBUG_SET(0)
3 #include <magic_range.h>
5 /*===========================================================================*
6 * magic_range_is_shlib *
7 *===========================================================================*/
8 PRIVATE
int magic_range_is_shlib(void *addr
, void **container
)
11 * NB!: This function requires the calling thread to already
12 * hold the DSODESC lock.
15 struct _magic_sodesc
*sodesc
;
16 struct _magic_dsodesc
*dsodesc
;
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
;
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
;
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
;
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
;
54 ret
|= MAGIC_STATE_LIB
| MAGIC_STATE_LIB_SO
;
55 if (container
!= NULL
)
56 *container
= (void *)(sodesc
);
59 ret
|= MAGIC_STATE_LIB
| MAGIC_STATE_LIB_DSO
;
60 if (container
!= NULL
) {
61 *container
= (void *)(dsodesc
);
67 /*===========================================================================*
68 * magic_range_is_data *
69 *===========================================================================*/
70 PRIVATE INLINE
int magic_range_is_data(void *addr
)
72 MAGIC_RANGE_DEBUG_ADDR(addr
, magic_data_range
);
73 return MAGIC_ADDR_IS_IN_RANGE(addr
, magic_data_range
) ? MAGIC_STATE_DATA
: 0;
76 /*===========================================================================*
77 * magic_range_is_text *
78 *===========================================================================*/
79 PRIVATE INLINE
int magic_range_is_text(void *addr
)
81 MAGIC_RANGE_DEBUG_ADDR(addr
, magic_text_range
);
82 return MAGIC_ADDR_IS_IN_RANGE(addr
, magic_text_range
) ? MAGIC_STATE_TEXT
: 0;
85 /*===========================================================================*
86 * magic_range_is_heap *
87 *===========================================================================*/
88 PRIVATE INLINE
int magic_range_is_heap(void *addr
)
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;
97 /*===========================================================================*
98 * magic_range_is_stack *
99 *===========================================================================*/
100 PUBLIC
int magic_range_is_stack(void *addr
)
103 * NB!: This function requires the calling thread to already
104 * hold the DSENTRY lock.
106 struct _magic_sentry
*sentry
;
108 void *stack_range
[2];
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
-
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
);
121 MAGIC_RANGE_DEBUG_ADDR(addr
, stack_range
);
122 ret
= MAGIC_ADDR_IS_IN_RANGE(addr
, stack_range
) ? MAGIC_STATE_STACK
: 0;
127 /*===========================================================================*
128 * magic_range_is_dsentry *
129 *===========================================================================*/
130 PUBLIC
int magic_range_is_dsentry(void *addr
)
133 * NB!: This function requires the calling thread to already
134 * hold the DSENTRY lock.
137 void *start_address
, *end_address
;
138 struct _magic_dsentry
*prev_dsentry
, *dsentry
;
139 struct _magic_sentry
*sentry
;
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
);
155 else if(region
& MAGIC_STATE_MAP
) {
156 MAGIC_RANGE_UPDATE(magic_map_range
, start_address
, end_address
);
158 else if(region
& MAGIC_STATE_SHM
) {
159 MAGIC_RANGE_UPDATE(magic_shm_range
, start_address
, end_address
);
161 else if(region
& MAGIC_STATE_STACK
) {
162 MAGIC_RANGE_UPDATE(magic_stack_range
, start_address
, end_address
);
165 magic_update_dsentry_ranges
= 0;
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
;
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
;
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
;
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
;
187 /*===========================================================================*
188 * magic_range_is_dfunction *
189 *===========================================================================*/
190 PUBLIC
int magic_range_is_dfunction(void *addr
)
193 * NB!: This function requires the calling thread to already
194 * hold the DFUNCTION lock.
198 struct _magic_dfunction
* dfunction
;
199 struct _magic_function
* function
;
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
);
210 magic_update_dfunction_ranges
= 0;
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
;
220 /*===========================================================================*
221 * magic_ranges_init *
222 *===========================================================================*/
223 PUBLIC
void magic_ranges_init(void)
226 void *start_address
, *end_address
;
227 const char* linker_vars
[] = { MAGIC_LINKER_VAR_NAMES
};
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
);
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
)) {
242 MAGIC_RANGE_UPDATE(magic_data_range
, start_address
, end_address
);
244 #if MAGIC_RANGE_ROUND_DATA
245 MAGIC_RANGE_PAGE_ROUND(magic_data_range
);
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
);
255 /* Init text range. */
257 MAGIC_RANGE_SET(magic_text_range
, MAGIC_TEXT_START
,
258 MAGIC_TEXT_END
? MAGIC_TEXT_END
: ((char *)magic_function_range
[1]));
260 MAGIC_RANGE_SET(magic_text_range
, MAGIC_TEXT_START
,
261 MAGIC_TEXT_END
? MAGIC_TEXT_END
: ((char *)magic_data_range
[0] - 1));
263 #if MAGIC_RANGE_ROUND_TEXT
264 MAGIC_RANGE_PAGE_ROUND(magic_text_range
);
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;
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
);
279 /*===========================================================================*
280 * magic_range_lookup_by_addr *
281 *===========================================================================*/
282 PUBLIC
int magic_range_lookup_by_addr(void *addr
, void **container
)
285 * NB!: This function requires the calling thread to already
286 * hold the DSENTRY, DFUNCTION and DSODESC locks.
289 /* Constant ranges first. */
290 if (magic_range_is_data(addr
)) {
291 return MAGIC_STATE_DATA
;
293 if (magic_range_is_text(addr
)) {
294 return MAGIC_STATE_TEXT
;
297 /* Non-dsentry ranges next. */
298 if (magic_range_is_heap(addr
)) {
299 return MAGIC_STATE_HEAP
;
301 if (magic_range_is_stack(addr
)) {
302 return MAGIC_STATE_STACK
;
305 /* Shared library ranges. */
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
;
313 if ((ret
= magic_range_is_shlib(addr
, container
))) {
317 /* Dsentry ranges last. */
318 return magic_range_is_dsentry(addr
);