xref: /minix/minix/lib/libmagicrt/magic_range.c (revision d2532d3d)
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