;;; tag: Tom Lord Tue Dec  4 14:59:28 2001 (=scaffolding/log-formats.scm)
;;;
;;; logs.scm - Descriptions of the kinds of log entries generated by PIW.
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Copyright (C) 1998 UUNET Technologies, Inc.
;;;
;;; See the file "COPYING.PIW" for further information
;;; about the copyright status of this work.
;;;


(define-module (piw log-formats))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Log Record Type Specifications
;;;
;;; This file contains specifications for the format of log records
;;; generated by PIW instrumentation.
;;;
;;; Record type specifications are divided by category into a series of
;;; lists.  These lists are defined below, and enumerated in the
;;; function "record-type-sections".
;;;
;;; Unless otherwise noted, each record type is specified by a list:
;;;
;;;	(record-type-name <field-specification>
;;;			  <real-time?>
;;;			  <documentation>)
;;;
;;; A record-type-name is a C identifier.  Several identifiers in
;;; the generated code are derived from this.
;;;
;;; A "field-specification" is a list of structure fields.  Each
;;; element is:
;;;
;;;	(name-of-c-type name-of-field <optional-expression>)
;;;
;;; All three are strings.  This string should be a valid C structure
;;; field declaration:
;;;
;;;	(string-append name-of-c-type " " name-of-field ";")
;;;
;;; The "optional-expression" (which may be omitted) is a string which
;;; is a valid C expression for an rvalue of the specified field type.
;;; This expression is used to generate the value for the field in a 
;;; binary text record.
;;;
;;; If no expression is specified, then the field is initialized from
;;; a parameter to the binary record printer.
;;;
;;; "real-time?" is #t if the log buffer should be flushed after 
;;; writing a log entry of this type and #f otherwise.  The log
;;; buffer should be flushed if a real-time error message might be
;;; generated for this type of log entry.
;;;
;;; The documentation string is a list of strings describing the
;;; record type.  They should begin with a sentence which is only a
;;; noun phrase and which makes sense if prepended by "This record
;;; type is generated by ". (The noun phrase should be capitalized,
;;; though.)
;;;
;;; For example:
;;;
;;;	(malloc ((int call_number calls_to_malloc++)
;;;		 (int amt_requested)
;;;		 ("void *" new_block))
;;;		 #f
;;;              ("A return from a call to malloc, if the variable"
;;;               "piw_malloc_log is set."))
;;;
;;; Generates a structure type:
;;;
;;;	struct piw_malloc_data /* record-type: malloc */
;;;	{
;;;	  int call_number;
;;;	  int amt_requested;
;;;	  void * new_block;
;;;	};
;;;
;;; this binary log printing function:
;;;
;;;      void
;;;      piw_log_malloc (int amt_requested, void * new_block)
;;;      {
;;;        struct piw_malloc_data data;
;;;        data.call_number = calls_to_malloc++;
;;;        data.amt_requested = amt_requested;
;;;        data.new_block = new_block;
;;;        piw_log("malloc", (void *)&data, sizeof (data));
;;;      }
;;;
;;; this text log printing function:
;;;
;;;      static void
;;;      piw_print_log_malloc (struct piw_malloc_data * data)
;;;      {
;;;        if (0 > printfmt ("(malloc %u %u %lu)\n",
;;;                          data->call_number,
;;;                          data->amt_requested,
;;;                          data->new_block))
;;;          panic ("I/O error while printing record");
;;;      }
;;;
;;; and this documentation:
;;;
;;;      * malloc
;;;      --------
;;;      
;;;       A return from a call to malloc, if the variable
;;;       piw_malloc_log is set.
;;;      
;;;          struct piw_malloc_data
;;;          {
;;;            int call_number;
;;;            int amt_requested;
;;;            void * new_block;
;;;          };
;;;
;;; If the first string in list of documentation strings begins with "", then
;;; that string is printed before the rest of the documentation, like this:
;;;
;;; (bogus_malloc_padding (("void *" block)
;;;                        ("void *" location))
;;;                       ("\n\n\n"
;;;                        "A malloc-related function's discovery that a padded or filled region"
;;;                        "(either freed memory or memory padding allocating memory) has been"
;;;                        "overwritten."
;;;                        ))
;;;
;;;        
;;;        
;;;        
;;;        * bogus_malloc_padding
;;;        ----------------------
;;;        
;;;         A malloc-related function's discovery that a padded or filled region
;;;         (either freed memory or memory padding allocating memory) has been
;;;         overwritten.
;;;        
;;;            struct piw_bogus_malloc_padding_data
;;;            {
;;;              void * block;
;;;              void * location;
;;;            };
;;;        
;;;


;; A set of top-level declarations for the file containing
;; log-record generation functions.
;;
(define-public record-generation-decls
  '("static int calls_to_malloc = 0;"
    "static int calls_to_realloc = 0;"
    "static int calls_to_free = 0;"))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; The Complete Set of Log Record Specifications
;;; 

;; record-type-sections
;;
;; Return an assoc list whose keys are the names of documentation
;; sections, and whose values are lists of record type specifications.
;;
(define-public (record-type-sections)
  `((malloc/malloc-related-records ,malloc-related-records)
    (string-functions/string-function-related-records ,string-function-related-records)
    (pointer-checking/pointer-checking-related-records
     ,pointer-checking-related-records)
    (debugging-record-types ,debugging-records)))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; The Format of Log Record Specifications
;;; 

(define-public (record-type spec) (car spec))
(define-public (struct-name spec) (string-append "piw_" (record-type spec) "_data"))
(define-public (text-log-function-name spec) (string-append "piw_text_log_" (record-type spec)))
(define-public (record-type-real-time? spec) (caddr spec))
(define-public (record-type-documentation spec) (cadddr spec))

(define-public (fields spec) (cadr spec))
(define-public (field-type field) (car field))
(define-public (field-name field) (cadr field))
(define-public (field-expression field) (and (cddr field) (caddr field)))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Records for the PIW implementation of "malloc"
;;;

(define-public malloc-related-records
  '(
    (malloc ((int call_number calls_to_malloc++)
	     (int amt_requested)
	     ("void *" new_block))
	    #f
	    ("A return from a call to malloc, if the variable"
	     "piw_malloc_log is set."))

    (realloc ((int call_number calls_to_realloc++)
	      ("void *" block)
	      (int amt_requested)
	      ("void *" new_block))
	     #f
	     ("A return from a call to realloc, if the variable"
	      "piw_malloc_log  is set."))

    (free ((int call_number calls_to_free++)
	   ("void *" block))
	  #f
	  ("A return from a call to free, if the variable"
	   "piw_malloc_log  is set."))

    (malloc_call ((int call_number calls_to_malloc)
		  (int amt_requested)
		  ("unsigned long" caller_address 0))
		 #f
		 ("\n\n\n"
		  "A call to malloc, if the variable piw_malloc_call_log is set."))

    (realloc_call ((int call_number calls_to_realloc)
		   ("void *" block)
		   (int amt_requested)
		  ("unsigned long" caller_address 0))
		  #f
		  ("A call to realloc, if the variable piw_malloc_call_log is set."))

    (free_call ((int call_number calls_to_free)
		("void *" block)
		("unsigned long" caller_address 0))
	       #f
	       ("A call to free, if the variable piw_malloc_call_log is set."))

    (bogus_realloc ((int call_number "calls_to_realloc")
		    ("void *" location))
		   #t
		   ("\n\n\n"
		    "A call to realloc, if realloc discovers that it"
		    "was passed something other than a valid block"
		    "of malloced memory."))

    (bogus_free ((int call_number "calls_to_free")
		 ("void *" location))
		#t
		("A call to free, if free discovers that it was passed something"
		 "other than a valid block of malloced memory."
		 ))

    (bogus_malloc_padding (("void *" block)
			   ("void *" location))
			  #t
			  ("\n\n\n"
			   "A malloc-related function's discovery that a padding region (memory"
			   "padding surrounding allocating memory) has been overwritten."
			   ))

    (bogus_malloc_fill (("void *" block)
			("void *" location))
		       #t
		       ("\n\n\n"
			"A malloc-related function's discovery that a filled region (a free block"
			"of memory, filled by the PIW run-time system) has been overwritten."
			))


    (bogus_malloc_meta_data (("void *" location))
			    #t
			    ("A malloc-related function's discovery that its"
			     "internal data structures are corrupt."))

    (malloc_tags_map_overflow ()
			      #t
			      ("The size of the malloc arena exceeds the maximum"
			       "implied by piw_tag_map_range."))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Records for the PIW libc string functions.
;;;

(define-public string-function-related-records
  '(
    (block_write (("void *" location)
		  ("void *" origin)
		  (int size))
		 #f
		 ("Call to a string-function that writes memory."
		  "Selected by piw_log_string_functions."))
    (block_read (("void *" location)
		 ("void *" origin)
		 (int size))
		#f
		("Call to a string-function that reads memory."
		 "Selected by piw_log_string_functions."))
    (bad_block_write (("void *" location)
		      ("void *" origin)
		      (int size))
		     #t
		     ("A string-function write error (imminent write to an illegal location)."
		      "Selected by piw_string_function_checks.  The technique used to"
		      "check string function parameters varies, depending on what whether"
		      "or not tag bits are kept (piw_keep_tag_bits)."))
    (bad_block_read (("void *" location)
		      ("void *" origin)
		      (int size))
		    #t
		    ("A string-function read error (imminent read from an illegal location)."
		     "Selected by piw_string_function_checks.  The technique used to"
		     "check string function parameters varies, depending on what whether"
		     "or not tag bits are kept (piw_keep_tag_bits)."))))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Records for the PIW read and write barriers.
;;;

(define-public pointer-checking-related-records
  '(
    (rm	       (("void *" location)
		(int size))
	       #f
	       ("A read barrier was encountered."
		"These records are generated only when piw_log_reads flag is set."))
    (wm	       (("void *" location)
		(int size))
	       #f
	       ("A write barrier was encountered."
		"These records are generated only when piw_log_writes flag is set."))
    (bad_write (("void *" location)
		(int size))
	       #t
	       ("A write barrier error (imminent write to an illegal location)."))
    (bad_read (("void *" location)
	       (int size))
	      #t
	      ("A read barrier error (imminent read of an illegal location)."))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Debugging Record Types
;;;

(define-public debugging-records
  '(
    (init	((int pid))
		#t
		("A new log sequence."
		 "This is the record type of the first log entry generated."))
    (sequence	((int seq))
		#f
		("An application-defined sequence number."
		 "These records are generated only when the application being"
		 "debugged calls piw_log_sequence."))
    (stray_write (("void *" location))
		 #t
		 ("An imminent stray write to `location'."
		  "These records are generated by the PIW write barrier function"
		  "`piw_write_checking_barrier'."))))

