scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | 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 }