mprof: DEC MIPS patches

John T Kohl jtkohl at MIT.EDU
Wed Jun 26 00:30:57 AEST 1991


I've gotten a few requests for these patches, so here they are: The
MIPS-specific enhancements and GNU_C frame pointer frobbery are mine
(including the null-pointer avoidance code), the other stuff is from
Marc Horowitz <marc at mit.edu>.

shar & enjoy

diffs are vs. standard mprof 3.0 distributions.

RCS file: RCS/Makefile.mips,v
retrieving revision 1.1
diff -c -r1.1 Makefile.mips
*** /tmp/,RCSt1019637	Tue Jun 25 10:20:37 1991
--- Makefile.mips	Wed Feb 20 13:07:19 1991
***************
*** 113,119 ****
  	$(BIN)/mprof -normal test1 test1.data > test1.mprof
  
  test1.data: test1
! 	test1
  	cp mprof.data test1.data
  
  test1: test1.o $(MPLIB)
--- 113,119 ----
  	$(BIN)/mprof -normal test1 test1.data > test1.mprof
  
  test1.data: test1
! 	./test1
  	cp mprof.data test1.data
  
  test1: test1.o $(MPLIB)
***************
*** 131,137 ****
  	$(BIN)/mprof -normal test2 test2.data > test2.mprof
  
  test2.data: test2
! 	test2
  	cp mprof.data test2.data
  
  test2: test2.o $(MPLIB)
--- 131,137 ----
  	$(BIN)/mprof -normal test2 test2.data > test2.mprof
  
  test2.data: test2
! 	./test2
  	cp mprof.data test2.data
  
  test2: test2.o $(MPLIB)
===================================================================
RCS file: RCS/Makefile.vax,v
retrieving revision 1.1
diff -c -r1.1 Makefile.vax
*** /tmp/,RCSt1019637	Tue Jun 25 10:20:39 1991
--- Makefile.vax	Wed Feb 20 13:25:23 1991
***************
*** 15,20 ****
--- 15,21 ----
  
  CFLAGS = -I. -g
  ASFLAGS =
+ CPP = /lib/cpp
  BIN = /mit/watchmaker/vaxbin
  LIB = /mit/watchmaker/vaxlib
  INCLUDE = /mit/watchmaker/include
***************
*** 21,33 ****
  MPLIB = libc_mp.a
  LINTFLAGS = -bhx
  
! # sun4,mips 		ASM_SRC = md.s
! # sun4,mips 		ASM_OBJ = md.o
! # vax,sun3 		ASM_SRC =
! # vax,sun3 		ASM_SRC =
  
! ASM_SRC =
! ASM_OBJ =
  
  MPROF_MON_SRCS = leak.c malloc.c mpattach.c mprof_mon.c mpstruct.c $(ASM_SRC)
  MPROF_MON_OBJS = leak.o malloc.o mpattach.o mprof_mon.o mpstruct.o $(ASM_OBJ)
--- 22,34 ----
  MPLIB = libc_mp.a
  LINTFLAGS = -bhx
  
! # sun4,mips,vax 	ASM_SRC = md.s
! # sun4,mips,vax		ASM_OBJ = md.o
! # sun3	 		ASM_SRC =
! # sun3 			ASM_OBJ =
  
! ASM_SRC = md.s
! ASM_OBJ = md.o
  
  MPROF_MON_SRCS = leak.c malloc.c mpattach.c mprof_mon.c mpstruct.c $(ASM_SRC)
  MPROF_MON_OBJS = leak.o malloc.o mpattach.o mprof_mon.o mpstruct.o $(ASM_OBJ)
***************
*** 62,69 ****
  
  $(MPLIB): $(MPROF_MON_OBJS)
  	cp /lib/libc.a $(MPLIB)
! 	ar d $(MPLIB) malloc.o valloc.o $(LIB_REPLACE)
! 	ar r $(MPLIB) $(MPROF_MON_OBJS)
  	ranlib $(MPLIB)
  
  test: $(TEST_OBJS) test1-demo test2-demo
--- 63,70 ----
  
  $(MPLIB): $(MPROF_MON_OBJS)
  	cp /lib/libc.a $(MPLIB)
! 	ar dv $(MPLIB) malloc.o valloc.o $(LIB_REPLACE)
! 	ar rv $(MPLIB) $(MPROF_MON_OBJS)
  	ranlib $(MPLIB)
  
  test: $(TEST_OBJS) test1-demo test2-demo
***************
*** 88,94 ****
  mpgraph.o: mpgraph.c
  mprof.o: mprof.c
  md.o: md.s
! 	$(AS) $(ASFLAGS) -o md.o md.s
  
  malloc.o: malloc.c
  	$(CC) $(CFLAGS) -Dmalloc=__malloc__ -Dfree=__free__ -Drealloc=__realloc__ malloc.c -c
--- 89,95 ----
  mpgraph.o: mpgraph.c
  mprof.o: mprof.c
  md.o: md.s
! 	$(CPP) md.s | $(AS) $(ASFLAGS) -o md.o
  
  malloc.o: malloc.c
  	$(CC) $(CFLAGS) -Dmalloc=__malloc__ -Dfree=__free__ -Drealloc=__realloc__ malloc.c -c
***************
*** 116,122 ****
  	$(BIN)/mprof -normal test1 test1.data > test1.mprof
  
  test1.data: test1
! 	test1
  	cp mprof.data test1.data
  
  test1: test1.o $(MPLIB)
--- 117,123 ----
  	$(BIN)/mprof -normal test1 test1.data > test1.mprof
  
  test1.data: test1
! 	./test1
  	cp mprof.data test1.data
  
  test1: test1.o $(MPLIB)
***************
*** 134,140 ****
  	$(BIN)/mprof -normal test2 test2.data > test2.mprof
  
  test2.data: test2
! 	test2
  	cp mprof.data test2.data
  
  test2: test2.o $(MPLIB)
--- 135,141 ----
  	$(BIN)/mprof -normal test2 test2.data > test2.mprof
  
  test2.data: test2
! 	./test2
  	cp mprof.data test2.data
  
  test2: test2.o $(MPLIB)
===================================================================
RCS file: RCS/md.s,v
retrieving revision 1.1
diff -c -r1.1 md.s
*** /tmp/,RCSt1019637	Tue Jun 25 10:20:40 1991
--- md.s	Wed Feb 20 13:21:33 1991
***************
*** 51,53 ****
--- 51,59 ----
  	j	$31
  	.end	getsp
  #endif
+ #ifdef vax
+ .globl _startaddr
+ .globl start
+ _startaddr:
+ 	.long start
+ #endif
===================================================================
RCS file: RCS/mpgraph.c,v
retrieving revision 1.1
diff -c -r1.1 mpgraph.c
*** /tmp/,RCSt1019637	Tue Jun 25 10:20:41 1991
--- mpgraph.c	Wed Feb 20 15:01:43 1991
***************
*** 90,95 ****
--- 90,97 ----
  int	*scratch;
  {
      vertex result = (vertex) malloc(sizeof(vertex_item));
+     if (!name)
+ 	name = "(anonymous)";
      result->name = name;
      result->number = number;
      result->srefs = 0;
***************
*** 491,497 ****
  char	*key;
  {
      ENTRY	e, *result;
!     e.key = key;
      
      result = hsearch(e, FIND);
      return (vertex) result->data;
--- 493,502 ----
  char	*key;
  {
      ENTRY	e, *result;
!     if (key)
! 	e.key = key;
!     else
! 	e.key = "(anonymous)";
      
      result = hsearch(e, FIND);
      return (vertex) result->data;
===================================================================
RCS file: RCS/mprof.h,v
retrieving revision 1.1
diff -c -r1.1 mprof.h
*** /tmp/,RCSt1019637	Tue Jun 25 10:20:43 1991
--- mprof.h	Wed Feb 20 18:11:48 1991
***************
*** 1,8 ****
  /*	mprof.h 2.5 9/14/90 16:01:19	*/
  /*	Copyright (c) 1987, Benjamin G. Zorn */
  
! /* $Id: mprof.h,v 1.1 90/11/17 02:14:48 marc Exp $ */
  
  typedef	int	bool;
  #define	TRUE	1
  #define	FALSE	0
--- 1,24 ----
  /*	mprof.h 2.5 9/14/90 16:01:19	*/
  /*	Copyright (c) 1987, Benjamin G. Zorn */
  
! /* $Id: mprof.h,v 1.3 91/02/20 10:04:42 jtkohl Exp $ */
  
+ /* definitions for programs which modify mprof's default behavior */
+ 
+ #ifdef __STDC__
+ #define ARG(x) x
+ #else
+ #define ARG(x) ()
+ #endif
+ 
+ void set_mprof_autosave ARG((int));
+ void set_mprof_keep_file_open ARG((int));
+ void set_mprof_append_pid ARG((int));
+ void mprof_stop ARG((void));
+ void mprof_restart ARG((char *));
+ 
+ #undef ARG
+ 
  typedef	int	bool;
  #define	TRUE	1
  #define	FALSE	0
***************
*** 111,119 ****
  
  extern	char	*strdup();
  
! #if (defined(vax) || (defined(sun) && !defined(sun4)))
! #define get_current_fp(first_local) ((unsigned)&(first_local) + 4)
  #endif
  
  #if (defined(vax) || defined(sun))
  #include <sys/types.h>
--- 127,143 ----
  
  extern	char	*strdup();
  
! #if defined(vax) || defined(__vax__)
! #ifdef __GNUC__
! #define get_current_fp(fp, first_local) asm("movl fp,%0" : "=g" (fp));
! #else
! #define get_current_fp(fp, first_local) fp = ((unsigned)&(first_local) + 4)
  #endif
+ #else /* not vax */
+ #if (defined(sun) && !defined(sun4))
+ #define get_current_fp(fp, first_local) fp = ((unsigned)&(first_local) + 4)
+ #endif /* sun */
+ #endif /* vax */
  
  #if (defined(vax) || defined(sun))
  #include <sys/types.h>
===================================================================
RCS file: RCS/mprof_mon.c,v
retrieving revision 1.1
diff -c -r1.1 mprof_mon.c
*** /tmp/,RCSt1019637	Tue Jun 25 10:20:45 1991
--- mprof_mon.c	Thu Feb 21 11:51:53 1991
***************
*** 1,7 ****
  /*	mprof_mon.c 1.1 9/14/90 11:59:04	*/
  /*	Copyright (c) 1987, Benjamin G. Zorn */
  
! /* $Id: mprof_mon.c,v 1.1 90/11/17 00:34:16 marc Exp $ */
  
  /* mprof_mon -- code that is attached to executing programs.
   */
--- 1,7 ----
  /*	mprof_mon.c 1.1 9/14/90 11:59:04	*/
  /*	Copyright (c) 1987, Benjamin G. Zorn */
  
! /* $Id: mprof_mon.c,v 1.5 91/02/21 11:51:16 jtkohl Exp $ */
  
  /* mprof_mon -- code that is attached to executing programs.
   */
***************
*** 8,13 ****
--- 8,14 ----
  
  #include	<stdio.h>
  #include	<sys/file.h>
+ #include	<sys/param.h>
  #include	"mprof.h"
  
  #ifdef mips
***************
*** 38,44 ****
--- 39,48 ----
  /* local variables */
    
  char	*mprof_filename = "mprof.data";
+ char	mprof_filename_buf[MAXPATHLEN];
  int	mprof_autosave = 0;
+ int	mprof_keep_file_open = 1;
+ int	mprof_append_pid = 0;
  int	mprof_file;
  bool	mprof_initialized = FALSE;
  bool	mprofing = TRUE;
***************
*** 249,254 ****
--- 253,259 ----
  
  #ifdef mips
      pPDR pdr;
+     unsigned getretaddr();
  #endif
  
      if (!mprof_initialized) {
***************
*** 269,275 ****
      /* gather return addresses from the callstack
       */
  #ifndef mips
!     fp = get_current_fp(first_local);
      ret_addr = ret_addr_from_fp(fp);
      
      /* Step back 1 frame (to the caller of malloc)
--- 274,280 ----
      /* gather return addresses from the callstack
       */
  #ifndef mips
!     get_current_fp(fp, first_local);
      ret_addr = ret_addr_from_fp(fp);
      
      /* Step back 1 frame (to the caller of malloc)
***************
*** 277,282 ****
--- 282,288 ----
      fp = prev_fp_from_fp(fp);
      ret_addr = ret_addr_from_fp(fp);
      
+ 
      while (ret_addr > mp_root_address) {
  	if (no_call_graph && (fstk_i > SHORT_CALLSTACK_SIZE))
  	  break;
***************
*** 408,425 ****
  }
  
  void
! mprof_startup()
  {
- #ifdef sun
-     on_exit(mprof_exit, NULL);
- #endif    
      if (strcmp(mprof_filename, "") == 0) {
  	mprof_file = 1;
      } else {
! 	mprof_file = open(mprof_filename,
  			  (O_WRONLY | O_CREAT | O_TRUNC),
  			  mprof_create_mask);
      }
      mpstruct_init();
      mp_zero_bins();
      mpleak_init();
--- 414,453 ----
  }
  
  void
! mprof_open_file()
  {
      if (strcmp(mprof_filename, "") == 0) {
  	mprof_file = 1;
      } else {
! 	char fname[MAXPATHLEN];
! 
! 	if (mprof_append_pid)
! 	    sprintf(fname,"%s%d",mprof_filename,getpid());
! 	else
! 	    sprintf(fname,"%s",  mprof_filename);
! 
! 	mprof_file = open(fname,
  			  (O_WRONLY | O_CREAT | O_TRUNC),
  			  mprof_create_mask);
      }
+ }
+ 
+ void
+ mprof_startup()
+ {
+ #if defined(vax) || defined(__vax__)
+     /* if using P0INVALID code, we need to make sure we know the real
+        address of start().  start+CRT0_ADDRESS is the return address
+        of the active start(). see sa_vax.s */
+     extern unsigned long startaddr;
+     mp_root_address += startaddr;
+ #endif
+ 
+ #ifdef sun
+     on_exit(mprof_exit, NULL);
+ #endif
+     if (mprof_keep_file_open)
+ 	mprof_open_file();
      mpstruct_init();
      mp_zero_bins();
      mpleak_init();
***************
*** 447,452 ****
--- 475,483 ----
      char	stats[256];
      extern	int mprof_fmemC, mprof_dmemC, mprof_lmemC, mprof_smemC;
  
+     if (!mprof_keep_file_open)
+ 	mprof_open_file();
+ 
      ftruncate(mprof_file, 0);
      lseek(mprof_file, 0L, 0);
      
***************
*** 471,476 ****
--- 502,510 ----
      mp_print_leak_table(mprof_file);
      
      mprof_print(mprof_file);
+ 
+     if (!mprof_keep_file_open)
+ 	close(mprof_file);
  }
  
  void
***************
*** 478,484 ****
  {
      if (mprof_initialized) {
      	mprof_writefile();
!     	close(mprof_file);
      }
  }
  
--- 512,519 ----
  {
      if (mprof_initialized) {
      	mprof_writefile();
! 	if (mprof_keep_file_open)
! 	    close(mprof_file);
      }
  }
  
***************
*** 490,499 ****
     int count;			   count = 0 (default)  implies no autosave
  
     void
     mprof_stop()			-- stop the memory profile in progress
  
     void
!    mprof_restart(datafile)	-- restart memory profiling
  
  */
     
--- 525,546 ----
     int count;			   count = 0 (default)  implies no autosave
  
     void
+    set_mprof_keep_file_open(onoff)
+    int onoff			-- if onoff != 0 (default) keeps the file
+    				   open between writes.  Otherwise, closes
+ 				   and opens each time.  
+ 
+    void
+    set_mprof_append_pid(onoff) 
+    int onoff			-- appends pid to datafile name before
+ 				   reopening it the next time.
+ 
+    void
     mprof_stop()			-- stop the memory profile in progress
  
     void
!    mprof_restart(datafile)	-- restart memory profiling.   If datafile ==
! 				   NULL, opens old file.
  
  */
     
***************
*** 504,521 ****
      mprof_autosave = count;
  }
        
  
  void
  mprof_restart(datafile)
  char	*datafile;
  {
      if (mprofing)
  	fprintf(stderr,
! 	"mprof_restart -- restart ingnored; memory profiling in progress\n");
      else {
  	mprof_initialized = FALSE;
  	mprofing = TRUE;
! 	mprof_filename = datafile;
      }
  }
  
--- 551,582 ----
      mprof_autosave = count;
  }
        
+ void
+ set_mprof_keep_file_open(onoff)
+ int	onoff;
+ {
+     mprof_keep_file_open = onoff;
+ }
  
  void
+ set_mprof_append_pid(onoff)
+ int	onoff;
+ {
+     mprof_append_pid = onoff;
+ }
+ 
+ void
  mprof_restart(datafile)
  char	*datafile;
  {
      if (mprofing)
  	fprintf(stderr,
! 	"mprof_restart -- restart ignored; memory profiling in progress\n");
      else {
  	mprof_initialized = FALSE;
  	mprofing = TRUE;
! 	if (datafile)
! 	   mprof_filename = datafile;
      }
  }
  
***************
*** 524,530 ****
  {
      if (!mprofing) 
  	fprintf(stderr,
! 	"mprof_stop -- stop ingnored; memory profiling not in progress\n");
      else {
  	mprof_cleanup();
  	mprofing = FALSE;
--- 585,591 ----
  {
      if (!mprofing) 
  	fprintf(stderr,
! 	"mprof_stop -- stop ignored; memory profiling not in progress\n");
      else {
  	mprof_cleanup();
  	mprofing = FALSE;
***************
*** 538,544 ****
  
  pdrinit()
  {
! 	int i;
  	SYMR asym;
  	extern char **__Argv;	/* hack */
  	pFDR pfd;
--- 599,605 ----
  
  pdrinit()
  {
! 	register int i, j;
  	SYMR asym;
  	extern char **__Argv;	/* hack */
  	pFDR pfd;
***************
*** 576,582 ****
--- 637,702 ----
  	    }
  	  }
  	}
+ 	for (i = 0; i < SYMHEADER(ldptr).ipdMax - 1; i++) {
+ 	    if (!pdrarray[i].adr) {
+ 		/* jtkohl at mit.edu: this (apparently)
+ 		   happens when the symbol name for the referenced function
+ 		   has been stripped out, such as when it's a static function
+ 		   and the .o file had ld -x -r run over it.
+ 		   What we really ought to do is determine where the
+ 		   procedure really starts.
+ 		  
+ 		   we attempt to do so, by starting with the previous address,
+ 		   looking for the SECOND addiu   sp,sp,{neg_size}.
  
+ 		   since the MIPS and GCC compilers only generate one such
+ 		   instruction per C function, the second one should be
+ 		   in the prologue of the desired function.
+ 
+ 		   HOWEVER, if we have a static function which is a LEAF (no
+ 		   locals, no function calls) we will actually miss the
+ 		   function and find the next one.  Luckily, such a function
+ 		   can never appear on the call graph leading to a malloc, so
+ 		   if we assign it an address just before the address of the
+ 		   next function, then we should never mistakenly "find"
+ 		   it when doing a binary search for a return address.
+ 
+ 		   If we have two or more functions with no args before
+ 		   the next known function, it gets hairier...
+ 
+ 		   ADDIU sp,sp, {size} is:
+ 		   0x27bd.... (16-bit offset size)
+ 
+ 		 */
+ 		unsigned long *search;
+ 		if (i == 0 || i == SYMHEADER(ldptr).ipdMax - 2)
+ 		    punt("can't fix up first/last address in table");
+ 		search = (unsigned long *)pdrarray[i-1].adr;
+ 		search++;		/* skip over the adjustment
+ 					   in the previous procedure */
+ 		while ((*search & 0xffff8000) != 0x27bd8000)
+ 		    search++;
+ 		if (pdrarray[i+1].adr) {
+ 		    if (search == (unsigned long *)pdrarray[i+1].adr) {
+ 			/* found next function...back up */
+ 			search--;
+ 		    }
+ 		} else {
+ 		    for (j = i+2; j < SYMHEADER(ldptr).ipdMax - 2; j++) {
+ 			if (pdrarray[j].adr) {
+ 			    if (search == (unsigned long *)pdrarray[j].adr) {
+ 				search -= (j-1);
+ 			    }
+ 			    break;
+ 			}
+ 		    }
+ 		    if (j == SYMHEADER(ldptr).ipdMax - 2)
+ 			punt("can't find a new anchor address");
+ 		}
+ 		pdrarray[i].adr = (unsigned long) search;
+ 	    }
+ 	}
+ 
  	/* This is guaranteed to be between __start and main. */
  	mp_root_address = pdrarray[1].adr - 1;
  }
***************
*** 585,591 ****
  getpdr(loc)
  int loc;
  {
! 	int low = 0, high = SYMHEADER(ldptr).ipdMax - 1, mid;
  
  	/* do binary search on address */
  	while (low <= high) {
--- 705,711 ----
  getpdr(loc)
  int loc;
  {
! 	register int low = 0, high = SYMHEADER(ldptr).ipdMax - 1, mid;
  
  	/* do binary search on address */
  	while (low <= high) {
***************
*** 603,608 ****
--- 723,729 ----
  
  }
  
+ unsigned
  getretaddr(pfp, pdr)
  int *pfp;
  pPDR pdr;
***************
*** 626,632 ****
--- 747,761 ----
  
  	if (!(pdr->regmask & (1 << pdr->pcreg))) {
  	  /* in a register and register is not saved */
+ 	  /* jtkohl at mit.edu: this probably is indicative of using
+ 	     the wrong pdr somewhere in the stack trace.  see above comments
+ 	     about static functions and ld -x -r. */
+ 	  /* just lie and terminate the search, rather than aborting
+ 	     the program. */
+ 	    return mp_root_address;
+ #if 0	    
  	  punt("don't know how to get register");
+ #endif
  	}
  
  	if (pdr->framereg != 29) punt("framereg != 29");
--
John Kohl <jtkohl at MIT.EDU>
Digital Equipment Corporation/Project Athena
(The above opinions are MINE.  Don't put my words in somebody else's mouth!)
___This signature printed on recycled bits___ [not original; heard 2nd hand]



More information about the Alt.sources mailing list