scc

A fork of https://git.simple-cc.org/scc/ for Qute

git clone https://git.8pit.net/scc.git

  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
 12struct sizes {
 13	unsigned long long text;
 14	unsigned long long data;
 15	unsigned long long bss;
 16};
 17
 18static int status;
 19static char *filename, *membname;
 20static int tflag;
 21static unsigned long long ttext, tdata, tbss, ttotal;
 22char *argv0;
 23
 24static void
 25error(char *fmt, ...)
 26{
 27	va_list va;
 28
 29	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);
 36
 37	status = EXIT_FAILURE;
 38}
 39
 40static void
 41sizeobj(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
 96err:
 97	delobj(obj);
 98}
 99
100static void
101sizelib(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
129static void
130size(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
152static void
153usage(void)
154{
155	fputs("usage: scc-size [-t] [file...]\n", stderr);
156	exit(EXIT_FAILURE);
157}
158
159int
160main(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}