|
|
1.1 ! root 1: /* ! 2: * D U M P C A T C H ! 3: * ! 4: * This program examines kernel memory through /dev/kmem, and looks at ! 5: * the dump buffers in the dumpld line discipline (see /usr/sys/dev/dumpld.c). ! 6: * The command takes a filename prefix. For any active dump buffers, ! 7: * an identification code is appended to the filename prefix, and everything ! 8: * placed into the buffer by dumpld is appended to the resulting file. ! 9: * The identification code is 'M.m.ls', where 'M' is the major device number, ! 10: * 'm' is the minor device number, 'l' is the line-discipline number (from 0), ! 11: * and 's' (side) is 'w' for the writer or 'r' for the reader. If the old ! 12: * version of dumpld is installed in the kernel, the identification code is ! 13: * just the buffer number (from 0). ! 14: * ! 15: * ! 16: * Written by Kurt Gollhardt (Nirvonics, Inc.) ! 17: * Last update Sun Mar 31 03:32:57 1985 ! 18: * ! 19: */ ! 20: ! 21: #include <stdio.h> ! 22: #include <ctype.h> ! 23: #include <nlist.h> ! 24: #include <sys/types.h> ! 25: #include <sys/dumpl.h> ! 26: #include <sys/stream.h> ! 27: ! 28: #define getme(s, kind, off, type) _get(kind, off, 1, sizeof(type), &s) ! 29: #define getarray(s, kind, n, type) _get(kind, 0, n, sizeof(type), s) ! 30: #define getspace(s, n, type) s = (type *)malloc((n) * sizeof(type)) ! 31: ! 32: struct nlist nl[] = { ! 33: #define _ndumpbuf 0 ! 34: {"_ndumpbuf"}, ! 35: #define _dumpld 1 ! 36: {"_dumpld"}, ! 37: #define _dumpver 2 ! 38: {"_dumpver"}, ! 39: #define _dumpinf 3 ! 40: {"_dumpinf"}, ! 41: {""} ! 42: }; ! 43: ! 44: #define MEMFILE "/dev/kmem" ! 45: #define SYMFILE "/unix" ! 46: ! 47: struct blockdump { ! 48: struct dumpheader h; ! 49: char buf[1024]; ! 50: char *fillp; ! 51: }; ! 52: ! 53: int mem; ! 54: struct dumpld *dumpld; ! 55: struct dumpinf *dumpinf; ! 56: struct blockdump *bdump; ! 57: int ndumpbuf, dumpver; ! 58: FILE **file; ! 59: char **readp; ! 60: ! 61: char *malloc(), *calloc(); ! 62: ! 63: ! 64: main(ac, av) ! 65: char *av[]; ! 66: { ! 67: struct dumpld *di; ! 68: register int i; ! 69: ! 70: if (ac != 2) { ! 71: fprintf(stderr, "Usage: %s filename_prefix\n", av[0]); ! 72: exit(1); ! 73: } ! 74: ! 75: if (access(SYMFILE, 0) < 0) { ! 76: perror(SYMFILE); ! 77: exit(2); ! 78: } ! 79: if ((mem = open(MEMFILE, 0)) < 0) { ! 80: perror(MEMFILE); ! 81: exit(2); ! 82: } ! 83: ! 84: nlist(SYMFILE, nl); ! 85: if (nl[_ndumpbuf].n_value == 0) { ! 86: fprintf(stderr, "No dumpld line-discipline present\n"); ! 87: exit(5); ! 88: } ! 89: getme(ndumpbuf, _ndumpbuf, 0, int); ! 90: ! 91: if (nl[_dumpver].n_value == 0) ! 92: dumpver = 0; ! 93: else ! 94: getme(dumpver, _dumpver, 0, int); ! 95: ! 96: getspace(dumpld, ndumpbuf, struct dumpld); ! 97: getspace(readp, ndumpbuf, char *); ! 98: file = (FILE **)calloc(sizeof(FILE *), ndumpbuf); ! 99: if (dumpld == NULL || file == NULL || readp == NULL) { ! 100: fprintf(stderr, "Can't allocate enough memory\n"); ! 101: exit(3); ! 102: } ! 103: if (dumpver > 0) { ! 104: getspace(dumpinf, ndumpbuf, struct dumpinf); ! 105: getspace(bdump, ndumpbuf, struct blockdump); ! 106: if (dumpinf == NULL || bdump== NULL) { ! 107: fprintf(stderr, "Can't allocate enough memory\n"); ! 108: exit(3); ! 109: } ! 110: for (i = 0; i < ndumpbuf; ++i) ! 111: bdump[i].fillp = (char *)&bdump[i]; ! 112: } ! 113: ! 114: for (;;) { ! 115: getarray(dumpld, _dumpld, ndumpbuf, struct dumpld); ! 116: if (dumpver > 0) ! 117: getarray(dumpinf, _dumpinf, ndumpbuf, struct dumpinf); ! 118: for (di = dumpld; di < &dumpld[ndumpbuf]; di++) ! 119: if (di->base != NULL) { ! 120: if (file[di - dumpld] == 0) ! 121: new_file(di - dumpld, av[1]); ! 122: if (readp[di - dumpld] != di->fillp) ! 123: read_buf(di - dumpld, di); ! 124: } ! 125: } ! 126: } ! 127: ! 128: ! 129: new_file(i, prefix) ! 130: char *prefix; ! 131: { ! 132: char filename[100]; ! 133: ! 134: if (dumpver == 0) ! 135: sprintf(filename, "%s%d", prefix, i); ! 136: else ! 137: sprintf(filename, "%s%d.%d.%d%c", prefix, major(dumpinf[i].dev), ! 138: minor(dumpinf[i].dev), i/2, (i&1 ? 'w' : 'r')); ! 139: if ((file[i] = fopen(filename, "a")) == NULL) { ! 140: perror(filename); ! 141: exit(4); ! 142: } ! 143: ! 144: readp[i] = dumpld[i].base; ! 145: } ! 146: ! 147: ! 148: read_buf(i, di) ! 149: register struct dumpld *di; ! 150: { ! 151: if (di->fillp < readp[i]) { ! 152: dump(readp[i], (di->base + di->size) - readp[i], file[i], i); ! 153: readp[i] = di->base; ! 154: } ! 155: if (di->fillp > readp[i]) { ! 156: dump(readp[i], di->fillp - readp[i], file[i], i); ! 157: readp[i] = di->fillp; ! 158: } ! 159: fflush(file[i]); ! 160: } ! 161: ! 162: ! 163: char buf[BUFSIZ]; ! 164: ! 165: dump(loc, n, stream, i) ! 166: char *loc; ! 167: FILE *stream; ! 168: { ! 169: int count; ! 170: ! 171: if (dumpver > 0) ! 172: return fancy_dump(loc, n, stream, i); ! 173: ! 174: while (n > 0) { ! 175: count = (n > BUFSIZ ? BUFSIZ : n); ! 176: getarray(buf, loc, count, char); ! 177: fwrite(buf, 1, count, stream); ! 178: n -= count; ! 179: loc += count; ! 180: } ! 181: } ! 182: ! 183: ! 184: fancy_dump(loc, count, stream, i) ! 185: char *loc; ! 186: FILE *stream; ! 187: { ! 188: register struct blockdump *bd = &bdump[i]; ! 189: register int n, have_block; ! 190: ! 191: while (count > 0) { ! 192: have_block = 0; ! 193: n = bd->buf - bd->fillp; ! 194: if (n <= 0) { ! 195: have_block = 1; ! 196: n += bd->h.count; ! 197: } ! 198: if (count < n) { ! 199: have_block = 0; ! 200: n = count; ! 201: } ! 202: if (n > 0) { ! 203: getarray(bd->fillp, loc, n, char); ! 204: loc += n; bd->fillp += n; ! 205: count -= n; ! 206: } ! 207: if (have_block) { ! 208: dump_block(bd, stream); ! 209: bd->fillp = (char *)bd; ! 210: } ! 211: } ! 212: } ! 213: ! 214: ! 215: #define BYTE_PER_LINE 16 ! 216: ! 217: dump_block(bd, stream) ! 218: struct blockdump *bd; ! 219: FILE *stream; ! 220: { ! 221: print_type(bd->h.type, stream); ! 222: fprintf(stream, ":%s", (bd->h.count == 0 ? "\n" : "")); ! 223: bd->fillp = bd->buf; ! 224: while (bd->h.count > 0) { ! 225: dump_line(bd, stream); ! 226: bd->h.count -= BYTE_PER_LINE; ! 227: bd->fillp += BYTE_PER_LINE; ! 228: } ! 229: } ! 230: ! 231: ! 232: dump_line(bd, stream) ! 233: struct blockdump *bd; ! 234: FILE *stream; ! 235: { ! 236: register int n, byte; ! 237: register char *p; ! 238: char ascii[BYTE_PER_LINE+1]; ! 239: ! 240: putc('\t', stream); ! 241: p = bd->fillp; ! 242: for (n = 0; n < BYTE_PER_LINE; n++) { ! 243: byte = *p++ & 0xFF; ! 244: if (n < bd->h.count) ! 245: fprintf(stream, "%02x ", byte); ! 246: else ! 247: fprintf(stream, " "); ! 248: ascii[n] = (n < bd->h.count && isprint(byte) ? byte : '.'); ! 249: } ! 250: ascii[BYTE_PER_LINE] = '\0'; ! 251: fprintf(stream, "!%s!\n", ascii); ! 252: } ! 253: ! 254: ! 255: char *mtype_names[] = { ! 256: "DATA", "BREAK", "HANGUP", "DELIM", "ECHO", "ACK", "IOCTL", ! 257: "DELAY", "CTL", "PASS", "SIGNAL", "FLUSH", "STOP", "START", ! 258: "IOCACK", "IOCNAK", "CLOSE", "YDEL", "NDEL", "IOCWAIT",NULL ! 259: }; ! 260: int mtype_codes[] = { ! 261: M_DATA, M_BREAK, M_HANGUP, M_DELIM, M_ECHO, M_ACK, M_IOCTL, ! 262: M_DELAY, M_CTL, M_PASS, M_SIGNAL, M_FLUSH, M_STOP, M_START, ! 263: M_IOCACK, M_IOCNAK, M_CLOSE, M_YDEL, M_NDEL, M_IOCWAIT,0 ! 264: }; ! 265: ! 266: print_type(type, stream) ! 267: FILE *stream; ! 268: { ! 269: register int i; ! 270: ! 271: for (i = 0; mtype_names[i] != NULL; ++i) ! 272: if (mtype_codes[i] == type) { ! 273: fputs(mtype_names[i], stream); ! 274: return; ! 275: } ! 276: ! 277: fprintf(stream, "[%02x]", type); ! 278: } ! 279: ! 280: ! 281: _get(addr, off, n, size, loc) ! 282: unsigned long addr; ! 283: char *loc; ! 284: { ! 285: if (addr < sizeof(nl)/sizeof(nl[0])) ! 286: addr = nl[addr].n_value; ! 287: addr += off*size; ! 288: lseek(mem, addr, 0); ! 289: read(mem, loc, n*size); ! 290: return(addr); ! 291: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.