diff options
author | Russ Cox <rsc@golang.org> | 2013-12-16 12:51:58 -0500 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2013-12-16 12:51:58 -0500 |
commit | 43cad0aa4d6d397630daa553bf4ed28a078637f0 (patch) | |
tree | ecb464b206a70772c61e514e72a3b14d4c776b71 /src/liblink/ld.c | |
parent | 737d6de29569572e16839f9cf6d91cc1db75b622 (diff) | |
download | go-43cad0aa4d6d397630daa553bf4ed28a078637f0.tar.gz |
cmd/ld: move instruction selection + layout into compilers, assemblers
- new object file reader/writer (liblink/objfile.c)
- remove old object file writing routines
- add pcdata iterator
- remove all trace of "line number stack" and "path fragments" from
object files, linker (!!!)
- dwarf now writes a single "compilation unit" instead of one per package
This CL disables the check for chains of no-split functions that
could overflow the stack red zone. A future CL will attack the problem
of reenabling that check (issue 6931).
This CL is just the liblink and cmd/ld changes.
There are minor associated adjustments in CL 37030045.
Each depends on the other.
R=golang-dev, dave, iant
CC=golang-dev
https://codereview.appspot.com/39680043
Diffstat (limited to 'src/liblink/ld.c')
-rw-r--r-- | src/liblink/ld.c | 340 |
1 files changed, 11 insertions, 329 deletions
diff --git a/src/liblink/ld.c b/src/liblink/ld.c index f6632877b..1d06f809a 100644 --- a/src/liblink/ld.c +++ b/src/liblink/ld.c @@ -35,329 +35,14 @@ #include <link.h> void -copyhistfrog(Link *ctxt, char *buf, int nbuf) +addlib(Link *ctxt, char *src, char *obj, char *pathname) { - char *p, *ep; + char name[1024], pname[1024], *p; int i; - p = buf; - ep = buf + nbuf; - for(i=0; i<ctxt->histfrogp; i++) { - p = seprint(p, ep, "%s", ctxt->histfrog[i]->name+1); - if(i+1<ctxt->histfrogp && (p == buf || p[-1] != '/')) - p = seprint(p, ep, "/"); - } -} - -void -addhist(Link *ctxt, int32 line, int type) -{ - Auto *u; - LSym *s; - int i, j, k; - - u = emallocz(sizeof(Auto)); - s = emallocz(sizeof(LSym)); - s->name = emallocz(2*(ctxt->histfrogp+1) + 1); - - u->asym = s; - u->type = type; - u->aoffset = line; - u->link = ctxt->curhist; - ctxt->curhist = u; - - s->name[0] = 0; - j = 1; - for(i=0; i<ctxt->histfrogp; i++) { - k = ctxt->histfrog[i]->value; - s->name[j+0] = k>>8; - s->name[j+1] = k; - j += 2; - } - s->name[j] = 0; - s->name[j+1] = 0; -} - -void -histtoauto(Link *ctxt) -{ - Auto *l; - - while(l = ctxt->curhist) { - ctxt->curhist = l->link; - l->link = ctxt->curauto; - ctxt->curauto = l; - } -} - -void -collapsefrog(Link *ctxt, LSym *s) -{ - int i; - - /* - * bad encoding of path components only allows - * MAXHIST components. if there is an overflow, - * first try to collapse xxx/.. - */ - for(i=1; i<ctxt->histfrogp; i++) - if(strcmp(ctxt->histfrog[i]->name+1, "..") == 0) { - memmove(ctxt->histfrog+i-1, ctxt->histfrog+i+1, - (ctxt->histfrogp-i-1)*sizeof(ctxt->histfrog[0])); - ctxt->histfrogp--; - goto out; - } - - /* - * next try to collapse . - */ - for(i=0; i<ctxt->histfrogp; i++) - if(strcmp(ctxt->histfrog[i]->name+1, ".") == 0) { - memmove(ctxt->histfrog+i, ctxt->histfrog+i+1, - (ctxt->histfrogp-i-1)*sizeof(ctxt->histfrog[0])); - goto out; - } - - /* - * last chance, just truncate from front - */ - memmove(ctxt->histfrog+0, ctxt->histfrog+1, - (ctxt->histfrogp-1)*sizeof(ctxt->histfrog[0])); - -out: - ctxt->histfrog[ctxt->histfrogp-1] = s; -} - -// Saved history stacks encountered while reading archives. -// Keeping them allows us to answer virtual lineno -> file:line -// queries. -// -// The history stack is a complex data structure, described best at the -// bottom of http://plan9.bell-labs.com/magic/man2html/6/a.out. -// One of the key benefits of interpreting it here is that the runtime -// does not have to. Perhaps some day the compilers could generate -// a simpler linker input too. - -// savehist processes a single line, off history directive -// found in the input object file. -void -savehist(Link *ctxt, int32 line, int32 off) -{ - char tmp[1024]; - LSym *file; - Hist2 *h; - - // NOTE(rsc): We used to do the copyctxt->histfrog first and this - // condition was if(tmp[0] != '\0') to check for an empty string, - // implying that ctxt->histfrogp == 0, implying that this is a history pop. - // However, on Windows in the misc/cgo test, the linker is - // presented with an ANAME corresponding to an empty string, - // that ANAME ends up being the only ctxt->histfrog, and thus we have - // a situation where ctxt->histfrogp > 0 (not a pop) but the path we find - // is the empty string. Really that shouldn't happen, but it doesn't - // seem to be bothering anyone yet, and it's easier to fix the condition - // to test ctxt->histfrogp than to track down where that empty string is - // coming from. Probably it is coming from go tool pack's P command. - if(ctxt->histfrogp > 0) { - tmp[0] = '\0'; - copyhistfrog(ctxt, tmp, sizeof tmp); - file = linklookup(ctxt, tmp, HistVersion); - } else - file = nil; - - if(file != nil && line == 1 && off == 0) { - // start of new stack - if(ctxt->histdepth != 0) - sysfatal("history stack phase error: unexpected start of new stack depth=%d file=%s", ctxt->histdepth, tmp); - ctxt->nhist2 = 0; - ctxt->histcopy = nil; - } - - if(ctxt->nhist2 >= ctxt->maxhist2) { - if(ctxt->maxhist2 == 0) - ctxt->maxhist2 = 1; - ctxt->maxhist2 *= 2; - ctxt->hist2 = erealloc(ctxt->hist2, ctxt->maxhist2*sizeof ctxt->hist2[0]); - } - h = &ctxt->hist2[ctxt->nhist2++]; - h->line = line; - h->off = off; - h->file = file; - - if(file != nil) { - if(off == 0) - ctxt->histdepth++; - } else { - if(off != 0) - sysfatal("history stack phase error: bad offset in pop"); - ctxt->histdepth--; - } -} - -// gethist returns the history stack currently in effect. -// The result is valid indefinitely. -Hist2* -gethist(Link *ctxt) -{ - if(ctxt->histcopy == nil) { - if(ctxt->nhist2 == 0) - return nil; - ctxt->histcopy = emallocz((ctxt->nhist2+1)*sizeof ctxt->hist2[0]); - memmove(ctxt->histcopy, ctxt->hist2, ctxt->nhist2*sizeof ctxt->hist2[0]); - ctxt->histcopy[ctxt->nhist2].line = -1; - } - return ctxt->histcopy; -} - -typedef struct Hstack Hstack; -struct Hstack -{ - Hist2 *h; - int delta; -}; - -// getline sets *f to the file number and *l to the line number -// of the virtual line number line according to the history stack h. -void -linkgetline(Link *ctxt, Hist2 *h, int32 line, LSym **f, int32 *l) -{ - Hstack stk[100]; - int nstk, start; - Hist2 *top, *h0; - static Hist2 *lasth; - static int32 laststart, lastend, lastdelta; - static LSym *lastfile; - - h0 = h; - *f = 0; - *l = 0; - start = 0; - if(h == nil || line == 0) { - print("%s: getline: h=%p line=%d\n", ctxt->cursym->name, h, line); - return; - } - - // Cache span used during last lookup, so that sequential - // translation of line numbers in compiled code is efficient. - if(!ctxt->debughist && lasth == h && laststart <= line && line < lastend) { - *f = lastfile; - *l = line - lastdelta; - return; - } - - if(ctxt->debughist) - print("getline %d laststart=%d lastend=%d\n", line, laststart, lastend); - - nstk = 0; - for(; h->line != -1; h++) { - if(ctxt->debughist) - print("\t%s %d %d\n", h->file ? h->file->name : "?", h->line, h->off); - - if(h->line > line) { - if(nstk == 0) - sysfatal("history stack phase error: empty stack at line %d", (int)line); - top = stk[nstk-1].h; - lasth = h; - lastfile = top->file; - laststart = start; - lastend = h->line; - lastdelta = stk[nstk-1].delta; - *f = lastfile; - *l = line - lastdelta; - if(ctxt->debughist) - print("\tgot %d %d [%d %d %d]\n", *f, *l, laststart, lastend, lastdelta); - return; - } - if(h->file == nil) { - // pop included file - if(nstk == 0) - sysfatal("history stack phase error: stack underflow"); - nstk--; - if(nstk > 0) - stk[nstk-1].delta += h->line - stk[nstk].h->line; - start = h->line; - } else if(h->off == 0) { - // push included file - if(nstk >= nelem(stk)) - sysfatal("history stack phase error: stack overflow"); - start = h->line; - stk[nstk].h = h; - stk[nstk].delta = h->line - 1; - nstk++; - } else { - // #line directive - if(nstk == 0) - sysfatal("history stack phase error: stack underflow"); - stk[nstk-1].h = h; - stk[nstk-1].delta = h->line - h->off; - start = h->line; - } - if(ctxt->debughist) - print("\t\tnstk=%d delta=%d\n", nstk, stk[nstk].delta); - } - - sysfatal("history stack phase error: cannot find line for %d", line); - nstk = 0; - for(h = h0; h->line != -1; h++) { - print("\t%d %d %s\n", h->line, h->off, h->file ? h->file->name : ""); - if(h->file == nil) - nstk--; - else if(h->off == 0) - nstk++; - } -} - -void -addlib(Link *ctxt, char *src, char *obj) -{ - char name[1024], pname[1024], comp[256], *p; - int i, search; - - if(ctxt->histfrogp <= 0) - return; - - search = 0; - if(ctxt->histfrog[0]->name[1] == '/') { - sprint(name, ""); - i = 1; - } else - if(isalpha((uchar)ctxt->histfrog[0]->name[1]) && ctxt->histfrog[0]->name[2] == ':') { - strcpy(name, ctxt->histfrog[0]->name+1); - i = 1; - } else - if(ctxt->histfrog[0]->name[1] == '.') { - sprint(name, "."); - i = 0; - } else { - sprint(name, ""); - i = 0; - search = 1; - } - - for(; i<ctxt->histfrogp; i++) { - snprint(comp, sizeof comp, "%s", ctxt->histfrog[i]->name+1); - for(;;) { - p = strstr(comp, "$O"); - if(p == 0) - break; - memmove(p+1, p+2, strlen(p+2)+1); - p[0] = ctxt->thechar; - } - for(;;) { - p = strstr(comp, "$M"); - if(p == 0) - break; - if(strlen(comp)+strlen(ctxt->thestring)-2+1 >= sizeof comp) - sysfatal("library component too long"); - memmove(p+strlen(ctxt->thestring), p+2, strlen(p+2)+1); - memmove(p, ctxt->thestring, strlen(ctxt->thestring)); - } - if(strlen(name) + strlen(comp) + 3 >= sizeof(name)) - sysfatal("library component too long"); - if(i > 0 || !search) - strcat(name, "/"); - strcat(name, comp); - } + if(strlen(pathname) >= sizeof name) + sysfatal("addlib pathname too long"); + strcpy(name, pathname); cleanname(name); // runtime.a -> runtime @@ -376,15 +61,12 @@ addlib(Link *ctxt, char *src, char *obj) if(p != nil) *p = '.'; - if(search) { - // try dot, -L "libdir", and then goroot. - for(i=0; i<ctxt->nlibdir; i++) { - snprint(pname, sizeof pname, "%s/%s", ctxt->libdir[i], name); - if(access(pname, AEXIST) >= 0) - break; - } - }else - strcpy(pname, name); + // try dot, -L "libdir", and then goroot. + for(i=0; i<ctxt->nlibdir; i++) { + snprint(pname, sizeof pname, "%s/%s", ctxt->libdir[i], name); + if(access(pname, AEXIST) >= 0) + break; + } cleanname(pname); /* runtime.a -> runtime */ |