scc

A fork of https://git.simple-cc.org/scc/ for Qute

git clone https://git.8pit.net/scc.git

  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
 11static int status;
 12static char *filename = "a.out";
 13char *argv0;
 14
 15static void
 16error(char *fmt, ...)
 17{
 18	va_list va;
 19
 20	va_start(va, fmt);
 21	fprintf(stderr, "scc-addr2line: %s: ", filename);
 22	vfprintf(stderr, fmt, va);
 23	putc('\n', stderr);
 24	va_end(va);
 25
 26	status = EXIT_FAILURE;
 27}
 28
 29static void
 30addr2line(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
 51static char *
 52getln(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
 74static Obj *
 75loadexe(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
104static void
105usage(void)
106{
107	fputs("usage: scc-addr2line [-e file] [addr ...]\n", stderr);
108	exit(EXIT_FAILURE);
109}
110
111int
112main(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}