Index: gnu/lib/libg2c/Makefile
===========================================================================
--- gnu/lib/libg2c/Makefile	2006/03/21 18:14:55	#2
+++ gnu/lib/libg2c/Makefile	2006/03/21 18:14:55
@@ -117,6 +117,15 @@
 	@mv ${.TARGET}.tmp ${.TARGET}
 .endif
 
+.if !defined(NOPROFILE) &&  !defined(NOPIC)
+${E77OBJS:.o=.pSo}: f2cext.c
+	${CC} -p ${PICFLAG} -DPIC ${CFLAGS} -c -DL${.PREFIX} -o ${.TARGET} \
+	    ${.ALLSRC:M*.c}
+	@${LD} -o ${.TARGET}.tmp -x -r ${.TARGET}
+	@mv ${.TARGET}.tmp ${.TARGET}
+.endif
+
+
 INCS=	g2c.h
 
 .include <bsd.lib.mk>
Index: gnu/usr.bin/perl/libperl/Makefile
===========================================================================
--- gnu/usr.bin/perl/libperl/Makefile	2006/03/21 18:14:55	#2
+++ gnu/usr.bin/perl/libperl/Makefile	2006/03/21 18:14:55
@@ -25,6 +25,6 @@
 
 .SUFFIXES:
 
-.SUFFIXES: .o .po .So .s .S .c
+.SUFFIXES: .o .po .So .pSo .s .S .c
 
 .PATH:	${PERL5SRC}
Index: lib/libc/gen/dlfcn.c
===========================================================================
--- lib/libc/gen/dlfcn.c	2006/03/21 18:14:55	#2
+++ lib/libc/gen/dlfcn.c	2006/03/21 18:14:55
@@ -116,6 +116,17 @@
 	return NULL;
 }
 
+
+
+#pragma weak dll_set_event_callback
+int
+dll_set_event_callback()
+{
+	return 1;
+} 
+
+
+
 #else /* a.out format */
 
 #include <sys/types.h>
Index: lib/libc/gmon/Makefile.inc
===========================================================================
--- lib/libc/gmon/Makefile.inc	2006/03/21 18:14:55	#2
+++ lib/libc/gmon/Makefile.inc	2006/03/21 18:14:55
@@ -15,3 +15,6 @@
 # mcount cannot be compiled with profiling
 mcount.po: mcount.o
 	cp mcount.o mcount.po
+
+mcount.pSo: mcount.So
+	cp mcount.So mcount.pSo
Index: lib/libc/gmon/gmon.c
===========================================================================
--- lib/libc/gmon/gmon.c	2006/03/21 18:14:55	#1
+++ lib/libc/gmon/gmon.c	2006/03/21 18:14:55
@@ -67,6 +67,8 @@
 void	moncontrol __P((int));
 static int hertz __P((void));
 
+#pragma weak monstartup
+
 void
 monstartup(lowpc, highpc)
 	u_long lowpc;
@@ -132,6 +134,8 @@
 	moncontrol(1);
 }
 
+#pragma weak _mcleanup
+
 void
 _mcleanup()
 {
@@ -225,6 +229,9 @@
  *	profiling is what mcount checks to see if
  *	all the data structures are ready.
  */
+
+#pragma _weak moncontrol
+
 void
 moncontrol(mode)
 	int mode;
Index: lib/libc/gmon/mcount.c
===========================================================================
--- lib/libc/gmon/mcount.c	2006/03/21 18:14:55	#1
+++ lib/libc/gmon/mcount.c	2006/03/21 18:14:55
@@ -67,6 +67,9 @@
  * both frompcindex and frompc.  Any reasonable, modern compiler will
  * perform this optimization.
  */
+
+void (*_gmon_xmcount) (uintfptr_t frompc, uintfptr_t selfpc) = NULL;
+
 _MCOUNT_DECL(frompc, selfpc)	/* _mcount; may be static, inline, etc */
 	register uintfptr_t frompc, selfpc;
 {
@@ -82,6 +85,9 @@
 	MCOUNT_DECL(s)
 #endif
 
+		if (_gmon_xmcount != NULL)
+			return (*_gmon_xmcount)(frompc,selfpc);
+
 	p = &_gmonparam;
 #ifndef GUPROF			/* XXX */
 	/*
Index: libexec/rtld-elf/rtld.c
===========================================================================
--- libexec/rtld-elf/rtld.c	2006/03/21 18:14:55	#25
+++ libexec/rtld-elf/rtld.c	2006/03/21 18:14:55
@@ -128,6 +128,31 @@
 
 void r_debug_state(struct r_debug*, struct link_map*);
 
+
+static void do_callback(Obj_Entry * obj,int reason);
+
+#define DLL_ITERATE_OBJECT 1
+#define DLL_ADD_OBJECT 2
+#define DLL_REMOVE_OBJECT 3
+
+
+struct dl_event {
+	int	dle_reason;
+	void*  dle_handle;
+	char * dle_path;
+	size_t dle_textsize;
+	caddr_t dle_relocbase;		/* Relocation constant = mapbase - vaddrbase */
+	caddr_t dle_mapbase;		/* Base address of mapped region */
+	Elf_Addr dle_vaddrbase;		/* Base address in shared object file */
+};
+
+
+
+typedef void (*ddl_event_callback_t) (struct dl_event*);
+
+int
+dll_set_event_callback(ddl_event_callback_t fpointer,int iterate);
+
 /*
  * Data declarations.
  */
@@ -180,6 +205,7 @@
     (func_ptr_type) &dladdr,
     (func_ptr_type) &dllockinit,
     (func_ptr_type) &dlinfo,
+    (func_ptr_type) &dll_set_event_callback,
     NULL
 };
 
@@ -1300,6 +1326,8 @@
 	obj_count++;
 	linkmap_add(obj);	/* for GDB & dlinfo() */
 
+	do_callback(obj,DLL_ADD_OBJECT);
+
 	dbg("  %p .. %p: %s", obj->mapbase,
 	  obj->mapbase + obj->mapsize - 1, obj->path);
 	if (obj->textrel)
@@ -2174,6 +2202,55 @@
     return (0);
 }
 
+
+
+
+
+
+
+ddl_event_callback_t ddl_event_callback = NULL;
+
+
+static void
+do_callback(Obj_Entry * obj,int reason)
+{
+	struct dl_event event;
+
+	if (ddl_event_callback == NULL)
+		return;
+
+	event.dle_reason = reason;
+	event.dle_handle = obj;
+	event.dle_path = obj->path;
+	event.dle_textsize = obj->textsize;
+	event.dle_relocbase = obj->relocbase;
+	event.dle_mapbase = obj->mapbase;
+	event.dle_vaddrbase = obj->vaddrbase;
+	(*ddl_event_callback) (&event);
+
+}
+
+
+int
+dll_set_event_callback(ddl_event_callback_t fpointer,int iterate)
+{
+	Obj_Entry * obj;
+	ddl_event_callback = fpointer;
+
+	if (fpointer != NULL && iterate ) {
+		do_callback(&obj_rtld,DLL_ITERATE_OBJECT);
+		if (obj_main)
+			do_callback(obj_main,DLL_ITERATE_OBJECT);
+
+		for (obj = obj_list->next;  obj != NULL;  obj = obj->next)
+			do_callback(obj,DLL_ITERATE_OBJECT);
+	}
+	return 0;
+}
+
+
+
+
 static void
 linkmap_add(Obj_Entry *obj)
 {
@@ -2543,6 +2620,9 @@
 	    linkmap_delete(obj);
 	    *linkp = obj->next;
 	    obj_count--;
+
+	    do_callback(obj,DLL_REMOVE_OBJECT);
+
 	    obj_free(obj);
 	} else
 	    linkp = &obj->next;
Index: share/mk/bsd.lib.mk
===========================================================================
--- share/mk/bsd.lib.mk	2006/03/21 18:14:55	#9
+++ share/mk/bsd.lib.mk	2006/03/21 18:14:55
@@ -20,6 +20,15 @@
 SHLIB_LINK?=	${SHLIB_NAME:R}
 .endif
 SONAME?=	${SHLIB_NAME}
+.if !defined(NOPROFILE)
+.if !defined(PSHLIB_NAME) && defined(LIB) && defined(SHLIB_MAJOR)
+PSHLIB_NAME=	lib${LIB}_p.so.${SHLIB_MAJOR}
+.endif
+.if defined(PSHLIB_NAME) && ${PSHLIB_NAME:M*.so.*}
+PSHLIB_LINK?=	${PSHLIB_NAME:R}
+.endif
+PSONAME?=	${PSHLIB_NAME}
+.endif
 .else
 .if defined(SHLIB_MAJOR) && defined(SHLIB_MINOR)
 SHLIB_NAME?=	lib${LIB}.so.${SHLIB_MAJOR}.${SHLIB_MINOR}
@@ -42,7 +51,7 @@
 # prefer .s to a .c, add .po, remove stuff not used in the BSD libraries
 # .So used for PIC object files
 .SUFFIXES:
-.SUFFIXES: .out .o .po .So .S .s .c .cc .cpp .cxx .m .C .f .y .l
+.SUFFIXES: .out .o .po .So .pSo .S .s .c .cc .cpp .cxx .m .C .f .y .l
 
 .if !defined(PICFLAG)
 PICFLAG=-fpic
@@ -63,6 +72,11 @@
 	@${LD} ${LDFLAGS} -o ${.TARGET}.tmp -x -r ${.TARGET}
 	@mv ${.TARGET}.tmp ${.TARGET}
 
+.c.pSo:
+	${CC} -pg ${PICFLAG} -DPIC ${CFLAGS} -c ${.IMPSRC} -o ${.TARGET}
+	@${LD} ${LDFLAGS} -o ${.TARGET}.tmp -x -r ${.TARGET}
+	@mv ${.TARGET}.tmp ${.TARGET}
+
 .cc.o .C.o .cpp.o .cxx.o:
 	${CXX} ${CXXFLAGS} -c ${.IMPSRC} -o ${.TARGET}
 	@${LD} -o ${.TARGET}.tmp -x -r ${.TARGET}
@@ -78,6 +92,11 @@
 	@${LD} ${LDFLAGS} -o ${.TARGET}.tmp -x -r ${.TARGET}
 	@mv ${.TARGET}.tmp ${.TARGET}
 
+.cc.pSo .C.pSo .cpp.pSo .cxx.pSo:
+	${CXX} -pg ${PICFLAG} -DPIC ${CXXFLAGS} -c ${.IMPSRC} -o ${.TARGET}
+	@${LD} ${LDFLAGS} -o ${.TARGET}.tmp -x -r ${.TARGET}
+	@mv ${.TARGET}.tmp ${.TARGET}
+
 .f.o:
 	${FC} ${FFLAGS} -o ${.TARGET} -c ${.IMPSRC} 
 	@${LD} -o ${.TARGET}.tmp -x -r ${.TARGET}
@@ -92,6 +111,10 @@
 	${FC} ${PICFLAG} -DPIC ${FFLAGS} -o ${.TARGET} -c ${.IMPSRC}
 	@${LD} ${LDFLAGS} -o ${.TARGET}.tmp -x -r ${.TARGET}
 	@mv ${.TARGET}.tmp ${.TARGET}
+.f.pSo:
+	${FC} -pg ${PICFLAG} -DPIC ${FFLAGS} -o ${.TARGET} -c ${.IMPSRC}
+	@${LD} ${LDFLAGS} -o ${.TARGET}.tmp -x -r ${.TARGET}
+	@mv ${.TARGET}.tmp ${.TARGET}
 
 .m.o:
 	${OBJC} ${OBJCFLAGS} -c ${.IMPSRC} -o ${.TARGET}
@@ -107,6 +130,10 @@
 	${OBJC} ${PICFLAG} -DPIC ${OBJCFLAGS} -c ${.IMPSRC} -o ${.TARGET}
 	@${LD} ${LDFLAGS} -o ${.TARGET}.tmp -x -r ${.TARGET}
 	@mv ${.TARGET}.tmp ${.TARGET}
+.m.pSo:
+	${OBJC} -pg ${PICFLAG} -DPIC ${OBJCFLAGS} -c ${.IMPSRC} -o ${.TARGET}
+	@${LD} ${LDFLAGS} -o ${.TARGET}.tmp -x -r ${.TARGET}
+	@mv ${.TARGET}.tmp ${.TARGET}
 
 .s.o:
 	${CC} -x assembler-with-cpp ${CFLAGS} ${AINC} -c \
@@ -126,6 +153,12 @@
 	@${LD} -o ${.TARGET}.tmp -x -r ${.TARGET}
 	@mv ${.TARGET}.tmp ${.TARGET}
 
+.s.pSo:
+	${CC} -x assembler-with-cpp ${PICFLAG} -DPIC -DPROF ${CFLAGS} \
+	    ${AINC} -c ${.IMPSRC} -o ${.TARGET}
+	@${LD} -o ${.TARGET}.tmp -X -r ${.TARGET}
+	@mv ${.TARGET}.tmp ${.TARGET}
+
 .S.o:
 	${CC} ${CFLAGS} ${AINC} -c ${.IMPSRC} -o ${.TARGET}
 	@${LD} ${LDFLAGS} -o ${.TARGET}.tmp -x -r ${.TARGET}
@@ -142,6 +175,12 @@
 	@${LD} -o ${.TARGET}.tmp -x -r ${.TARGET}
 	@mv ${.TARGET}.tmp ${.TARGET}
 
+.S.pSo:
+	${CC} -DPROF ${PICFLAG} -DPIC ${CFLAGS} ${AINC} -c ${.IMPSRC} \
+	    -o ${.TARGET}
+	@${LD} -o ${.TARGET}.tmp -X -r ${.TARGET}
+	@mv ${.TARGET}.tmp ${.TARGET}
+
 all: objwarn
 
 .if defined(LIB) && !empty(LIB) || defined(SHLIB_NAME)
@@ -196,6 +235,23 @@
 .endif
 .endif
 
+.if defined(PSHLIB_NAME) && ${OBJFORMAT} == elf
+_LIBS+=		${PSHLIB_NAME}
+PSOBJS+=	${OBJS:.o=.pSo}
+
+${PSHLIB_NAME}: ${PSOBJS}
+	@${ECHO} building profiled shared library ${PSHLIB_NAME}
+	@rm -f ${.TARGET} ${PSHLIB_LINK}
+.if defined(PSHLIB_LINK)
+	@ln -fs ${.TARGET} ${PSHLIB_LINK}
+.endif
+	@${CC} ${LDFLAGS} -shared -Wl,-x \
+	    -o ${.TARGET} -Wl,-soname,${PSONAME} \
+	    `lorder ${PSOBJS} | tsort -q` ${LDADD}
+.endif
+
+
+
 .if defined(INSTALL_PIC_ARCHIVE) && defined(LIB) && !empty(LIB)
 _LIBS+=		lib${LIB}_pic.a
 
@@ -266,6 +322,14 @@
 	ln -fs ${SHLIB_NAME} ${DESTDIR}${SHLIBDIR}/${SHLIB_LINK}
 .endif
 .endif
+.if defined(PSHLIB_NAME)
+	${INSTALL}  -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} \
+	    ${_INSTALLFLAGS} ${_SHLINSTALLFLAGS} \
+	    ${PSHLIB_NAME} ${DESTDIR}${SHLIBDIR}
+.if defined(PSHLIB_LINK)
+	ln -fs ${PSHLIB_NAME} ${DESTDIR}${SHLIBDIR}/${PSHLIB_LINK}
+.endif
+.endif
 .if defined(INSTALL_PIC_ARCHIVE) && defined(LIB) && !empty(LIB)
 	${INSTALL} -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} \
 	    ${_INSTALLFLAGS} lib${LIB}_pic.a ${DESTDIR}${LIBDIR}
@@ -297,7 +361,10 @@
     defined(INSTALL_PIC_ARCHIVE) && defined(LIB) && !empty(LIB)
 ${SOBJS}: ${SRCS:M*.h}
 .endif
+.if defined(PSHLIB_NAME)
+${PSOBJS}: ${SRCS:M*.h}
 .endif
+.endif
 
 .if !target(clean)
 clean:
@@ -315,12 +382,22 @@
     defined(INSTALL_PIC_ARCHIVE) && defined(LIB) && !empty(LIB)
 	rm -f ${SOBJS} ${SOBJS:.So=.so} ${SOBJS:S/$/.tmp/}
 .endif
+.if defined(PSHLIB_NAME) 
+	rm -f ${PSOBJS} ${PSOBJS:.pSo=.so} ${PSOBJS:S/$/.tmp/}
+.endif
 .if defined(SHLIB_NAME)
 .if defined(SHLIB_LINK)
 	rm -f ${SHLIB_LINK}
 .endif
+
+.if defined(PSHLIB_NAME)
+.if defined(PSHLIB_LINK)
+	rm -f ${PSHLIB_LINK}
+.endif
+.endif
 .if defined(LIB) && !empty(LIB)
 	rm -f lib${LIB}.so.* lib${LIB}.so
+	rm -f lib${LIB}_p.so.* lib${LIB}_p.so
 .endif
 .endif
 .endif !defined(INTERNALLIB)
Index: sys/conf/options
===========================================================================
--- sys/conf/options	2006/03/21 18:14:55	#27
+++ sys/conf/options	2006/03/21 18:14:55
@@ -403,6 +403,7 @@
 INVARIANTS		opt_global.h
 SIMPLELOCK_DEBUG	opt_global.h
 VFS_BIO_DEBUG		opt_global.h
+XPROF			opt_global.h
 
 # These are VM related options
 VM_KMEM_SIZE		opt_vm.h
Index: sys/i386/include/asm.h
===========================================================================
--- sys/i386/include/asm.h	2006/03/21 18:14:55	#1
+++ sys/i386/include/asm.h	2006/03/21 18:14:55
@@ -51,12 +51,19 @@
 	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b],%ebx
 #define	PIC_EPILOGUE	\
 	popl	%ebx
+#define PIC_PROF_PROLOGUE \
+	call	1f;	  \
+1:			  \
+	popl	%ebx;	  \
+	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b],%ebx
+    
 #define	PIC_PLT(x)	x@PLT
 #define	PIC_GOT(x)	x@GOT(%ebx)
 #define	PIC_GOTOFF(x)	x@GOTOFF(%ebx)
 #else
 #define	PIC_PROLOGUE
 #define	PIC_EPILOGUE
+#define PIC_PROF_PROLOGUE
 #define	PIC_PLT(x)	x
 #define	PIC_GOT(x)	x
 #define	PIC_GOTOFF(x)	x
@@ -86,11 +93,13 @@
 #ifdef PROF
 #define	ALTENTRY(x)	_ENTRY(x); \
 			pushl %ebp; movl %esp,%ebp; \
+                        PIC_PROF_PROLOGUE; \
 			call PIC_PLT(HIDENAME(mcount)); \
 			popl %ebp; \
 			jmp 9f
 #define	ENTRY(x)	_ENTRY(x); \
 			pushl %ebp; movl %esp,%ebp; \
+                        PIC_PROF_PROLOGUE; \
 			call PIC_PLT(HIDENAME(mcount)); \
 			popl %ebp; \
 			9:
Index: sys/kern/init_main.c
===========================================================================
--- sys/kern/init_main.c	2006/03/21 18:14:55	#4
+++ sys/kern/init_main.c	2006/03/21 18:14:55
@@ -357,7 +357,13 @@
 	 * We continue to place resource usage info and signal
 	 * actions in the user struct so they're pageable.
 	 */
+#ifdef XPROF
+	p->p_stats = &p->p_addr->u_stats.xpp_pstats;
+	p->p_addr->u_stats.xpp_pstats.p_prof.pr_scale = 0;
+	p->p_addr->u_stats.xpp_prof = NULL;
+#else
 	p->p_stats = &p->p_addr->u_stats;
+#endif
 	p->p_sigacts = &p->p_addr->u_sigacts;
 
 	/*
Index: sys/kern/kern_exec.c
===========================================================================
--- sys/kern/kern_exec.c	2006/03/21 18:14:55	#8
+++ sys/kern/kern_exec.c	2006/03/21 18:14:55
@@ -280,8 +280,12 @@
 	}
 
 	/* Stop profiling */
+#ifdef XPROF
+	if (p->p_flag & P_PROFIL)
+		stopprofiling(p);
+#else
 	stopprofclock(p);
-
+#endif
 	/* close files on exec */
 	fdcloseexec(p);
 
Index: sys/kern/kern_exit.c
===========================================================================
--- sys/kern/kern_exit.c	2006/03/21 18:14:55	#10
+++ sys/kern/kern_exit.c	2006/03/21 18:14:55
@@ -163,7 +163,11 @@
 		(*ep->function)(p);
 
 	if (p->p_flag & P_PROFIL)
+#ifdef XPROF
+		stopprofiling(p);
+#else
 		stopprofclock(p);
+#endif
 	MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage),
 		M_ZOMBIE, M_WAITOK);
 	/*
Index: sys/kern/subr_prof.c
===========================================================================
--- sys/kern/subr_prof.c	2006/03/21 18:14:55	#3
+++ sys/kern/subr_prof.c	2006/03/21 18:14:55
@@ -425,6 +425,60 @@
 };
 #endif
 /* ARGSUSED */
+
+
+#ifdef XPROF
+
+#define memmove(d, s, l)	ovbcopy(s, d, l)
+#define memcpy(d, s, l)	bcopy(s, d, l)
+
+
+struct xprof_entry
+{
+	caddr_t	xpe_buffer;	/* buffer base */
+	caddr_t	xpe_start;		
+	caddr_t	xpe_end;	
+	u_long	xpe_scale;	/* pc scaling */
+};
+
+
+struct xprof
+{
+	u_int   xp_usage;
+	u_int	xp_size;
+	u_int	xp_count;
+
+	struct xprof_entry* xp_entries ;
+
+};
+
+
+#define XPROF_MAGIC_SCALE ((1 << 16) + 42)
+
+#define XPROF_DELETE_ALL 	1
+#define XPROF_DELETE 		2
+#define XPROF_ADD 		3
+
+
+int xprof_profile(struct proc *p, struct profil_args *uap);
+
+static struct xprof* xprof_get(struct proc *p);
+static  void xprof_set(struct proc *p,struct xprof* xprof);
+caddr_t xprof_tick_addr(struct proc *p, register u_long pc);
+static int xprof_find(struct xprof* xp,caddr_t start,int* location);
+void prof_remove_reference(struct xprof *xp);
+static int prof_allocate(struct xprof **xprofp,int size);
+
+static void xprof_delete_all(struct proc *p);
+static int xprof_delete(struct proc *p,caddr_t start);
+static int xprof_insert(struct proc *p,struct xprof_entry* entry);
+
+#endif
+
+
+
+
+
 int
 profil(p, uap)
 	struct proc *p;
@@ -433,10 +487,21 @@
 	register struct uprof *upp;
 	int s;
 
+#ifdef XPROF
+	
+	if (uap->scale == XPROF_MAGIC_SCALE)
+		return xprof_profile(p,uap);
+#endif
+
+
 	if (uap->scale > (1 << 16))
 		return (EINVAL);
 	if (uap->scale == 0) {
+#ifdef XPROF
+		stopprofiling(p);
+#else
 		stopprofclock(p);
+#endif
 		return (0);
 	}
 	upp = &p->p_stats->p_prof;
@@ -489,11 +554,20 @@
 	if (ticks == 0)
 		return;
 	prof = &p->p_stats->p_prof;
+
+#ifdef XPROF
+	if (NULL == (addr = xprof_tick_addr(p,pc))) {
+		if (prof->pr_scale == 0) return;
+#endif XPROF
+
 	if (pc < prof->pr_off ||
 	    (i = PC_TO_INDEX(pc, prof)) >= prof->pr_size)
 		return;			/* out of range; ignore */
 
 	addr = prof->pr_base + i;
+#ifdef XPROF
+	}
+#endif
 	if ((v = fuswintr(addr)) == -1 || suswintr(addr, v + ticks) == -1) {
 		prof->pr_addr = pc;
 		prof->pr_ticks = ticks;
@@ -521,15 +595,383 @@
 		return;
 
 	prof = &p->p_stats->p_prof;
+
+#ifdef XPROF
+	if (NULL == (addr = xprof_tick_addr(p,pc))) {
+		if (prof->pr_scale == 0) return;
+
+#endif XPROF
+
 	if (pc < prof->pr_off ||
 	    (i = PC_TO_INDEX(pc, prof)) >= prof->pr_size)
 		return;
 
 	addr = prof->pr_base + i;
+
+#ifdef XPROF
+	}
+#endif
 	if (copyin(addr, (caddr_t)&v, sizeof(v)) == 0) {
 		v += ticks;
 		if (copyout((caddr_t)&v, addr, sizeof(v)) == 0)
 			return;
 	}
+#ifdef XPROF
+	stopprofiling(p);
+#else
+	stopprofclock(p);
+#endif
+}
+
+
+#ifdef XPROF
+
+
+
+
+static struct xprof* 
+xprof_get(struct proc *p)
+{
+	struct xprof* xprof;
+	xprof = ((struct xppstats*) (p)->p_stats)->xpp_prof;
+	return xprof;
+}
+	      
+
+static  void
+xprof_set(struct proc *p,struct xprof* xprof )
+{
+
+	((struct xppstats*) (p)->p_stats)->xpp_prof = xprof;
+}
+
+
+caddr_t
+xprof_tick_addr(p, pc)
+register struct proc *p;
+	register u_long pc;
+{
+	int found;
+	int index;
+	struct xprof* xprof;
+	struct xprof_entry* entry;
+	caddr_t addr;
+
+	xprof = xprof_get(p);
+	if (xprof == NULL) return 0;
+
+	
+	found = xprof_find(xprof,(caddr_t)pc,&index);
+
+	if(!found) return 0;
+
+	entry =  &xprof->xp_entries[index];
+	
+	
+	/*
+	 * Scale is a fixed-point number with the binary point 16 bits
+	 * into the value, and is <= 1.0.  pc is at most 32 bits, so the
+	 * intermediate result is at most 48 bits.
+	 */
+
+	addr = entry->xpe_buffer +
+		((int)(((u_quad_t)(((caddr_t) pc) - entry->xpe_start) * (u_quad_t)((entry)->xpe_scale)) >> 16) & ~1);
+
+
+
+	return addr;
+}
+
+		
+
+
+static int
+xprof_find(struct xprof* xp,caddr_t start,int* location)
+{
+	int min,max,i;
+	struct xprof_entry* entries = xp->xp_entries;
+	caddr_t entry_start,entry_end;
+
+	min = 0;
+	max = xp->xp_count;
+	i = 0;
+
+	while(min < max) {
+		i = (min + max) / 2;
+		entry_start = entries[i].xpe_start;
+		entry_end   = entries[i].xpe_end;
+
+		if  (start < entry_start) {
+			max = i;
+		} else if (start < entry_end) {
+			*location = i;
+			return 1;
+		} else	
+			min = i + 1;
+	}
+
+	*location = min;
+	return 0;
+}
+
+static MALLOC_DEFINE(M_XPROFBUF, "xprof", "extended profiling buffer");
+
+void
+prof_remove_reference(struct xprof *xp)
+{
+	KASSERT(xp->xp_usage > 0,("Invalid reference count"));
+	xp->xp_usage--;
+	if (xp->xp_usage == 0) {
+		free(xp->xp_entries,M_XPROFBUF);
+		free(xp,M_XPROFBUF);
+	}
+}
+
+
+#define PROF_ALLOC_ROUNDUP	32
+
+static int
+prof_allocate(struct xprof **xprofp,int size)
+{
+	struct xprof *xprof;
+	struct xprof_entry* entries;
+
+	size = ROUNDUP(size,PROF_ALLOC_ROUNDUP);
+
+	xprof = malloc(sizeof(struct xprof) ,M_XPROFBUF,M_WAITOK);
+	if (xprof == NULL) return ENOMEM;
+	
+	entries = malloc(sizeof(struct xprof_entry) * size, M_XPROFBUF,M_WAITOK);
+	if (entries == NULL) {
+		free(xprof,M_XPROFBUF);
+		return ENOMEM;
+	}
+	
+	xprof->xp_count = 0;
+	xprof->xp_size  = size;
+	xprof->xp_usage = 1;
+	xprof->xp_entries = entries;
+
+	*xprofp =xprof;
+	return 0;
+}
+
+		
+static void
+xprof_delete_all(struct proc *p)
+{
+	int s;
+	struct xprof* xprof;
+
+	xprof = xprof_get(p);
+	if (xprof != NULL) {
+		s = splstatclock();
+		xprof_set(p, NULL);
+		if (p->p_stats->p_prof.pr_scale == 0)
+			stopprofclock(p);
+		splx(s);       
+		prof_remove_reference(xprof);
+	}
+
+}
+
+static int
+xprof_delete(struct proc *p,caddr_t start)
+{
+	int found;
+	int index;
+	int s,status;
+	struct xprof *xprof;
+	struct xprof * new_xprof;
+
+	xprof = xprof_get(p);
+	if (xprof == NULL) return EINVAL;
+
+	found = xprof_find(xprof,start,&index);
+
+	if (!found || xprof->xp_entries[index].xpe_start != start)
+		return EINVAL;
+
+	if (xprof->xp_count == 1) {
+		/* This is the last entry - stop profiling */
+		xprof_delete_all(p);
+		return 0;
+	}
+
+	if (xprof->xp_usage == 1) {
+		/* We are the only user of this xprof and can modify the array */
+		s = splstatclock();
+		memmove(&xprof->xp_entries[index],
+		    &xprof->xp_entries[index + 1],
+		    sizeof(struct xprof_entry) * (xprof->xp_count - index ));
+		xprof->xp_count--;
+		splx(s);
+		return 0;
+	}
+
+	/* 
+	 * We share the profiling information with another process 
+	 * and need to unshare before proceeding to modify the information
+	 */
+
+	status = prof_allocate(&new_xprof,xprof->xp_count - 1);
+	if (status) return status;
+
+	/* Copy up to deleted entry */
+	memcpy(&new_xprof->xp_entries[0],&xprof->xp_entries[0],index * sizeof(struct xprof_entry));
+
+	/* Copy after deleted entry */
+	memcpy(&new_xprof->xp_entries[index],&xprof->xp_entries[index + 1], (xprof->xp_count - index) * sizeof(struct xprof_entry));
+
+	new_xprof->xp_count = xprof->xp_count - 1;
+
+	s = splstatclock();
+	
+	xprof_set(p,new_xprof);
+
+	splx(s);
+
+	prof_remove_reference(xprof);
+	return 0;
+}
+		
+
+static int
+xprof_insert(struct proc *p,struct xprof_entry* entry)
+{
+
+	struct xprof* xprof;
+	struct xprof* new_xprof;
+	int found,index,status,s;
+
+	if (entry->xpe_start >= entry->xpe_end)
+		return EINVAL;
+
+
+	xprof = xprof_get(p);
+
+	if (xprof == NULL) {
+		status = prof_allocate(&xprof,1);
+		if (status) return status;
+
+		memcpy(&xprof->xp_entries[0],entry,sizeof(struct xprof_entry));
+		xprof->xp_count = 1;
+	
+		s = splstatclock();
+		xprof_set(p,xprof);
+		startprofclock(p);
+		
+		splx(s);
+		return 0;
+	}
+
+
+	found = xprof_find(xprof,entry->xpe_start,&index);
+
+	/* Test for overlap with existing entries */
+	if (found || (index < xprof->xp_count && xprof->xp_entries[index].xpe_start < entry->xpe_end))
+		return EINVAL;
+
+	
+	if(xprof->xp_usage == 1 &&  xprof->xp_count < xprof->xp_size) {
+
+		s = splstatclock();
+		
+		memmove(&xprof->xp_entries[index + 1],
+		    &xprof->xp_entries[index],
+		    sizeof(struct xprof_entry) * (xprof->xp_count - index));
+
+		memcpy(&xprof->xp_entries[index],entry,sizeof(struct xprof_entry));
+
+		xprof->xp_count++;
+
+		splx(s);
+
+		return 0;
+
+	    }
+
+	status = prof_allocate(&new_xprof,xprof->xp_count + 1);
+	if (status) return status;
+
+	/* Copy up to inserted entry */
+	memcpy(&new_xprof->xp_entries[0],&xprof->xp_entries[0],index * sizeof(struct xprof_entry));
+
+	
+        /* Copy new  entry */
+	memcpy(&new_xprof->xp_entries[index],entry,sizeof(struct xprof_entry));
+
+	/* Copy after dew entry */
+	memcpy(&new_xprof->xp_entries[index + 1],&xprof->xp_entries[index],(xprof->xp_count - index) * sizeof(struct xprof_entry));
+
+	new_xprof->xp_count = xprof->xp_count + 1;
+
+	s = splstatclock();
+	xprof_set(p,new_xprof);
+	splx(s);
+
+	prof_remove_reference(xprof);
+	return 0;
+}
+int
+xprof_profile(p, uap)
+	struct proc *p;
+	register struct profil_args *uap;
+{
+	int status = 0;
+	int command;
+	struct xprof_entry entry;
+	
+	command = uap->offset; 
+
+
+	switch(command) {
+
+	case XPROF_DELETE_ALL:
+		xprof_delete_all(p);
+		break;
+	case XPROF_DELETE:		
+		status =  xprof_delete(p,uap->samples);
+		break;
+
+	case XPROF_ADD:
+	{
+		status = copyin(uap->samples,&entry,sizeof(struct xprof_entry));
+		if (status) break;
+
+		status = xprof_insert(p,&entry);
+		break;
+	}
+			
+	default:
+		status = EINVAL;
+
+	}	       
+	
+	return status;
+}
+
+
+void 
+stopprofiling(struct proc *p)
+{
+	int s;
+	struct xprof* xprof;
+
+
+	xprof = xprof_get(p);
+	if (xprof) {
+		s = splstatclock();
+		xprof_set(p, NULL);
+		splx(s);
+		prof_remove_reference(xprof);
+	}
+
 	stopprofclock(p);
+
+	p->p_stats->p_prof.pr_scale = 0;
+
 }
+
+#endif
+
Index: sys/sys/resourcevar.h
===========================================================================
--- sys/sys/resourcevar.h	2006/03/21 18:14:55	#2
+++ sys/sys/resourcevar.h	2006/03/21 18:14:55
@@ -64,6 +64,17 @@
 	struct	timeval p_start;	/* starting time */
 };
 
+#ifdef XPROF
+
+struct xprof;
+
+struct xppstats {
+	struct pstats xpp_pstats;
+	struct xprof* xpp_prof;
+}; 
+
+#endif
+
 /*
  * Kernel shareable process resource limits.  Because this structure
  * is moderately large but changes infrequently, it is normally
Index: sys/sys/systm.h
===========================================================================
--- sys/sys/systm.h	2006/03/21 18:14:55	#15
+++ sys/sys/systm.h	2006/03/21 18:14:55
@@ -186,6 +186,9 @@
 void	statclock __P((struct clockframe *frame));
 
 void	startprofclock __P((struct proc *));
+#ifdef XPROF
+void	stopprofiling __P((struct proc *));
+#endif
 void	stopprofclock __P((struct proc *));
 void	setstatclockrate __P((int hzrate));
 
Index: sys/sys/user.h
===========================================================================
--- sys/sys/user.h	2006/03/21 18:14:55	#3
+++ sys/sys/user.h	2006/03/21 18:14:55
@@ -102,7 +102,11 @@
 struct	user {
 	struct	pcb u_pcb;
 	struct	sigacts u_sigacts;	/* p_sigacts points here (use it!) */
+#ifdef XPROF
+	struct	xppstats u_stats;	/* p_stats points here (use it!) */
+#else
 	struct	pstats u_stats;		/* p_stats points here (use it!) */
+#endif
 	/*
 	 * Remaining fields for a.out core dumps - not valid at other times!
 	 */
Index: sys/vm/vm_glue.c
===========================================================================
--- sys/vm/vm_glue.c	2006/03/21 18:14:55	#5
+++ sys/vm/vm_glue.c	2006/03/21 18:14:55
@@ -249,20 +249,35 @@
 	 * If procsig->ps_refcnt is 1 and p2->p_sigacts is NULL we dont' need
 	 * to share sigacts, so we use the up->u_sigacts.
 	 */
+#ifdef XPROF
+	p2->p_stats = &up->u_stats.xpp_pstats;
+	up->u_stats.xpp_prof = ((struct xppstats*) p1->p_stats)->xpp_prof;
+#else
 	p2->p_stats = &up->u_stats;
+#endif
 	if (p2->p_sigacts == NULL) {
 		if (p2->p_procsig->ps_refcnt != 1)
 			printf ("PID:%d NULL sigacts with refcnt not 1!\n",p2->p_pid);
 		p2->p_sigacts = &up->u_sigacts;
 		up->u_sigacts = *p1->p_sigacts;
 	}
+#ifdef XPROF
 
+	bzero(&up->u_stats.xpp_pstats.pstat_startzero,
+	    (unsigned) ((caddr_t) &up->u_stats.xpp_pstats.pstat_endzero -
+		(caddr_t) &up->u_stats.xpp_pstats.pstat_startzero));
+	bcopy(&p1->p_stats->pstat_startcopy, &up->u_stats.xpp_pstats.pstat_startcopy,
+	    ((caddr_t) &up->u_stats.xpp_pstats.pstat_endcopy -
+		(caddr_t) &up->u_stats.xpp_pstats.pstat_startcopy));
+
+#else
 	bzero(&up->u_stats.pstat_startzero,
 	    (unsigned) ((caddr_t) &up->u_stats.pstat_endzero -
 		(caddr_t) &up->u_stats.pstat_startzero));
 	bcopy(&p1->p_stats->pstat_startcopy, &up->u_stats.pstat_startcopy,
 	    ((caddr_t) &up->u_stats.pstat_endcopy -
 		(caddr_t) &up->u_stats.pstat_startcopy));
+#endif
 
 
 	/*
Index: usr.bin/gprof/aout.c
===========================================================================
--- usr.bin/gprof/aout.c	2006/03/21 18:14:55	#1
+++ usr.bin/gprof/aout.c	2006/03/21 18:14:55
@@ -3,7 +3,7 @@
 #include "gprof.h"
 
 static void getstrtab(FILE *, const char *);
-static void getsymtab(FILE *, const char *);
+static void getsymtab(struct module* module, FILE *, const char *);
 static void gettextspace(FILE *);
 static bool funcsymbol(struct nlist *);
 
@@ -22,7 +22,7 @@
      * Returns 0 on success, -1 on failure.
      */
 int
-aout_getnfile(const char *filename, char ***defaultEs)
+aout_getnfile(struct module* module, const char *filename, char ***defaultEs)
 {
     FILE	*nfile;
     int		valcmp();
@@ -38,7 +38,7 @@
 	return -1;
     }
     getstrtab(nfile, filename);
-    getsymtab(nfile, filename);
+    getsymtab(module,nfile, filename);
     gettextspace( nfile );
     fclose(nfile);
 #   ifdef DEBUG
@@ -78,7 +78,7 @@
      * Read in symbol table
      */
 static void
-getsymtab(FILE *nfile, const char *filename)
+getsymtab(struct module* module, FILE *nfile, const char *filename)
 {
     register long	i;
     int			askfor;
@@ -86,29 +86,29 @@
 
     /* pass1 - count symbols */
     fseek(nfile, (long)N_SYMOFF(xbuf), 0);
-    nname = 0;
+    module->nname = 0;
     for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) {
 	fread(&nbuf, sizeof(nbuf), 1, nfile);
 	if ( ! funcsymbol( &nbuf ) ) {
 	    continue;
 	}
-	nname++;
+	module->nname++;
     }
-    if (nname == 0) {
+    if (module->nname == 0) {
 	warnx("%s: no symbols", filename );
 	done();
     }
-    askfor = nname + 1;
-    nl = (nltype *) calloc( askfor , sizeof(nltype) );
-    if (nl == 0) {
+    askfor = module->nname + 1;
+    module->nl = (nltype *) calloc( askfor , sizeof(nltype) );
+    if (module->nl == 0) {
 	warnx("no room for %d bytes of symbol table", askfor * sizeof(nltype) );
 	done();
     }
 
     /* pass2 - read symbols */
     fseek(nfile, (long)N_SYMOFF(xbuf), 0);
-    npe = nl;
-    nname = 0;
+    module->npe = module->nl;
+    module->nname = 0;
     for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) {
 	fread(&nbuf, sizeof(nbuf), 1, nfile);
 	if ( ! funcsymbol( &nbuf ) ) {
@@ -120,18 +120,18 @@
 #	    endif DEBUG
 	    continue;
 	}
-	npe->value = nbuf.n_value;
-	npe->name = strtab+nbuf.n_un.n_strx;
+	module->npe->value = nbuf.n_value;
+	module->npe->name = strtab+nbuf.n_un.n_strx;
 #	ifdef DEBUG
 	    if ( debug & AOUTDEBUG ) {
 		printf( "[getsymtab] %d %s 0x%08x\n" ,
 			nname , npe -> name , npe -> value );
 	    }
 #	endif DEBUG
-	npe++;
-	nname++;
+	module->npe++;
+	module->nname++;
     }
-    npe->value = -1;
+    module->npe->value = -1;
 }
 
     /*
Index: usr.bin/gprof/arcs.c
===========================================================================
--- usr.bin/gprof/arcs.c	2006/03/21 18:14:55	#1
+++ usr.bin/gprof/arcs.c	2006/03/21 18:14:55
@@ -113,9 +113,9 @@
 }
 
 nltype **
-doarcs()
+doarcs(struct info* info)
 {
-    nltype	*parentp, **timesortnlp;
+    nltype	*parentp, **parentpp, **timesortnlp;
     arctype	*arcp;
     long	index;
     long	pass;
@@ -126,7 +126,8 @@
 	 *	    count self-recursive calls.
 	 *	    indicate that nothing is on cycles.
 	 */
-    for ( parentp = nl ; parentp < npe ; parentp++ ) {
+    for ( parentpp = info->nl ; parentpp < info->npe ; parentpp++ ) {
+	 parentp = *parentpp;
 	parentp -> childtime = 0.0;
 	arcp = arclookup( parentp , parentp );
 	if ( arcp != 0 ) {
@@ -154,7 +155,8 @@
 	     *	if any node is unnumbered,
 	     *	    number it and any of its descendents.
 	     */
-	for ( dfn_init() , parentp = nl ; parentp < npe ; parentp++ ) {
+	for ( dfn_init() , parentpp = info->nl ; parentpp < info->npe ; parentpp++ ) {
+		parentp = *parentpp;
 	    if ( parentp -> toporder == DFN_NAN ) {
 		dfn( parentp );
 	    }
@@ -162,7 +164,7 @@
 	    /*
 	     *	link together nodes on the same cycle
 	     */
-	cyclelink();
+	cyclelink(info);
 	    /*
 	     *	if no cycles to break up, proceed
 	     */
@@ -186,7 +188,8 @@
 	    break;
 	free ( cyclenl );
 	ncycle = 0;
-	for ( parentp = nl ; parentp < npe ; parentp++ ) {
+	for ( parentpp = info->nl ; parentpp < info->npe ; parentpp++ ) {
+		parentp = *parentpp;
 	    parentp -> toporder = DFN_NAN;
 	    parentp -> cycleno = 0;
 	    parentp -> cyclehead = parentp;
@@ -201,18 +204,18 @@
 	/*
 	 *	Sort the symbol table in reverse topological order
 	 */
-    topsortnlp = (nltype **) calloc( nname , sizeof(nltype *) );
+    topsortnlp = (nltype **) calloc( info->nname , sizeof(nltype *) );
     if ( topsortnlp == (nltype **) 0 ) {
 	fprintf( stderr , "[doarcs] ran out of memory for topo sorting\n" );
     }
-    for ( index = 0 ; index < nname ; index += 1 ) {
-	topsortnlp[ index ] = &nl[ index ];
+    for ( index = 0 ; index < info->nname ; index += 1 ) {
+	topsortnlp[ index ] = info->nl[ index ];
     }
-    qsort( topsortnlp , nname , sizeof(nltype *) , topcmp );
+    qsort( topsortnlp , info->nname , sizeof(nltype *) , topcmp );
 #   ifdef DEBUG
 	if ( debug & DFNDEBUG ) {
 	    printf( "[doarcs] topological sort listing\n" );
-	    for ( index = 0 ; index < nname ; index += 1 ) {
+	    for ( index = 0 ; index < info->nname ; index += 1 ) {
 		printf( "[doarcs] " );
 		printf( "%d:" , topsortnlp[ index ] -> toporder );
 		printname( topsortnlp[ index ] );
@@ -227,40 +230,40 @@
 	 *	this happens before time propagation
 	 *	since time propagation uses the fractions.
 	 */
-    doflags();
+    doflags(info);
 	/*
 	 *	starting from the topological bottom,
 	 *	propogate children times up to parents.
 	 */
-    dotime();
+    dotime(info);
 	/*
 	 *	Now, sort by propself + propchild.
 	 *	sorting both the regular function names
 	 *	and cycle headers.
 	 */
-    timesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) );
+    timesortnlp = (nltype **) calloc( info->nname + ncycle , sizeof(nltype *) );
     if ( timesortnlp == (nltype **) 0 ) {
 	warnx("ran out of memory for sorting");
     }
-    for ( index = 0 ; index < nname ; index++ ) {
-	timesortnlp[index] = &nl[index];
+    for ( index = 0 ; index < info->nname ; index++ ) {
+	timesortnlp[index] = info->nl[index];
     }
     for ( index = 1 ; index <= ncycle ; index++ ) {
-	timesortnlp[nname+index-1] = &cyclenl[index];
+	timesortnlp[info->nname+index-1] = &cyclenl[index];
     }
-    qsort( timesortnlp , nname + ncycle , sizeof(nltype *) , totalcmp );
-    for ( index = 0 ; index < nname + ncycle ; index++ ) {
+    qsort( timesortnlp , info->nname + ncycle , sizeof(nltype *) , totalcmp );
+    for ( index = 0 ; index < info->nname + ncycle ; index++ ) {
 	timesortnlp[ index ] -> index = index + 1;
     }
     return( timesortnlp );
 }
 
-dotime()
+dotime(struct info* info)
 {
     int	index;
 
     cycletime();
-    for ( index = 0 ; index < nname ; index += 1 ) {
+    for ( index = 0 ; index < info->nname ; index += 1 ) {
 	timepropagate( topsortnlp[ index ] );
     }
 }
@@ -353,9 +356,9 @@
     }
 }
 
-cyclelink()
+cyclelink(struct info* info)
 {
-    register nltype	*nlp;
+    register nltype	*nlp,**nlpp;
     register nltype	*cyclenlp;
     int			cycle;
     nltype		*memberp;
@@ -365,7 +368,8 @@
 	 *	Count the number of cycles, and initialze the cycle lists
 	 */
     ncycle = 0;
-    for ( nlp = nl ; nlp < npe ; nlp++ ) {
+    for ( nlpp = info->nl ; nlpp < info->npe ; nlpp++ ) {
+	    nlp = *nlpp;
 	    /*
 	     *	this is how you find unattached cycles
 	     */
@@ -388,7 +392,8 @@
 	 *	number them, accumulate the data for the cycle
 	 */
     cycle = 0;
-    for ( nlp = nl ; nlp < npe ; nlp++ ) {
+    for ( nlpp = info->nl ; nlpp < info->npe ; nlpp++ ) {
+	    nlp = *nlpp;
 	if ( !( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) ) {
 	    continue;
 	}
@@ -788,14 +793,14 @@
      *		propfraction as the sum of fractional parents' propfractions
      *	and while we're here, sum time for functions.
      */
-doflags()
+doflags(struct info* info)
 {
     int		index;
     nltype	*childp;
     nltype	*oldhead;
 
     oldhead = 0;
-    for ( index = nname-1 ; index >= 0 ; index -= 1 ) {
+    for ( index = info->nname-1 ; index >= 0 ; index -= 1 ) {
 	childp = topsortnlp[ index ];
 	    /*
 	     *	if we haven't done this function or cycle,
Index: usr.bin/gprof/elf.c
===========================================================================
--- usr.bin/gprof/elf.c	2006/03/21 18:14:55	#2
+++ usr.bin/gprof/elf.c	2006/03/21 18:14:55
@@ -21,7 +21,7 @@
 static char	*excludes[] = { ".mcount", "_mcleanup", NULL };
 
 int
-elf_getnfile(const char *filename, char ***defaultEs)
+elf_getnfile(struct module* module,const char *filename, char ***defaultEs,int failIfNoSymbols)
 {
     int fd;
     Elf_Ehdr h;
@@ -35,6 +35,7 @@
     const Elf_Sym *symtab;
     int symtabct;
     int i;
+    nltype	*nlp;	
 
     if ((fd = open(filename, O_RDONLY)) == -1)
 	err(1, "%s", filename);
@@ -56,8 +57,14 @@
     for (i = 1;  i < h.e_shnum;  i++)
 	if (shdrs[i].sh_type == SHT_SYMTAB)
 	    break;
-    if (i == h.e_shnum)
-	errx(1, "%s has no symbol table", filename);
+    if (i == h.e_shnum) {
+	    if (failIfNoSymbols)
+		    errx(1, "%s has no symbol table", filename);
+	    else {
+		    *defaultEs = excludes;
+		    return -1;
+	    }
+    }
     sh_symtab = &shdrs[i];
     sh_strtab = &shdrs[sh_symtab->sh_link];
 
@@ -66,27 +73,28 @@
     strtab = (const char *)(base + sh_strtab->sh_offset);
 
     /* Count the symbols that we're interested in. */
-    nname = 0;
+    module->nname = 0;
     for (i = 1;  i < symtabct;  i++)
 	if (wantsym(&symtab[i], strtab))
-	    nname++;
+	    module->nname++;
 
     /* Allocate memory for them, plus a terminating entry. */
-    if ((nl = (nltype *)calloc(nname + 1, sizeof(nltype))) == NULL)
+    if ((module->nl = (nltype *)calloc(module->nname + 1, sizeof(nltype))) == NULL)
 	errx(1, "Insufficient memory for symbol table");
 
     /* Read them in. */
-    npe = nl;
+    nlp = module->nl;
     for (i = 1;  i < symtabct;  i++) {
 	const Elf_Sym *sym = &symtab[i];
 
 	if (wantsym(sym, strtab)) {
-	    npe->value = sym->st_value;
-	    npe->name = strtab + sym->st_name;
-	    npe++;
+	    nlp->value = sym->st_value;
+	    nlp->name = strtab + sym->st_name;
+	    nlp++;
 	}
     }
-    npe->value = -1;
+    nlp->value = -1;
+    module->npe = nlp;
 
     *defaultEs = excludes;
     return 0;
Index: usr.bin/gprof/gprof.c
===========================================================================
--- usr.bin/gprof/gprof.c	2006/03/21 18:14:55	#1
+++ usr.bin/gprof/gprof.c	2006/03/21 18:14:55
@@ -50,10 +50,16 @@
 
 static int valcmp(const void *, const void *);
 
+static struct module program_module;
+static struct info ginfo;
+
+void xprof_process(struct info* info,char **argv);
+void xprof_buildinfo(struct info* info);
 
 static struct gmonhdr	gmonhdr;
 static int lflag;
 static int Lflag;
+static int xprof = FALSE;
 
 main(argc, argv)
     int argc;
@@ -139,12 +145,23 @@
 	case 'u':
 	    uflag = TRUE;
 	    break;
+	case 'x':
+		xprof = TRUE;
+		break;
 	case 'z':
 	    zflag = TRUE;
 	    break;
 	}
 	argv++;
     }
+
+    TAILQ_INIT(&ginfo.modulelist);
+
+    if(xprof) {
+	    xprof_process(&ginfo,argv);
+	    goto common;
+    }
+	    
     if ( *argv != 0 ) {
 	a_outname  = *argv;
 	argv++;
@@ -162,13 +179,13 @@
 	/*
 	 *	get information from the executable file.
 	 */
-    if (elf_getnfile(a_outname, &defaultEs) == -1 &&
-      aout_getnfile(a_outname, &defaultEs) == -1)
+    if (elf_getnfile(&program_module, a_outname, &defaultEs,1) == -1 &&
+      aout_getnfile(&program_module,a_outname, &defaultEs) == -1)
 	errx(1, "%s: bad format", a_outname);
 	/*
 	 *	sort symbol table.
 	 */
-    qsort(nl, nname, sizeof(nltype), valcmp);
+    qsort(program_module.nl, program_module.nname, sizeof(nltype), valcmp);
 	/*
 	 *	turn off default functions
 	 */
@@ -182,7 +199,7 @@
 	 *	get information about mon.out file(s).
 	 */
     do	{
-	getpfile( gmonname );
+	getpfile(&program_module, gmonname );
 	if ( *argv != 0 ) {
 	    gmonname = *argv;
 	}
@@ -204,27 +221,33 @@
 	/*
 	 *	assign samples to procedures
 	 */
-    asgnsamples();
+    asgnsamples(&program_module);
+
+    
+    TAILQ_INSERT_TAIL(&ginfo.modulelist,&program_module,modulelink);
+
+    xprof_buildinfo(&ginfo);
+common:
 	/*
 	 *	assemble the dynamic profile
 	 */
-    timesortnlp = doarcs();
+    timesortnlp = doarcs(&ginfo);
 	/*
 	 *	print the dynamic profile
 	 */
     if(!lflag) {
-	    printgprof( timesortnlp );
+	    printgprof(&ginfo,timesortnlp);
     }
 	/*
 	 *	print the flat profile
 	 */
     if(!Lflag) {
-	    printprof();
+	    printprof(&ginfo);
     }
 	/*
 	 *	print the index
 	 */
-    printindex();
+    printindex(&ginfo);
     done();
 }
 
@@ -233,15 +256,16 @@
      *	an array of sampling hits within pc ranges,
      *	and the arcs.
      */
-getpfile(filename)
+getpfile(module, filename)
+	struct module* module;
     char *filename;
 {
     FILE		*pfile;
     FILE		*openpfile();
     struct rawarc	arc;
 
-    pfile = openpfile(filename);
-    readsamples(pfile);
+    pfile = openpfile(module,filename);
+    readsamples(module,pfile);
 	/*
 	 *	the rest of the file consists of
 	 *	a bunch of <from,self,count> tuples.
@@ -256,13 +280,14 @@
 	    /*
 	     *	add this arc
 	     */
-	tally( &arc );
+	tally(module, &arc );
     }
     fclose(pfile);
 }
 
 FILE *
-openpfile(filename)
+openpfile(module,filename)
+	struct module* module;
     char *filename;
 {
     struct gmonhdr	tmp;
@@ -275,7 +300,7 @@
 	done();
     }
     fread(&tmp, sizeof(struct gmonhdr), 1, pfile);
-    if ( s_highpc != 0 && ( tmp.lpc != gmonhdr.lpc ||
+    if (module-> s_highpc != 0 && ( tmp.lpc != gmonhdr.lpc ||
 	 tmp.hpc != gmonhdr.hpc || tmp.ncnt != gmonhdr.ncnt ) ) {
 	warnx("%s: incompatible with first gmon file", filename);
 	done();
@@ -298,36 +323,38 @@
 	    filename, rate, "incompatible with clock rate", hz);
 	done();
     }
-    s_lowpc = (unsigned long) gmonhdr.lpc;
-    s_highpc = (unsigned long) gmonhdr.hpc;
-    lowpc = (unsigned long)gmonhdr.lpc / sizeof(UNIT);
-    highpc = (unsigned long)gmonhdr.hpc / sizeof(UNIT);
-    sampbytes = gmonhdr.ncnt - size;
-    nsamples = sampbytes / sizeof (UNIT);
+    module->s_lowpc = (unsigned long) gmonhdr.lpc;
+    module->s_highpc = (unsigned long) gmonhdr.hpc;
+    module->lowpc = (unsigned long)gmonhdr.lpc / sizeof(UNIT);
+    module->highpc = (unsigned long)gmonhdr.hpc / sizeof(UNIT);
+    module->sampbytes = gmonhdr.ncnt - size;
+    module->nsamples = module->sampbytes / sizeof (UNIT);
 #   ifdef DEBUG
 	if ( debug & SAMPLEDEBUG ) {
 	    printf( "[openpfile] hdr.lpc 0x%x hdr.hpc 0x%x hdr.ncnt %d\n",
 		gmonhdr.lpc , gmonhdr.hpc , gmonhdr.ncnt );
 	    printf( "[openpfile]   s_lowpc 0x%x   s_highpc 0x%x\n" ,
-		s_lowpc , s_highpc );
+		module->s_lowpc , module->s_highpc );
 	    printf( "[openpfile]     lowpc 0x%x     highpc 0x%x\n" ,
-		lowpc , highpc );
+		module->lowpc , module->highpc );
 	    printf( "[openpfile] sampbytes %d nsamples %d\n" ,
-		sampbytes , nsamples );
+		module->sampbytes , module->nsamples );
 	    printf( "[openpfile] sample rate %d\n" , hz );
 	}
 #   endif DEBUG
     return(pfile);
 }
 
-tally( rawp )
+tally( parent_module, child_module,rawp )
+	struct module* parent_module;
+	struct module* child_module;
     struct rawarc	*rawp;
 {
     nltype		*parentp;
     nltype		*childp;
 
-    parentp = nllookup( rawp -> raw_frompc );
-    childp = nllookup( rawp -> raw_selfpc );
+    parentp = nllookup( parent_module, rawp -> raw_frompc );
+    childp = nllookup( child_module, rawp -> raw_selfpc );
     if ( parentp == 0 || childp == 0 )
 	return;
     if ( kflag
@@ -348,7 +375,8 @@
 /*
  * dump out the gmon.sum file
  */
-dumpsum( sumfile )
+dumpsum( module, sumfile )
+	struct	module* module;
     char *sumfile;
 {
     register nltype *nlp;
@@ -370,14 +398,14 @@
     /*
      * dump the samples
      */
-    if (fwrite(samples, sizeof (UNIT), nsamples, sfile) != nsamples) {
+    if (fwrite(module->samples, sizeof (UNIT), module->nsamples, sfile) != module->nsamples) {
 	perror( sumfile );
 	done();
     }
     /*
      * dump the normalized raw arc information
      */
-    for ( nlp = nl ; nlp < npe ; nlp++ ) {
+    for ( nlp = module->nl ; nlp < module->npe ; nlp++ ) {
 	for ( arcp = nlp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
 	    arc.raw_frompc = arcp -> arc_parentp -> value;
 	    arc.raw_selfpc = arcp -> arc_childp -> value;
@@ -414,27 +442,28 @@
     return EQUALTO;
 }
 
-readsamples(pfile)
-    FILE	*pfile;
+readsamples(module, pfile)
+	struct	module* module; 	
+	FILE	*pfile;
 {
     register i;
     UNIT	sample;
 
-    if (samples == 0) {
-	samples = (UNIT *) calloc(sampbytes, sizeof (UNIT));
-	if (samples == 0) {
-	    warnx("no room for %d sample pc's", sampbytes / sizeof (UNIT));
+    if (module->samples == 0) {
+	module->samples = (UNIT *) calloc(module->sampbytes, sizeof (UNIT));
+	if (module->samples == 0) {
+	    warnx("no room for %d sample pc's", module->sampbytes / sizeof (UNIT));
 	    done();
 	}
     }
-    for (i = 0; i < nsamples; i++) {
+    for (i = 0; i < module->nsamples; i++) {
 	fread(&sample, sizeof (UNIT), 1, pfile);
 	if (feof(pfile))
 		break;
-	samples[i] += sample;
+	module->samples[i] += sample;
     }
-    if (i != nsamples) {
-	warnx("unexpected EOF after reading %d/%d samples", --i , nsamples );
+    if (i != module->nsamples) {
+	warnx("unexpected EOF after reading %d/%d samples", --i , module->nsamples );
 	done();
     }
 }
@@ -471,7 +500,7 @@
  *	only one sample for every four bytes of text space and never
  *	have any overlap (the two end cases, above).
  */
-asgnsamples()
+asgnsamples(struct module* module)
 {
     register int	j;
     UNIT		ccnt;
@@ -482,15 +511,15 @@
     unsigned long	svalue0, svalue1;
 
     /* read samples and assign to namelist symbols */
-    scale = highpc - lowpc;
-    scale /= nsamples;
-    alignentries();
-    for (i = 0, j = 1; i < nsamples; i++) {
-	ccnt = samples[i];
+    scale = module->highpc - module->lowpc;
+    scale /= module->nsamples;
+    alignentries(module);
+    for (i = 0, j = 1; i < module->nsamples; i++) {
+	ccnt = module->samples[i];
 	if (ccnt == 0)
 		continue;
-	pcl = lowpc + (unsigned long)(scale * i);
-	pch = lowpc + (unsigned long)(scale * (i + 1));
+	pcl = module->lowpc + (unsigned long)(scale * i);
+	pch = module->lowpc + (unsigned long)(scale * (i + 1));
 	time = ccnt;
 #	ifdef DEBUG
 	    if ( debug & SAMPLEDEBUG ) {
@@ -499,9 +528,9 @@
 	    }
 #	endif DEBUG
 	totime += time;
-	for (j = j - 1; j < nname; j++) {
-	    svalue0 = nl[j].svalue;
-	    svalue1 = nl[j+1].svalue;
+	for (j = j - 1; j < module->nname; j++) {
+	    svalue0 = module->nl[j].svalue;
+	    svalue1 = module->nl[j+1].svalue;
 		/*
 		 *	if high end of tick is below entry address,
 		 *	go for next tick.
@@ -519,12 +548,12 @@
 #		ifdef DEBUG
 		    if (debug & SAMPLEDEBUG) {
 			printf("[asgnsamples] (0x%x->0x%x-0x%x) %s gets %f ticks %d overlap\n",
-				nl[j].value/sizeof(UNIT), svalue0, svalue1,
-				nl[j].name,
+				module->nl[j].value/sizeof(UNIT), svalue0, svalue1,
+				module->nl[j].name,
 				overlap * time / scale, overlap);
 		    }
 #		endif DEBUG
-		nl[j].time += overlap * time / scale;
+		module->nl[j].time += overlap * time / scale;
 	    }
 	}
     }
@@ -560,16 +589,16 @@
      *	if it turns out that the entry point is in one bucket and the code
      *	for a routine is in the next bucket.
      */
-alignentries()
+alignentries(struct module* module)
 {
     register struct nl	*nlp;
     unsigned long	bucket_of_entry;
     unsigned long	bucket_of_code;
 
-    for (nlp = nl; nlp < npe; nlp++) {
+    for (nlp = module->nl; nlp < module->npe; nlp++) {
 	nlp -> svalue = nlp -> value / sizeof(UNIT);
-	bucket_of_entry = (nlp->svalue - lowpc) / scale;
-	bucket_of_code = (nlp->svalue + UNITS_TO_CODE - lowpc) / scale;
+	bucket_of_entry = (nlp->svalue - module->lowpc) / scale;
+	bucket_of_code = (nlp->svalue + UNITS_TO_CODE - module->lowpc) / scale;
 	if (bucket_of_entry < bucket_of_code) {
 #	    ifdef DEBUG
 		if (debug & SAMPLEDEBUG) {
@@ -587,3 +616,205 @@
 
     exit(0);
 }
+
+struct module  *
+xprof_nextModule(struct info* info,FILE	*pfile,char* gmonfilename)
+{
+
+	char* pathname;
+	struct module  *module = NULL;
+	struct module* m;
+	struct xmodheader xmodheader;
+	char	**defaultEs;
+	char	**sp;	
+
+	if ((1 != fread(&xmodheader, sizeof(struct xmodheader), 1, pfile))
+	    || xmodheader.magic != XMODMAGIC) {
+		warnx("%s: corrupt gmon file", gmonfilename);
+		done();
+	}
+
+	pathname = malloc(xmodheader.pathLength + 1);
+	if (malloc == NULL) {
+		warnx("Out of memory");
+		done();
+	}
+
+	if (1 != fread(pathname,xmodheader.pathLength, 1, pfile)) {
+		warnx("%s: corrupt gmon file", gmonfilename);		
+		done();		
+	}
+	pathname[xmodheader.pathLength] = 0;
+
+	TAILQ_FOREACH(m,&info->modulelist,modulelink) {
+		if (0 == strcmp(pathname,m->pathname)) {
+			module = m;
+			break;
+		}
+	}	
+		    
+	if(module != NULL) {
+
+		if (module-> s_highpc != xmodheader.lpc
+		    || module->s_highpc  !=  xmodheader.hpc
+		    || module->sampbytes !=  xmodheader.sampbytes) {
+			warnx("%s: incompatible with earlier gmon file", gmonfilename);
+			done();
+		}
+
+		free(pathname);
+	} else {
+		module = calloc(1,sizeof(struct module));
+		if (module == NULL) {
+			    warnx("Out of memory");
+			    done();
+		}
+		
+		
+		module->id = info->modulecount++;
+		TAILQ_INSERT_TAIL(&info->modulelist,module,modulelink);
+
+		module->s_lowpc = (unsigned long)  xmodheader.lpc;
+		module->s_highpc = (unsigned long) xmodheader.hpc;
+		module->lowpc = (unsigned long) xmodheader.lpc / sizeof(UNIT);
+		module->highpc = (unsigned long) xmodheader.hpc / sizeof(UNIT);
+		module->sampbytes = xmodheader.sampbytes;
+		module->nsamples = module->sampbytes / sizeof (UNIT);
+
+		module->pathname = pathname;
+
+		/* Suck in symbol information */
+		if (elf_getnfile(module,pathname, &defaultEs,0) == -1) {
+			fprintf(stderr,"Warning: Could not load %s\n",pathname);
+			/* XXXX To DO generate a single symbol table entry */
+		}
+
+		qsort(module->nl, module->nname, sizeof(nltype), valcmp);
+
+
+		if (!info->defaultEsSet) {
+			info->defaultEsSet = 1;
+			  for ( sp = defaultEs ; *sp ; sp++ ) {
+				  Eflag = TRUE;
+				  addlist( Elist , *sp );
+				  eflag = TRUE;
+				  addlist( elist , *sp );
+			  }
+		}
+	}
+
+	readsamples(module,pfile);
+
+	return module;
+
+}
+
+
+int
+xprof_readFile(struct info* info, char* filename) {
+
+  FILE		        *pfile;
+    int			size;
+    int			rate;
+    struct xgmonheader	header;
+    int                 count;
+    struct module  **moduleMap;
+    struct module  *child_module,*parent_module;
+    int i;
+    struct xarc xarc;
+
+    if((pfile = fopen(filename, "r")) == NULL) {
+	perror(filename);
+	done();
+    }
+    size =  fread(&header, sizeof(struct xgmonheader), 1, pfile);
+
+    if (size != 1) {
+	    fprintf(stderr,"Could not read header for file %s\n",filename);
+	    done();
+    }
+    
+    if (header.magic != XGMONMAGIC) {
+	    fprintf(stderr,"%s is not a valid gprof file\n",filename);
+	    done();
+    }
+
+    count = header.modules;
+    hz = header.profrate;
+    
+    moduleMap = calloc(count,sizeof(struct module*));
+
+    for (i=0; i<count ;i++) {
+	    moduleMap[i] = xprof_nextModule(info,pfile,filename);
+    }
+
+    while ( fread( &xarc , sizeof (xarc) , 1 , pfile ) == 1 ) {
+	    parent_module = moduleMap[xarc.parent];
+	    child_module  = moduleMap[xarc.child];
+	    if(parent_module->nname > 0 && child_module->nname > 0)
+		    tally(parent_module,child_module,&xarc.rawarc);
+    }
+
+    free(moduleMap);
+    fclose(pfile);
+}
+
+
+void
+xprof_buildinfo(struct info* info)
+{
+
+	nltype	**nlp;
+	struct  module* module;
+	int i;
+
+	info->nname = 0;
+	
+	TAILQ_FOREACH(module,&info->modulelist,modulelink) {
+		info->nname += module->nname;
+	}
+
+	info->nl = malloc(sizeof(nltype	*) * (info->nname + 1));
+	if (info->nl == NULL) {
+		fprintf(stderr,"Out of memory\n");
+		done();
+	}
+
+	info->npe  = info->nl +info->nname;
+
+	nlp = info->nl;
+
+	TAILQ_FOREACH(module,&info->modulelist,modulelink) {
+		for(i = 0; i <  module->nname;i++) {
+			*nlp = &module->nl[i];
+			nlp++;
+		}
+	}	
+}
+
+
+
+void
+xprof_process(struct info* info,char **argv)
+{
+	struct module* module;
+
+	if (*argv == NULL) {
+		fprintf(stderr,"Please specify a .xgmon file");
+		done();
+	}
+
+	while(*argv != NULL) {
+		xprof_readFile(info,*argv);
+		argv++;
+	}
+
+	xprof_buildinfo(info);
+
+	TAILQ_FOREACH(module,&info->modulelist,modulelink) {
+		asgnsamples(module);
+	}
+
+	
+}
+
Index: usr.bin/gprof/gprof.h
===========================================================================
--- usr.bin/gprof/gprof.h	2006/03/21 18:14:55	#1
+++ usr.bin/gprof/gprof.h	2006/03/21 18:14:55
@@ -40,6 +40,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include <sys/queue.h>
+
+
 #if __alpha__
 #   include "alpha.h"
 #endif
@@ -146,9 +149,7 @@
 };
 typedef struct nl	nltype;
 
-nltype	*nl;			/* the whole namelist */
-nltype	*npe;			/* the virtual end of the namelist */
-int	nname;			/* the number of function names */
+
 
 #define	HASCYCLEXIT	0x08	/* node has arc exiting from cycle */
 #define	CYCLEHEAD	0x10	/* node marked as head of a cycle */
@@ -186,6 +187,59 @@
 nltype	*cyclenl;		/* cycle header namelist */
 int	ncycle;			/* number of cycles discovered */
 
+
+
+
+
+/*
+ * Per Module structure
+ */
+
+
+
+struct module {
+
+	nltype	*nl;			/* the whole namelist */
+	nltype	*npe;			/* the virtual end of the namelist */
+	int	nname;			/* the number of function names */
+
+	unsigned long	s_lowpc;	/* lowpc from the profile file */
+	unsigned long	s_highpc;	/* highpc from the profile file */
+	unsigned long	lowpc, highpc;	/* range profiled, in UNIT's */
+
+	int	id;
+
+	unsigned sampbytes;		/* number of bytes of samples */
+	int	nsamples;		/* number of samples */
+	/* Samples */
+	int	sample_size;
+
+	/*
+	 * Each discretized pc sample has
+	 * a count of the number of samples in its range
+	 */
+	UNIT	*samples;
+
+	TAILQ_ENTRY(module)	modulelink; 
+	
+	char* pathname;
+};
+
+
+struct info {
+
+       	int	nname;	/* the number of function names */
+	nltype	**nl;   /* the whole namelist */
+	nltype	**npe;   /* virtual end of namelist */
+
+	int modulecount;
+	TAILQ_HEAD(,module) modulelist;
+	int defaultEsSet;
+};
+
+
+
+
     /*
      * The header on the gmon.out file.
      * gmon.out consists of a struct phdr (defined in gmon.h)
@@ -202,17 +256,8 @@
 
 int	debug;
 
-    /*
-     * Each discretized pc sample has
-     * a count of the number of samples in its range
-     */
-UNIT	*samples;
+
 
-unsigned long	s_lowpc;	/* lowpc from the profile file */
-unsigned long	s_highpc;	/* highpc from the profile file */
-unsigned long	lowpc, highpc;	/* range profiled, in UNIT's */
-unsigned sampbytes;		/* number of bytes of samples */
-int	nsamples;		/* number of samples */
 double	actime;			/* accumulated time thus far for putprofline */
 double	totime;			/* total time for all routines */
 double	printtime;		/* total of time being printed */
@@ -258,7 +303,7 @@
 /*
 		addarc();
 */
-int		aout_getnfile(const char *, char ***);
+int		aout_getnfile(struct module*, const char *, char ***);
 int		arccmp();
 arctype		*arclookup();
 /*
@@ -277,11 +322,11 @@
 		dfn_pre_visit();
 		dfn_self_cycle();
 */
-nltype		**doarcs();
+nltype		**doarcs(struct info* info);
 /*
 		done();
 */
-int		elf_getnfile(const char *, char ***);
+int		elf_getnfile(struct module*, const char *, char ***,int failIfNoSymbols);
 /*
 		findcalls();
 		flatprofheader();
@@ -342,3 +387,30 @@
 #define	BREAKCYCLE	1024
 #define	SUBCYCLELIST	2048
 #define	ANYDEBUG	4096
+
+
+#define XMODMAGIC 20050901
+
+struct xmodheader {
+	int     magic;
+	u_long	lpc;		/* base pc address of sample buffer */
+	u_long	hpc;		/* max pc address of sampled buffer */
+	int	pathLength;     /* Length of the pathname following this header */
+	int	sampbytes;	/* Number of sample bytes to follow the pathanme*/		
+};
+
+
+#define XGMONMAGIC 20050902
+
+
+struct xgmonheader {
+	int     magic;
+	int	profrate;	/* profiling clock rate */
+	int	modules;	/* Number of modules to follow */
+};
+
+struct xarc {
+	u_short	parent;
+	u_short	child;
+	struct rawarc rawarc;
+};
Index: usr.bin/gprof/lookup.c
===========================================================================
--- usr.bin/gprof/lookup.c	2006/03/21 18:14:55	#1
+++ usr.bin/gprof/lookup.c	2006/03/21 18:14:55
@@ -43,7 +43,8 @@
      *	    entry point.
      */
 nltype *
-nllookup( address )
+nllookup( module, address )
+	struct module* module;
     unsigned long	address;
 {
     register long	low;
@@ -54,20 +55,20 @@
 
 	probes = 0;
 #   endif DEBUG
-    for ( low = 0 , high = nname - 1 ; low != high ; ) {
+    for ( low = 0 , high = module->nname - 1 ; low != high ; ) {
 #	ifdef DEBUG
 	    probes += 1;
 #	endif DEBUG
 	middle = ( high + low ) >> 1;
-	if ( nl[ middle ].value <= address && nl[ middle+1 ].value > address ) {
+	if ( module->nl[ middle ].value <= address && module->nl[ middle+1 ].value > address ) {
 #	    ifdef DEBUG
 		if ( debug & LOOKUPDEBUG ) {
 		    printf( "[nllookup] %d (%d) probes\n" , probes , nname-1 );
 		}
 #	    endif DEBUG
-	    return &nl[ middle ];
+	    return &module->nl[ middle ];
 	}
-	if ( nl[ middle ].value > address ) {
+	if ( module->nl[ middle ].value > address ) {
 	    high = middle;
 	} else {
 	    low = middle + 1;
Index: usr.bin/gprof/printgprof.c
===========================================================================
--- usr.bin/gprof/printgprof.c	2006/03/21 18:14:55	#1
+++ usr.bin/gprof/printgprof.c	2006/03/21 18:14:55
@@ -43,7 +43,7 @@
 #include "gprof.h"
 #include "pathnames.h"
 
-printprof()
+printprof(struct info* info)
 {
     register nltype	*np;
     nltype		**sortednlp;
@@ -55,15 +55,15 @@
 	/*
 	 *	Sort the symbol table in by time
 	 */
-    sortednlp = (nltype **) calloc( nname , sizeof(nltype *) );
+    sortednlp = (nltype **) calloc( info->nname , sizeof(nltype *) );
     if ( sortednlp == (nltype **) 0 ) {
 	fprintf( stderr , "[printprof] ran out of memory for time sorting\n" );
     }
-    for ( index = 0 ; index < nname ; index += 1 ) {
-	sortednlp[ index ] = &nl[ index ];
+    for ( index = 0 ; index < info->nname ; index += 1 ) {
+	sortednlp[ index ] = info->nl[ index ];
     }
-    qsort( sortednlp , nname , sizeof(nltype *) , timecmp );
-    for ( index = 0 ; index < nname ; index += 1 ) {
+    qsort( sortednlp , info->nname , sizeof(nltype *) , timecmp );
+    for ( index = 0 ; index < info->nname ; index += 1 ) {
 	np = sortednlp[ index ];
 	flatprofline( np );
     }
@@ -207,7 +207,8 @@
     printf( "\n" );
 }
 
-printgprof(timesortnlp)
+printgprof(info,timesortnlp)
+	struct info* info;
     nltype	**timesortnlp;
 {
     int		index;
@@ -217,7 +218,7 @@
 	 *	Print out the structured profiling list
 	 */
     gprofheader();
-    for ( index = 0 ; index < nname + ncycle ; index ++ ) {
+    for ( index = 0 ; index < info->nname + ncycle ; index ++ ) {
 	parentp = timesortnlp[ index ];
 	if ( zflag == 0 &&
 	     parentp -> ncall == 0 &&
@@ -690,7 +691,7 @@
     return( strcmp( (*npp1) -> name , (*npp2) -> name ) );
 }
 
-printindex()
+printindex(struct info* info)
 {
     nltype		**namesortnlp;
     register nltype	*nlp;
@@ -701,14 +702,14 @@
 	 *	Now, sort regular function name alphbetically
 	 *	to create an index.
 	 */
-    namesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) );
+    namesortnlp = (nltype **) calloc( info->nname + ncycle , sizeof(nltype *) );
     if ( namesortnlp == (nltype **) 0 ) {
 	warnx("ran out of memory for sorting");
     }
-    for ( index = 0 , nnames = 0 ; index < nname ; index++ ) {
-	if ( zflag == 0 && nl[index].ncall == 0 && nl[index].time == 0 )
+    for ( index = 0 , nnames = 0 ; index < info->nname ; index++ ) {
+	if ( zflag == 0 && info->nl[index]->ncall == 0 && info->nl[index]->time == 0 )
 		continue;
-	namesortnlp[nnames++] = &nl[index];
+	namesortnlp[nnames++] = info->nl[index];
     }
     qsort( namesortnlp , nnames , sizeof(nltype *) , namecmp );
     for ( index = 1 , todo = nnames ; index <= ncycle ; index++ ) {
