scc-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
---
scc-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 }