scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

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 }