scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit d259624d7eb89c684fc0fdbeecb81f98488263c4
parent 9b06386d77ef77bca4f3f02706449246bd81fc8d
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Tue,  8 Jan 2019 16:02:52 +0000

[addr2line] Add basic program code

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

Diffstat:
Minclude/scc/scc/mach.h | 9+++++----
Msrc/cmd/addr2line.c | 143+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/libmach/object.c | 7+++++++
3 files changed, 152 insertions(+), 7 deletions(-)

diff --git a/include/scc/scc/mach.h b/include/scc/scc/mach.h @@ -51,12 +51,13 @@ extern int objread(Obj *obj, FILE *fp); 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); diff --git 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; } diff --git a/src/libmach/object.c b/src/libmach/object.c @@ -212,3 +212,10 @@ objsize(Obj *obj, 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; +}