1: /* 2: * Copyright (c) 1986 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: * 6: * @(#)checksys.c 1.6 (2.11BSD) 1998/12/5 7: */ 8: 9: /* 10: * checksys 11: * checks the system size and reports any limits exceeded. 12: */ 13: 14: #include "param.h" 15: #include "user.h" 16: #include "file.h" 17: #include "ioctl.h" 18: #include "clist.h" 19: #include "a.out.h" 20: #include "stdio.h" 21: #include "namei.h" 22: #include "msgbuf.h" 23: 24: /* Round up to a click boundary. */ 25: #define cround(bytes) ((bytes + ctob(1) - 1) / ctob(1) * ctob(1)); 26: #define round(x) (ctob(stoc(ctos(btoc(x))))) 27: 28: #define KB(val) ((u_int)(val * 1024)) 29: 30: #define N_END 0 31: #define N_NBUF 1 32: #define N_PROC 4 33: #define N_NINODE 9 34: #define N_CLIST 14 35: #define N_RAM 15 36: #define N_XITDESC 16 37: #define N_QUOTDESC 17 38: #define N_NAMECACHE 18 39: #define N_IOSIZE 19 40: #define N_NLOG 20 41: #define N_NUMSYMS 21 42: 43: struct nlist nl[N_NUMSYMS]; 44: 45: char *names[] = { 46: "_end", /* 0 */ 47: "_nbuf", /* 1 */ 48: "_buf", /* 2 */ 49: "_nproc", /* 3 */ 50: "_proc", /* 4 */ 51: "_ntext", /* 5 */ 52: "_text", /* 6 */ 53: "_nfile", /* 7 */ 54: "_file", /* 8 */ 55: "_ninode", /* 9 */ 56: "_inode", /* 10 */ 57: "_ncallout", /* 11 */ 58: "_callout", /* 12 */ 59: "_ucb_clist", /* 13 */ 60: "_nclist", /* 14 */ 61: "_ram_size", /* 15 */ 62: "_xitdesc", /* 16 */ 63: "_quotdesc", /* 17 */ 64: "_namecache", /* 18 */ 65: "__iosize", /* 19 */ 66: "_nlog" /* 20 */ 67: }; 68: 69: static struct exec obj; 70: static struct ovlhdr ovlhdr; 71: static int fi; 72: 73: main(argc, argv) 74: int argc; 75: char **argv; 76: { 77: register int i; 78: long size, totsize, ramdisk, getval(); 79: int errs = 0, texterrs = 0, ninode; 80: 81: if (argc != 2) { 82: fputs("usage: checksys unix-binary\n", stderr); 83: exit(-1); 84: } 85: /* 86: * Can't (portably) initialize unions, so we do it at run time 87: */ 88: for (i = 0; i < N_NUMSYMS; i++) 89: nl[i].n_un.n_name = names[i]; 90: if ((fi = open(argv[1], O_RDONLY)) < 0) { 91: perror(argv[1]); 92: exit(-1); 93: } 94: if (read(fi, &obj, sizeof(obj)) != sizeof(obj)) { 95: fputs("checksys: can't read object header.\n", stderr); 96: exit(-1); 97: } 98: if (obj.a_magic == A_MAGIC5 || obj.a_magic == A_MAGIC6) 99: if (read(fi, &ovlhdr, sizeof(ovlhdr)) != sizeof(ovlhdr)) { 100: fputs("checksys: can't read overlay header.\n", stderr); 101: exit(-1); 102: } 103: switch(obj.a_magic) { 104: 105: /* 106: * 0407-- nonseparate I/D "vanilla" 107: */ 108: case A_MAGIC1: 109: case A_MAGIC2: 110: size = obj.a_text + obj.a_data + obj.a_bss; 111: if (size > KB(48)) { 112: printf("total size is %ld, max is %u, too large by %ld bytes.\n", size, KB(48), size - KB(48)); 113: errs++; 114: } 115: totsize = cround(size); 116: break; 117: 118: /* 119: * 0411-- separate I/D 120: */ 121: case A_MAGIC3: 122: size = obj.a_data + obj.a_bss; 123: if (size > KB(48)) { 124: printf("data is %ld, max is %u, too large by %ld bytes.\n", size, KB(48), size - KB(48)); 125: errs++; 126: } 127: totsize = obj.a_text + cround(size); 128: break; 129: 130: /* 131: * 0430-- overlaid nonseparate I/D 132: */ 133: case A_MAGIC5: 134: if (obj.a_text > KB(16)) { 135: printf("base segment is %u, max is %u, too large by %u bytes.\n", obj.a_text, KB(16), obj.a_text - KB(16)); 136: errs++; 137: texterrs++; 138: } 139: if (obj.a_text <= KB(8)) { 140: printf("base segment is %u, minimum is %u, too small by %u bytes.\n", obj.a_text, KB(8), KB(8) - obj.a_text); 141: errs++; 142: } 143: size = obj.a_data + obj.a_bss; 144: if (size > KB(24)) { 145: printf("data is %ld, max is %u, too large by %ld bytes.\n", size, KB(24), size - KB(24)); 146: errs++; 147: } 148: /* 149: * Base and overlay 1 occupy 16K and 8K of physical 150: * memory, respectively, regardless of actual size. 151: */ 152: totsize = KB(24) + cround(size); 153: /* 154: * Subtract the first overlay, it will be added below 155: * and it has already been included. 156: */ 157: totsize -= ovlhdr.ov_siz[0]; 158: goto checkov; 159: break; 160: 161: /* 162: * 0431-- overlaid separate I/D 163: */ 164: case A_MAGIC6: 165: if (obj.a_text > KB(56)) { 166: printf("base segment is %u, max is %u, too large by %u bytes.\n", obj.a_text, KB(56), obj.a_text - KB(56)); 167: errs++; 168: } 169: if (obj.a_text <= KB(48)) { 170: printf("base segment is %u, min is %u, too small by %u bytes.\n", obj.a_text, KB(48), KB(48) - obj.a_text); 171: errs++; 172: } 173: size = obj.a_data + obj.a_bss; 174: if (size > KB(48)) { 175: printf("data is %ld, max is %u, too large by %ld bytes.\n", size, KB(48), size - KB(48)); 176: errs++; 177: } 178: totsize = obj.a_text + cround(size); 179: 180: checkov: 181: for (i = 0;i < NOVL;i++) { 182: totsize += ovlhdr.ov_siz[i]; 183: if (ovlhdr.ov_siz[i] > KB(8)) { 184: printf("overlay %d is %u, max is %u, too large by %u bytes.\n", i + 1, ovlhdr.ov_siz[i], KB(8), ovlhdr.ov_siz[i] - KB(8)); 185: errs++; 186: texterrs++; 187: } 188: /* 189: * check for zero length overlay in the middle of 190: * non-zero length overlays (boot croaks when faced 191: * with this) ... 192: */ 193: if (i < NOVL-1 194: && ovlhdr.ov_siz[i] == 0 195: && ovlhdr.ov_siz[i+1] > 0) { 196: printf("overlay %d is empty and there are non-empty overlays following it.\n", i + 1); 197: errs++; 198: texterrs++; 199: } 200: } 201: break; 202: 203: default: 204: printf("magic number 0%o not recognized.\n", obj.a_magic); 205: exit(-1); 206: } 207: 208: (void)nlist(argv[1], nl); 209: 210: if (!nl[N_NINODE].n_type) { 211: puts("\"ninode\" not found in namelist."); 212: exit(-1); 213: } 214: ninode = getval(N_NINODE); 215: if (!texterrs) 216: { 217: if (nl[N_PROC].n_value >= 0120000) { 218: printf("The remapping area (0120000-0140000, KDSD5)\n\tcontains data other than the proc, text and file tables.\n\tReduce other data by %u bytes.\n", nl[N_PROC].n_value - 0120000); 219: errs++; 220: } 221: } 222: totsize += (getval(N_NBUF) * MAXBSIZE); 223: if (nl[N_CLIST].n_value) 224: totsize += cround(getval(N_CLIST) * (long)sizeof(struct cblock)); 225: if (nl[N_RAM].n_type) 226: totsize += getval(N_RAM)*512; 227: if (nl[N_QUOTDESC].n_type) 228: totsize += 8192; 229: if (nl[N_XITDESC].n_type) 230: totsize += (ninode * 3 * sizeof (long)); 231: if (nl[N_NAMECACHE].n_type) 232: totsize += (ninode * sizeof(struct namecache)); 233: if (nl[N_IOSIZE].n_type) 234: totsize += getval(N_IOSIZE); 235: if (nl[N_NLOG].n_type) 236: totsize += (getval(N_NLOG) * MSG_BSIZE); 237: totsize += ctob(USIZE); 238: printf("System will occupy %ld bytes of memory (including buffers and clists).\n", totsize); 239: for (i = 0; i < N_NUMSYMS; i++) { 240: if (!(i % 3)) 241: putchar('\n'); 242: printf("\t%10.10s {0%06o}", nl[i].n_un.n_name+1, nl[i].n_value); 243: } 244: putchar('\n'); 245: if (errs) 246: puts("**** SYSTEM IS NOT BOOTABLE. ****"); 247: exit(errs); 248: } 249: 250: /* 251: * Get the value of an initialized variable from the object file. 252: */ 253: static long 254: getval(indx) 255: int indx; 256: { 257: register int novl; 258: u_int ret; 259: off_t offst; 260: 261: if ((nl[indx].n_type&N_TYPE) == N_BSS) 262: return((long)0); 263: offst = nl[indx].n_value; 264: offst += obj.a_text; 265: offst += sizeof(obj); 266: if (obj.a_magic == A_MAGIC2 || obj.a_magic == A_MAGIC5) 267: offst -= (off_t)round(obj.a_text); 268: if (obj.a_magic == A_MAGIC5 || obj.a_magic == A_MAGIC6) { 269: offst += sizeof ovlhdr; 270: if (obj.a_magic == A_MAGIC5) 271: offst -= (off_t)round(ovlhdr.max_ovl); 272: for (novl = 0;novl < NOVL;novl++) 273: offst += (off_t)ovlhdr.ov_siz[novl]; 274: } 275: (void)lseek(fi, offst, L_SET); 276: read(fi, &ret, sizeof(ret)); 277: return((long)ret); 278: }