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