]> Cypherpunks repositories - gostls13.git/commitdiff
ld: add .gcdata and .gcbss sections
authorJan Ziak <0xe2.0x9a.0x9b@gmail.com>
Thu, 13 Sep 2012 19:59:34 +0000 (15:59 -0400)
committerRuss Cox <rsc@golang.org>
Thu, 13 Sep 2012 19:59:34 +0000 (15:59 -0400)
R=rsc
CC=golang-dev
https://golang.org/cl/6281048

src/cmd/5l/asm.c
src/cmd/6l/asm.c
src/cmd/8l/asm.c
src/cmd/gc/subr.c
src/cmd/ld/data.c
src/cmd/ld/decodesym.c [new file with mode: 0644]
src/cmd/ld/dwarf.c
src/cmd/ld/lib.h
src/cmd/ld/symtab.c

index 3c5a9a770114afdfaddeb06b47fd6485897f992f..108722979013ced6e6babde95e1767fe37007da9 100644 (file)
@@ -505,6 +505,8 @@ doelf(void)
        if(HEADTYPE == Hnetbsd)
                elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
        addstring(shstrtab, ".rodata");
+       addstring(shstrtab, ".gcdata");
+       addstring(shstrtab, ".gcbss");
        addstring(shstrtab, ".gosymtab");
        addstring(shstrtab, ".gopclntab");
        if(!debug['s']) {
@@ -661,7 +663,7 @@ asmb(void)
        cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
        codeblk(sect->vaddr, sect->len);
 
-       /* output read-only data in text segment (rodata, gosymtab and pclntab) */
+       /* output read-only data in text segment (rodata, gosymtab, pclntab, ...) */
        for(sect = sect->next; sect != nil; sect = sect->next) {
                cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
                datblk(sect->vaddr, sect->len);
@@ -2274,6 +2276,8 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
                        case SNOPTRDATA:
                        case SSYMTAB:
                        case SPCLNTAB:
+                       case SGCDATA:
+                       case SGCBSS:
                                if(!s->reachable)
                                        continue;
                                put(s, s->name, 'D', s->value, s->size, s->version, s->gotype);
index a9901c737480e0fa989cee0b2d0eb485f2c71f58..3b7feeca431000b5aa9c77c5c98b548976f24980 100644 (file)
@@ -579,6 +579,8 @@ doelf(void)
                elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
        addstring(shstrtab, ".elfdata");
        addstring(shstrtab, ".rodata");
+       addstring(shstrtab, ".gcdata");
+       addstring(shstrtab, ".gcbss");
        addstring(shstrtab, ".gosymtab");
        addstring(shstrtab, ".gopclntab");
        if(!debug['s']) {
@@ -732,7 +734,7 @@ asmb(void)
        cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
        codeblk(sect->vaddr, sect->len);
 
-       /* output read-only data in text segment (rodata, gosymtab and pclntab) */
+       /* output read-only data in text segment (rodata, gosymtab, pclntab, ...) */
        for(sect = sect->next; sect != nil; sect = sect->next) {
                cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
                datblk(sect->vaddr, sect->len);
@@ -1200,6 +1202,8 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
                case SSTRING:
                case SGOSTRING:
                case SWINDOWS:
+               case SGCDATA:
+               case SGCBSS:
                        if(!s->reachable)
                                continue;
                        put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
index 99c9b238b128abd333212f01d1f650763448ba5a..87888d2bb249470caae8eb3267a20fc7af0016de 100644 (file)
@@ -536,6 +536,8 @@ doelf(void)
                elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
        addstring(shstrtab, ".elfdata");
        addstring(shstrtab, ".rodata");
+       addstring(shstrtab, ".gcdata");
+       addstring(shstrtab, ".gcbss");
        addstring(shstrtab, ".gosymtab");
        addstring(shstrtab, ".gopclntab");
        if(!debug['s']) {
@@ -684,7 +686,7 @@ asmb(void)
        cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
        codeblk(sect->vaddr, sect->len);
 
-       /* output read-only data in text segment (rodata, gosymtab and pclntab) */
+       /* output read-only data in text segment (rodata, gosymtab, pclntab, ...) */
        for(sect = sect->next; sect != nil; sect = sect->next) {
                cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
                datblk(sect->vaddr, sect->len);
@@ -1266,6 +1268,8 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
                        case SNOPTRDATA:
                        case SSYMTAB:
                        case SPCLNTAB:
+                       case SGCDATA:
+                       case SGCBSS:
                                if(!s->reachable)
                                        continue;
                                put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
index c04c1edc7100100dd71ed053b3eef1b421951413..383340f323160ff7f8caf82aeb820b393056d43e 100644 (file)
@@ -3515,7 +3515,6 @@ ngotype(Node *n)
 {
        if(n->sym != S && n->realtype != T)
        if(strncmp(n->sym->name, "autotmp_", 8) != 0)
-       if(strncmp(n->sym->name, "statictmp_", 8) != 0)
                return typename(n->realtype)->left->sym;
 
        return S;
index 865f282114e489dc3d94512756a9ee0eaddf78fc..e1d380b317fb61d86726a72ceca2489c159dc687 100644 (file)
@@ -34,6 +34,7 @@
 #include       "../ld/lib.h"
 #include       "../ld/elf.h"
 #include       "../ld/pe.h"
+#include       "../../pkg/runtime/mgc0.h"
 
 void   dynreloc(void);
 static vlong addaddrplus4(Sym *s, Sym *t, int32 add);
@@ -628,41 +629,51 @@ addstring(Sym *s, char *str)
 }
 
 vlong
-adduintxx(Sym *s, uint64 v, int wid)
+setuintxx(Sym *s, vlong off, uint64 v, int wid)
 {
-       int32 i, r, fl;
+       int32 i, fl;
        vlong o;
        uchar *cast;
 
        if(s->type == 0)
                s->type = SDATA;
        s->reachable = 1;
-       r = s->size;
-       s->size += wid;
-       symgrow(s, s->size);
-       assert(r+wid <= s->size);
+       if(s->size < off+wid) {
+               s->size = off+wid;
+               symgrow(s, s->size);
+       }
        fl = v;
        cast = (uchar*)&fl;
        switch(wid) {
        case 1:
-               s->p[r] = cast[inuxi1[0]];
+               s->p[off] = cast[inuxi1[0]];
                break;
        case 2:
                for(i=0; i<2; i++)
-                       s->p[r+i] = cast[inuxi2[i]];
+                       s->p[off+i] = cast[inuxi2[i]];
                break;
        case 4:
                for(i=0; i<4; i++)
-                       s->p[r+i] = cast[inuxi4[i]];
+                       s->p[off+i] = cast[inuxi4[i]];
                break;
        case 8:
                o = v;
                cast = (uchar*)&o;
                for(i=0; i<8; i++)
-                       s->p[r+i] = cast[inuxi8[i]];
+                       s->p[off+i] = cast[inuxi8[i]];
                break;
        }
-       return r;
+       return off;
+}
+
+vlong
+adduintxx(Sym *s, uint64 v, int wid)
+{
+       int32 off;
+
+       off = s->size;
+       setuintxx(s, off, v, wid);
+       return off;
 }
 
 vlong
@@ -689,6 +700,30 @@ adduint64(Sym *s, uint64 v)
        return adduintxx(s, v, 8);
 }
 
+void
+setuint8(Sym *s, vlong r, uint8 v)
+{
+       setuintxx(s, r, v, 1);
+}
+
+void
+setuint16(Sym *s, vlong r, uint16 v)
+{
+       setuintxx(s, r, v, 2);
+}
+
+void
+setuint32(Sym *s, vlong r, uint32 v)
+{
+       setuintxx(s, r, v, 4);
+}
+
+void
+setuint64(Sym *s, vlong r, uint64 v)
+{
+       setuintxx(s, r, v, 8);
+}
+
 vlong
 addaddrplus(Sym *s, Sym *t, int32 add)
 {
@@ -793,17 +828,87 @@ dosymtype(void)
        }
 }
 
+static int32
+alignsymsize(int32 s)
+{
+       if(s >= PtrSize)
+               s = rnd(s, PtrSize);
+       else if(s > 2)
+               s = rnd(s, 4);
+       return s;
+}
+
+static int32
+aligndatsize(int32 datsize, Sym *s)
+{
+       int32 t;
+
+       if(s->align != 0) {
+               datsize = rnd(datsize, s->align);
+       } else {
+               t = alignsymsize(s->size);
+               if(t & 1) {
+                       ;
+               } else if(t & 2)
+                       datsize = rnd(datsize, 2);
+               else if(t & 4)
+                       datsize = rnd(datsize, 4);
+               else
+                       datsize = rnd(datsize, 8);
+       }
+       return datsize;
+}
+
+static void
+gcaddsym(Sym *gc, Sym *s, int32 off)
+{
+       int32 a;
+       Sym *gotype;
+
+       if(s->size < PtrSize)
+               return;
+       if(strcmp(s->name, ".string") == 0)
+               return;
+
+       gotype = s->gotype;
+       if(gotype != nil) {
+               //print("gcaddsym:    %s    %d    %s\n", s->name, s->size, gotype->name);
+               adduintxx(gc, GC_CALL, PtrSize);
+               adduintxx(gc, off, PtrSize);
+               addaddrplus(gc, decodetype_gc(gotype), 1*PtrSize);
+       } else {
+               //print("gcaddsym:    %s    %d    <unknown type>\n", s->name, s->size);
+               for(a = -off&(PtrSize-1); a+PtrSize<=s->size; a+=PtrSize) {
+                       adduintxx(gc, GC_APTR, PtrSize);
+                       adduintxx(gc, off+a, PtrSize);
+               }
+       }
+}
+
 void
 dodata(void)
 {
        int32 t, datsize;
-       Section *sect, *noptr;
+       Section *sect;
        Sym *s, *last, **l;
+       Sym *gcdata1, *gcbss1;
 
        if(debug['v'])
                Bprint(&bso, "%5.2f dodata\n", cputime());
        Bflush(&bso);
 
+       // define garbage collection symbols
+       gcdata1 = lookup("gcdata1", 0);
+       gcdata1->type = SGCDATA;
+       gcdata1->reachable = 1;
+       gcbss1 = lookup("gcbss1", 0);
+       gcbss1->type = SGCBSS;
+       gcbss1->reachable = 1;
+
+       // size of .data and .bss section. the zero value is later replaced by the actual size of the section.
+       adduintxx(gcdata1, 0, PtrSize);
+       adduintxx(gcbss1, 0, PtrSize);
+
        last = nil;
        datap = nil;
 
@@ -847,16 +952,102 @@ dodata(void)
        datap = datsort(datap);
 
        /*
-        * allocate data sections.  list is sorted by type,
+        * allocate sections.  list is sorted by type,
         * so we can just walk it for each piece we want to emit.
+        * segdata is processed before segtext, because we need
+        * to see all symbols in the .data and .bss sections in order
+        * to generate garbage collection information.
         */
 
+       /* begin segdata */
+
+       /* skip symbols belonging to segtext */
+       s = datap;
+       for(; s != nil && s->type < SELFSECT; s = s->next);
+
+       /* writable ELF sections */
+       datsize = 0;
+       for(; s != nil && s->type < SNOPTRDATA; s = s->next) {
+               sect = addsection(&segdata, s->name, 06);
+               if(s->align != 0)
+                       datsize = rnd(datsize, s->align);
+               sect->vaddr = datsize;
+               s->type = SDATA;
+               s->value = datsize;
+               datsize += rnd(s->size, PtrSize);
+               sect->len = datsize - sect->vaddr;
+       }
+
+       /* pointer-free data */
+       sect = addsection(&segdata, ".noptrdata", 06);
+       sect->vaddr = datsize;
+       for(; s != nil && s->type < SDATA; s = s->next) {
+               s->type = SDATA;
+               t = alignsymsize(s->size);
+               datsize = aligndatsize(datsize, s);
+               s->value = datsize;
+               datsize += t;
+       }
+       sect->len = datsize - sect->vaddr;
+       datsize = rnd(datsize, PtrSize);
+
+       /* data */
+       sect = addsection(&segdata, ".data", 06);
+       sect->vaddr = datsize;
+       for(; s != nil && s->type < SBSS; s = s->next) {
+               s->type = SDATA;
+               t = alignsymsize(s->size);
+               datsize = aligndatsize(datsize, s);
+               s->value = datsize;
+               gcaddsym(gcdata1, s, datsize - sect->vaddr);  // gc
+               datsize += t;
+       }
+       sect->len = datsize - sect->vaddr;
+       datsize = rnd(datsize, PtrSize);
+
+       adduintxx(gcdata1, GC_END, PtrSize);
+       setuintxx(gcdata1, 0, sect->len, PtrSize);
+
+       /* bss */
+       sect = addsection(&segdata, ".bss", 06);
+       sect->vaddr = datsize;
+       for(; s != nil && s->type < SNOPTRBSS; s = s->next) {
+               t = alignsymsize(s->size);
+               datsize = aligndatsize(datsize, s);
+               s->value = datsize;
+               gcaddsym(gcbss1, s, datsize - sect->vaddr);  // gc
+               datsize += t;
+       }
+       sect->len = datsize - sect->vaddr;
+       datsize = rnd(datsize, PtrSize);
+
+       adduintxx(gcbss1, GC_END, PtrSize);
+       setuintxx(gcbss1, 0, sect->len, PtrSize);
+
+       /* pointer-free bss */
+       sect = addsection(&segdata, ".noptrbss", 06);
+       sect->vaddr = datsize;
+       for(; s != nil; s = s->next) {
+               if(s->type > SNOPTRBSS) {
+                       cursym = s;
+                       diag("unexpected symbol type %d", s->type);
+               }
+               t = alignsymsize(s->size);
+               datsize = aligndatsize(datsize, s);
+               s->value = datsize;
+               datsize += t;
+       }
+       sect->len = datsize - sect->vaddr;
+       datsize = rnd(datsize, PtrSize);
+
+       /* we finished segdata, begin segtext */
+
        /* read-only data */
        sect = addsection(&segtext, ".rodata", 04);
        sect->vaddr = 0;
        datsize = 0;
        s = datap;
-       for(; s != nil && s->type < SSYMTAB; s = s->next) {
+       for(; s != nil && s->type < SGCDATA; s = s->next) {
                if(s->align != 0)
                        datsize = rnd(datsize, s->align);
                s->type = SRODATA;
@@ -865,6 +1056,28 @@ dodata(void)
        }
        sect->len = datsize - sect->vaddr;
 
+       /* gcdata */
+       sect = addsection(&segtext, ".gcdata", 04);
+       sect->vaddr = datsize;
+       for(; s != nil && s->type == SGCDATA; s = s->next) {
+               s->type = SRODATA;
+               s->value = datsize;
+               datsize += s->size;
+       }
+       sect->len = datsize - sect->vaddr;
+       datsize = rnd(datsize, PtrSize);
+
+       /* gcbss */
+       sect = addsection(&segtext, ".gcbss", 04);
+       sect->vaddr = datsize;
+       for(; s != nil && s->type == SGCBSS; s = s->next) {
+               s->type = SRODATA;
+               s->value = datsize;
+               datsize += s->size;
+       }
+       sect->len = datsize - sect->vaddr;
+       datsize = rnd(datsize, PtrSize);
+
        /* gosymtab */
        sect = addsection(&segtext, ".gosymtab", 04);
        sect->vaddr = datsize;
@@ -898,96 +1111,6 @@ dodata(void)
                datsize += rnd(s->size, PtrSize);
                sect->len = datsize - sect->vaddr;
        }
-
-       /* writable ELF sections */
-       datsize = 0;
-       for(; s != nil && s->type < SNOPTRDATA; s = s->next) {
-               sect = addsection(&segdata, s->name, 06);
-               if(s->align != 0)
-                       datsize = rnd(datsize, s->align);
-               sect->vaddr = datsize;
-               s->type = SDATA;
-               s->value = datsize;
-               datsize += rnd(s->size, PtrSize);
-               sect->len = datsize - sect->vaddr;
-       }
-       
-       /* pointer-free data, then data */
-       sect = addsection(&segdata, ".noptrdata", 06);
-       sect->vaddr = datsize;
-       noptr = sect;
-       for(; ; s = s->next) {
-               if((s == nil || s->type >= SDATA) && sect == noptr) {
-                       // finish noptrdata, start data
-                       datsize = rnd(datsize, 8);
-                       sect->len = datsize - sect->vaddr;
-                       sect = addsection(&segdata, ".data", 06);
-                       sect->vaddr = datsize;
-               }
-               if(s == nil || s->type >= SBSS) {
-                       // finish data
-                       sect->len = datsize - sect->vaddr;
-                       break;
-               }
-               s->type = SDATA;
-               t = s->size;
-               if(t >= PtrSize)
-                       t = rnd(t, PtrSize);
-               else if(t > 2)
-                       t = rnd(t, 4);
-               if(s->align != 0)
-                       datsize = rnd(datsize, s->align);
-               else if(t & 1) {
-                       ;
-               } else if(t & 2)
-                       datsize = rnd(datsize, 2);
-               else if(t & 4)
-                       datsize = rnd(datsize, 4);
-               else
-                       datsize = rnd(datsize, 8);
-               s->value = datsize;
-               datsize += t;
-       }
-
-       /* bss, then pointer-free bss */
-       noptr = nil;
-       sect = addsection(&segdata, ".bss", 06);
-       sect->vaddr = datsize;
-       for(; ; s = s->next) {
-               if((s == nil || s->type >= SNOPTRBSS) && noptr == nil) {
-                       // finish bss, start noptrbss
-                       datsize = rnd(datsize, 8);
-                       sect->len = datsize - sect->vaddr;
-                       sect = addsection(&segdata, ".noptrbss", 06);
-                       sect->vaddr = datsize;
-                       noptr = sect;
-               }
-               if(s == nil) {
-                       sect->len = datsize - sect->vaddr;
-                       break;
-               }
-               if(s->type > SNOPTRBSS) {
-                       cursym = s;
-                       diag("unexpected symbol type %d", s->type);
-               }
-               t = s->size;
-               if(t >= PtrSize)
-                       t = rnd(t, PtrSize);
-               else if(t > 2)
-                       t = rnd(t, 4);
-               if(s->align != 0)
-                       datsize = rnd(datsize, s->align);
-               else if(t & 1) {
-                       ;
-               } else if(t & 2)
-                       datsize = rnd(datsize, 2);
-               else if(t & 4)
-                       datsize = rnd(datsize, 4);
-               else
-                       datsize = rnd(datsize, 8);
-               s->value = datsize;
-               datsize += t;
-       }
 }
 
 // assign addresses to text
@@ -1038,6 +1161,7 @@ void
 address(void)
 {
        Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss;
+       Section *gcdata, *gcbss;
        Sym *sym, *sub;
        uvlong va;
 
@@ -1084,7 +1208,9 @@ address(void)
 
        text = segtext.sect;
        rodata = text->next;
-       symtab = rodata->next;
+       gcdata = rodata->next;
+       gcbss = gcdata->next;
+       symtab = gcbss->next;
        pclntab = symtab->next;
 
        for(sym = datap; sym != nil; sym = sym->next) {
@@ -1101,6 +1227,10 @@ address(void)
        xdefine("etext", STEXT, text->vaddr + text->len);
        xdefine("rodata", SRODATA, rodata->vaddr);
        xdefine("erodata", SRODATA, rodata->vaddr + rodata->len);
+       xdefine("gcdata", SGCDATA, gcdata->vaddr);
+       xdefine("egcdata", SGCDATA, gcdata->vaddr + gcdata->len);
+       xdefine("gcbss", SGCBSS, gcbss->vaddr);
+       xdefine("egcbss", SGCBSS, gcbss->vaddr + gcbss->len);
        xdefine("symtab", SRODATA, symtab->vaddr);
        xdefine("esymtab", SRODATA, symtab->vaddr + symtab->len);
        xdefine("pclntab", SRODATA, pclntab->vaddr);
diff --git a/src/cmd/ld/decodesym.c b/src/cmd/ld/decodesym.c
new file mode 100644 (file)
index 0000000..f3f91c3
--- /dev/null
@@ -0,0 +1,215 @@
+// Copyright 2012 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       "l.h"
+#include       "lib.h"
+#include       "../../pkg/runtime/typekind.h"
+
+// Decoding the type.* symbols.         This has to be in sync with
+// ../../pkg/runtime/type.go, or more specificaly, with what
+// ../gc/reflect.c stuffs in these.
+
+static Reloc*
+decode_reloc(Sym *s, int32 off)
+{
+       int i;
+
+       for (i = 0; i < s->nr; i++)
+               if (s->r[i].off == off)
+                       return s->r + i;
+       return nil;
+}
+
+static Sym*
+decode_reloc_sym(Sym *s, int32 off)
+{
+       Reloc *r;
+
+       r = decode_reloc(s,off);
+       if (r == nil)
+               return nil;
+       return r->sym;
+}
+
+static uvlong
+decode_inuxi(uchar* p, int sz)
+{
+       uint64 v;
+       uint32 l;
+       uchar *cast, *inuxi;
+       int i;
+
+       v = l = 0;
+       cast = nil;
+       inuxi = nil;
+       switch (sz) {
+       case 2:
+               cast = (uchar*)&l;
+               inuxi = inuxi2;
+               break;
+       case 4:
+               cast = (uchar*)&l;
+               inuxi = inuxi4;
+               break;
+       case 8:
+               cast = (uchar*)&v;
+               inuxi = inuxi8;
+               break;
+       default:
+               diag("dwarf: decode inuxi %d", sz);
+               errorexit();
+       }
+       for (i = 0; i < sz; i++)
+               cast[inuxi[i]] = p[i];
+       if (sz == 8)
+               return v;
+       return l;
+}
+
+// Type.commonType.kind
+uint8
+decodetype_kind(Sym *s)
+{
+       return s->p[3*PtrSize + 7] & ~KindNoPointers;   //  0x13 / 0x1f
+}
+
+// Type.commonType.size
+vlong
+decodetype_size(Sym *s)
+{
+       return decode_inuxi(s->p + 2*PtrSize, PtrSize);  // 0x8 / 0x10
+}
+
+// Type.commonType.gc
+Sym*
+decodetype_gc(Sym *s)
+{
+       return decode_reloc_sym(s, 3*PtrSize + 8 + 1*PtrSize);
+}
+
+// Type.ArrayType.elem and Type.SliceType.Elem
+Sym*
+decodetype_arrayelem(Sym *s)
+{
+       return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30
+}
+
+vlong
+decodetype_arraylen(Sym *s)
+{
+       return decode_inuxi(s->p + CommonSize+PtrSize, PtrSize);
+}
+
+// Type.PtrType.elem
+Sym*
+decodetype_ptrelem(Sym *s)
+{
+       return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30
+}
+
+// Type.MapType.key, elem
+Sym*
+decodetype_mapkey(Sym *s)
+{
+       return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30
+}
+Sym*
+decodetype_mapvalue(Sym *s)
+{
+       return decode_reloc_sym(s, CommonSize+PtrSize); // 0x20 / 0x38
+}
+
+// Type.ChanType.elem
+Sym*
+decodetype_chanelem(Sym *s)
+{
+       return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30
+}
+
+// Type.FuncType.dotdotdot
+int
+decodetype_funcdotdotdot(Sym *s)
+{
+       return s->p[CommonSize];
+}
+
+// Type.FuncType.in.len
+int
+decodetype_funcincount(Sym *s)
+{
+       return decode_inuxi(s->p + CommonSize+2*PtrSize, 4);
+}
+
+int
+decodetype_funcoutcount(Sym *s)
+{
+       return decode_inuxi(s->p + CommonSize+3*PtrSize + 2*4, 4);
+}
+
+Sym*
+decodetype_funcintype(Sym *s, int i)
+{
+       Reloc *r;
+
+       r = decode_reloc(s, CommonSize + PtrSize);
+       if (r == nil)
+               return nil;
+       return decode_reloc_sym(r->sym, r->add + i * PtrSize);
+}
+
+Sym*
+decodetype_funcouttype(Sym *s, int i)
+{
+       Reloc *r;
+
+       r = decode_reloc(s, CommonSize + 2*PtrSize + 2*4);
+       if (r == nil)
+               return nil;
+       return decode_reloc_sym(r->sym, r->add + i * PtrSize);
+}
+
+// Type.StructType.fields.Slice::len
+int
+decodetype_structfieldcount(Sym *s)
+{
+       return decode_inuxi(s->p + CommonSize + PtrSize, 4);
+}
+
+enum {
+       StructFieldSize = 5*PtrSize
+};
+// Type.StructType.fields[]-> name, typ and offset.
+char*
+decodetype_structfieldname(Sym *s, int i)
+{
+       Reloc *r;
+
+       // go.string."foo"  0x28 / 0x40
+       s = decode_reloc_sym(s, CommonSize + PtrSize + 2*4 + i*StructFieldSize);
+       if (s == nil)                   // embedded structs have a nil name.
+               return nil;
+       r = decode_reloc(s, 0);         // s has a pointer to the string data at offset 0
+       if (r == nil)                   // shouldn't happen.
+               return nil;
+       return (char*) r->sym->p + r->add;      // the c-string
+}
+
+Sym*
+decodetype_structfieldtype(Sym *s, int i)
+{
+       return decode_reloc_sym(s, CommonSize + PtrSize + 2*4 + i*StructFieldSize + 2*PtrSize);
+}
+
+vlong
+decodetype_structfieldoffs(Sym *s, int i)
+{
+       return decode_inuxi(s->p + CommonSize + PtrSize + 2*4 + i*StructFieldSize + 4*PtrSize, 4);
+}
+
+// InterfaceTYpe.methods.len
+vlong
+decodetype_ifacemethodcount(Sym *s)
+{
+       return decode_inuxi(s->p + CommonSize + PtrSize, 4);
+}
index 9a78d9610d7be3fd61e57da994f9509f4adf0f60..2cf450eda92c6fb07eadd7fd725298f90c65c7f6 100644 (file)
@@ -19,6 +19,7 @@
 #include       "../ld/elf.h"
 #include       "../ld/macho.h"
 #include       "../ld/pe.h"
+#include       "../../pkg/runtime/typekind.h"
 
 /*
  * Offsets and sizes of the debug_* sections in the cout file.
@@ -740,241 +741,6 @@ newabslocexprattr(DWDie *die, vlong addr)
        memmove(die->attr->data, block, i);
 }
 
-// Decoding the type.* symbols.         This has to be in sync with
-// ../../pkg/runtime/type.go, or more specificaly, with what
-// ../gc/reflect.c stuffs in these.
-
-enum {
-       KindBool = 1,
-       KindInt,
-       KindInt8,
-       KindInt16,
-       KindInt32,
-       KindInt64,
-       KindUint,
-       KindUint8,
-       KindUint16,
-       KindUint32,
-       KindUint64,
-       KindUintptr,
-       KindFloat32,
-       KindFloat64,
-       KindComplex64,
-       KindComplex128,
-       KindArray,
-       KindChan,
-       KindFunc,
-       KindInterface,
-       KindMap,
-       KindPtr,
-       KindSlice,
-       KindString,
-       KindStruct,
-       KindUnsafePointer,
-
-       KindNoPointers = 1<<7,
-
-       // size of Type interface header + CommonType structure.
-       CommonSize = 2*PtrSize+ 6*PtrSize + 8,
-};
-
-static Reloc*
-decode_reloc(Sym *s, int32 off)
-{
-       int i;
-
-       for (i = 0; i < s->nr; i++)
-               if (s->r[i].off == off)
-                       return s->r + i;
-       return nil;
-}
-
-static Sym*
-decode_reloc_sym(Sym *s, int32 off)
-{
-       Reloc *r;
-
-       r = decode_reloc(s,off);
-       if (r == nil)
-               return nil;
-       return r->sym;
-}
-
-static uvlong
-decode_inuxi(uchar* p, int sz)
-{
-       uint64 v;
-       uint32 l;
-       uchar *cast, *inuxi;
-       int i;
-
-       v = l = 0;
-       cast = nil;
-       inuxi = nil;
-       switch (sz) {
-       case 2:
-               cast = (uchar*)&l;
-               inuxi = inuxi2;
-               break;
-       case 4:
-               cast = (uchar*)&l;
-               inuxi = inuxi4;
-               break;
-       case 8:
-               cast = (uchar*)&v;
-               inuxi = inuxi8;
-               break;
-       default:
-               diag("dwarf: decode inuxi %d", sz);
-               errorexit();
-       }
-       for (i = 0; i < sz; i++)
-               cast[inuxi[i]] = p[i];
-       if (sz == 8)
-               return v;
-       return l;
-}
-
-// Type.commonType.kind
-static uint8
-decodetype_kind(Sym *s)
-{
-       return s->p[3*PtrSize + 7] & ~KindNoPointers;   //  0x13 / 0x1f
-}
-
-// Type.commonType.size
-static vlong
-decodetype_size(Sym *s)
-{
-       return decode_inuxi(s->p + 2*PtrSize, PtrSize);  // 0x8 / 0x10
-}
-
-// Type.ArrayType.elem and Type.SliceType.Elem
-static Sym*
-decodetype_arrayelem(Sym *s)
-{
-       return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30
-}
-
-static vlong
-decodetype_arraylen(Sym *s)
-{
-       return decode_inuxi(s->p + CommonSize+PtrSize, PtrSize);
-}
-
-// Type.PtrType.elem
-static Sym*
-decodetype_ptrelem(Sym *s)
-{
-       return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30
-}
-
-// Type.MapType.key, elem
-static Sym*
-decodetype_mapkey(Sym *s)
-{
-       return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30
-}
-static Sym*
-decodetype_mapvalue(Sym *s)
-{
-       return decode_reloc_sym(s, CommonSize+PtrSize); // 0x20 / 0x38
-}
-
-// Type.ChanType.elem
-static Sym*
-decodetype_chanelem(Sym *s)
-{
-       return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30
-}
-
-// Type.FuncType.dotdotdot
-static int
-decodetype_funcdotdotdot(Sym *s)
-{
-       return s->p[CommonSize];
-}
-
-// Type.FuncType.in.len
-static int
-decodetype_funcincount(Sym *s)
-{
-       return decode_inuxi(s->p + CommonSize+2*PtrSize, 4);
-}
-
-static int
-decodetype_funcoutcount(Sym *s)
-{
-       return decode_inuxi(s->p + CommonSize+3*PtrSize + 2*4, 4);
-}
-
-static Sym*
-decodetype_funcintype(Sym *s, int i)
-{
-       Reloc *r;
-
-       r = decode_reloc(s, CommonSize + PtrSize);
-       if (r == nil)
-               return nil;
-       return decode_reloc_sym(r->sym, r->add + i * PtrSize);
-}
-
-static Sym*
-decodetype_funcouttype(Sym *s, int i)
-{
-       Reloc *r;
-
-       r = decode_reloc(s, CommonSize + 2*PtrSize + 2*4);
-       if (r == nil)
-               return nil;
-       return decode_reloc_sym(r->sym, r->add + i * PtrSize);
-}
-
-// Type.StructType.fields.Slice::len
-static int
-decodetype_structfieldcount(Sym *s)
-{
-       return decode_inuxi(s->p + CommonSize + PtrSize, 4);
-}
-
-enum {
-       StructFieldSize = 5*PtrSize
-};
-// Type.StructType.fields[]-> name, typ and offset.
-static char*
-decodetype_structfieldname(Sym *s, int i)
-{
-       Reloc *r;
-
-       // go.string."foo"  0x28 / 0x40
-       s = decode_reloc_sym(s, CommonSize + PtrSize + 2*4 + i*StructFieldSize);
-       if (s == nil)                   // embedded structs have a nil name.
-               return nil;
-       r = decode_reloc(s, 0);         // s has a pointer to the string data at offset 0
-       if (r == nil)                   // shouldn't happen.
-               return nil;
-       return (char*) r->sym->p + r->add;      // the c-string
-}
-
-static Sym*
-decodetype_structfieldtype(Sym *s, int i)
-{
-       return decode_reloc_sym(s, CommonSize + PtrSize + 2*4 + i*StructFieldSize + 2*PtrSize);
-}
-
-static vlong
-decodetype_structfieldoffs(Sym *s, int i)
-{
-       return decode_inuxi(s->p + CommonSize + PtrSize + 2*4 + i*StructFieldSize + 4*PtrSize, 4);
-}
-
-// InterfaceTYpe.methods.len
-static vlong
-decodetype_ifacemethodcount(Sym *s)
-{
-       return decode_inuxi(s->p + CommonSize + PtrSize, 4);
-}
-
 
 // Fake attributes for slices, maps and channel
 enum {
index 25c0b3709d7c2871732dee1e827158dfe2461da0..d322df5c6b4775c7938df291782ed78ea7c4dbe5 100644 (file)
@@ -39,6 +39,8 @@ enum
        SSTRING,
        SGOSTRING,
        SRODATA,
+       SGCDATA,
+       SGCBSS,
        SSYMTAB,
        SPCLNTAB,
        SELFROSECT,
@@ -186,14 +188,18 @@ void      savedata(Sym*, Prog*, char*);
 void   symgrow(Sym*, int32);
 void   addstrdata(char*, char*);
 vlong  addstring(Sym*, char*);
+vlong  adduint8(Sym*, uint8);
+vlong  adduint16(Sym*, uint16);
 vlong  adduint32(Sym*, uint32);
 vlong  adduint64(Sym*, uint64);
 vlong  addaddr(Sym*, Sym*);
 vlong  addaddrplus(Sym*, Sym*, int32);
 vlong  addpcrelplus(Sym*, Sym*, int32);
 vlong  addsize(Sym*, Sym*);
-vlong  adduint8(Sym*, uint8);
-vlong  adduint16(Sym*, uint16);
+void   setuint8(Sym*, vlong, uint8);
+void   setuint16(Sym*, vlong, uint16);
+void   setuint32(Sym*, vlong, uint32);
+void   setuint64(Sym*, vlong, uint64);
 void   asmsym(void);
 void   asmelfsym(void);
 void   asmplan9sym(void);
@@ -315,3 +321,23 @@ void       cseek(vlong);
 void   cwrite(void*, int);
 void   importcycles(void);
 int    Zconv(Fmt*);
+
+uint8  decodetype_kind(Sym*);
+vlong  decodetype_size(Sym*);
+Sym*   decodetype_gc(Sym*);
+Sym*   decodetype_arrayelem(Sym*);
+vlong  decodetype_arraylen(Sym*);
+Sym*   decodetype_ptrelem(Sym*);
+Sym*   decodetype_mapkey(Sym*);
+Sym*   decodetype_mapvalue(Sym*);
+Sym*   decodetype_chanelem(Sym*);
+int    decodetype_funcdotdotdot(Sym*);
+int    decodetype_funcincount(Sym*);
+int    decodetype_funcoutcount(Sym*);
+Sym*   decodetype_funcintype(Sym*, int);
+Sym*   decodetype_funcouttype(Sym*, int);
+int    decodetype_structfieldcount(Sym*);
+char*  decodetype_structfieldname(Sym*, int);
+Sym*   decodetype_structfieldtype(Sym*, int);
+vlong  decodetype_structfieldoffs(Sym*, int);
+vlong  decodetype_ifacemethodcount(Sym*);
index c43051a39210dfbf2b756ded5f83983e5d4bbe31..7513ff570df5471edd29c960921172466cbf9cff 100644 (file)
@@ -339,6 +339,10 @@ symtab(void)
        xdefine("etext", STEXT, 0);
        xdefine("rodata", SRODATA, 0);
        xdefine("erodata", SRODATA, 0);
+       xdefine("gcdata", SGCDATA, 0);
+       xdefine("egcdata", SGCDATA, 0);
+       xdefine("gcbss", SGCBSS, 0);
+       xdefine("egcbss", SGCBSS, 0);
        xdefine("noptrdata", SNOPTRDATA, 0);
        xdefine("enoptrdata", SNOPTRDATA, 0);
        xdefine("data", SDATA, 0);