scc-size.c (3016B)
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); 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 filename = fname; 136 if ((fp = fopen(fname, "rb")) == NULL) { 137 error(strerror(errno)); 138 return; 139 } 140 141 if ((t = objprobe(fp, NULL)) != -1) 142 sizeobj(fp, t); 143 else if (archive(fp)) 144 sizelib(fp); 145 else 146 error("bad format"); 147 148 fclose(fp); 149 } 150 151 static void 152 usage(void) 153 { 154 fputs("usage: size [-t] [file...]\n", stderr); 155 exit(EXIT_FAILURE); 156 } 157 158 int 159 main(int argc, char *argv[]) 160 { 161 unsigned long long total; 162 163 ARGBEGIN { 164 case 't': 165 tflag = 1; 166 break; 167 default: 168 usage(); 169 } ARGEND 170 171 puts("text\tdata\tbss\tdec\thex\tfilename"); 172 173 if (argc == 0) { 174 size("a.out"); 175 } else { 176 for (; *argv; ++argv) 177 size(*argv); 178 } 179 180 if (tflag) { 181 total = ttext + tdata + tbss; 182 printf("%llu\t%llu\t%llu\t%llu\t%llx\t%s\n", 183 ttext, tdata, tbss, total, total, "(TOTALS)"); 184 } 185 186 if (fflush(stdout)) { 187 fprintf(stderr, 188 "size: error writing in output:%s\n", 189 strerror(errno)); 190 status = 1; 191 } 192 193 return status; 194 }