symbols for all out-of-line code
Subsystems (3)
PATCH 1/1 symbols for all out-of-line code
2.4.18 includes a patch to set a local symbol for the start of out-of-line .text.lock (now subsection 1 of .text) code, but it merges the entire translation unit's out of line code under the one symbol, and can give erroneous results when two files have the same KBUILD_BASENAME. The patch below details exactly where such code comes from, so you can get :
...
53 __stabslock-at-dec_and_lock.c-line-35 2.2083
233 __stabs&pagemap_lru_lock-at-swap.c-line-49 14.5625 381 __stabs&kernel_flag-at-sched.c-line-701 23.8125
...
from readprofile (actually you need a modified version, attached).
(I haven't yet updated this for kaos' LOCK_START etc. patch)
regards
john
arch/i386/config.in renamed from arch/i386/config.in.old +1 -0
@@ -421,6 +421,7 @@ bool ' Memory mapped I/O debugging' CONFIG_DEBUG_IOVIRT bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK + bool ' .text.lock debugging symbols' CONFIG_DEBUG_TEXT_LOCK_STABS bool ' Verbose BUG() reporting (adds 70K)' CONFIG_DEBUG_BUGVERBOSE fi
include/asm-i386/text_lock_stabs.h new file +44 -0
44 lines not on this page · raw message
include/linux/rwsem.h renamed from include/linux/rwsem.old.h +28 -40
73 lines not on this page · raw message
include/asm-i386/semaphore.h renamed from include/asm-i386/semaphore.old.h +10 -16
@@ -38,6 +38,7 @@#include <asm/system.h> #include <asm/atomic.h> +#include <asm/text_lock_stabs.h> #include <linux/wait.h> #include <linux/rwsem.h> #include <linux/stringify.h>
@@ -112,7 +113,7 @@* "__down_failed" is a special asm handler that calls the C * routine that actually waits. See arch/i386/kernel/semaphore.c */ -static inline void down (struct semaphore * sem) +static inline void p__down (struct semaphore * sem) {#if WAITQUEUE_DEBUG CHECK_MAGIC (sem->__magic);
@@ -124,9 +125,6 @@"js 2f\n" "1:\n" ".subsection 1\n" - ".ifndef _text_lock_" __stringify(KBUILD_BASENAME) "\n" - "_text_lock_" __stringify(KBUILD_BASENAME) ":\n" -".endif\n" "2:\tcall __down_failed\n\t" "jmp 1b\n" ".subsection 0\n"
@@ -139,7 +137,7 @@* Interruptible try to acquire a semaphore. If we obtained * it, return zero. If we were interrupted, returns -EINTR */ -static inline int down_interruptible (struct semaphore * sem) +static inline int p__down_interruptible (struct semaphore * sem) {int result;
@@ -154,9 +152,6 @@"xorl %0,%0\n" "1:\n" ".subsection 1\n" - ".ifndef _text_lock_" __stringify(KBUILD_BASENAME) "\n" - "_text_lock_" __stringify(KBUILD_BASENAME) ":\n" -".endif\n" "2:\tcall __down_failed_interruptible\n\t" "jmp 1b\n" ".subsection 0\n"
@@ -170,7 +165,7 @@* Non-blockingly attempt to down() a semaphore. * Returns zero if we acquired it */ -static inline int down_trylock (struct semaphore * sem) +static inline int p__down_trylock (struct semaphore * sem) {int result;
@@ -185,9 +180,6 @@"xorl %0,%0\n" "1:\n" ".subsection 1\n" - ".ifndef _text_lock_" __stringify(KBUILD_BASENAME) "\n" - "_text_lock_" __stringify(KBUILD_BASENAME) ":\n" -".endif\n" "2:\tcall __down_failed_trylock\n\t" "jmp 1b\n" ".subsection 0\n"
@@ -203,7 +195,7 @@* The default case (no contention) will result in NO * jumps for both down() and up(). */ -static inline void up (struct semaphore * sem) +static inline void p__up (struct semaphore * sem) {#if WAITQUEUE_DEBUG CHECK_MAGIC (sem->__magic);
@@ -214,9 +206,6 @@"jle 2f\n" "1:\n" ".subsection 1\n" - ".ifndef _text_lock_" __stringify(KBUILD_BASENAME) "\n" - "_text_lock_" __stringify(KBUILD_BASENAME) ":\n" -".endif\n" "2:\tcall __up_wakeup\n\t" "jmp 1b\n" ".subsection 0\n"
@@ -224,6 +213,11 @@ :"c" (sem) :"memory"); } + +#define down (s) __stabs_common(p__down, s) +#define down_interruptible (s) __stabs_common(p__down_interruptible, s) +#define down_trylock (s) __stabs_common(p__down_trylock, s) +#define up (s) __stabs_common(p__up, s)#endif #endif
include/asm-i386/rwsem.h renamed from include/asm-i386/rwsem.old.h +10 -16
@@ -38,6 +38,7 @@#ifdef __KERNEL__ +#include <asm/text_lock_stabs.h> #include <linux/list.h> #include <linux/spinlock.h> #include <linux/stringify.h>
@@ -95,7 +96,7 @@/* * lock for reading */ -static inline void __down_read (struct rw_semaphore *sem) +static inline void p__down_read (struct rw_semaphore *sem) { __asm__ __volatile__( "# beginning down_read\n\t"
@@ -103,9 +104,6 @@" js 2f\n\t" /* jump if we weren't granted the lock */ "1:\n\t" ".subsection 1\n" - ".ifndef _text_lock_" __stringify(KBUILD_BASENAME) "\n" - "_text_lock_" __stringify(KBUILD_BASENAME) ":\n" -".endif\n" "2:\n\t" " pushl %%ecx\n\t" " pushl %%edx\n\t"
@@ -123,7 +121,7 @@/* * lock for writing */ -static inline void __down_write (struct rw_semaphore *sem) +static inline void p__down_write (struct rw_semaphore *sem) {int tmp;
@@ -135,9 +133,6 @@" jnz 2f\n\t" /* jump if we weren't granted the lock */ "1:\n\t" ".subsection 1\n" - ".ifndef _text_lock_" __stringify(KBUILD_BASENAME) "\n" - "_text_lock_" __stringify(KBUILD_BASENAME) ":\n" -".endif\n" "2:\n\t" " pushl %%ecx\n\t" " call rwsem_down_write_failed\n\t"
@@ -153,7 +148,7 @@/* * unlock after reading */ -static inline void __up_read (struct rw_semaphore *sem) +static inline void p__up_read (struct rw_semaphore *sem) {__s32 tmp = -RWSEM_ACTIVE_READ_BIAS ; __asm__ __volatile__(
@@ -162,9 +157,6 @@" js 2f\n\t" /* jump if the lock is being waited upon */ "1:\n\t" ".subsection 1\n" - ".ifndef _text_lock_" __stringify(KBUILD_BASENAME) "\n" - "_text_lock_" __stringify(KBUILD_BASENAME) ":\n" -".endif\n" "2:\n\t" " decw %%dx\n\t" /* do nothing if still outstanding active readers */ " jnz 1b\n\t"
@@ -182,7 +174,7 @@/* * unlock after writing */ -static inline void __up_write (struct rw_semaphore *sem) +static inline void p__up_write (struct rw_semaphore *sem) { __asm__ __volatile__( "# beginning __up_write\n\t"
@@ -191,9 +183,6 @@" jnz 2f\n\t" /* jump if the lock is being waited upon */ "1:\n\t" ".subsection 1\n" - ".ifndef _text_lock_" __stringify(KBUILD_BASENAME) "\n" - "_text_lock_" __stringify(KBUILD_BASENAME) ":\n" -".endif\n" "2:\n\t" " decw %%dx\n\t" /* did the active count reduce to 0? */ " jnz 1b\n\t" /* jump back if not */
@@ -235,5 +224,10 @@return tmp+delta; } +#define __down_read (s) __stabs_common(p__down_read, s) +#define __down_write (s) __stabs_common(p__down_write, s) +#define __up_read (s) __stabs_common(p__up_read, s) +#define __up_write (s) __stabs_common(p__up_write, s) +#endif /* __KERNEL__ */ #endif /* _I386_RWSEM_H */
include/asm-i386/spinlock.h renamed from include/asm-i386/spinlock.old.h +8 -6
@@ -3,6 +3,7 @@#include <asm/atomic.h> #include <asm/rwlock.h> +#include <asm/text_lock_stabs.h> #include <asm/page.h> #include <linux/config.h> #include <linux/stringify.h>
@@ -58,9 +59,6 @@"lock ; decb %0\n\t" \"js 2f\n" \".subsection 1\n" \ - ".ifndef _text_lock_" __stringify(KBUILD_BASENAME) "\n" \ - "_text_lock_" __stringify(KBUILD_BASENAME) ":\n" \ -".endif\n" \"2:\t" \"cmpb $0,%0\n\t" \"rep;nop\n\t" \
@@ -127,7 +125,7 @@return oldval >0 ; } -static inline void spin_lock (spinlock_t *lock) +static inline void p__spin_lock (spinlock_t *lock) {#if SPINLOCK_DEBUG __label__ here;
@@ -142,6 +140,7 @@ :"=m" (lock->lock) : : "memory"); } +#define spin_lock (l) __stabs_common(p__spin_lock,l)/* * Read-write spinlocks, allowing multiple readers
@@ -183,7 +182,7 @@*/ /* the spinlock helpers are in arch/i386/kernel/semaphore.c */ -static inline void read_lock (rwlock_t *rw) +static inline void p__read_lock (rwlock_t *rw) {#if SPINLOCK_DEBUG if (rw->magic !=RWLOCK_MAGIC )
@@ -192,7 +191,7 @@__build_read_lock (rw,"__read_lock_failed" ); } -static inline void write_lock (rwlock_t *rw) +static inline void p__write_lock (rwlock_t *rw) {#if SPINLOCK_DEBUG if (rw->magic !=RWLOCK_MAGIC )
@@ -200,6 +199,9 @@#endif __build_write_lock (rw,"__write_lock_failed" ); } + +#define read_lock (r) __stabs_common(p__read_lock, r) +#define write_lock (r) __stabs_common(p__write_lock, r)#define read_unlock (rw) asm volatile("lock ; incl %0" :"=m" ((rw)->lock) : : "memory")#define write_unlock (rw) asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ",%0":"=m" ((rw)->lock) : : "memory")
include/asm-i386/rwlock.h renamed from include/asm-i386/rwlock.old.h +0 -12
@@ -27,9 +27,6 @@"js 2f\n" \"1:\n" \".subsection 1\n" \ - ".ifndef _text_lock_" __stringify(KBUILD_BASENAME) "\n" \ - "_text_lock_" __stringify(KBUILD_BASENAME) ":\n" \ -".endif\n" \"2:\tcall " helper"\n\t" \"jmp 1b\n" \".subsection 0\n" \
@@ -40,9 +37,6 @@"js 2f\n" \"1:\n" \".subsection 1\n" \ - ".ifndef _text_lock_" __stringify(KBUILD_BASENAME) "\n" \ - "_text_lock_" __stringify(KBUILD_BASENAME) ":\n" \ -".endif\n" \"2:\tpushl %%eax\n\t" \"leal %0,%%eax\n\t" \"call " helper"\n\t" \
@@ -63,9 +57,6 @@"jnz 2f\n" \"1:\n" \".subsection 1\n" \ - ".ifndef _text_lock_" __stringify(KBUILD_BASENAME) "\n" \ - "_text_lock_" __stringify(KBUILD_BASENAME) ":\n" \ -".endif\n" \"2:\tcall " helper"\n\t" \"jmp 1b\n" \".subsection 0\n" \
@@ -76,9 +67,6 @@"jnz 2f\n" \"1:\n" \".subsection 1\n" \ - ".ifndef _text_lock_" __stringify(KBUILD_BASENAME) "\n" \ - "_text_lock_" __stringify(KBUILD_BASENAME) ":\n" \ -".endif\n" \"2:\tpushl %%eax\n\t" \"leal %0,%%eax\n\t" \"call " helper"\n\t" \
include/asm-i386/softirq.h renamed from include/asm-i386/softirq.old.h +3 -3
@@ -3,6 +3,7 @@#include <asm/atomic.h> #include <asm/hardirq.h> +#include <asm/text_lock_stabs.h> #include <linux/stringify.h> #define __cpu_bh_enable (cpu) \
@@ -34,10 +35,9 @@"jnz 2f;" \"1:;" \ \ + __stabs_string(local_bh_enable) \ + \".subsection 1;" \ - ".ifndef _text_lock_" __stringify(KBUILD_BASENAME) "\n" \ - "_text_lock_" __stringify(KBUILD_BASENAME) ":\n" \ -".endif\n" \"2: pushl %%eax; pushl %%ecx; pushl %%edx;" \"call %c1;" \"popl %%edx; popl %%ecx; popl %%eax;" \
include/asm-i386/smplock.h renamed from include/asm-i386/smplock.old.h +4 -25
@@ -40,36 +40,15 @@* so we only need to worry about other * CPU's. */ -static __inline__void lock_kernel (void ) -{ -#if 1 -if (!++current->lock_depth) -spin_lock (&kernel_flag); -#else - __asm__ __volatile__( -"incl %1\n\t" -"jne 9f" - spin_lock_string -"\n9:" - :"=m" (__dummy_lock (&kernel_flag)), -"=m" (current->lock_depth)); -#endif -} +#define lock_kernel () do { \ + if (!++current->lock_depth) \ + __stabs_common(p__spin_lock, &kernel_flag); \ + } while (0)static __inline__void unlock_kernel (void ) {if (current->lock_depth <0 )BUG (); -#if 1 if (--current->lock_depth <0 )spin_unlock (&kernel_flag); -#else - __asm__ __volatile__( -"decl %1\n\t" -"jns 9f\n\t" - spin_unlock_string -"\n9:" - :"=m" (__dummy_lock (&kernel_flag)), -"=m" (current->lock_depth)); -#endif }
Documentation/Configure.help renamed from Documentation/Configure.help.old +6 -0
@@ -24006,6 +24006,12 @@ verbose debugging messages. If you suspect a semaphore problem or a kernel hacker asks for this option then say Y. Otherwise say N. +Lock debugging +CONFIG_DEBUG_TEXT_LOCK_STABS + If you say Y here then debugging symbols will be created for each + piece of .text.lock code that corresponds to the contention path for + the locking primitives. + Verbose BUG() reporting (adds 70K) CONFIG_DEBUG_BUGVERBOSE Say Y here to make BUG() panics output the file name and line number
/Makefile renamed from Makefile.old +12 -0
@@ -229,6 +229,7 @@ .version .config* config.in config.old \ scripts/tkparse scripts/kconfig.tk scripts/kconfig.tmp \ scripts/lxdialog/*.o scripts/lxdialog/lxdialog \ + scripts/add_lock_syms scripts/add_lock_syms.o \ .menuconfig.log \ include/asm \ .hdepend scripts/mkdep scripts/split-include scripts/docproc \
@@ -268,6 +269,17 @@ --end-group \ -o vmlinux $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map + if [ "$(CONFIG_DEBUG_TEXT_LOCK_STABS)" = "y" ]; then \ + $(MAKE) map-stabs; \ + fi + +map-stabs: scripts/add_lock_syms + cp System.map System.map.tmp + scripts/add_lock_syms vmlinux >> System.map.tmp + cat System.map.tmp | sort -u >System.map + +scripts/add_lock_syms: scripts/add_lock_syms.c + $(MAKE) -C scripts add_lock_syms symlinks: rm -f include/asm
scripts/Makefile renamed from scripts/Makefile.old +3 -0
@@ -42,4 +42,7 @@ clean: rm -f *~ kconfig.tk *.o tkparse mkdep split-include docproc +add_lock_syms: add_lock_syms.c + $(HOSTCC) $(HOSTCFLAGS) -o $@ $< + include $(TOPDIR)/Rules.make
scripts/add_lock_syms.c new file +102 -0
102 lines not on this page · raw message
/*
* readprofile.c - used to read /proc/profile
*
* Copyright (C) 1994,1996 Alessandro Rubini ([email protected]) *
* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* 1999-02-22 Arkadiusz Mi¶kiewicz <[email protected]>
* - added Native Language Support
* 1999-09-01 Stephane Eranian <[email protected]>
* - 64bit clean patch
* 3Feb2001 Andrew Morton <[email protected]>
* - -M option to write profile multiplier.
* 2001-11-07 Werner Almesberger <[email protected]>
* - byte order auto-detection and -n option
* 2001-11-09 Werner Almesberger <[email protected]>
* - skip step size (index 0)
* 2002-03-09 John Levon <[email protected]>
* - make maplineno do something
* 2002-03-11 John Levon <[email protected]>
* - rework for lock syms: no static buffers, no early quit */
#define _GNU_SOURCE
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#if 0
#include "nls.h"
#else
#define _(s) s
#endif
#define RELEASE "2.1, March 2002"
static char *prgname;
/* These are the defaults */
static char defaultmap[]="/usr/src/linux/System.map"; static char defaultpro[]="/proc/profile"; static char optstring[]="M:m:np:itvarV";
struct qstr {
char * str;
size_t len;
};static void
usage(void) {
fprintf(stderr,
_("%s: Usage: \"%s [options]\n" "\t -m <mapfile> (default = \"%s\")\n" "\t -p <pro-file> (default = \"%s\")\n"
"\t -M <mult> set the profiling multiplier to <mult>\n"
"\t -i print only info about the sampling step\n"
"\t -v print verbose data\n"
"\t -a print all symbols, even if count is 0\n"
"\t -r reset all the counters (root only)\n"
"\t -n disable byte order auto-detection\n"
"\t -V print version and exit\n")
,prgname,prgname,defaultmap,defaultpro);
exit(1);
}
static void *
xmalloc (size_t size) {
void *t;
if (size == 0)
return NULL;
t = malloc (size);
if (t == NULL) {
fprintf(stderr, _("out of memory"));
exit(1);
}
return t;
}static FILE *
myopen(char *name, char *mode, int *flag) {
int len = strlen(name);
if (!strcmp(name+len-3,".gz")) {
FILE *res;
char *cmdline = xmalloc(len+6);
sprintf(cmdline, "zcat %s", name);
res = popen(cmdline,mode);
free(cmdline);
*flag = 1;
return res;
}
*flag = 0;
return fopen(name,mode);
}voidrealloc_string(struct qstr * str, size_t len)
{
if (len > str->len) {
str->str = realloc(str->str, len);
if (!str->str) {
fprintf(stderr, "%s: malloc(%u) failed.\n", prgname, len);
exit(1);
}
str->len = len;
}
}voidcopy_string(struct qstr * str, struct qstr * new)
{
realloc_string(str, new->len);
strcpy(str->str, new->str);
}int
main (int argc, char **argv) {
FILE *map;
int proFd;
char *mapFile, *proFile, *mult=0;
unsigned long len=0, add0=0, indx=1;
unsigned int step;
unsigned int *buf, total, fn_len;
unsigned long fn_add, next_add; /* current and next address */
struct qstr fn_name = { NULL, 0 }; /* current and next name */
struct qstr next_name = { NULL, 0 };
char mode;
int c;
int optAll=0, optInfo=0, optReset=0, optVerbose=0, optNative=0;
char * mapline = NULL;
int maplineno=1;
int popenMap; /* flag to tell if popen() has been used */
size_t size;
ssize_t chars_read;#define next (current^1)
#if 0 setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE);
#endif
prgname=argv[0];
proFile=defaultpro;
mapFile=defaultmap;
while ((c = getopt(argc,argv,optstring)) != -1) {
switch(c) {
case 'm': mapFile=optarg; break;
case 'n': optNative++; break;
case 'p': proFile=optarg; break;
case 'a': optAll++; break;
case 'i': optInfo++; break;
case 'M': mult=optarg; break;
case 'r': optReset++; break;
case 'v': optVerbose++; break;
case 'V': printf(_("%s Version %s\n"),prgname,RELEASE);
exit(0);
default: usage();
}
}
if (optReset || mult) {
int multiplier, fd, to_write;
/*
* When writing the multiplier, if the length of the write is
* not sizeof(int), the multiplier is not changed
*/
if (mult) {
multiplier = strtoul(mult, 0, 10);
to_write = sizeof(int);
} else {
multiplier = 0;
to_write = 1; /* sth different from sizeof(int) */
}
/* try to become root, just in case */
setuid(0);
fd = open(defaultpro,O_WRONLY);
if (fd < 0) {
perror(defaultpro);
exit(1);
}
if (write(fd, &multiplier, to_write) != to_write) {
fprintf(stderr, "readprofile: error writing %s: %s\n",
defaultpro, strerror(errno));
exit(1);
}
close(fd);
exit(0);
}
/*
* Use an fd for the profiling buffer, to skip stdio overhead
*/
if ( ((proFd=open(proFile,O_RDONLY)) < 0)
|| ((int)(len=lseek(proFd,0,SEEK_END)) < 0)
|| (lseek(proFd,0,SEEK_SET)<0) ) {
fprintf(stderr,"%s: %s: %s\n",prgname,proFile,strerror(errno));
exit(1);
}
if ( !(buf=malloc(len)) ) {
fprintf(stderr,"%s: malloc(): %s\n",prgname, strerror(errno));
exit(1);
}
if (read(proFd,buf,len) != len) {
fprintf(stderr,"%s: %s: %s\n",prgname,proFile,strerror(errno));
exit(1);
}
close(proFd);
if (!optNative) {
int entries = len/sizeof(*buf);
int big = 0,small = 0,i;
unsigned *p;
for (p = buf+1; p < buf+entries; p++)
if (*p) {
if (*p >= 1 << (sizeof(*buf)/2)) big++;
else small++;
}
if (big > small) {
fprintf(stderr,"Assuming reversed byte order. "
"Use -n to force native byte order.\n");
for (p = buf; p < buf+entries; p++)
for (i = 0; i < sizeof(*buf)/2; i++) {
unsigned char *b = (unsigned char *) p;
unsigned char tmp;
tmp = b[i];
b[i] = b[sizeof(*buf)-i-1];
b[sizeof(*buf)-i-1] = tmp;
}
}
}
step=buf[0];
if (optInfo) {
printf(_("Sampling_step: %i\n"),step);
exit(0);
}
total=0;
if (!(map=myopen(mapFile,"r",&popenMap))) {
fprintf(stderr,"%s: ",prgname);perror(mapFile);
exit(1);
}
while ((chars_read = getline(&mapline, &size, map)) != -1) {
realloc_string(&fn_name, (size_t)(chars_read + 1));
if (sscanf(mapline,"%lx %c %s",&fn_add, &mode, fn_name.str) != 3) {
fprintf(stderr,_("%s: %s(%i): wrong map line\n"),
prgname, mapFile, maplineno);
exit(1);
}
if (!strcmp(fn_name.str,"_stext")) /* only elf works like this */ {
add0=fn_add;
break;
}
maplineno++;
}
if (!add0) {
fprintf(stderr,_("%s: can't find \"_stext\" in %s\n"),
prgname, mapFile);
exit(1);
}
/*
* Main loop.
*/
while ((chars_read = getline(&mapline, &size, map)) != -1) {
unsigned int this=0;
realloc_string(&next_name, (size_t)(chars_read + 1));
if (sscanf(mapline,"%lx %c %s",&next_add, &mode, next_name.str)!=3) {
fprintf(stderr,_("%s: %s(%i): wrong map line\n"),
prgname,mapFile, maplineno);
exit(1);
}
/* ignore anything past _etext */
if (mode == 'A')
break;
if (mode != 'T' && mode != 't')
continue;
if (indx >= len / sizeof(*buf)) {
fprintf(stderr, _("%s: profile address out of range for %s. "
"Wrong map file?\n"), prgname, next_name.str);
exit(1);
}
while (indx < (next_add-add0)/step)
this += buf[indx++];
total += this;
fn_len = next_add-fn_add;
if (fn_len && (this || optAll)) {
if (optVerbose)
printf("%08lx %-60s %6i %8.4f\n", fn_add,
fn_name.str,this,this/(double)fn_len);
else
printf("%6i %-60s %8.4f\n",
this,fn_name.str,this/(double)fn_len);
}
fn_add=next_add;
copy_string(&fn_name, &next_name);
maplineno++;
}
free(mapline);
/* trailer */
if (optVerbose)
printf("%08x %-60s %6i %8.4f\n",
0,"total",total,total/(double)(fn_add-add0));
else
printf("%6i %-60s %8.4f\n",
total,_("total"),total/(double)(fn_add-add0));
popenMap ? pclose(map) : fclose(map);
exit(0);
}