check_gcc for -m64, pmap shows shmid

This commit is contained in:
albert 2004-01-29 22:28:13 +00:00
parent 74954d33e3
commit f4367392c8
4 changed files with 195 additions and 97 deletions

View File

@ -61,12 +61,13 @@ MANFILES := $(man1)uptime.1 $(man1)tload.1 $(man1)free.1 $(man1)w.1 \
TARFILES := AUTHORS BUGS NEWS README TODO COPYING COPYING.LIB \
Makefile procps.lsm procps.spec v t README.top \
minimal.c $(notdir $(MANFILES)) \
minimal.c $(notdir $(MANFILES)) dummy.c \
uptime.c tload.c free.c w.c top.c vmstat.c watch.c skill.c \
sysctl.c pgrep.c top.h pmap.c slabtop.c
# Stuff (tests, temporary hacks, etc.) left out of the standard tarball
_TARFILES :=
# plus the top-level Makefile to make it work stand-alone.
_TARFILES := Makefile
CURSES := -I/usr/include/ncurses -lncurses
@ -94,6 +95,27 @@ PKG_LDFLAGS := -Wl,-warn-common
LDFLAGS :=
ALL_LDFLAGS := $(PKG_LDFLAGS) $(LDFLAGS)
############ Add some extra flags if gcc allows
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),tar)
ifneq ($(MAKECMDGOALS),extratar)
# Unlike the kernel one, this check_gcc goes all the way to
# producing an executable. There might be a -m64 that works
# until you go looking for a 64-bit curses library.
check_gcc = $(shell if $(CC) $(ALL_CFLAGS) dummy.c $(ALL_LDFLAGS) $(1) -o /dev/null $(CURSES) > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
ALL_CFLAGS += $(call check_gcc,-Wdeclaration-after-statement,)
ALL_CFLAGS += $(call check_gcc,-Wpadded,)
# Be 64-bit if at all possible.
ALL_CFLAGS += $(call check_gcc,-m64,)
endif
endif
endif
############ misc.
# free.c pmap.c sysctl.c uptime.c vmstat.c watch.c pgrep.c skill.c tload.c top.c w.c
@ -179,13 +201,13 @@ w.o: w.c
############ prog.o --> prog
pmap w uptime tload free sysctl vmstat utmp pgrep skill: % : %.o $(LIBPROC)
$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) -o $@ $^
$(CC) $(ALL_CFLAGS) $^ $(ALL_LDFLAGS) -o $@
slabtop top: % : %.o $(LIBPROC)
$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) -o $@ $^ $(CURSES)
$(CC) $(ALL_CFLAGS) $^ $(ALL_LDFLAGS) -o $@ $(CURSES)
watch: % : %.o
$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) -o $@ $^ $(CURSES)
$(CC) $(ALL_CFLAGS) $^ $(ALL_LDFLAGS) -o $@ $(CURSES)
############ progX --> progY

31
dummy.c Normal file
View File

@ -0,0 +1,31 @@
// This is to test the compiler.
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <curses.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Foul POS defines all sorts of stuff...
#include <term.h>
#undef tab
#include <termios.h>
#include <time.h>
#include <unistd.h>
#include <values.h>
int main(int argc, char *argv[]){
(void)argc;
(void)argv;
return 0;
}

227
pmap.c
View File

@ -17,8 +17,13 @@
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "proc/readproc.h"
#include "proc/version.h"
#include "proc/escape.h"
static void usage(void) NORETURN;
static void usage(void){
@ -40,81 +45,111 @@ static int d_option;
static int q_option;
static const char *get_args(unsigned pid){
static char cmdbuf[64];
char buf[32];
int fd;
ssize_t count;
static unsigned shm_minor = ~0u;
do{
sprintf(buf,"/proc/%u/cmdline",pid);
if( (( fd=open(buf,O_RDONLY) )) == -1) break;
count = read(fd, cmdbuf, sizeof(cmdbuf)-1);
close(fd);
if(count<1) break;
cmdbuf[count] = '\0';
if(!isprint(cmdbuf[0])) break;
while(count--) if(!isprint(cmdbuf[count])) cmdbuf[count]=' ';
return cmdbuf;
}while(0);
static void discover_shm_minor(void){
void *addr;
int shmid;
char mapbuf[256];
do{
char *cp;
sprintf(buf,"/proc/%u/stat",pid);
if( (( fd=open(buf,O_RDONLY) )) == -1) break;
count = read(fd, cmdbuf, sizeof(cmdbuf)-1);
close(fd);
if(count<1) break;
cmdbuf[count] = '\0';
while(count--) if(!isprint(cmdbuf[count])) cmdbuf[count]=' ';
cp = strrchr(cmdbuf,')');
if(!cp) break;
cp[0] = ']';
cp[1] = '\0';
cp = strchr(cmdbuf,'(');
if(!cp) break;
if(!isprint(cp[1])) break;
cp[0] = '[';
return cp;
}while(0);
if(!freopen("/proc/self/maps", "r", stdin)) return;
return "[]"; // as good as anything
// create
shmid = shmget(IPC_PRIVATE, 42, IPC_CREAT | 0666);
if(shmid==-1) return; // failed; oh well
// attach
addr = shmat(shmid, NULL, SHM_RDONLY);
if(addr==(void*)-1) goto out_destroy;
while(fgets(mapbuf, sizeof mapbuf, stdin)){
char flags[32];
char *tmp; // to clean up unprintables
unsigned KLONG start, end;
unsigned long long file_offset, inode;
unsigned dev_major, dev_minor;
sscanf(mapbuf,"%"KLF"x-%"KLF"x %31s %Lx %x:%x %Lu", &start, &end, flags, &file_offset, &dev_major, &dev_minor, &inode);
tmp = strchr(mapbuf,'\n');
if(tmp) *tmp='\0';
tmp = mapbuf;
while(*tmp){
if(!isprint(*tmp)) *tmp='?';
tmp++;
}
if(start > (unsigned long)addr) continue;
if(dev_major) continue;
if(flags[3] != 's') continue;
if(strstr(mapbuf,"/SYSV")){
shm_minor = dev_minor;
break;
}
}
if(shmdt(addr)) perror("shmdt");
out_destroy:
if(shmctl(shmid, IPC_RMID, NULL)) perror("IPC_RMID");
return;
}
static const char *anon_name(int pid, unsigned KLONG addr, unsigned KLONG len){
const char *cp = " [ anon ]";
proc_t proc;
static int oldpid = -1;
if (pid==oldpid || get_proc_stats(pid, &proc)){
oldpid = pid;
if( (proc.start_stack >= addr) && (proc.start_stack <= addr+len) ) cp = " [ stack ]";
static const char *mapping_name(proc_t *p, unsigned KLONG addr, unsigned KLONG len, const char *mapbuf, unsigned advance, unsigned dev_major, unsigned dev_minor, unsigned long long inode){
const char *cp;
if(!dev_major && dev_minor==shm_minor && strstr(mapbuf,"/SYSV")){
static char shmbuf[64];
snprintf(shmbuf, sizeof shmbuf, " [ shmid=0x%Lx ]", inode);
return shmbuf;
}
cp = strrchr(mapbuf,'/');
if(cp){
if(cp[1]) cp += advance;
return cp;
}
cp = " [ anon ]";
if( (p->start_stack >= addr) && (p->start_stack <= addr+len) ) cp = " [ stack ]";
return cp;
}
static int one_proc(unsigned pid){
// Overkill, but who knows what is proper? The "w" prog
// uses the tty width to determine this.
#define maxcmd 0xfffff
static int one_proc(proc_t *p){
char buf[32];
char mapbuf[9600];
char cmdbuf[512];
unsigned long total_shared = 0ul;
unsigned long total_private_readonly = 0ul;
unsigned long total_private_writeable = 0ul;
sprintf(buf,"/proc/%u/maps",pid);
sprintf(buf,"/proc/%u/maps",p->tgid);
if(!freopen(buf, "r", stdin)) return 1;
printf("%u: %s\n", pid, get_args(pid));
if(x_option && !q_option)
printf("Address Kbytes RSS Anon Locked Mode Mapping\n");
if(d_option && !q_option)
printf("Address Kbytes Mode Offset Device Mapping\n");
escape_command(cmdbuf, p, sizeof cmdbuf, maxcmd, ESC_ARGS|ESC_BRACKETS);
printf("%u: %s\n", p->tgid, cmdbuf);
if(!q_option && (x_option|d_option)){
if(x_option){
if(sizeof(KLONG)==4) printf("Address Kbytes RSS Anon Locked Mode Mapping\n");
else printf("Address Kbytes RSS Anon Locked Mode Mapping\n");
}
if(d_option){
if(sizeof(KLONG)==4) printf("Address Kbytes Mode Offset Device Mapping\n");
else printf("Address Kbytes Mode Offset Device Mapping\n");
}
}
while(fgets(mapbuf,sizeof mapbuf,stdin)){
char flags[32];
char *tmp; // to clean up unprintables
unsigned KLONG start, end, diff;
unsigned long long file_offset;
unsigned long long file_offset, inode;
unsigned dev_major, dev_minor;
sscanf(mapbuf,"%"KLF"x-%"KLF"x %31s %Lx %x:%x", &start, &end, flags, &file_offset, &dev_major, &dev_minor);
sscanf(mapbuf,"%"KLF"x-%"KLF"x %31s %Lx %x:%x %Lu", &start, &end, flags, &file_offset, &dev_major, &dev_minor, &inode);
tmp = strchr(mapbuf,'\n');
if(tmp) *tmp='\0';
tmp = mapbuf;
@ -126,19 +161,18 @@ static int one_proc(unsigned pid){
diff = end-start;
if(flags[3]=='s') total_shared += diff;
if(flags[3]=='p'){
flags[3] = '-';
if(flags[1]=='w') total_private_writeable += diff;
else total_private_readonly += diff;
}
// format used by Solaris 9 and procps-3.2.0+
if(flags[3] == 'p') flags[3] = '-';
flags[4] = '-'; // an 'R' if swap not reserved (MAP_NORESERVE, SysV ISM shared mem, etc.)
// an 'R' if swap not reserved (MAP_NORESERVE, SysV ISM shared mem, etc.)
flags[4] = '-';
flags[5] = '\0';
if(x_option){
const char *cp = strrchr(mapbuf,'/');
if(cp && cp[1]) cp++;
if(!cp) cp = anon_name(pid, start, diff);
const char *cp = mapping_name(p, start, diff, mapbuf, 1, dev_major, dev_minor, inode);
printf(
(sizeof(KLONG)==8)
? "%016"KLF"x %7lu - - - %s %s\n"
@ -150,13 +184,11 @@ static int one_proc(unsigned pid){
);
}
if(d_option){
const char *cp = strrchr(mapbuf,'/');
if(cp && cp[1]) cp++;
if(!cp) cp = anon_name(pid, start, diff);
const char *cp = mapping_name(p, start, diff, mapbuf, 1, dev_major, dev_minor, inode);
printf(
(sizeof(KLONG)==8)
? "%016"KLF"x %7lu %s %016Lx %03x:%05x %s\n"
: "%08lx %7lu %s %016Lx %03x:%05x %s\n",
? "%016"KLF"x %7lu %s %016Lx %03x:%05x %s\n"
: "%08lx %7lu %s %016Lx %03x:%05x %s\n",
start,
(unsigned long)(diff>>10),
flags,
@ -166,8 +198,7 @@ static int one_proc(unsigned pid){
);
}
if(!x_option && !d_option){
const char *cp = strchr(mapbuf,'/');
if(!cp) cp = anon_name(pid, start, diff);
const char *cp = mapping_name(p, start, diff, mapbuf, 0, dev_major, dev_minor, inode);
printf(
(sizeof(KLONG)==8)
? "%016"KLF"x %6luK %s %s\n"
@ -181,32 +212,34 @@ static int one_proc(unsigned pid){
}
if(x_option && !q_option){
if(sizeof(KLONG)==8){
printf("---------------- ------ ------ ------ ------\n");
printf(
"total kB %15ld - - -\n",
(total_shared + total_private_writeable + total_private_readonly) >> 10
);
}else{
printf("-------- ------- ------- ------- -------\n");
printf(
"total kB %7ld - - -\n",
(total_shared + total_private_writeable + total_private_readonly) >> 10
);
if(!q_option){
if(x_option){
if(sizeof(KLONG)==8){
printf("---------------- ------ ------ ------ ------\n");
printf(
"total kB %15ld - - -\n",
(total_shared + total_private_writeable + total_private_readonly) >> 10
);
}else{
printf("-------- ------- ------- ------- -------\n");
printf(
"total kB %7ld - - -\n",
(total_shared + total_private_writeable + total_private_readonly) >> 10
);
}
}
if(d_option){
printf(
"mapped %ldK writeable/private: %ldK shared: %ldK\n",
(total_shared + total_private_writeable + total_private_readonly) >> 10,
total_private_writeable >> 10,
total_shared >> 10
);
}
if(!x_option && !d_option){
if(sizeof(KLONG)==8) printf(" total %16ldK\n", (total_shared + total_private_writeable + total_private_readonly) >> 10);
else printf(" total %8ldK\n", (total_shared + total_private_writeable + total_private_readonly) >> 10);
}
}
if(d_option && !q_option){
printf(
"mapped %ldK writeable/private: %ldK shared: %ldK\n",
(total_shared + total_private_writeable + total_private_readonly) >> 10,
total_private_writeable >> 10,
total_shared >> 10
);
}
if(!x_option && !d_option && !q_option){
if(sizeof(KLONG)==8) printf(" total %16ldK\n", (total_shared + total_private_writeable + total_private_readonly) >> 10);
else printf(" total %8ldK\n", (total_shared + total_private_writeable + total_private_readonly) >> 10);
}
return 0;
@ -216,7 +249,8 @@ static int one_proc(unsigned pid){
int main(int argc, char *argv[]){
unsigned *pidlist;
unsigned count = 0;
unsigned u;
PROCTAB* PT;
proc_t p;
int ret = 0;
if(argc<2) usage();
@ -276,8 +310,17 @@ int main(int argc, char *argv[]){
if(count<1) usage(); // no processes
if(d_option && x_option) usage();
u=0;
while(u<count) ret |= one_proc(pidlist[u++]);
discover_shm_minor();
pidlist[count] = 0; // old libproc interface is zero-terminated
PT = openproc(PROC_FILLSTAT|PROC_FILLARG|PROC_PID, pidlist);
while(readproc(PT, &p)){
ret |= one_proc(&p);
if(p.cmdline) free((void*)*p.cmdline);
count--;
}
closeproc(PT);
if(count) ret |= 42; // didn't find all processes asked for
return ret;
}

View File

@ -55,9 +55,11 @@ proc/.depend: $(LIBSRC) $(LIBHDR)
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),tar)
ifneq ($(MAKECMDGOALS),extratar)
-include proc/.depend
endif
endif
endif
$(lib)/$(SONAME) : proc/$(SONAME)