]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/ld: fix bad merge
authorShenghou Ma <minux.ma@gmail.com>
Thu, 21 Mar 2013 19:54:14 +0000 (03:54 +0800)
committerShenghou Ma <minux.ma@gmail.com>
Thu, 21 Mar 2013 19:54:14 +0000 (03:54 +0800)
CL 7504044 accidentally reverted part of CL 7891044 and 7552045, this CL
bring those part back.

R=golang-dev
TBR=rsc
CC=golang-dev
https://golang.org/cl/7950045

src/cmd/ld/dwarf.c

index a90f8691af243d41ce02e596bd655ec7e4644687..3f55340560adf0eee3aecf057f03df5b97496ac5 100644 (file)
@@ -41,9 +41,13 @@ static vlong arangeso;
 static vlong arangessize;
 static vlong gdbscripto;
 static vlong gdbscriptsize;
+static vlong inforeloco;
+static vlong inforelocsize;
 
 static char  gdbscript[1024];
 
+static Sym *dsym;
+
 /*
  *  Basic I/O
  */
@@ -485,26 +489,43 @@ mkindex(DWDie *die)
        die->hash = mal(HASHSIZE * sizeof(DWDie*));
 }
 
+static DWDie*
+walktypedef(DWDie *die)
+{
+       DWAttr *attr;
+
+       // Resolve typedef if present.
+       if (die->abbrev == DW_ABRV_TYPEDECL) {
+               for (attr = die->attr; attr; attr = attr->link) {
+                       if (attr->atr == DW_AT_type && attr->cls == DW_CLS_REFERENCE && attr->data != nil) {
+                               return (DWDie*)attr->data;
+                       }
+               }
+       }
+       return die;
+}
+
 // Find child by AT_name using hashtable if available or linear scan
 // if not.
 static DWDie*
 find(DWDie *die, char* name)
 {
-       DWDie *a, *b;
+       DWDie *a, *b, *die2;
        int h;
 
+top:
        if (die->hash == nil) {
                for (a = die->child; a != nil; a = a->link)
                        if (strcmp(name, getattr(a, DW_AT_name)->data) == 0)
                                return a;
-               return nil;
+               goto notfound;
        }
 
        h = hashstr(name);
        a = die->hash[h];
 
        if (a == nil)
-               return nil;
+               goto notfound;
 
 
        if (strcmp(name, getattr(a, DW_AT_name)->data) == 0)
@@ -522,6 +543,14 @@ find(DWDie *die, char* name)
                a = b;
                b = b->hlink;
        }
+
+notfound:
+       die2 = walktypedef(die);
+       if(die2 != die) {
+               die = die2;
+               goto top;
+       }
+
        return nil;
 }
 
@@ -531,7 +560,7 @@ find_or_diag(DWDie *die, char* name)
        DWDie *r;
        r = find(die, name);
        if (r == nil) {
-               diag("dwarf find: %s has no %s", getattr(die, DW_AT_name)->data, name);
+               diag("dwarf find: %s %p has no %s", getattr(die, DW_AT_name)->data, die, name);
                errorexit();
        }
        return r;
@@ -548,14 +577,33 @@ newrefattr(DWDie *die, uint8 attr, DWDie* ref)
 static int fwdcount;
 
 static void
-putattr(int form, int cls, vlong value, char *data)
+putattr(int abbrev, int form, int cls, vlong value, char *data)
 {
+       Reloc *r;
+
        switch(form) {
        case DW_FORM_addr:      // address
                addrput(value);
                break;
 
        case DW_FORM_block1:    // block
+               if(cls == DW_CLS_ADDRESS) {
+                       cput(1+PtrSize);
+                       cput(DW_OP_addr);
+                       if(linkmode == LinkExternal) {
+                               r = addrel(dsym);
+                               r->sym = (Sym*)data;
+                               r->xsym = r->sym;
+                               r->off = cpos() - infoo;
+                               r->siz = PtrSize;
+                               r->type = D_ADDR;
+                               r->add = value - r->sym->value;
+                               r->xadd = r->add;
+                               value = r->add;
+                       }
+                       addrput(value);
+                       break;
+               }
                value &= 0xff;
                cput(value);
                while(value--)
@@ -615,13 +663,23 @@ putattr(int form, int cls, vlong value, char *data)
                break;
 
        case DW_FORM_ref_addr:  // reference to a DIE in the .info section
+               // In DWARF 2 (which is what we claim to generate),
+               // the ref_addr is the same size as a normal address.
+               // In DWARF 3 it is always 32 bits, unless emitting a large
+               // (> 4 GB of debug info aka "64-bit") unit, which we don't implement.
                if (data == nil) {
-                       diag("dwarf: null reference");
-                       LPUT(0);  // invalid dwarf, gdb will complain.
+                       diag("dwarf: null reference in %d", abbrev);
+                       if(PtrSize == 8)
+                               VPUT(0); // invalid dwarf, gdb will complain.
+                       else
+                               LPUT(0); // invalid dwarf, gdb will complain.
                } else {
                        if (((DWDie*)data)->offs == 0)
                                fwdcount++;
-                       LPUT(((DWDie*)data)->offs);
+                       if(PtrSize == 8)
+                               VPUT(((DWDie*)data)->offs);
+                       else
+                               LPUT(((DWDie*)data)->offs);
                }
                break;
 
@@ -654,12 +712,12 @@ putattrs(int abbrev, DWAttr* attr)
 
        for(af = abbrevs[abbrev].attr; af->attr; af++)
                if (attrs[af->attr])
-                       putattr(af->form,
+                       putattr(abbrev, af->form,
                                attrs[af->attr]->cls,
                                attrs[af->attr]->value,
                                attrs[af->attr]->data);
                else
-                       putattr(af->form, 0, 0, 0);
+                       putattr(abbrev, af->form, 0, 0, 0);
 }
 
 static void putdie(DWDie* die);
@@ -729,16 +787,9 @@ newmemberoffsetattr(DWDie *die, int32 offs)
 // GDB doesn't like DW_FORM_addr for DW_AT_location, so emit a
 // location expression that evals to a const.
 static void
-newabslocexprattr(DWDie *die, vlong addr)
+newabslocexprattr(DWDie *die, vlong addr, Sym *sym)
 {
-       char block[10];
-       int i;
-
-       i = 0;
-       block[i++] = DW_OP_constu;
-       i += uleb128enc(addr, block+i);
-       newattr(die, DW_AT_location, DW_CLS_BLOCK, i, mal(i));
-       memmove(die->attr->data, block, i);
+       newattr(die, DW_AT_location, DW_CLS_ADDRESS, addr, (char*)sym);
 }
 
 
@@ -766,6 +817,31 @@ lookup_or_diag(char *n)
        return s;
 }
 
+static void
+dotypedef(DWDie *parent, char *name, DWDie *def)
+{
+       DWDie *die;
+
+       // Only emit typedefs for real names.
+       if(strncmp(name, "map[", 4) == 0)
+               return;
+       if(strncmp(name, "struct {", 8) == 0)
+               return;
+       if(strncmp(name, "chan ", 5) == 0)
+               return;
+       if(*name == '[' || *name == '*')
+               return;
+       if(def == nil)
+               diag("dwarf: bad def in dotypedef");
+
+       // The typedef entry must be created after the def,
+       // so that future lookups will find the typedef instead
+       // of the real definition. This hooks the typedef into any
+       // circular definition loops, so that gdb can understand them.
+       die = newdie(parent, DW_ABRV_TYPEDECL, name);
+       newrefattr(die, DW_AT_type, def);
+}
+
 // Define gotype, for composite ones recurse into constituents.
 static DWDie*
 defgotype(Sym *gotype)
@@ -840,6 +916,7 @@ defgotype(Sym *gotype)
 
        case KindArray:
                die = newdie(&dwtypes, DW_ABRV_ARRAYTYPE, name);
+               dotypedef(&dwtypes, name, die);
                newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
                s = decodetype_arrayelem(gotype);
                newrefattr(die, DW_AT_type, defgotype(s));
@@ -857,6 +934,7 @@ defgotype(Sym *gotype)
 
        case KindFunc:
                die = newdie(&dwtypes, DW_ABRV_FUNCTYPE, name);
+               dotypedef(&dwtypes, name, die);
                newrefattr(die, DW_AT_type, find_or_diag(&dwtypes, "void"));
                nfields = decodetype_funcincount(gotype);
                for (i = 0; i < nfields; i++) {
@@ -876,6 +954,7 @@ defgotype(Sym *gotype)
 
        case KindInterface:
                die = newdie(&dwtypes, DW_ABRV_IFACETYPE, name);
+               dotypedef(&dwtypes, name, die);
                newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
                nfields = decodetype_ifacemethodcount(gotype);
                if (nfields == 0)
@@ -895,12 +974,14 @@ defgotype(Sym *gotype)
 
        case KindPtr:
                die = newdie(&dwtypes, DW_ABRV_PTRTYPE, name);
+               dotypedef(&dwtypes, name, die);
                s = decodetype_ptrelem(gotype);
                newrefattr(die, DW_AT_type, defgotype(s));
                break;
 
        case KindSlice:
                die = newdie(&dwtypes, DW_ABRV_SLICETYPE, name);
+               dotypedef(&dwtypes, name, die);
                newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
                s = decodetype_arrayelem(gotype);
                newrefattr(die, DW_AT_internal_elem_type, defgotype(s));
@@ -913,6 +994,7 @@ defgotype(Sym *gotype)
 
        case KindStruct:
                die = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, name);
+               dotypedef(&dwtypes, name, die);
                newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
                nfields = decodetype_structfieldcount(gotype);
                for (i = 0; i < nfields; i++) {
@@ -998,7 +1080,7 @@ synthesizestringtypes(DWDie* die)
 {
        DWDie *prototype;
 
-       prototype = defgotype(lookup_or_diag("type.runtime._string"));
+       prototype = walktypedef(defgotype(lookup_or_diag("type.runtime._string")));
        if (prototype == nil)
                return;
 
@@ -1014,7 +1096,7 @@ synthesizeslicetypes(DWDie *die)
 {
        DWDie *prototype, *elem;
 
-       prototype = defgotype(lookup_or_diag("type.runtime.slice"));
+       prototype = walktypedef(defgotype(lookup_or_diag("type.runtime.slice")));
        if (prototype == nil)
                return;
 
@@ -1082,9 +1164,9 @@ synthesizechantypes(DWDie *die)
        DWAttr *a;
        int elemsize, sudogsize;
 
-       sudog = defgotype(lookup_or_diag("type.runtime.sudog"));
-       waitq = defgotype(lookup_or_diag("type.runtime.waitq"));
-       hchan = defgotype(lookup_or_diag("type.runtime.hchan"));
+       sudog = walktypedef(defgotype(lookup_or_diag("type.runtime.sudog")));
+       waitq = walktypedef(defgotype(lookup_or_diag("type.runtime.waitq")));
+       hchan = walktypedef(defgotype(lookup_or_diag("type.runtime.hchan")));
        if (sudog == nil || waitq == nil || hchan == nil)
                return;
 
@@ -1153,7 +1235,7 @@ defdwsymb(Sym* sym, char *s, int t, vlong v, vlong size, int ver, Sym *gotype)
        case 'D':
        case 'B':
                dv = newdie(&dwglobals, DW_ABRV_VARIABLE, s);
-               newabslocexprattr(dv, v);
+               newabslocexprattr(dv, v, sym);
                if (ver == 0)
                        newattr(dv, DW_AT_external, DW_CLS_FLAG, 1, 0);
                // fallthrough
@@ -1514,12 +1596,12 @@ mkvarname(char* name, int da)
 
 // flush previous compilation unit.
 static void
-flushunit(DWDie *dwinfo, vlong pc, vlong unitstart, int32 header_length)
+flushunit(DWDie *dwinfo, vlong pc, Sym *pcsym, vlong unitstart, int32 header_length)
 {
        vlong here;
 
        if (dwinfo != nil && pc != 0) {
-               newattr(dwinfo, DW_AT_high_pc, DW_CLS_ADDRESS, pc+1, 0);
+               newattr(dwinfo, DW_AT_high_pc, DW_CLS_ADDRESS, pc+1, (char*)pcsym);
        }
 
        if (unitstart >= 0) {
@@ -1530,7 +1612,7 @@ flushunit(DWDie *dwinfo, vlong pc, vlong unitstart, int32 header_length)
                here = cpos();
                cseek(unitstart);
                LPUT(here - unitstart - sizeof(int32));  // unit_length
-               WPUT(3);  // dwarf version
+               WPUT(2);  // dwarf version
                LPUT(header_length); // header length starting here
                cseek(here);
        }
@@ -1540,7 +1622,7 @@ static void
 writelines(void)
 {
        Prog *q;
-       Sym *s;
+       Sym *s, *epcs;
        Auto *a;
        vlong unitstart, headerend, offs;
        vlong pc, epc, lc, llc, lline;
@@ -1555,6 +1637,7 @@ writelines(void)
        headerend = -1;
        pc = 0;
        epc = 0;
+       epcs = S;
        lc = 1;
        llc = 1;
        currfile = -1;
@@ -1570,7 +1653,7 @@ writelines(void)
                // we're entering a new compilation unit
 
                if (inithist(s->autom)) {
-                       flushunit(dwinfo, epc, unitstart, headerend - unitstart - 10);
+                       flushunit(dwinfo, epc, epcs, unitstart, headerend - unitstart - 10);
                        unitstart = cpos();
 
                        if(debug['v'] > 1) {
@@ -1587,12 +1670,12 @@ writelines(void)
                        dwinfo = newdie(&dwroot, DW_ABRV_COMPUNIT, estrdup(histfile[1]));
                        newattr(dwinfo, DW_AT_language, DW_CLS_CONSTANT,lang, 0);
                        newattr(dwinfo, DW_AT_stmt_list, DW_CLS_PTR, unitstart - lineo, 0);
-                       newattr(dwinfo, DW_AT_low_pc, DW_CLS_ADDRESS, s->text->pc, 0);
+                       newattr(dwinfo, DW_AT_low_pc, DW_CLS_ADDRESS, s->text->pc, (char*)s);
 
                        // Write .debug_line Line Number Program Header (sec 6.2.4)
                        // Fields marked with (*) must be changed for 64-bit dwarf
                        LPUT(0);   // unit_length (*), will be filled in by flushunit.
-                       WPUT(3);   // dwarf version (appendix F)
+                       WPUT(2);   // dwarf version (appendix F)
                        LPUT(0);   // header_length (*), filled in by flushunit.
                        // cpos == unitstart + 4 + 2 + 4
                        cput(1);   // minimum_instruction_length
@@ -1616,6 +1699,7 @@ writelines(void)
 
                        pc = s->text->pc;
                        epc = pc;
+                       epcs = s;
                        currfile = 1;
                        lc = 1;
                        llc = 1;
@@ -1634,9 +1718,9 @@ writelines(void)
                }
 
                dwfunc = newdie(dwinfo, DW_ABRV_FUNCTION, s->name);
-               newattr(dwfunc, DW_AT_low_pc, DW_CLS_ADDRESS, s->value, 0);
+               newattr(dwfunc, DW_AT_low_pc, DW_CLS_ADDRESS, s->value, (char*)s);
                epc = s->value + s->size;
-               newattr(dwfunc, DW_AT_high_pc, DW_CLS_ADDRESS, epc, 0);
+               newattr(dwfunc, DW_AT_high_pc, DW_CLS_ADDRESS, epc, (char*)s);
                if (s->version == 0)
                        newattr(dwfunc, DW_AT_external, DW_CLS_FLAG, 1, 0);
 
@@ -1718,7 +1802,7 @@ writelines(void)
                dwfunc->hash = nil;
        }
 
-       flushunit(dwinfo, epc, unitstart, headerend - unitstart - 10);
+       flushunit(dwinfo, epc, epcs, unitstart, headerend - unitstart - 10);
        linesize = cpos() - lineo;
 }
 
@@ -1842,6 +1926,9 @@ writeinfo(void)
        vlong unitstart, here;
 
        fwdcount = 0;
+       if (dsym == S)
+               dsym = lookup(".dwarfinfo", 0);
+       dsym->nr = 0;
 
        for (compunit = dwroot.child; compunit; compunit = compunit->link) {
                unitstart = cpos();
@@ -1850,7 +1937,7 @@ writeinfo(void)
                // Fields marked with (*) must be changed for 64-bit dwarf
                // This must match COMPUNITHEADERSIZE above.
                LPUT(0);        // unit_length (*), will be filled in later.
-               WPUT(3);        // dwarf version (appendix F)
+               WPUT(2);        // dwarf version (appendix F)
                LPUT(0);        // debug_abbrev_offset (*)
                cput(PtrSize);  // address_size
 
@@ -1990,6 +2077,27 @@ align(vlong size)
                strnput("", rnd(size, PEFILEALIGN) - size);
 }
 
+static vlong
+writeinforeloc(void)
+{
+       int i;
+       vlong start;
+       Reloc *r;
+       
+       start = cpos();
+       for(r = dsym->r; r < dsym->r+dsym->nr; r++) {
+               if(iself)
+                       i = elfreloc1(r, r->off);
+               else if(HEADTYPE == Hdarwin)
+                       i = machoreloc1(r, r->off);
+               else
+                       i = -1;
+               if(i < 0)
+                       diag("unsupported obj reloc %d/%d to %s", r->type, r->siz, r->sym->name);
+       }
+       return start;
+}
+
 /*
  * This is the main entry point for generating dwarf.  After emitting
  * the mandatory debug_abbrev section, it calls writelines() to set up
@@ -2090,6 +2198,10 @@ dwarfemitdebugsections(void)
        gdbscripto = writegdbscript();
        gdbscriptsize = cpos() - gdbscripto;
        align(gdbscriptsize);
+       
+       inforeloco = writeinforeloc();
+       inforelocsize = cpos() - inforeloco;
+       align(inforelocsize);
 }
 
 /*
@@ -2249,6 +2361,8 @@ dwarfaddmachoheaders(void)
        msect = newMachoSect(ms, "__debug_info", "__DWARF");
        msect->off = infoo;
        msect->size = infosize;
+       msect->reloc = inforeloco;
+       msect->nreloc = inforelocsize / 8;
        ms->filesize += msect->size;
 
        if (pubnamessize > 0) {