jtkohl@MIT.EDU (John T Kohl) (06/25/91)
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@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@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@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@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]