shithub: scc

Download patch

ref: 682ca35d5df44aeb05d8b47e96688c06d9aad154
parent: 45fe8c2a4b1cfa77ccdf7670dfc62a9928153aac
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Tue Jan 8 11:02:52 EST 2019

[addr2line] Add basic program code

This patch adds the main program code, but it doesn't add the core
library functionality.

--- a/include/scc/scc/mach.h
+++ b/include/scc/scc/mach.h
@@ -51,12 +51,13 @@
 extern Symbol *objlookup(Obj *obj, char *name);
 extern int objtraverse(Obj *obj, int (*fn)(Symbol *sym, void *data), void *data);
 extern int objstrip(Obj *obj);
+extern int objsize(Obj *obj,
+                   unsigned long long *text,
+                   unsigned long long *data,
+                   unsigned long long *bss);
 
 /* TODO */
 extern int objload(Obj *obj, Obj *to);
 extern int objreloc(Obj *obj, char *sect, void *rel);
 extern int objwrite(Obj *obj, FILE *fp);
-extern int objsize(Obj *obj,
-                   unsigned long long *text,
-                   unsigned long long *data,
-                   unsigned long long *bss);
+extern int addr2line(Obj *obj, unsigned long long addr, char *fname, int *line);
--- a/src/cmd/addr2line.c
+++ b/src/cmd/addr2line.c
@@ -1,7 +1,144 @@
-/* TODO */
+#include <errno.h>
+#include <limits.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 = "a.out";
+char *argv0;
+
+static void
+error(char *fmt, ...)
+{
+	va_list va;
+
+	va_start(va, fmt);
+	fprintf(stderr, "strip: %s: ", filename);
+	vfprintf(stderr, fmt, va);
+	putc('\n', stderr);
+	va_end(va);
+
+	status = EXIT_FAILURE;
+}
+
+static void
+translate(Obj *obj, char *s)
+{
+	int line;
+	unsigned long long addr;
+	char *end;
+	char fname[FILENAME_MAX];
+
+	addr = strtoull(s, &end, 16);
+	if (*end  || addr == ULONG_MAX) {
+		error("invalid address: '%s'", s);
+		return;
+	}
+
+	if (!addr2line(obj, addr, fname, &line)) {
+		error("not matching line");
+		return;
+	}
+
+	printf("%s:%d\n", fname, line);
+}
+
+static char *
+getline(void)
+{
+	size_t len;
+	static char buf[BUFSIZ];
+
+	for (;;) {
+		if (!fgets(buf, sizeof(buf), stdin)) {
+			error(strerror(errno));
+			return NULL;
+		}
+		if ((len = strlen(buf)) == 0)
+			continue;
+		if (buf[len-1] != '\n') {
+			error("too long address");
+			continue;
+		}
+		buf[len-1] = '\0';
+
+		return buf;
+	}
+}
+
+static Obj *
+loadexe(char *fname)
+{
+	int t;
+	FILE *fp;
+	Obj *obj;
+
+	if ((fp = fopen(fname, "rb")) == NULL) {
+		error(strerror(errno));
+		return NULL;
+	}
+
+	if ((t = objtype(fp, NULL)) < 0) {
+		error("file format not recognized");
+		return NULL;
+	}
+
+	if ((obj = objnew(t)) == NULL) {
+		error("out of memory");
+		return NULL;
+	}
+
+	if (!objread(obj, fp)) {
+		error("file corrupted");
+		return NULL;
+	}
+
+	return obj;
+}
+
+static void
+usage(void)
+{
+	fputs("usage: addr2line [-e file] [addr ...]\n", stderr);
+	exit(EXIT_FAILURE);
+}
+
 int
-main()
+main(int argc, char *argv[])
 {
-	return 0;
+	char *ln;
+	Obj *obj;
+
+	ARGBEGIN {
+	case 'e':
+		filename = EARGF(usage());
+		break;
+	default:
+		usage();
+	} ARGEND
+
+	obj = loadexe(filename);
+	if (!obj)
+		return status;
+
+	if (argc > 0) {
+		for ( ; *argv; ++argv)
+			translate(obj, *argv);
+	} else {
+		while ((ln = getline()) != NULL)
+			translate(obj, ln);
+	}
+
+	fflush(stdout);
+	if (ferror(stdout)) {
+		filename = "stdout";
+		error("error writing stdout: %s", strerror(errno));
+	}
+
+	return status;
 }
--- a/src/libmach/object.c
+++ b/src/libmach/object.c
@@ -212,3 +212,10 @@
 	op = objfmt[fmt];
 	return (*op->size)(obj, text, data, bss);
 }
+
+int
+addr2line(Obj *obj, unsigned long long addr, char *fname, int *line)
+{
+	/* TODO */
+	return -1;
+}