commit f5ed5507fb01df5285cfbc5cdf86bd7b7ed1e6be
parent fe7dfc544705bbdea43716d08628036a7f1a6cbe
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Tue, 8 Jan 2019 11:02:42 +0000
[size] Add a first version of size
This version is not fully functional and it doesn't support libraries.
Diffstat:
7 files changed, 145 insertions(+), 3 deletions(-)
diff --git a/include/scc/scc/mach.h b/include/scc/scc/mach.h
@@ -56,3 +56,7 @@ extern void objstrip(Obj *obj);
extern int objload(Obj *obj, Obj *to);
extern int objreloc(Obj *obj, char *sect, void *rel);
extern int objwrite(Obj *obj, FILE *fp);
+extern void objsize(Obj *obj,
+ unsigned long long *text,
+ unsigned long long *data,
+ unsigned long long *bss);
diff --git a/src/cmd/.gitignore b/src/cmd/.gitignore
@@ -1,2 +1,3 @@
nm
strip
+size
diff --git a/src/cmd/Makefile b/src/cmd/Makefile
@@ -5,6 +5,7 @@ include $(PROJECTDIR)/scripts/rules.mk
TARGET = $(BINDIR)/nm \
$(BINDIR)/strip \
+ $(BINDIR)/size \
LIBS = -lmach
@@ -18,8 +19,11 @@ $(BINDIR)/nm: nm
$(BINDIR)/strip: strip
cp strip $@
+$(BINDIR)/size: size
+ cp size $@
+
clean:
- rm -f nm strip
+ rm -f nm strip size
dep: inc-dep
diff --git a/src/cmd/deps.mk b/src/cmd/deps.mk
@@ -1,5 +1,7 @@
#deps
nm.o: $(INCDIR)/scc/scc/arg.h
nm.o: $(INCDIR)/scc/scc/mach.h
+size.o: $(INCDIR)/scc/scc/arg.h
+size.o: $(INCDIR)/scc/scc/mach.h
strip.o: $(INCDIR)/scc/scc/arg.h
strip.o: $(INCDIR)/scc/scc/mach.h
diff --git a/src/cmd/size.c b/src/cmd/size.c
@@ -0,0 +1,111 @@
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/arg.h>
+#include <scc/mach.h>
+
+static int status;
+static char *filename;
+static int tflag;
+static unsigned long long ttext, tdata, tbss, ttotal;
+char *argv0;
+
+static void
+error(char *fmt, ...)
+{
+ va_list va;
+
+ va_start(va, fmt);
+ fprintf(stderr, "size: %s: ", filename);
+ vfprintf(stderr, fmt, va);
+ putc('\n', stderr);
+ va_end(va);
+
+ status = EXIT_FAILURE;
+}
+
+static void
+size(char *fname)
+{
+ int type;
+ Obj *obj;
+ FILE *fp;
+ unsigned long long text, data, bss, total;
+
+ filename = fname;
+ if ((fp = fopen(fname, "rb")) == NULL) {
+ error(strerror(errno));
+ return;
+ }
+ if ((type = objtype(fp, NULL)) < 0) {
+ error(strerror(errno));
+ goto err1;
+ }
+ if ((obj = objnew(type)) == NULL) {
+ error("out of memory");
+ goto err1;
+ }
+ if (objread(obj, fp) < 0) {
+ error("file corrupted");
+ goto err2;
+ }
+ objsize(obj, &text, &data, &bss);
+ total = text + data + bss;
+ printf("%llu\t%llu\t%llu\t%llu\t%llx\t%s\n",
+ text, data, bss, total, total, fname);
+
+ ttext += text;
+ tdata += data;
+ tbss += bss;
+ ttotal += total;
+
+err2:
+ objdel(obj);
+err1:
+ fclose(fp);
+ return;
+}
+
+static void
+usage(void)
+{
+ fputs("usage: size [-t] file ...\n", stderr);
+ exit(EXIT_FAILURE);
+}
+
+int
+main(int argc, char *argv[])
+{
+ unsigned long long total;
+
+ ARGBEGIN {
+ case 't':
+ tflag = 1;
+ break;
+ default:
+ usage();
+ } ARGEND
+
+ if (argc == 1)
+ usage;
+
+ puts("text\tdata\tbss\tdec\thex\tfilename");
+ for (argc--; argc > 0; argc--)
+ size(*argv++);
+
+ if (tflag) {
+ total = ttext + tdata + tbss;
+ printf("%llu\t%llu\t%llu\t%llu\t%llx\t%s\n",
+ ttext, tdata, tbss, total, total, "(TOTALS)");
+ }
+
+ if (fflush(stdout)) {
+ filename = "stdout";
+ error(strerror(errno));
+ }
+
+ return status;
+}
diff --git a/src/libmach/libmach.h b/src/libmach/libmach.h
@@ -28,11 +28,15 @@ enum order {
struct format {
int (*probe)(unsigned char *buf, char **name);
- void (*strip)(Obj *obj);
+ int (*strip)(Obj *obj);
int (*new)(Obj *obj);
int (*read)(Obj *obj, FILE *fp);
int (*write)(Obj *obj, FILE *fp);
void (*del)(Obj *obj);
+ int (*size)(Obj *obj,
+ unsigned long long *,
+ unsigned long long *,
+ unsigned long long *)
};
extern int pack(int order, unsigned char *dst, char *fmt, ...);
diff --git a/src/libmach/object.c b/src/libmach/object.c
@@ -180,7 +180,7 @@ objdel(Obj *obj)
free(obj);
}
-void
+int
objstrip(Obj *obj)
{
int fmt;
@@ -193,3 +193,19 @@ objstrip(Obj *obj)
(*op->strip)(obj);
delsyms(obj);
}
+
+void
+objsize(Obj *obj,
+ unsigned long long *text,
+ unsigned long long *data,
+ unsigned long long *bss)
+{
+ int fmt;
+ struct format *op;
+
+ fmt = FORMAT(obj->type);
+ if (fmt >= NFORMATS)
+ return -1;
+ op = objfmt[fmt];
+ (*op->size)(obj, text, data, bss);
+}