1#include <errno.h>2#include <limits.h>3#include <stdarg.h>4#include <stdio.h>5#include <stdlib.h>6#include <string.h>78#include <scc/arg.h>9#include <scc/mach.h>1011static int status;12static char *filename = "a.out";13char *argv0;1415static void16error(char *fmt, ...)17{18 va_list va;1920 va_start(va, fmt);21 fprintf(stderr, "scc-addr2line: %s: ", filename);22 vfprintf(stderr, fmt, va);23 putc('\n', stderr);24 va_end(va);2526 status = EXIT_FAILURE;27}2829static void30addr2line(Obj *obj, char *s)31{32 int line;33 unsigned long long addr;34 char *end;35 char fname[FILENAME_MAX];3637 addr = strtoull(s, &end, 16);38 if (*end || addr == ULONG_MAX) {39 error("invalid address: '%s'", s);40 return;41 }4243 if (pc2line(obj, addr, fname, &line) < 0) {44 error("not matching line");45 return;46 }4748 printf("%s:%d\n", fname, line);49}5051static char *52getln(void)53{54 size_t len;55 static char buf[BUFSIZ];5657 for (;;) {58 if (!fgets(buf, sizeof(buf), stdin)) {59 error(strerror(errno));60 return NULL;61 }62 if ((len = strlen(buf)) == 0)63 continue;64 if (buf[len-1] != '\n') {65 error("too long address");66 continue;67 }68 buf[len-1] = '\0';6970 return buf;71 }72}7374static Obj *75loadexe(char *fname)76{77 int t;78 FILE *fp;79 Obj *obj;8081 if ((fp = fopen(fname, "rb")) == NULL) {82 error(strerror(errno));83 return NULL;84 }8586 if ((t = objprobe(fp, NULL)) < 0) {87 error("file format not recognized");88 return NULL;89 }9091 if ((obj = newobj(t)) == NULL) {92 error("out of memory");93 return NULL;94 }9596 if (readobj(obj, fp) < 0) {97 error("file corrupted");98 return NULL;99 }100101 return obj;102}103104static void105usage(void)106{107 fputs("usage: scc-addr2line [-e file] [addr ...]\n", stderr);108 exit(EXIT_FAILURE);109}110111int112main(int argc, char *argv[])113{114 char *ln;115 Obj *obj;116117 ARGBEGIN {118 case 'e':119 filename = EARGF(usage());120 break;121 default:122 usage();123 } ARGEND124125 obj = loadexe(filename);126 if (!obj)127 return status;128129 if (argc > 0) {130 for ( ; *argv; ++argv)131 addr2line(obj, *argv);132 } else {133 while ((ln = getln()) != NULL)134 addr2line(obj, ln);135 }136137 fflush(stdout);138 if (ferror(stdout)) {139 filename = "stdout";140 error("error writing stdout: %s", strerror(errno));141 }142143 return status;144}