home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / biblioteki / c_library / apurify / doc / mot-apurify.doc < prev    next >
Text File  |  1977-12-31  |  29KB  |  651 lines

  1.                    MOT-APurify v1.3
  2.                    ----------------
  3.  
  4.                 MOTOROLA-syntax version.
  5.  
  6.                  (c) by Samuel DEVULDER
  7.                     jan. 1996
  8.  
  9.                Samuel.Devulder@info.unicaen.fr
  10.  
  11. DESCRIPTION (SHORT):
  12. --------------------
  13.     This is APurify for compilers with MOTOROLA syntax asm-files. As far as
  14.     I know, all compilers exept GCC uses such a syntax. If you're using the
  15.     GCC compiler, then read MIT-APurify.doc instead. That version is rather
  16.     a version for the DICE compiler, but I think it  can  work    with  other
  17.     compilers. In the  following  of  that  document,  APurify    stands    for
  18.     MOT-APurify, and I assume you're using the DICE compiler.
  19.  
  20.     APurify is a program that allows you to detect bad accesses  to  memory
  21.     of your programs without any kind of specific external  devices  (MMU).
  22.     It avoids bugs due to accessing memory not owned by your program.
  23.  
  24.  
  25. INSTALLATION:
  26. ------------
  27.     That archive contains the version of APurify for the DICE  compiler
  28.     as well for other compilers. Here  is  a  description  of  DICE-related
  29.     files of this archive for that version. It also gives you  what  to  do
  30.     with those files to make an installation.
  31.  
  32.     - doc/MOT-APurify.doc    The file you are currently  reading. Put it
  33.                 with all your doc files. It is usefull from
  34.                 time to time.
  35.  
  36.     - doc/History        The whole history.  (this  file is not very
  37.                 usefull for common people). Do whatever you
  38.                 want with it.
  39.  
  40.     - bin/MOT-APurify    The parser tuned  for  the MOTOROLA syntax.
  41.                 Rename it as APurify and put it someware in
  42.                 your path. That program can  be  used  with
  43.                 any compiler that outputs  MOTOROLA  syntax
  44.                 (ie. all compilers except GCC).
  45.  
  46.     - lib/APur-dcc.lib    The DICE link-time  library.  Rename  it as
  47.                 APur.lib  and  put  it    someware  in   your
  48.                 library search-path if you  are  using    the
  49.                 DICE  compiler.  It  may  work     well    for
  50.                 other compilers (it is  a  COMMODORE-format
  51.                 library). If that library is not  good    for
  52.                 you (generating undefined labels or  else),
  53.                 then try APur-pdc.lib.    If  it    fails  too,
  54.                 then please contact  me  and  I'll  try  to
  55.                 include a specific version of that  library
  56.                 for that compiler in a future release.
  57.  
  58.     - lib/APur-pdc.dir    The PDC link-time  library.  Rename  it  as
  59.     - lib/APur-pdc.lib    APur.lib  and  put  it    someware  in   your
  60.                 library search-path if you  are  using    the
  61.                 PDC compiler. It may work  well  for  other
  62.                 compilers   (it   is   a   COMMODORE-format
  63.                 library). If that library is not  good    for
  64.                 you (generating undefined labels or  else),
  65.                 please contact me and I'll try to include a
  66.                 specific version of that library  for  that
  67.                 compiler in a future release.
  68.  
  69.     - test/test.c        Source of a stupid test file.  Just here to
  70.                 let  you  remake  the  test   program.     Do
  71.                 whatever you want with it.
  72.  
  73.     - test/test.dcc     Test file  Apurify'ed.  Run it  to  see how
  74.                 APurify  is  useful  :-).  (dice  generated
  75.                 file)
  76.  
  77.     - test/test.pdc     Test file  Apurify'ed.  Run it  to  see how
  78.                 APurify is useful :-). (pdc generated file)
  79.  
  80.  
  81. SYNOPSIS:
  82. --------
  83.     Usage: APurify [-revinfo] <inputfile> [options]
  84.  
  85.     Where options can be:
  86.     -h     To display this usage
  87.     -?     To display this usage
  88.     -tb     To test memory referenced through base register
  89.     -ts     To test memory referenced through stack register
  90.     -tl     To test memory referenced through local stack frame
  91.     -tp     To test pea instructions
  92.     -sd     To use BaseRegister-relative mode (small data)
  93.     -sc     To use PC-relative mode (small code)
  94.     -o arg     Specifies output file (def=%s)
  95.     -br arg  Sets the base register (def=A4)
  96.     -mp arg  Sets the main entry-point (def=_main)
  97.  
  98.     Options can be anywhere on the command line. NOTE: They can  nomore  be
  99.     merged together, they must be separated by a space. You  can pre-define
  100.     them with the environment variable AP_MOTP_OPT. For example, if you do:
  101.  
  102.     CLI> SetEnv AP_MOTP_OPT "-tb -br A5"
  103.  
  104.     Then, when "-tb -br A5" will automatically  be  added  to  the  command
  105.     line. The space between an option and its argument can be ommited. Thus
  106.     "-br A4" is the same as "-brA4". Here is a description of arguments and
  107.     flags:
  108.  
  109.     -revinfo    This displays informations  about APurify  (name,  size and
  110.         date of modules and number of  compilation  done  for  that
  111.         version).
  112.  
  113.     -br arg    This  sets  the  base  register  used  to  reference memory
  114.         in SMALL_DATA model. Usually A4 is used  for  that  perpose
  115.         and that's the default. If A5  is  used  instead  then  add
  116.         -brA5 on your command line.
  117.  
  118.     -tb     This enable APurify to check all referenced  memory through
  119.         the base register (see -br). If you are using a  SMALL_DATA
  120.         model, add this flag on  your  command    line.  By  default,
  121.         APurify won't check  memory  referenced  through  the  base
  122.         register.
  123.  
  124.         NOTE: for safest check, you should always use that  option,
  125.         even if you're not in smalldata model (A4 may  be  used  as
  126.         a temporary register in that case). To allow this, you    can
  127.         use the environment variable.
  128.  
  129.     -ts     This  enable  APurify to  check memory referenced  by stack
  130.         pointer (SP or A7). By default  APurify  won't  check  such
  131.         memory accesses (to reduce the code size and  increase  the
  132.         runtime speed). That option will detect when  you  have  no
  133.         more room on your stack (stack overflow).
  134.  
  135.     -tl     This enable APurify to check  memory  referenced   by local
  136.         stack pointer (the one that is link'ed and  unlink'ed  when
  137.         enterring and exiting a C-function). By  default,  this  is
  138.         switch off. This  option  allow  APurify  to  detect  stack
  139.         overflow.
  140.  
  141.     -tp     This enable APurify to check indirect  adresses pushed onto
  142.         the stack by using a pea. By  default  this  is  off.  When
  143.         used, that option will check things like "pea  a2@(10)"  or
  144.         the like. This can help  you  with  memory  accessed  by  a
  145.         pointer in a code that has not been APurify'ed. For example
  146.         this is usefull  for  things  like  fread(&ptr[10],10,1,fp)
  147.         because in that case the "pea a2@(10)" used to push on  the
  148.         stack &ptr[10] will be checked and if ptr[10] is not  owned
  149.         by your program, you'll get an APurify error.  Please  note
  150.         that this may no work all the time  since  &ptr[0]  can  be
  151.         translated as "movel a0,sp@-" which  won't be checked.
  152.  
  153.     -sd     This  tells   APurify    to  use   the  SMALL_DATA model  of
  154.         adressing. It  produces a  shorter  code. APurify will    use
  155.         he base register (specified  with -br or  A4 by default) to
  156.         access     it's data. That will   only  work if  your code is
  157.         adressing less than 64Kbytes of static data.
  158.  
  159.     -sc     This  tells  APurify  to   use    the   SMALL_CODE  model  of
  160.         adressing.  It    produces a shorter   code. APurify will use
  161.         PC-relative mode to access  it subroutines. if you  code is
  162.         less than 32Kbytes.
  163.  
  164.     -o arg    This specifies the name of the outputfile. If  ommited    the
  165.         outputfile will be the same as the inputfile (source file).
  166.         The name of the output file can be defined by a  real  name
  167.         or a pattern. A pattern is a string where special sequences
  168.         of characters (called specifier) are  replaced  by  special
  169.         strings. Let's suppose that inputfile is equal to
  170.  
  171.                 drive:path/file.ext
  172.  
  173.         Here is a description of specifiers:
  174.  
  175.             %s    will be replaced by the full source name:
  176.  
  177.                 drive:path/file.ext
  178.  
  179.             %S    will expand to the  full  source name  without    the
  180.             extension:
  181.  
  182.                 drive:path/file
  183.  
  184.             %b    stands for the full basename:
  185.  
  186.                 file.ext
  187.  
  188.             %B    is a shortcut for the  full  basename  without    the
  189.             extension:
  190.  
  191.                 file
  192.  
  193.             %p    is the path (ending "/" or ":" is included):
  194.  
  195.                 drive:path/
  196.  
  197.             %e    is the extension ("." is ommited):
  198.  
  199.                 ext
  200.  
  201.         Thus, if you put "-o ram:%B-apurify.%e" in the commandline,
  202.         then the outputfile  will  be  "ram:file-apurify.ext"  with
  203.         our example.
  204.  
  205.     -mp arg    This tells APurify which label should be considered as    the
  206.         entry-point. By default it is set to "_main", and it should
  207.         not be modified.
  208.  
  209.     -?
  210.     -h
  211.     ?        Obvious options.
  212.  
  213.  
  214. DESCRIPTION (A BIT LONGER):
  215. --------------------------
  216.     As a general rule, at the microprocessor level, there is  two  kind
  217.     of ways to access memory. There is direct access and indirect access to
  218.     memory. For example, in C, direct access can be viewed as accessing  to
  219.     global variables. Indirect access corresponds  to  accessing  an  array
  220.     value. More precisely, direct access corresponds to reading or  writing
  221.     a variable whose address is known at compilation  time  (or  since  the
  222.     loading of the program into the memory). Indirect access  is  used    for
  223.     variables whose adress is dynamicaly determined  by  the  program.    For
  224.     example, if p is a pointer to an array allocated by malloc(), *p is  an
  225.     indirect access. Such an access occur also in case of instruction  like
  226.     T[i] where T is a global array, because the  address  of  T[i]  is    not
  227.     known at compilation time, since it depends on the index value i. Using
  228.     indirect access to memory is called indirection.
  229.  
  230.     A regular program must not access memory not owned by it. That kind
  231.     of access can be qualified as illegal.
  232.  
  233.     Illegal direct access  to   memory  is    not  possible, because     by
  234.     definition, only global  variables can be  accessed that  way and those
  235.     variables belongs obviously to the program    (except for code written in
  236.     assembly   language   that    references  absolute   values, for example:
  237.     "btst  #6,$bfe001"; but that  kind of  code  is not a  good programming
  238.     :-)). So we can assume that direct access to memory is always right.
  239.  
  240.     On the other hand,  it is sure    that indirect access to  memory can
  241.     be illegal.  Many bugs are made by    overstepping array  boundaries.  If
  242.     that oversteppings are  in reading a value, there  is not much  trouble
  243.     for over running tasks (it is an error inside your  task); but if it is
  244.     in writing you may directly interfere with other tasks and big mess can
  245.     happen (total breakdown of the system).
  246.  
  247.     APurify works on  that kind of access  by verifying the validity of
  248.     indirect access to memory. It remebers the memory that was allocated by
  249.     the program and check the integrity of  each access. One can think that
  250.     makes a lot of tests ! Well, yes, but APurify is  not  designed  to  be
  251.     used in the general use of programs; just  in  test  phases.  Moreover,
  252.     indirections  do  no  occur  very  often  actually.  Only    array-based
  253.     variables produces indirections.  Thus,  the  variables  on  the  stack
  254.     --although being accessed by  indirection--  are  not  checked  because
  255.     their access is always safe (at least if there is no stack overflow !).
  256.     Also, in SMALL_DATA model, global  variables  access  is  done  through
  257.     indirection, but they are not checked.
  258.  
  259.     If an illegal access is found, APurify displays an error message on
  260.     the error stream of the program. There is two kind of illegal accesses.
  261.     Some are  accesses to memory that doesn't  belong to the program (it is
  262.     called an access between blocks), some others are accesses to a part of
  263.     memory owned by a program and an  other part not  owned by it (it is an
  264.     overstepping of a block). You can see this visually: If [ 1 ] and [ 2 ]
  265.     represent  two blocks allocated   by the  program and  ( 3 ) the memory
  266.     accessed, then
  267.  
  268.          ---- [ 1 ] ---- ( 3 ) ---- [ 2 ] ---->
  269.         0                       increasing address
  270.  
  271.     corresponds to the first kind of illegal access and
  272.  
  273.              ---- [ 1 ( ] 3 ) ---- [ 2 ] ----->
  274.     or
  275.              ---- [ 1 ] ---- ( 3 [ ) 2 ] ----->
  276.  
  277.     corresonds to the second kind of access. The first kind is very  common
  278.     but the second is quite rare (it's rather a misaligment problem).
  279.  
  280.     APurify has two output modes. One is verbose an tries to  give    lot
  281.     of informations by using words. The other one is more brief  and  gives
  282.     you the same informations but you'll have to decode them.
  283.  
  284.     When APurify starts and ends, it outputs  the  date/time.  This  is
  285.     useful if you are using logfiles. With that, you can keep all your logs
  286.     in a  single  file    and  retrieve  any  execution  with  it's  date  of
  287.     execution.
  288.  
  289.     In case of an error, APurify displays some  text.  The    first  line
  290.     looks like this one:
  291.  
  292.     **** APURIFY ERROR ! [$<N1>(<N2>) <ATTR> (<TEXT1>)] <TEXT2>:
  293.  
  294.     That line represent  the  accessed    memory.  <N1>  is  the    hexadecimal
  295.     address accessed. <N2> is the length of the access (in decimal). <ATTR>
  296.     represents the type of acess. <TEXT1> allows you to find where in  your
  297.     code the illegal accessed had happened. <TEXT2> describe  the  kind  of
  298.     illegal access.
  299.  
  300.     If the length (<N1>) is 1, then it was a byte access. 2 stands  for
  301.     a short access,  4    for  a    int/long  and  >4  for    movem  instruction.
  302.     Attributes, <ATTR>, can be "R--" or "-W-". The first one represents  an
  303.     access in reading a value and the second an access in writing a value.
  304.  
  305.     The text <TEXT1> look like this:
  306.  
  307.         <NAME>, PC=$<PC#> HUNK=$<HUNK#> OFFSET=$<OFF#>
  308.  
  309.     <NAME> is the name of the subroutine where the  error  occured.  It  is
  310.     always displayed (even if it is a "static" one). The rest of  the  line
  311.     can be partially displayed, showing as much informations as APurify can
  312.     get. <PC#> is a hexadecimal address pointing to  the  instruction  that
  313.     produced the error. <HUNK#> and <OFF#> are    the  hunk  number  and    the
  314.     relative offset of <PC#>. Using <HUNK#> and <OFF#> and a  disassembler,
  315.     you can very easilly find where your code is bad (BTW, I use dobj  from
  316.     netdcc, (c) by Matt Dillon). Please note  that  in  this  new  version,
  317.     <PC#> will nomore point to some instruction before the faultly one.  It
  318.     is always the real faultly adress.
  319.  
  320.     The remaining lines show the context  of  the  illegal    access.  It
  321.     gives you informations about the  surronding  memory  blocks  owned  by
  322.     your program. Each    block  is  displayed  according  to  the  following
  323.     pattern:
  324.  
  325.                [$<N1>(<N2>) <ATTR> (<TEXT>)]
  326.  
  327.     where <N1> is the hexadecimal address of the beginning  of    the  block,
  328.     <N2> its length (in decimal). Note that  the  length  may  seem  to  be
  329.     longer than the one allocated by malloc() and  the  address  may  point
  330.     before the one you obtained via malloc(). This is not wrong !  In  fact
  331.     you must know that the malloc() subroutine may  add  some  informations
  332.     (like an double-chained list or the length of the  allocation)  to  the
  333.     block you've requested. Those extra informations  are  put  before  the
  334.     address you recieve. That explain this behavior.  In  this    version  of
  335.     APur-dice.lib, this takes 8 extra bytes. So if you allocate  10  bytes,
  336.     don't be suprised if APurify thinks you've requested 18 bytes.
  337.  
  338.     <ATTR> are 3 status characters RWS
  339.  
  340.     where R means: read-enable block
  341.           W means: write-enable block
  342.           S means: system block (block not controlled by the program).
  343.  
  344.     If one access is forbidden, the letter '-' replaces  the  corresponding
  345.     character. <TEXT> is actually  the    name  of  the  procedure  that    has
  346.     allocated the block.
  347.  
  348.     With each block you can find an offset. That offset is the distance
  349.     between that block and the faultly address. In verbose  mode,  you    can
  350.     see some text explaining things about the relative position of a  block
  351.     and the accessed memory. In non-verbose  mode  you    can  just  see    the
  352.     offsets followed by the blocks. The shorter offset is  displayed  first
  353.     since that block is the one that is more likely overstepped.
  354.  
  355.     When an illegal writing occur (the only dangerous thing you can  do
  356.     by indirection, indeed), APurify tells you    to  that  error  is  really
  357.     dangerous and asks if you wish to stop your program. If  you  wish    so,
  358.     exit() is called. You can also ignore that error  or  ignore  all  such
  359.     errors (but then you'll surely meet the guru !).
  360.  
  361.     APurify checks the memory allocated but not freed by  the  program.
  362.     (in fact, it detects non deallocated-blocks on library-closing time).
  363.  
  364.     It  knows  about  memory  location  independant  of   the   program
  365.     execution. That is to say, the first kilobyte of memory  that  contains
  366.     interrupt vectors of the 680x0 processor, the program segments and    the
  367.     stack. Accessing to those blocks will not be illegal. They    got  the  S
  368.     attribute (for SYSTEM blocks).
  369.  
  370.     It takes into  account    memory    block  allocated  by  malloc()  and
  371.     AllocMem(), and indirect allocated block (by OpenScreen() for example).
  372.     But I did not test the last kind of allocation. Anyway,  it  should  be
  373.     ok, because APurify patches AllocMem()  &  FreeMem()  entries.  Thus  a
  374.     program can access to the bitplanes of one of its screen without error.
  375.  
  376.     If  the  program  makes  a  legal  access,   but   attributes    are
  377.     incompatible  with    the  access-kind,  a  protection-error    message  is
  378.     displayed. Actually only the first    kilobyte  is  read/write-protected.
  379.     But it may change in the future.
  380.  
  381.  
  382. HOW TO USE APURIFY:
  383. ------------------
  384.     One can see APurify as a pre-assembler. It must be used on assembly
  385.     language sourcefile just before the assembler takes place. It scan    the
  386.     file and change it a bit so that APur.lib can be used.
  387.  
  388.     Normal way to use it for a C program is to:
  389.  
  390.     - compile C sourcefiles and leave assembly language source (.a).
  391.     - use APurify on each .a file.
  392.     - compile your .a file to get a .o file
  393.     - link all .o files together with APur.lib.
  394.  
  395.     For example, using dcc (DICE) on prog.c that gives
  396.  
  397.     CLI> dcc -a prog.c -o prog.a
  398.     CLI> APurify -tb prog.a
  399.     CLI> dcc -s prog.a -o prog -lAPur
  400.  
  401.  
  402.     As you can see, APurify needs no change to your C files to be used.
  403.     In this realease you need no more  to  call  AP_Init()  in  the  main()
  404.     function. The call is automatically inserted when the main-entry  label
  405.     (specified by -mp) is found. You shoud not  use  dos.library/Exit()  to
  406.     abort your program, I think it'll crash if APurify is running.  If  you
  407.     must use Exit() then call AP_Close() just before  calling  Exit().  The
  408.     explantion is simple: since some system functions  are  patched,  if  a
  409.     program  exits  without  closing  the  library,  those  patch  will  be
  410.     corruped, pointing to a code that is nomore in memory and  you'll  meet
  411.     the guru (ie: the computer will crash)... (You've been warned :-).
  412.  
  413.     You can disable/enable printing of messages by    making    a  call  to
  414.     AP_Report(flag). If  flag  is  true  (ie.  different  from  zero)  then
  415.     printing is enabled, if it is false (ie. equal to zero), no output will
  416.     be done. This is usefull for startup-codes. For  example,  if  you    are
  417.     using the argv[] array in C, APurify will make  a  lot  of    false-error
  418.     printing. This is because the values pointed by this array is allocated
  419.     before  the  library  is  opened.  You  can  avoid    this   by   calling
  420.     AP_Report(0) before, and AP_Report(1) after, the code that uses argv[].
  421.  
  422.     When debugging an APurify'ed program, you can put a  breakpoint  on
  423.     a function called AP_Err(). That function AP_Err() is called each  time
  424.     APurify detects an error. With that, you'll have the occasion  to  look
  425.     at your program just before a faultly memory-access occur.
  426.  
  427.     You can switch    from  a  verbose  output  to  a  shorter  one  with
  428.     AP_Verbose(flag). IF flag is true then the verbose mode is on. If it is
  429.     false then only short messages will be printed. Some people prefer    the
  430.     later so that is the default. If you perfer the verbose ouput then    put
  431.     AP_Verbose(1)  someware  in  your  code  and  you'll  get  some  longer
  432.     explanations about illegal accesses.
  433.  
  434.     You can specify a logfile where APurify can put its errors.  To  do
  435.     this, set the environment variable "APlog" (file ENV:APlog) to  a  name
  436.     of a logfile. If this variable is set, then APurify will append all its
  437.     outputs to the file indicated.
  438.  
  439.     You can use APurify on any  language  that  generates  a  temporary
  440.     assembly language sourcefile (included assembly itself :-) ). You  must
  441.     notice too, that you can use it on programs for which no source-code is
  442.     available (or .o files without .asm files). For  that,  use  a  program
  443.     that  can  do  reverse  engineering  on  your  executable    (ie:   that
  444.     disassembles the executable and  produces  a  .asm    file  ready  to  be
  445.     assembled). Then, with minor changes (prepend '_'  and  append  ':'  to
  446.     every interesting labels, put a call to AP_Init in the right place),
  447.     you get a file ready to be processed by APurify. If the processed file
  448.     has a HYNK_SYMBOL then you are very lucky and you need  not work on
  449.     labels. You then just have to  find the "_main:" and add "jsr _AP_Init"
  450.     as the first instruction of the "_main:" subroutine.
  451.  
  452.     Note:  you    can  use  ADIS    (by Martin Apel)  on  aminet  to do reverse
  453.     engineering (it seems to be quite good a tool to do it).
  454.  
  455.  
  456. EXAMPLE:
  457. -------
  458.     As an example, let's look at the test.dcc program. You'll  see  how
  459.     you can use the APurify report it produces to find what's wrong in  the
  460.     program. For this, I've included in that document the commented report.
  461.     My comments/explanations appear on lines beginning with a "#".
  462.  
  463.     **** APurify started on Sun Jan 07 18:41:55 1996
  464.  
  465.     #
  466.     # Well, the report started...
  467.     #
  468.  
  469.     **** APURIFY ERROR ! [$002727b8(4) R-- (_main, PC=$00286210 HUNK=$0
  470.     OFFSET=$240)] accessed between:
  471.     -29      [$002727d8(23) RW- (_main)]
  472.     +77253      [$0025f9e8(12) RW- (_main)]
  473.  
  474.     #
  475.     # Hum... First hit... it is an error in reading something in the main()
  476.     # procedure between two blocks already  allocated.    The  nearest  block
  477.     # appears in first position, so we can think that the error was done by
  478.     # accessing an array allocated in main() with a negative index. We  can
  479.     # look at the code to find what is wrong with it. Using DOBJ, we  found
  480.     # at offset $410 in the first hunk the following code:
  481.     #
  482.     #        00.00000240  24ab ffd8           MOVE.L -40(A3),(A2)
  483.     #
  484.     # This corresponds to the C code:
  485.     #
  486.     #                   a[0]=b[-10]
  487.     #
  488.     # Hence we've discovered a first error in the code. Note  that  -29  is
  489.     # the distance (in bytes) between the end of the  accessed  memory  and
  490.     # the beginning of the array. This is not the  difference  between    the
  491.     # beginning address of the two blocks!
  492.     #
  493.  
  494.     **** APURIFY ERROR ! [$0025f9f4(4) R-- (_main, PC=$00286238 HUNK=$0
  495.     OFFSET=$268)] accessed between:
  496.     +1      [$0025f9e8(12) RW- (_main)]
  497.     -79345      [$00272fe8(408)     RW- (_main)]
  498.  
  499.     #
  500.     # Well... here it seems to be an access just after an allocated  block.
  501.     # the offset +1 is the distance in bytes between the accessed block and
  502.     # a allocated block. The situation is like this:
  503.     #
  504.     #              ---------[ 1 ]( 2 )---------->
  505.     #
  506.     # Where "[ 1 ]" is the allocated block and "( 2 )" the accessed  block.
  507.     # If we look in the code, we find:
  508.     #
  509.     #         00.00000268  4aaa 0004            TST.L   0004(A2)
  510.     #
  511.     # that correponds to the test done by "if(a[1] == 0)". This is an error
  512.     # since the array 'a' is just 12-8=4 bytes long. So  a[1] points out of
  513.     # the array!
  514.     #
  515.  
  516.     **** APURIFY ERROR ! [$0025f9f2(4) R-- (_read_shifted, PC=$0028611a
  517.     HUNK=$0 OFFSET=$14a)] accessed across the ending boundary of:
  518.     -2      [$0025f9e8(12) RW- (_main)]
  519.  
  520.     #
  521.     # Hehe another error... Damn ! That test program is a  FULL  of  bug  !
  522.     # Yes, but that one is an other kind of error. It is an access across a
  523.     # boundary. That occur in the read_shifted() code. We need not look  in
  524.     # the asm file to see the  error.  Here  it  is  a    misaligment  error.
  525.     # Visually that gives:
  526.     #
  527.     #               ------------[ 1(]2 )----------->
  528.     #
  529.     #           [ 1 ] = allocated       ( 2 ) = accessed.
  530.     #
  531.  
  532.     **** APURIFY ERROR ! [$0025f9f0(4) R-- (_read_long, PC=$00286136
  533.     HUNK=$0 OFFSET=$166)] accessed between:
  534.     -79349      [$00272fe8(408)     RW- (_main)]
  535.     +2487793  [$00000000(1024)    --S (Basic 680x0 vectors)]
  536.  
  537.     #
  538.     # That error is strange! It is  not  an  access  to  an  array  with  a
  539.     # negative index as one think immediately: We never call read_long() in
  540.     # such a way, and the offsets are too big ! Indeed, the accessed memory
  541.     # was right some times ago since it lays in the array 'a'  (look at the
  542.     # second hit).  Hence, it must be an access to a free()'d memory.  That
  543.     # error is then obviously found in the code:
  544.     #
  545.     #              free_arg(a); read_long(a).
  546.     #                   ^^^^^^^^^^^^
  547.     #
  548.  
  549.     **** APURIFY ERROR ! [$00000004(4) R-- (_read_page_zero, PC=$00286176
  550.     HUNK=$0 OFFSET=$1a6)] accessed on a read-protected block:
  551.     +4      [$00000000(1024)    --S (Basic 680x0 vectors)]
  552.  
  553.     #
  554.     # Here the error is obvious, were are reading the zero-page. If it    was
  555.     # in writing, that error would be very dangerous.
  556.     #
  557.  
  558.     **** APURIFY WARNING ! Closing library without deallocation of the 
  559.     following block(s):
  560.     - [$00272fe8(408)   RW- (_main)]
  561.     - [$0029e928(12008) RW- (_main)]
  562.     - [$002a1810(40008) RW- (_main)]
  563.  
  564.     #
  565.     # The program has exit()ed. APurify tells us that we've forget to  free
  566.     # those blocks. It    is  a  case  of  memory  leak.    Those  blocks  were
  567.     # allocated in main(). Those  were allocated and lost by
  568.     #
  569.     #           a=malloc(4),malloc(400),malloc(12000),malloc(400000)
  570.     #
  571.     # since the assignment only affects the first item of ",,,".
  572.     #
  573.  
  574.     **** APurify ended on Sun Jan 07 18:41:56 1996
  575.  
  576.     #
  577.     # Well... done :-).
  578.     #
  579.  
  580.  
  581. LEGAL PART:
  582. ----------
  583.     That program is provided 'AS IS'. I  am  not  responsible  for  any
  584.     dammage it can cause (but I am responsible for the benefits it can give
  585.     to you :-). Use that software at you own risks.
  586.  
  587.     That program is FREEWARE. You can use and distribute it as long  as
  588.     you keep the archive  intact  (no  adulteration  of  files  except  for
  589.     compression). It can't be sold without my agreement (except  a  minimal
  590.     amount for media support). You must ask me for commercial use  of  (any
  591.     part of) that product. I keep all my rights on  that  program  and    its
  592.     future releases. I can modify that software without telling it  to    the
  593.     users.
  594.  
  595.     If you wish, you can send me a postcard or anything else  you  want
  596.     (money, documentation, amiga, hardware  stuff,  ...)  in  exchange  for
  597.     using APurify. But there is no obligation :-). My postal address is:
  598.  
  599.         M. DEVULDER Samuel
  600.         1, Rue du chateau
  601.         59380 STEENE
  602.         FRANCE
  603.  
  604.     (yes I'm french !). You can  send  suggestions  or  bugs  to  my  email
  605.     address:
  606.  
  607.         devulder@info.unicaen.fr
  608.  
  609.  
  610. NOTES:
  611. -----
  612.     It has been compiled with freedice 2.06.37.
  613.  
  614.     I had the idea of that program    after  a  chat    with  Cedric  BEUST
  615.     (AMIGA NEWS) on IRC (Internet Relay Chat). Thanks Cedric !
  616.  
  617.     All marks are proprietary of their respective owners.
  618.  
  619.     There are some programs like APurify. For example,  FORTIFY  (Simon
  620.     P. Bullen), but  it  only  detects    illegal  writes  to  boundaries  of
  621.     allocated blocks. Thus it can't detect big oversteps and  oversteps  in
  622.     reading and the detection is not real-time. Enforcer can detect illegal
  623.     access to memory (I think), but it needs a special device (MMU).
  624.  
  625.  
  626. HINTS & TIPS:
  627. ------------
  628.     You can see some memory leaks with that version of APurify.  It  is
  629.     not really good but it can help. Memory leak  occur  when  a  block  of
  630.     memory is nomore pointed by your  program.    Those  memory  blocks  will
  631.     necessary be displayed when your  program  exit()s.  So  with  all  the
  632.     messages printed on that occasion, you can find such  blocks.  I  known
  633.     this is not so great, but I think it can help you a little    bit  (maybe
  634.     in a future version I'll build some code to really check memory leaks).
  635.  
  636.  
  637. BUGS:
  638. ----
  639.     APurify don't known public memory where a program can read or write
  640.     without having allocated it. Thus, it  will  report  an  error  when  a
  641.     program reads or writes values in a message obtained  through  GetMsg()
  642.     calls. Use AP_Report() to avoid such reports.
  643.  
  644.     It can display messages about closing the library  without  freeing
  645.     some memory blocks. This is due to printf() that allocates memory  that
  646.     is free'd on exit. This is not a real bug, but you can  avoid  this  by
  647.     doing a AP_Report(0) just before exiting. But you must notice  that  it
  648.     is better to display false bugs than to not display real ones.
  649.  
  650.     Certainly more bugs, but I'm waiting for your bug-reports.
  651.