Skip to content
Snippets Groups Projects
handle-malloc-dump.el 4.16 KiB
;;;;
;;;; $Id: handle-malloc-dump.el,v 1.1 1991/09/21 12:09:35 ceder Exp $
;;;; Copyright (C) 1991  Lysator Academic Computer Association.
;;;;
;;;; This file is part of the LysKOM server.
;;;; 
;;;; LysKOM is free software; you can redistribute it and/or modify it
;;;; under the terms of the GNU General Public License as published by 
;;;; the Free Software Foundation; either version 1, or (at your option) 
;;;; any later version.
;;;; 
;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT
;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
;;;; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
;;;; for more details.
;;;; 
;;;; You should have received a copy of the GNU General Public License
;;;; along with LysKOM; see the file COPYING.  If not, write to
;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN,
;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, 
;;;; MA 02139, USA.
;;;;
;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. 
;;;;


;;; block - each block that is active is stored on a dll. The dll
;;; contains blocks. Each block consists of 'addr' - the base addr of
;;; the block - and 'marker' - a marker that points to the backtrace.

;;; Constructor:

(defun create-block (addr
			    marker)
  "Create a block from ADDR and MARKER."
  (cons
   'BLOCK
   (vector addr marker )))


;;; Selectors:

(defun block->addr (block)
  "Get addr from BLOCK."
  (elt (cdr block) 0))

(defun block->marker (block)
  "Get marker from BLOCK."
  (elt (cdr block) 1))


;;; Modifiers:

(defun set-block->addr (block newval)
  "Set addr in BLOCK to NEWVAL."
  (aset (cdr block) 0 newval))

(defun set-block->marker (block newval)
  "Set marker in BLOCK to NEWVAL."
  (aset (cdr block) 1 newval))



;;; Predicate:

(defun block-p (object)
  "Return t if OBJECT is a block."
  (eq (car-safe object) 'BLOCK))

			    
(defvar mstack nil
  "A dll that holds all currently active memory blocks.")

(defvar illegal-free nil
  "A dll that holds all illegal free attempts.")

(defun resolve-trace ()
  "Search the current buffer, and output any erroneous
mallocs/reallocs/frees to *Result*."
  (interactive)
  (setq mstack (dll-create))
  (setq illegal-free (dll-create))
  (goto-char (point-min))
  (while (re-search-forward "^--- \\(.*\\) ---$" nil 'foo)
    (let* ((fn (buffer-substring (match-beginning 1) (match-end 1)))
	   (btstart (match-end 0))
	   (btend (progn (re-search-forward "^==== end ====")
			 (match-beginning 0))))
	   
      (message fn)
      (cond
       ((string= fn "malloc")
	(beginning-of-line 0)
	(allocate))
       ((string= fn "free")
	(beginning-of-line 0)
	(free))
       ((string= fn "realloc")
	(beginning-of-line -1)
	(free)
	(beginning-of-line 2)
	(allocate)))))
  (report-stacks))

(defun get-number ()
  "Get the last hex-string on this line, as a string."
  (re-search-forward "0x[0-9a-f]*$")
  (buffer-substring (match-beginning 0) (match-end 0)))

(defun allocate ()
  "Add an unresolved allocation to mstack."
  (dll-enter-first mstack
		   (create-block (get-number)
				 (point))))

(defun free ()
  "Resolve an allocation from mstack."
  (let ((addr (get-number))
	(node (dll-nth mstack 0)))
    (while (and node
		(not (string= addr
			      (block->addr (dll-element mstack node)))))
      (setq node (dll-next mstack node)))
    (if node
	(dll-delete mstack node)
      (dll-enter-first illegal-free (create-block addr (point))))))

(defun report-stacks ()
  (save-window-excursion
    (pop-to-buffer "*Result*" t)
    (erase-buffer)
    (insert "Forgotten mallocs:\n\n"))
  (report-stack mstack)
  (save-window-excursion
    (pop-to-buffer "*Result*" t)
    (insert "\n\nIllegal frees:\n\n"))
  (report-stack illegal-free))

  

(defun report-stack (stack)
  (let ((gdb-buf (current-buffer))
	(node (dll-nth stack 0)))
    (while node
      (goto-char (block->marker (dll-element stack node)))
      (re-search-backward "^---")
      (let* ((b (point))
	     (e (progn
		  (re-search-forward "====$")
		  (point))))
	(save-excursion
	  (set-buffer "*Result*")
	  (insert (format "From char %d:\n" b))
	  (insert-buffer-substring gdb-buf (1- b) (1+ e))))
      (setq node (dll-next stack node)))))