scc-size.c - scc - simple c99 compiler
(HTM) git clone git://git.simple-cc.org/scc
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Submodules
(DIR) README
(DIR) LICENSE
---
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 }