source: git/omalloc/omDebugCheck.c @ 384936

spielwiese
Last change on this file since 384936 was 384936, checked in by Olaf Bachmann <obachman@…>, 24 years ago
made 64 bit clean git-svn-id: file:///usr/local/Singular/svn/trunk@4680 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 18.5 KB
Line 
1/*******************************************************************
2 *  File:    omDebugCheck.c
3 *  Purpose: implementation of omCheck functions
4 *  Author:  obachman@mathematik.uni-kl.de (Olaf Bachmann)
5 *  Created: 11/99
6 *  Version: $Id: omDebugCheck.c,v 1.10 2000-10-27 15:28:51 obachman Exp $
7 *******************************************************************/
8#include <limits.h>
9#include <stdarg.h>
10
11#include "omAlloc.h"
12#include "omDebug.h"
13
14#ifndef OM_NDEBUG
15/*******************************************************************
16 * 
17 *   Declarations: Static function
18 * 
19 *******************************************************************/
20unsigned long om_MaxAddr = 0;
21unsigned long om_MinAddr = ULONG_MAX;
22static omError_t omDoCheckLargeAddr(void* addr, void* bin_size, omTrackFlags_t flags, char level,
23                                    omError_t report, OM_FLR_DECL);
24omError_t omDoCheckBin(omBin bin, int normal_bin, char level, 
25                       omError_t report, OM_FLR_DECL);
26static omError_t omDoCheckBinPage(omBinPage page, int normal_page, int level, 
27                                  omError_t report, OM_FLR_DECL);
28static void _omPrintAddrInfo(FILE* fd, omError_t error, void* addr, void* bin_size, omTrackFlags_t flags, int max_frames, char* s);
29
30
31/*******************************************************************
32 * 
33 * First level omCheck routines: dispatch to lower-level omDoCheck
34 * routines which do the actual tests
35 * 
36 *******************************************************************/
37omError_t _omCheckAddr(void* addr, void* size_bin, 
38                       omTrackFlags_t flags, char check, omError_t report, OM_FLR_DECL)
39{
40  if (check <= 0) return omError_NoError;
41  if (check > 1)
42  {
43    omCheckReturn(check > 2 && _omCheckMemory(check - 2, (report ? report : omError_MemoryCorrupted), OM_FLR_VAL));
44    omCheckReturn(omIsBinPageAddr(addr) && omDoCheckBin(omGetBinOfAddr(addr), !omIsBinAddrTrackAddr(addr), check-1, 
45                                                        (report ? report : omError_MemoryCorrupted), OM_FLR_VAL));
46  }
47  return omDoCheckAddr(addr, size_bin, flags, check, report, OM_FLR_VAL);
48}
49
50omError_t _omCheckBin(omBin bin, int what_bin, char check, omError_t report, OM_FLR_DECL)
51{
52  if (check <= 0) return omError_NoError;
53
54  omCheckReturn(check > 1 && _omCheckMemory(check - 1, (report ? report : omError_MemoryCorrupted), OM_FLR_VAL));
55
56  return omDoCheckBin(bin, what_bin, check, report, OM_FLR_VAL);
57}
58
59omError_t _omCheckMemory(char check, omError_t report, OM_FLR_DECL)
60{
61  int i = 0;
62  omSpecBin s_bin;
63  omBin sticky;
64 
65  if (check <= 0) return omError_NoError;
66 
67  omCheckReturn(omCheckBinPageRegions(check, report, OM_FLR_VAL));
68 
69  for (i=0; i<= OM_MAX_BIN_INDEX; i++)
70  {
71    omCheckReturn(omDoCheckBin(&om_StaticBin[i], 1, check, report, OM_FLR_VAL));
72  }
73
74  s_bin = om_SpecBin;
75  omCheckReturn(omCheckGList(s_bin, next, check, omError_MemoryCorrupted, OM_FLR_VAL));
76  while (s_bin != NULL)
77  {
78    omCheckReturn(omDoCheckBin(s_bin->bin, 1, check, report, OM_FLR_VAL));
79    s_bin = s_bin->next;
80  }
81
82  sticky = om_StickyBins;
83  omCheckReturn(omCheckGList(sticky, next, check, omError_MemoryCorrupted, OM_FLR_VAL));
84  while (sticky != NULL)
85  {
86    omCheckReturn(omDoCheckBin(sticky, 1, check, report, OM_FLR_VAL));
87    sticky = sticky->next;
88  }
89 
90#ifdef OM_HAVE_TRACK
91  for (i=0; i<= OM_MAX_BIN_INDEX; i++)
92  {
93    omCheckReturn(omDoCheckBin(&om_StaticTrackBin[i], 0, check, report, OM_FLR_VAL));
94  }
95  s_bin = om_SpecTrackBin;
96  omCheckReturn(omCheckGList(s_bin, next, check, omError_MemoryCorrupted, OM_FLR_VAL));
97  while (s_bin != NULL)
98  {
99    omCheckReturn(omDoCheckBin(s_bin->bin, 0, check, report, OM_FLR_VAL));
100    s_bin = s_bin->next;
101  }
102#endif
103 
104  if (check > 1)
105  {
106    if (om_KeptAddr != NULL)
107    {
108      void* addr = om_KeptAddr;
109      omCheckReturn(omCheckList(om_KeptAddr, check - 1, (report ? report :  omError_KeptAddrListCorrupted), OM_FLR_VAL));
110      while (addr != NULL)
111      {
112        omCheckReturn(omDoCheckAddr(addr, NULL, OM_FKEPT, check, report, OM_FLR_VAL));
113        addr = *((void**) addr);
114      }
115    }
116    if (om_AlwaysKeptAddrs != NULL)
117    {
118      void* addr = om_AlwaysKeptAddrs;
119      omCheckReturn(omCheckList(om_AlwaysKeptAddrs, check - 1, (report ? report :  omError_KeptAddrListCorrupted), OM_FLR_VAL));
120      while (addr != NULL)
121      {
122        omCheckReturn(omDoCheckAddr(addr, NULL, OM_FKEPT, check, report, OM_FLR_VAL));
123        addr = *((void**) addr);
124      }
125    }
126  }
127
128  return omError_NoError;
129}
130
131/*******************************************************************
132 * 
133 * Second level omCheck routines: do the actual checks
134 * 
135 *******************************************************************/
136
137omError_t omCheckPtr(void* ptr, omError_t report, OM_FLR_DECL)
138{
139  omCheckReturnError(ptr == NULL, omError_NullAddr);
140  omCheckReturnError(!OM_IS_ALIGNED(ptr), omError_UnalignedAddr);
141  omCheckReturnError(((unsigned long) ptr) < om_MinAddr || 
142                     ((unsigned long) ptr) >= om_MaxAddr, omError_InvalidRangeAddr);
143  return omError_NoError;
144}
145 
146
147omError_t omDoCheckAddr(void* addr, void* bin_size, omTrackFlags_t flags, char level, 
148                        omError_t report, OM_FLR_DECL)
149{
150  if (level <= 0) return omError_NoError;
151  omAssume(! ((flags & OM_FSIZE) && (flags & OM_FBIN)));
152 
153  if (addr == NULL)
154  {
155    omCheckReturnError(!(flags & OM_FSLOPPY), omError_NullAddr);
156    return omError_NoError;
157  }
158  if ((flags & OM_FSIZE) && bin_size == NULL) return omError_NoError;
159  omAddrCheckReturn(omCheckPtr(addr, report, OM_FLR_VAL));
160  omAddrCheckReturnError((flags & OM_FALIGN) &&  !OM_IS_STRICT_ALIGNED(addr), omError_UnalignedAddr);
161  omAddrCheckReturnError((flags & OM_FBIN) && !omIsKnownTopBin((omBin) bin_size, 1), omError_UnknownBin);
162 
163  if (omIsBinPageAddr(addr))
164  {
165#ifdef OM_HAVE_TRACK
166    if (omIsBinAddrTrackAddr(addr))
167      return omCheckTrackAddr(addr, bin_size, flags, level, report, OM_FLR_VAL);
168    else
169#endif
170      return omDoCheckBinAddr(addr, bin_size, flags, level, report, OM_FLR_VAL);
171  }
172  else
173  {
174    return omDoCheckLargeAddr(addr, bin_size, flags, level, report, OM_FLR_VAL);
175  }
176}
177
178
179
180static omError_t omDoCheckLargeAddr(void* addr, void* bin_size, omTrackFlags_t flags, char level, 
181                                    omError_t report, OM_FLR_DECL)
182{
183  size_t r_size;
184 
185  omAssume(! omIsBinPageAddr(addr));
186  omAssume(! omCheckPtr(addr, omError_NoError, OM_FLR));
187 
188  omAddrCheckReturnError((flags & OM_FBIN) || (flags & OM_FBINADDR), omError_NotBinAddr);
189  omAddrCheckReturnError(level > 1 && omFindRegionOfAddr(addr) != NULL, omError_FreedAddrOrMemoryCorrupted);
190  r_size = omSizeOfLargeAddr(addr);
191  omAddrCheckReturnError(! OM_IS_ALIGNED(r_size), omError_FalseAddrOrMemoryCorrupted);
192  omAddrCheckReturnError(r_size <= OM_MAX_BLOCK_SIZE, omError_FalseAddrOrMemoryCorrupted);
193  omAddrCheckReturnError((flags & OM_FSIZE) && r_size < OM_ALIGN_SIZE((size_t) bin_size),
194                         omError_WrongSize);
195  omAddrCheckReturnError((level > 1) && (flags & OM_FUSED) && omIsInKeptAddrList(addr), omError_FreedAddr);
196  return omError_NoError;
197}
198
199omError_t omDoCheckBinAddr(void* addr, void* bin_size, omTrackFlags_t flags, char level, 
200                           omError_t report, OM_FLR_DECL)
201{
202  omBinPage page = omGetBinPageOfAddr(addr);
203  omBinPageRegion region = page->region;
204  omBin bin = omGetBinOfPage(page);
205 
206  omAssume(omIsBinPageAddr(addr));
207  omAssume(! omCheckPtr(addr, 0, OM_FLR));
208 
209  omAddrCheckReturnCorrupted(! omIsKnownTopBin(bin, ! omIsBinAddrTrackAddr(addr)));
210
211  if (flags & OM_FBINADDR && flags & OM_FSIZE)
212    omAddrCheckReturnError(bin->sizeW*SIZEOF_LONG != (size_t) bin_size, omError_WrongSize);
213   
214  if (level > 1)
215  {
216    omAddrCheckReturnError(omIsAddrOnFreeBinPage(addr), omError_FreedAddr);
217    omAddrCheckReturnError(omFindRegionOfAddr(addr) != region, omError_FreedAddrOrMemoryCorrupted);
218    omAddrCheckReturnError(!omIsOnGList(bin->last_page, prev, page), omError_FreedAddrOrMemoryCorrupted);
219
220    if (flags & OM_FUSED)
221    {
222      omAddrCheckReturnError(omIsOnList(page->current, addr), omError_FreedAddr);
223      omAddrCheckReturnError((level > 1) && omIsInKeptAddrList(addr), omError_FreedAddr);
224    }
225  }
226  else
227  {
228    omAddrCheckReturnError(omCheckPtr(region, omError_MaxError, OM_FLR_VAL), omError_FreedAddrOrMemoryCorrupted);
229  }
230 
231 
232  /* Check that addr is aligned within page of bin */
233  omAddrCheckReturnError((bin->max_blocks >= 1) &&
234                         ( ( ( (unsigned long) addr) 
235                             - ((unsigned long) page) 
236                             - SIZEOF_OM_BIN_PAGE_HEADER) 
237                           % (bin->sizeW * SIZEOF_VOIDP)
238                           != 0), omError_FalseAddr);
239
240  /* Check that specified bin or size is correct */
241  omAddrCheckReturnError((flags & OM_FBIN) &&  bin_size != NULL 
242                         && ((omBin) bin_size) != omGetTopBinOfAddr(addr), omError_WrongBin);
243
244  if ((flags & OM_FSIZE) && (!(flags & OM_FSLOPPY)  || (size_t) bin_size > 0))
245  {
246    size_t size = (size_t) bin_size;
247    omAssume(!omIsBinAddrTrackAddr(addr));
248    omAddrCheckReturnError((bin->sizeW << LOG_SIZEOF_LONG) < OM_ALIGN_SIZE(size), omError_WrongSize);
249  }
250
251  return omError_NoError;
252}
253
254omError_t omDoCheckBin(omBin bin, int normal_bin, char level, 
255                       omError_t report, OM_FLR_DECL)
256{
257  omBin top_bin = bin;
258 
259  omCheckReturnError(!omIsKnownTopBin(bin, normal_bin), omError_UnknownBin);
260  if (! omIsStickyBin(bin))
261    omCheckReturn(omCheckGList(bin->next, next, level, report, OM_FLR_VAL));
262 
263  do
264  {
265    int where;
266    omBinPage page;
267
268    if (bin->last_page == NULL || bin->current_page == om_ZeroPage)
269    {
270      omCheckReturnCorrupted(! (bin->current_page == om_ZeroPage && bin->last_page == NULL));
271      continue;
272    }
273    omCheckReturn(omDoCheckBinPage(bin->current_page, normal_bin, level, report, OM_FLR_VAL));
274    omCheckReturn(bin->current_page != bin->last_page  && 
275                  omDoCheckBinPage(bin->last_page, normal_bin, level, report, OM_FLR_VAL));
276    omCheckReturnCorrupted(bin->last_page->next != NULL);
277
278    if (bin != top_bin)
279    {
280      omCheckReturnCorrupted(bin->sizeW != top_bin->sizeW ||
281                             bin->max_blocks != top_bin->max_blocks);
282    }
283    if (level <= 1) continue;
284   
285    if (! omIsStickyBin(bin))
286      omCheckReturnCorrupted(omFindInGList(bin->next, next, sticky, bin->sticky));
287    omCheckReturn(omCheckGList(bin->last_page, prev, level-1, report, OM_FLR_VAL));
288    page = omGListLast(bin->last_page, prev);
289    omCheckReturn(omCheckGList(page, next, level-1, report, OM_FLR_VAL));
290    omCheckReturnCorrupted(omGListLength(bin->last_page, prev) != omGListLength(page, next));
291   
292    omCheckReturnCorrupted(! omIsOnGList(bin->last_page, prev, bin->current_page));
293   
294    page = bin->last_page;
295    where = 1;
296    while (page != NULL)
297    {
298      omCheckReturnCorrupted(omGetTopBinOfPage(page) != top_bin);
299      omCheckReturn(page != bin->last_page && page != bin->current_page &&
300                    omDoCheckBinPage(page, normal_bin, level - 1, report, OM_FLR_VAL));
301
302      omCheckReturnCorrupted(page != bin->last_page && 
303                             (page->next == NULL || page->next->prev != page));
304      omCheckReturnCorrupted(page->prev != NULL && page->prev->next != page);
305     
306      omCheckReturnCorrupted(omGetStickyOfPage(page) != bin->sticky && bin->sticky < SIZEOF_VOIDP);
307      omCheckReturnCorrupted(omGetBinOfPage(page) != bin);
308     
309      if (where == -1)
310      {
311        /* we are at the left of current_page,
312           i.e., page is empty */
313        omCheckReturnCorrupted(omGetUsedBlocksOfPage(page) != 0 || page->current != NULL);
314      }
315      else
316      {
317        if (page == bin->current_page)
318        {
319          where = -1;
320        }
321        else
322        {
323          /* we are at the right of current_page,
324             i.e., page is neither full nor empty */
325          omCheckReturnCorrupted(page->current == NULL ||
326                                 omGetUsedBlocksOfPage(page) == bin->max_blocks - 1);
327        }
328      }
329      page = page->prev;
330    }   /* while (page != NULL) */
331  } while (!omIsStickyBin(bin) && ((bin = bin->next) != NULL));
332 
333  return omError_NoError;
334}
335 
336
337static omError_t omDoCheckBinPage(omBinPage page, int normal_page, int level, 
338                                  omError_t report, OM_FLR_DECL)
339{
340  omBin bin;
341 
342  omCheckReturn(omCheckPtr(page, report, OM_FLR_VAL));
343  omCheckReturnCorrupted(! omIsAddrPageAligned(page));
344
345  omCheckReturn(omCheckPtr(page->region, report, OM_FLR_VAL));
346  omCheckReturnCorrupted(level > 1 && omFindRegionOfAddr(page) != page->region);
347
348 
349#ifdef OM_HAVE_TRACK
350  if (! normal_page)
351  {
352    omCheckReturnCorrupted(! omIsSetTrackOfUsedBlocks(page->used_blocks));
353  }
354  else
355#endif
356    omAssume(normal_page);
357 
358  bin = omGetTopBinOfPage(page);
359  if (bin->max_blocks > 1)
360  {
361    omCheckReturnCorrupted(omGetUsedBlocksOfPage(page) > bin->max_blocks - 1);
362    omCheckReturnCorrupted(omGetUsedBlocksOfPage(page) == bin->max_blocks - 1 && 
363                           page->current != NULL);
364    omCheckReturnCorrupted(omGetUsedBlocksOfPage(page) < 0);
365  }
366  else
367  {
368    omCheckReturnCorrupted(omGetUsedBlocksOfPage(page) != 0);
369  }
370 
371  omCheckReturn(omCheckList(page->current, level, report, OM_FLR_VAL));
372
373  if (level > 1)
374  {
375    void* current = page->current;
376
377    omCheckReturnCorrupted(current != NULL &&
378                           omListLength(current) != bin->max_blocks - omGetUsedBlocksOfPage(page) - 1);
379   
380    while (current != NULL)
381    {
382      omCheckReturnCorrupted(omGetPageOfAddr(current) != page);
383     
384      omCheckReturnCorrupted( ( ( (unsigned long) current) 
385                                - ((unsigned long) page) 
386                                - SIZEOF_OM_BIN_PAGE_HEADER) 
387                              % (bin->sizeW * SIZEOF_LONG)
388                              != 0);
389      current = *((void**) current);
390    }
391  }
392  return omError_NoError;
393}
394
395omError_t omReportAddrError(omError_t error, omError_t report_error, void* addr, void* bin_size, omTrackFlags_t flags, 
396                            OM_FLR_DECL, const char* fmt, ...) 
397{
398  int max_check, max_track;
399  va_list ap;
400  va_start(ap, fmt);
401 
402  /* reset MaxTrack and MaxCheck to prevent infinite loop, in case
403     printf allocates memory */
404  max_check = om_Opts.MaxCheck;
405  max_track = om_Opts.MaxTrack;
406  om_Opts.MaxCheck = 0;
407  om_Opts.MaxTrack = 0;
408 
409  om_CallErrorHook = 0;
410  omReportError(error, report_error, OM_FLR_VAL, fmt, ap);
411  om_CallErrorHook = 1;
412 
413  _omPrintAddrInfo(stderr, error, addr, bin_size, flags, 10, " occured for");
414  om_Opts.ErrorHook();
415 
416  om_Opts.MaxCheck = max_check;
417  om_Opts.MaxTrack = max_track;
418  return om_ErrorStatus;
419}
420
421void _omPrintAddrInfo(FILE* fd, omError_t error, void* addr, void* bin_size, omTrackFlags_t flags, int frames, char* s)
422{
423  if (! omCheckPtr(addr, omError_MaxError, OM_FLR))
424  {
425    fprintf(fd, "%s addr:%p size:%ld", s, addr, omSizeOfAddr(addr));
426 
427  if (error == omError_WrongSize && (flags & OM_FSIZE))
428    fprintf(fd, " specified size:%ld", (size_t) bin_size);
429 
430  if (error == omError_WrongBin && (flags & OM_FBIN))
431    fprintf(fd, " specified bin is of size:%ld", ((omBin) bin_size)->sizeW << LOG_SIZEOF_LONG);
432 
433  if (omIsTrackAddr(addr)) 
434    omPrintTrackAddrInfo(fd, addr, frames);
435  else
436    fprintf(fd, "\n");
437  }
438  else
439  {
440    fprintf(fd, "%s (invalid) addr: %p\n", s, addr);
441  }
442}
443
444void omPrintAddrInfo(FILE* fd, void *addr, char* s)
445{
446  _omPrintAddrInfo(fd, omError_NoError, addr, NULL, 0, 10, s);
447}
448
449/*******************************************************************
450 * 
451 * Misc for iterating, etc.
452 * 
453 *******************************************************************/
454
455void omIterateTroughBinAddrs(omBin bin, void (*CallBackUsed)(void*), void (*CallBackFree)(void*))
456{
457  omBinPage page;
458  void* addr;
459  int is_free;
460  int i;
461 
462  do
463  {
464    page = bin->last_page;
465    while (page != NULL)
466    {
467      addr = (void*) page + SIZEOF_OM_BIN_PAGE_HEADER;
468      i = 0;
469      do
470      {
471        is_free = omIsOnList(page->current, addr) != NULL || omIsInKeptAddrList(addr);
472        if (is_free)
473        {
474          if (CallBackFree != NULL) CallBackFree(addr);
475        }
476        else 
477        {
478          if (CallBackUsed != NULL) CallBackUsed(addr);
479        }
480        addr = (void**) addr + bin->sizeW;
481        i++;
482      } while (i < bin->max_blocks);
483      page = page->prev;
484    }
485    if (omIsStickyBin(bin))
486      bin = NULL;
487    else 
488      bin = bin->next;
489  } while (bin != NULL);
490 
491}
492
493void omIterateTroughAddrs(int normal, int track, void (*CallBackUsed)(void*), void (*CallBackFree)(void*))
494{
495  int i;
496  omSpecBin s_bin;
497  omBin sticky;
498
499  if (normal)
500  {
501    for (i=0; i<=OM_MAX_BIN_INDEX; i++)
502    {
503      omIterateTroughBinAddrs(&om_StaticBin[i], CallBackUsed, CallBackFree);
504    }
505    s_bin = om_SpecBin;
506    while (s_bin != NULL)
507    {
508      omIterateTroughBinAddrs(s_bin->bin, CallBackUsed, CallBackFree);
509      s_bin = s_bin->next;
510    }
511  }
512 
513#ifdef OM_HAVE_TRACK
514  if (track)
515  {
516    for (i=0; i<=OM_MAX_BIN_INDEX; i++)
517    {
518      omIterateTroughBinAddrs(&om_StaticTrackBin[i], CallBackUsed, CallBackFree);
519    }
520    s_bin = om_SpecTrackBin;
521    while (s_bin != NULL)
522    {
523      omIterateTroughBinAddrs(s_bin->bin, CallBackUsed, CallBackFree);
524      s_bin = s_bin->next;
525    }
526  }
527#endif
528  sticky = om_StickyBins;
529  while (sticky != NULL)
530  {
531    omIterateTroughBinAddrs(sticky, CallBackUsed, CallBackFree);
532    sticky = sticky->next;
533  }
534}
535
536static FILE* om_print_used_addr_fd;
537static size_t om_total_used_size;
538static unsigned long om_total_used_blocks;
539static int om_print_frames;
540
541static void _omPrintUsedAddr(void* addr)
542{
543  if (!omIsTrackAddr(addr) || !omIsStaticTrackAddr(addr))
544  {
545    om_total_used_blocks++;
546    om_total_used_size += omSizeOfAddr(addr);
547    if (om_print_frames > 0)
548    {
549      _omPrintAddrInfo(om_print_used_addr_fd, omError_NoError, addr, NULL, 0, om_print_frames, "");
550      fprintf(om_print_used_addr_fd, "\n");
551    }
552  }
553}
554
555void omPrintUsedAddrs(FILE* fd, int max)
556{
557  om_total_used_size = 0;
558  om_total_used_blocks = 0;
559  om_print_used_addr_fd = (fd == NULL ? stdout : fd);
560  om_print_frames = max;
561  omIterateTroughAddrs(1, 1, _omPrintUsedAddr, NULL);
562  fprintf(fd, "UsedAddrs Summary: UsedBlocks:%ld  TotalSize:%ld\n", 
563          om_total_used_blocks, om_total_used_size);
564}
565
566void omPrintUsedTrackAddrs(FILE* fd, int max)
567{
568  om_total_used_size = 0;
569  om_total_used_blocks = 0;
570  om_print_used_addr_fd = (fd == NULL ? stdout : fd);
571  om_print_frames = max;
572  omIterateTroughAddrs(0, 1 ,  _omPrintUsedAddr, NULL);
573  fprintf(fd, "UsedTrackAddrs Summary: UsedBlocks:%ld  TotalSize:%ld\n", 
574          om_total_used_blocks, om_total_used_size);
575}
576
577#endif /* ! OM_NDEBUG */
Note: See TracBrowser for help on using the repository browser.