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;
+}