addr2line.c - scc - simple c99 compiler
 (HTM) git clone git://git.simple-cc.org/scc
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
 (DIR) README
 (DIR) LICENSE
       ---
       addr2line.c (2135B)
       ---
            1 #include <errno.h>
            2 #include <limits.h>
            3 #include <stdarg.h>
            4 #include <stdio.h>
            5 #include <stdlib.h>
            6 #include <string.h>
            7 
            8 #include <scc/arg.h>
            9 #include <scc/mach.h>
           10 
           11 static int status;
           12 static char *filename = "a.out";
           13 char *argv0;
           14 
           15 static void
           16 error(char *fmt, ...)
           17 {
           18         va_list va;
           19 
           20         va_start(va, fmt);
           21         fprintf(stderr, "strip: %s: ", filename);
           22         vfprintf(stderr, fmt, va);
           23         putc('\n', stderr);
           24         va_end(va);
           25 
           26         status = EXIT_FAILURE;
           27 }
           28 
           29 static void
           30 addr2line(Obj *obj, char *s)
           31 {
           32         int line;
           33         unsigned long long addr;
           34         char *end;
           35         char fname[FILENAME_MAX];
           36 
           37         addr = strtoull(s, &end, 16);
           38         if (*end  || addr == ULONG_MAX) {
           39                 error("invalid address: '%s'", s);
           40                 return;
           41         }
           42 
           43         if (pc2line(obj, addr, fname, &line) < 0) {
           44                 error("not matching line");
           45                 return;
           46         }
           47 
           48         printf("%s:%d\n", fname, line);
           49 }
           50 
           51 static char *
           52 getln(void)
           53 {
           54         size_t len;
           55         static char buf[BUFSIZ];
           56 
           57         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';
           69 
           70                 return buf;
           71         }
           72 }
           73 
           74 static Obj *
           75 loadexe(char *fname)
           76 {
           77         int t;
           78         FILE *fp;
           79         Obj *obj;
           80 
           81         if ((fp = fopen(fname, "rb")) == NULL) {
           82                 error(strerror(errno));
           83                 return NULL;
           84         }
           85 
           86         if ((t = objprobe(fp, NULL)) < 0) {
           87                 error("file format not recognized");
           88                 return NULL;
           89         }
           90 
           91         if ((obj = newobj(t)) == NULL) {
           92                 error("out of memory");
           93                 return NULL;
           94         }
           95 
           96         if (readobj(obj, fp) < 0) {
           97                 error("file corrupted");
           98                 return NULL;
           99         }
          100 
          101         return obj;
          102 }
          103 
          104 static void
          105 usage(void)
          106 {
          107         fputs("usage: addr2line [-e file] [addr ...]\n", stderr);
          108         exit(EXIT_FAILURE);
          109 }
          110 
          111 int
          112 main(int argc, char *argv[])
          113 {
          114         char *ln;
          115         Obj *obj;
          116 
          117         ARGBEGIN {
          118         case 'e':
          119                 filename = EARGF(usage());
          120                 break;
          121         default:
          122                 usage();
          123         } ARGEND
          124 
          125         obj = loadexe(filename);
          126         if (!obj)
          127                 return status;
          128 
          129         if (argc > 0) {
          130                 for ( ; *argv; ++argv)
          131                         addr2line(obj, *argv);
          132         } else {
          133                 while ((ln = getln()) != NULL)
          134                         addr2line(obj, ln);
          135         }
          136 
          137         fflush(stdout);
          138         if (ferror(stdout)) {
          139                 filename = "stdout";
          140                 error("error writing stdout: %s", strerror(errno));
          141         }
          142 
          143         return status;
          144 }