scc-size.c (3040B)
1 #include <errno.h> 2 #include <limits.h> 3 #include <stdarg.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 8 #include <scc/ar.h> 9 #include <scc/arg.h> 10 #include <scc/mach.h> 11 12 struct sizes { 13 unsigned long long text; 14 unsigned long long data; 15 unsigned long long bss; 16 }; 17 18 static int status; 19 static char *filename, *membname; 20 static int tflag; 21 static unsigned long long ttext, tdata, tbss, ttotal; 22 char *argv0; 23 24 static void 25 error(char *fmt, ...) 26 { 27 va_list va; 28 29 va_start(va, fmt); 30 fprintf(stderr, "size: %s: ", filename); 31 if (membname) 32 fprintf(stderr, "%s: ", membname); 33 vfprintf(stderr, fmt, va); 34 putc('\n', stderr); 35 va_end(va); 36 37 status = EXIT_FAILURE; 38 } 39 40 static void 41 sizeobj(FILE *fp, int type) 42 { 43 int i; 44 Obj *obj; 45 unsigned long long total, *p; 46 struct sizes siz; 47 Section sec; 48 49 if ((obj = newobj(type)) == NULL) { 50 error("failed allocation"); 51 return; 52 } 53 54 if (readobj(obj, fp) < 0) { 55 error("invalid file"); 56 goto err; 57 } 58 59 siz.text = siz.data = siz.bss = 0; 60 for (i = 0; getsec(obj, &i, &sec); i++) { 61 switch (sec.type) { 62 case 'R': 63 case 'T': 64 p = &siz.text; 65 break; 66 case 'D': 67 p = &siz.data; 68 break; 69 case 'B': 70 p = &siz.bss; 71 break; 72 default: 73 continue; 74 } 75 76 if (*p > ULLONG_MAX - sec.size) { 77 error("integer overflow"); 78 goto err; 79 } 80 81 *p += sec.size; 82 } 83 84 total = siz.text + siz.data + siz.bss; 85 printf("%llu\t%llu\t%llu\t%llu\t%llx\t%s\n", 86 siz.text, 87 siz.data, 88 siz.bss, 89 total, total, filename); 90 91 ttext += siz.text; 92 tdata += siz.data; 93 tbss += siz.bss; 94 ttotal += total; 95 96 err: 97 delobj(obj); 98 } 99 100 static void 101 sizelib(FILE *fp) 102 { 103 int t; 104 long off, cur; 105 char memb[SARNAM+1]; 106 107 for (;;) { 108 cur = ftell(fp); 109 off = armember(fp, memb, NULL); 110 switch (off) { 111 case -1: 112 error("library corrupted"); 113 if (ferror(fp)) 114 error(strerror(errno)); 115 case 0: 116 return; 117 default: 118 membname = memb; 119 if ((t = objprobe(fp, NULL)) != -1) 120 sizeobj(fp, t); 121 membname = NULL; 122 fseek(fp, cur, SEEK_SET); 123 fseek(fp, off, SEEK_CUR); 124 break; 125 } 126 } 127 } 128 129 static void 130 size(char *fname) 131 { 132 int t; 133 FILE *fp; 134 135 membname = NULL; 136 filename = fname; 137 if ((fp = fopen(fname, "rb")) == NULL) { 138 error(strerror(errno)); 139 return; 140 } 141 142 if ((t = objprobe(fp, NULL)) != -1) 143 sizeobj(fp, t); 144 else if (archive(fp)) 145 sizelib(fp); 146 else 147 error("bad format"); 148 149 fclose(fp); 150 } 151 152 static void 153 usage(void) 154 { 155 fputs("usage: size [-t] [file...]\n", stderr); 156 exit(EXIT_FAILURE); 157 } 158 159 int 160 main(int argc, char *argv[]) 161 { 162 unsigned long long total; 163 164 ARGBEGIN { 165 case 't': 166 tflag = 1; 167 break; 168 default: 169 usage(); 170 } ARGEND 171 172 puts("text\tdata\tbss\tdec\thex\tfilename"); 173 174 if (argc == 0) { 175 size("a.out"); 176 } else { 177 for (; *argv; ++argv) 178 size(*argv); 179 } 180 181 if (tflag) { 182 total = ttext + tdata + tbss; 183 printf("%llu\t%llu\t%llu\t%llu\t%llx\t%s\n", 184 ttext, tdata, tbss, total, total, "(TOTALS)"); 185 } 186 187 if (fflush(stdout)) { 188 fprintf(stderr, 189 "size: error writing in output:%s\n", 190 strerror(errno)); 191 status = 1; 192 } 193 194 return status; 195 }