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 }