tabs->spaces
[AROS.git] / compiler / arossupport / purify.c
blobd53c1a6611687aaab65549a854c1285e7074b68a
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Support files for purify (incomplete)
6 Lang: english
7 */
9 /* Local prototypes */
10 #include <exec/lists.h>
11 #include <exec/execbase.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <proto/arossupport.h>
15 #include <proto/exec.h>
16 #include <aros/purify.h>
17 #include <aros/rt.h>
19 struct PNode
21 struct Node Node;
22 UBYTE * Memory;
23 ULONG Size;
24 UBYTE State[0];
27 static const char * pmsNames[] =
29 "free", "empty", "init.", "ro"
32 static struct List P_Memory;
33 static int InitWasCalled;
35 static struct PNode * FindNode (APTR memPtr);
36 static int FindNextNodes (APTR memPtr, struct PNode **, struct PNode **);
38 extern void RT_ShowRTStack (void);
40 /*****************************************************************************
42 NAME */
43 #include <aros/purify.h>
45 void Purify_Init (
47 /* SYNOPSIS */
48 void)
50 /* FUNCTION
51 Initialize purify.
53 INPUTS
54 none
56 RESULT
57 none
59 NOTES
60 This function is not part of any library and may thus be called at
61 any time.
63 EXAMPLE
65 BUGS
67 SEE ALSO
69 INTERNALS
71 HISTORY
73 ******************************************************************************/
75 NEWLIST (&P_Memory);
76 } /* Purify_Init */
79 /*****************************************************************************
81 NAME */
82 #include <aros/purify.h>
84 void Purify_AddMemory (
86 /* SYNOPSIS */
87 APTR memPtr,
88 ULONG size)
90 /* FUNCTION
91 Add size bytes of memory at memPtr to watch. Any access to this
92 memory will be checked after this call.
94 INPUTS
95 memPtr - Start of the memory block
96 size - The size of the memory block
98 RESULT
99 none
101 NOTES
102 This function is not part of any library and may thus be called at
103 any time.
105 EXAMPLE
107 BUGS
109 SEE ALSO
111 INTERNALS
113 HISTORY
115 ******************************************************************************/
117 struct PNode * node;
119 if (!InitWasCalled)
120 Purify_Init ();
122 if (!(node = malloc (sizeof (struct PNode) + size)) )
123 return;
125 node->Memory = memPtr;
126 node->Size = size;
127 memset (node->State, PMS_FREE, size);
129 AddHead (&P_Memory, (struct Node *)node);
130 } /* Purify_AddMemory */
133 /*****************************************************************************
135 NAME */
136 #include <aros/purify.h>
138 void Purify_SetState (
140 /* SYNOPSIS */
141 APTR memPtr,
142 ULONG size,
143 ULONG state)
145 /* FUNCTION
146 Brings a block of memory into a certain state (eg. empty, initialized,
147 read-only). memPtr and size must be within a block beforehand
148 declared with Purify_AddMemory().
150 INPUTS
151 memPtr - Where to start
152 size - How many bytes after memPtr
153 state - The new state of the memory:
154 PMS_EMPTY - The memory may be read from and written to,
155 but any read before the first write will yield an
156 error (read from uninitialized memory).
157 PMS_INITIALIZED - The memory has been initialized and may
158 be read and writen to.
159 PMS_READONLY - The memory may be read but not written to.
160 PMS_FREE - The memory may not be read from or written to.
162 RESULT
163 none
165 NOTES
167 EXAMPLE
169 BUGS
171 SEE ALSO
173 INTERNALS
175 HISTORY
177 ******************************************************************************/
179 struct PNode * node, * nodeBefore, * nodeAfter;
180 UBYTE * mem;
182 if (!InitWasCalled)
183 Purify_Init ();
185 /* Look for a node which contains memPtr */
186 node = FindNode (memPtr);
188 mem = memPtr;
190 /* Is there one ? */
191 if (!node)
193 /* Look for the node we know about which comes least before and
194 right next after memPtr. This will _not_ return any node
195 which contains memPtr because there is none. If there are
196 none or the area we look for is in none of them, print a
197 message and exit. */
198 if (!FindNextNodes (memPtr, &nodeBefore, &nodeAfter)
199 || mem+size <= nodeAfter->Memory
202 kprintf ("Purify: Tried to set state %s for unpurifed memory at %p:%ld\n"
203 , pmsNames[state]
204 , memPtr
205 , size
207 return;
210 /* If we get here, we have found a node which comes after memPtr
211 but memPtr is not inside the node */
213 else
215 if (mem+size <= node->Memory+node->Size)
216 memset (&node->State[mem - node->Memory], state, size);
217 else
218 kprintf ("Purify: %p:%ld exceeds PNode %p:%ld\n"
219 , mem
220 , size
221 , node->Memory
222 , node->Size
225 } /* Purify_SetState */
228 /*****************************************************************************
230 NAME */
231 #include <aros/purify.h>
233 void Purify_CheckAccess (
235 /* SYNOPSIS */
236 APTR memPtr,
237 ULONG size,
238 ULONG type)
240 /* FUNCTION
241 Checks a specific kind of access to memPtr[0...size-1].
243 INPUTS
244 memPtr - Where the access happens
245 size - How many bytes are accessed
246 type - Kind of access (PMA_READ, PMA_WRITE or PMA_MODIFY)
248 RESULT
249 none
251 NOTES
253 EXAMPLE
255 BUGS
257 SEE ALSO
259 INTERNALS
261 HISTORY
263 ******************************************************************************/
265 struct PNode * node;
266 UBYTE * mem;
268 if (!InitWasCalled)
269 Purify_Init ();
271 /* Look for a node which contains memPtr */
272 node = FindNode (memPtr);
274 mem = memPtr;
276 /* Is there one ? */
277 if (!node)
279 kprintf ("Purify: Illegal access %p:%ld\n"
280 , mem
281 , size
283 RT_ShowRTStack ();
285 else
287 if (mem+size > node->Memory+node->Size)
288 kprintf ("Purify: Access %p:%ld beyond bounds %p:%ld\n"
289 , mem
290 , size
291 , node->Memory
292 , node->Size
294 else
296 switch (type)
298 case PMA_READ:
299 mem = &node->State[mem - node->Memory];
301 for ( ; size; size --)
303 switch (*mem)
305 case PMS_EMPTY:
306 kprintf ("Purify: Read of undefined memory at %p (%ld bytes from the beginning of the block)\n"
307 , node->Memory - node->State + mem
308 , mem - node->State
310 RT_ShowRTStack ();
311 size = 1;
312 break;
314 case PMS_INITIALIZED:
315 break;
317 case PMS_READONLY:
318 break;
320 case PMS_FREE:
321 kprintf ("Purify: Read of freed memory at %p (%ld bytes from the beginning of the block)\n"
322 , node->Memory - node->State + mem
323 , mem - node->State
325 RT_ShowRTStack ();
326 size = 1;
327 break;
328 } /* switch */
329 } /* for */
331 break;
333 case PMA_WRITE:
334 mem = &node->State[mem - node->Memory];
336 for ( ; size; size --)
338 switch (*mem)
340 case PMS_EMPTY:
341 *mem = PMS_INITIALIZED;
342 break;
344 case PMS_INITIALIZED:
345 break;
347 case PMS_READONLY:
348 kprintf ("Purify: Write to readonly memory at %p (%ld bytes from the beginning of the block)\n"
349 , node->Memory - node->State + mem
350 , mem - node->State
352 RT_ShowRTStack ();
353 size = 1;
354 break;
355 break;
357 case PMS_FREE:
358 kprintf ("Purify: Write to freed memory at %p (%ld bytes from the beginning of the block)\n"
359 , node->Memory - node->State + mem
360 , mem - node->State
362 RT_ShowRTStack ();
363 size = 1;
364 break;
365 } /* switch */
368 break;
370 case PMA_MODIFY:
371 mem = &node->State[mem - node->Memory];
373 for ( ; size; size --)
375 switch (*mem)
377 case PMS_EMPTY:
378 kprintf ("Purify: Modify of undefined memory at %p (%ld bytes from the beginning of the block)\n"
379 , node->Memory - node->State + mem
380 , mem - node->State
382 RT_ShowRTStack ();
383 size = 1;
384 break;
386 case PMS_INITIALIZED:
387 break;
389 case PMS_READONLY:
390 kprintf ("Purify: Modify of readonly memory at %p (%ld bytes from the beginning of the block)\n"
391 , node->Memory - node->State + mem
392 , mem - node->State
394 RT_ShowRTStack ();
395 size = 1;
396 break;
398 case PMS_FREE:
399 kprintf ("Purify: Modify of freed memory at %p (%ld bytes from the beginning of the block)\n"
400 , node->Memory - node->State + mem
401 , mem - node->State
403 RT_ShowRTStack ();
404 size = 1;
405 break;
406 } /* switch */
409 break;
411 } /* switch (access type) */
412 } /* Complete within bounds ? */
413 } /* Node with memPtr found ? */
414 } /* Purify_CheckAccess */
417 /*****************************************************************************
419 NAME */
420 static struct PNode * FindNode (
422 /* SYNOPSIS */
423 APTR memPtr)
425 /* FUNCTION
426 Searches for the PNode which contains memPtr.
428 INPUTS
429 memPtr - A pointer into a piece of memory previously made known
430 with Purify_AddMemory.
432 RESULT
433 A pointer to a PNode which contains the memPtr or NULL if there
434 is no such pointer. No error will be printed.
436 NOTES
437 Must not be called before Purify_Init().
439 EXAMPLE
441 BUGS
443 SEE ALSO
445 INTERNALS
447 HISTORY
449 ******************************************************************************/
451 struct PNode * node;
453 for (node=(struct PNode *)GetHead(&P_Memory); node; node=(struct PNode *)GetSucc(node))
455 if (node->Memory <= (UBYTE *)memPtr
456 || (UBYTE *)memPtr < node->Memory+node->Size
458 break;
461 return node;
462 } /* FindNode */
465 /*****************************************************************************
467 NAME */
468 static int FindNextNodes (
470 /* SYNOPSIS */
471 APTR memPtr,
472 struct PNode ** before,
473 struct PNode ** after)
475 /* FUNCTION
476 Returns the addresses of the PNodes right before and right right
477 after memPtr.
479 INPUTS
480 memPtr - The address to look for
481 before - Pointer to a pointer to PNode where the address of
482 the node right before memPtr will be stored.
483 after - Pointer to a pointer to PNode where the address of
484 the node right after memPtr will be stored.
486 RESULT
487 The number of found PNodes. *before will contain a pointer to
488 the PNode which is before memPtr or which contains memPtr or NULL
489 if there is no node before PNode. *after will contain a pointer
490 to the first PNode which comes right after memPtr or NULL if no
491 PNode follows memPtr.
493 NOTES
494 Must not be called before Purify_Init().
496 EXAMPLE
498 BUGS
500 SEE ALSO
502 INTERNALS
504 HISTORY
506 ******************************************************************************/
508 int found = 0;
509 struct PNode * node;
511 *before = NULL;
512 *after = NULL;
514 for (node=(struct PNode *)GetHead(&P_Memory); node; node=(struct PNode *)GetSucc(node))
516 if (!*before)
518 if (node->Memory < (UBYTE *)memPtr)
520 found |= 1;
521 *before = node;
524 else
526 if (node->Memory < (UBYTE *)memPtr
527 && (*before)->Memory < node->Memory
530 found |= 1;
531 *before = node;
535 if (!*after)
537 if (node->Memory > (UBYTE *)memPtr)
539 found |= 2;
540 *after = node;
543 else
545 if (node->Memory > (UBYTE *)memPtr
546 && (*after)->Memory > node->Memory
549 found |= 2;
550 *after = node;
555 if (found == 2)
556 found = 1;
557 else if (found == 3)
558 found = 2;
560 return found;
561 } /* FindNextNodes */