summaryrefslogtreecommitdiff
path: root/src/liblink/obj.c
diff options
context:
space:
mode:
authorMichael Stapelberg <stapelberg@debian.org>2014-06-19 09:22:53 +0200
committerMichael Stapelberg <stapelberg@debian.org>2014-06-19 09:22:53 +0200
commit8a39ee361feb9bf46d728ff1ba4f07ca1d9610b1 (patch)
tree4449f2036cccf162e8417cc5841a35815b3e7ac5 /src/liblink/obj.c
parentc8bf49ef8a92e2337b69c14b9b88396efe498600 (diff)
downloadgolang-8a39ee361feb9bf46d728ff1ba4f07ca1d9610b1.tar.gz
Imported Upstream version 1.3upstream/1.3
Diffstat (limited to 'src/liblink/obj.c')
-rw-r--r--src/liblink/obj.c296
1 files changed, 296 insertions, 0 deletions
diff --git a/src/liblink/obj.c b/src/liblink/obj.c
new file mode 100644
index 000000000..b8083b0ec
--- /dev/null
+++ b/src/liblink/obj.c
@@ -0,0 +1,296 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <link.h>
+
+enum
+{
+ HISTSZ = 10,
+ NSYM = 50,
+};
+
+int
+linklinefmt(Link *ctxt, Fmt *fp)
+{
+ struct
+ {
+ Hist* incl; /* start of this include file */
+ int32 idel; /* delta line number to apply to include */
+ Hist* line; /* start of this #line directive */
+ int32 ldel; /* delta line number to apply to #line */
+ } a[HISTSZ];
+ int32 lno, d;
+ int i, n;
+ Hist *h;
+
+ lno = va_arg(fp->args, int32);
+
+ n = 0;
+ for(h=ctxt->hist; h!=nil; h=h->link) {
+ if(h->offset < 0)
+ continue;
+ if(lno < h->line)
+ break;
+ if(h->name) {
+ if(h->offset > 0) {
+ // #line directive
+ if(n > 0 && n < HISTSZ) {
+ a[n-1].line = h;
+ a[n-1].ldel = h->line - h->offset + 1;
+ }
+ } else {
+ // beginning of file
+ if(n < HISTSZ) {
+ a[n].incl = h;
+ a[n].idel = h->line;
+ a[n].line = 0;
+ }
+ n++;
+ }
+ continue;
+ }
+ n--;
+ if(n > 0 && n < HISTSZ) {
+ d = h->line - a[n].incl->line;
+ a[n-1].ldel += d;
+ a[n-1].idel += d;
+ }
+ }
+
+ if(n > HISTSZ)
+ n = HISTSZ;
+
+ for(i=n-1; i>=0; i--) {
+ if(i != n-1) {
+ if(fp->flags & ~(FmtWidth|FmtPrec))
+ break;
+ fmtprint(fp, " ");
+ }
+ if(ctxt->debugline || (fp->flags&FmtLong))
+ fmtprint(fp, "%s/", ctxt->pathname);
+ if(a[i].line)
+ fmtprint(fp, "%s:%d[%s:%d]",
+ a[i].line->name, lno-a[i].ldel+1,
+ a[i].incl->name, lno-a[i].idel+1);
+ else
+ fmtprint(fp, "%s:%d",
+ a[i].incl->name, lno-a[i].idel+1);
+ lno = a[i].incl->line - 1; // now print out start of this file
+ }
+ if(n == 0)
+ fmtprint(fp, "<unknown line number>");
+
+ return 0;
+}
+
+// Does s have t as a path prefix?
+// That is, does s == t or does s begin with t followed by a slash?
+// For portability, we allow ASCII case folding, so that haspathprefix("a/b/c", "A/B") is true.
+// Similarly, we allow slash folding, so that haspathprefix("a/b/c", "a\\b") is true.
+static int
+haspathprefix(char *s, char *t)
+{
+ int i, cs, ct;
+
+ if(t == nil)
+ return 0;
+ for(i=0; t[i]; i++) {
+ cs = s[i];
+ ct = t[i];
+ if('A' <= cs && cs <= 'Z')
+ cs += 'a' - 'A';
+ if('A' <= ct && ct <= 'Z')
+ ct += 'a' - 'A';
+ if(cs == '\\')
+ cs = '/';
+ if(ct == '\\')
+ ct = '/';
+ if(cs != ct)
+ return 0;
+ }
+ return s[i] == '\0' || s[i] == '/' || s[i] == '\\';
+}
+
+// This is a simplified copy of linklinefmt above.
+// It doesn't allow printing the full stack, and it returns the file name and line number separately.
+// TODO: Unify with linklinefmt somehow.
+void
+linkgetline(Link *ctxt, int32 line, LSym **f, int32 *l)
+{
+ struct
+ {
+ Hist* incl; /* start of this include file */
+ int32 idel; /* delta line number to apply to include */
+ Hist* line; /* start of this #line directive */
+ int32 ldel; /* delta line number to apply to #line */
+ } a[HISTSZ];
+ int32 lno, d, dlno;
+ int n;
+ Hist *h;
+ char buf[1024], buf1[1024], *file;
+
+ lno = line;
+ n = 0;
+ for(h=ctxt->hist; h!=nil; h=h->link) {
+ if(h->offset < 0)
+ continue;
+ if(lno < h->line)
+ break;
+ if(h->name) {
+ if(h->offset > 0) {
+ // #line directive
+ if(n > 0 && n < HISTSZ) {
+ a[n-1].line = h;
+ a[n-1].ldel = h->line - h->offset + 1;
+ }
+ } else {
+ // beginning of file
+ if(n < HISTSZ) {
+ a[n].incl = h;
+ a[n].idel = h->line;
+ a[n].line = 0;
+ }
+ n++;
+ }
+ continue;
+ }
+ n--;
+ if(n > 0 && n < HISTSZ) {
+ d = h->line - a[n].incl->line;
+ a[n-1].ldel += d;
+ a[n-1].idel += d;
+ }
+ }
+
+ if(n > HISTSZ)
+ n = HISTSZ;
+
+ if(n <= 0) {
+ *f = linklookup(ctxt, "??", HistVersion);
+ *l = 0;
+ return;
+ }
+
+ n--;
+ if(a[n].line) {
+ file = a[n].line->name;
+ dlno = a[n].ldel-1;
+ } else {
+ file = a[n].incl->name;
+ dlno = a[n].idel-1;
+ }
+ if((!ctxt->windows && file[0] == '/') || (ctxt->windows && file[1] == ':') || file[0] == '<')
+ snprint(buf, sizeof buf, "%s", file);
+ else
+ snprint(buf, sizeof buf, "%s/%s", ctxt->pathname, file);
+
+ // Remove leading ctxt->trimpath, or else rewrite $GOROOT to $GOROOT_FINAL.
+ if(haspathprefix(buf, ctxt->trimpath)) {
+ if(strlen(buf) == strlen(ctxt->trimpath))
+ strcpy(buf, "??");
+ else {
+ snprint(buf1, sizeof buf1, "%s", buf+strlen(ctxt->trimpath)+1);
+ if(buf1[0] == '\0')
+ strcpy(buf1, "??");
+ strcpy(buf, buf1);
+ }
+ } else if(ctxt->goroot_final != nil && haspathprefix(buf, ctxt->goroot)) {
+ snprint(buf1, sizeof buf1, "%s%s", ctxt->goroot_final, buf+strlen(ctxt->goroot));
+ strcpy(buf, buf1);
+ }
+
+ lno -= dlno;
+ *f = linklookup(ctxt, buf, HistVersion);
+ *l = lno;
+}
+
+void
+linklinehist(Link *ctxt, int lineno, char *f, int offset)
+{
+ Hist *h;
+
+ if(0) // debug['f']
+ if(f) {
+ if(offset)
+ print("%4d: %s (#line %d)\n", lineno, f, offset);
+ else
+ print("%4d: %s\n", lineno, f);
+ } else
+ print("%4d: <pop>\n", lineno);
+
+ h = malloc(sizeof(Hist));
+ memset(h, 0, sizeof *h);
+ h->name = f;
+ h->line = lineno;
+ h->offset = offset;
+ h->link = nil;
+ if(ctxt->ehist == nil) {
+ ctxt->hist = h;
+ ctxt->ehist = h;
+ return;
+ }
+ ctxt->ehist->link = h;
+ ctxt->ehist = h;
+}
+
+void
+linkprfile(Link *ctxt, int32 l)
+{
+ int i, n;
+ Hist a[HISTSZ], *h;
+ int32 d;
+
+ n = 0;
+ for(h = ctxt->hist; h != nil; h = h->link) {
+ if(l < h->line)
+ break;
+ if(h->name) {
+ if(h->offset == 0) {
+ if(n >= 0 && n < HISTSZ)
+ a[n] = *h;
+ n++;
+ continue;
+ }
+ if(n > 0 && n < HISTSZ)
+ if(a[n-1].offset == 0) {
+ a[n] = *h;
+ n++;
+ } else
+ a[n-1] = *h;
+ continue;
+ }
+ n--;
+ if(n >= 0 && n < HISTSZ) {
+ d = h->line - a[n].line;
+ for(i=0; i<n; i++)
+ a[i].line += d;
+ }
+ }
+ if(n > HISTSZ)
+ n = HISTSZ;
+ for(i=0; i<n; i++)
+ print("%s:%ld ", a[i].name, (long)(l-a[i].line+a[i].offset+1));
+}
+
+/*
+ * start a new Prog list.
+ */
+Plist*
+linknewplist(Link *ctxt)
+{
+ Plist *pl;
+
+ pl = malloc(sizeof(*pl));
+ memset(pl, 0, sizeof *pl);
+ if(ctxt->plist == nil)
+ ctxt->plist = pl;
+ else
+ ctxt->plast->link = pl;
+ ctxt->plast = pl;
+
+ return pl;
+}