1#include <errno.h>2#include <limits.h>3#include <stdarg.h>4#include <stdio.h>5#include <stdlib.h>6#include <string.h>78#include <scc/ar.h>9#include <scc/arg.h>10#include <scc/mach.h>1112struct sizes {13 unsigned long long text;14 unsigned long long data;15 unsigned long long bss;16};1718static int status;19static char *filename, *membname;20static int tflag;21static unsigned long long ttext, tdata, tbss, ttotal;22char *argv0;2324static void25error(char *fmt, ...)26{27 va_list va;2829 va_start(va, fmt);30 fprintf(stderr, "scc-size: %s: ", filename);31 if (membname)32 fprintf(stderr, "%s: ", membname);33 vfprintf(stderr, fmt, va);34 putc('\n', stderr);35 va_end(va);3637 status = EXIT_FAILURE;38}3940static void41sizeobj(FILE *fp, int type)42{43 int i;44 Obj *obj;45 unsigned long long total, *p;46 struct sizes siz;47 Section sec;4849 if ((obj = newobj(type)) == NULL) {50 error("failed allocation");51 return;52 }5354 if (readobj(obj, fp) < 0) {55 error("invalid file");56 goto err;57 }5859 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 }7576 if (*p > ULLONG_MAX - sec.size) {77 error("integer overflow");78 goto err;79 }8081 *p += sec.size;82 }8384 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);9091 ttext += siz.text;92 tdata += siz.data;93 tbss += siz.bss;94 ttotal += total;9596err:97 delobj(obj);98}99100static void101sizelib(FILE *fp)102{103 int t;104 long off, cur;105 char memb[SARNAM+1];106107 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}128129static void130size(char *fname)131{132 int t;133 FILE *fp;134135 membname = NULL;136 filename = fname;137 if ((fp = fopen(fname, "rb")) == NULL) {138 error(strerror(errno));139 return;140 }141142 if ((t = objprobe(fp, NULL)) != -1)143 sizeobj(fp, t);144 else if (archive(fp))145 sizelib(fp);146 else147 error("bad format");148149 fclose(fp);150}151152static void153usage(void)154{155 fputs("usage: scc-size [-t] [file...]\n", stderr);156 exit(EXIT_FAILURE);157}158159int160main(int argc, char *argv[])161{162 unsigned long long total;163164 ARGBEGIN {165 case 't':166 tflag = 1;167 break;168 default:169 usage();170 } ARGEND171172 puts("text\tdata\tbss\tdec\thex\tfilename");173174 if (argc == 0) {175 size("a.out");176 } else {177 for (; *argv; ++argv)178 size(*argv);179 }180181 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 }186187 if (fflush(stdout)) {188 fprintf(stderr,189 "size: error writing in output:%s\n",190 strerror(errno));191 status = 1;192 }193194 return status;195}