]> Cypherpunks repositories - gostls13.git/commitdiff
8l: emit DWARF in ELF.
authorLuuk van Dijk <lvd@golang.org>
Mon, 30 Aug 2010 20:20:38 +0000 (22:20 +0200)
committerLuuk van Dijk <lvd@golang.org>
Mon, 30 Aug 2010 20:20:38 +0000 (22:20 +0200)
R=rsc, r, ken2
CC=golang-dev
https://golang.org/cl/2004046

src/cmd/6l/asm.c
src/cmd/6l/l.h
src/cmd/8l/Makefile
src/cmd/8l/asm.c
src/cmd/8l/l.h
src/cmd/8l/obj.c
src/cmd/ld/dwarf.c

index db11f14efb591cfe30eecff04d2922e1a80d6653..af615e693864e98efb8bd3562e4b6530acb58186 100644 (file)
@@ -641,8 +641,7 @@ asmb(void)
 
                         dwarfemitdebugsections();
                }
-       } else
-       if(dlm){
+       } else if(dlm){
                seek(cout, HEADR+textsize+datsize, 0);
                asmdyn();
                cflush();
index 9a77658c3da477a14ce1b15b622fa8c3039ec72f..a8428865a77a3e4a00260c3a430b72431ab232a8 100644 (file)
@@ -394,9 +394,9 @@ Prog*       brchain(Prog*);
 Prog*  brloop(Prog*);
 void   buildop(void);
 void   cflush(void);
-vlong   cpos(void);
 void   ckoff(Sym*, int32);
 Prog*  copyp(Prog*);
+vlong   cpos(void);
 double cputime(void);
 void   datblk(int32, int32);
 void   deadcode(void);
index 2b509b3613968f398441ffe59af95b5bfc54e937..49064ca6a65c5e3304aaa642113da7b9d8c81889 100644 (file)
@@ -9,8 +9,10 @@ TARG=8l
 
 OFILES=\
        asm.$O\
+       dwarf.$O\
        elf.$O\
        enam.$O\
+       go.$O\
        lib.$O\
        list.$O\
        macho.$O\
@@ -19,11 +21,12 @@ OFILES=\
        pass.$O\
        pe.$O\
        span.$O\
-       go.$O\
+
 
 HFILES=\
        l.h\
        ../8l/8.out.h\
+       ../ld/dwarf.h\
        ../ld/elf.h\
        ../ld/macho.h\
        ../ld/pe.h\
index a7f894aa281a61af1312ab7f3376f682f801e985..277fba37abb121c61d5b326adf8e6958ca3b649e 100644 (file)
@@ -31,6 +31,7 @@
 #include       "l.h"
 #include       "../ld/lib.h"
 #include       "../ld/elf.h"
+#include       "../ld/dwarf.h"
 #include       "../ld/macho.h"
 #include       "../ld/pe.h"
 
@@ -293,6 +294,7 @@ doelf(void)
                elfstr[ElfStrGosymcounts] = addstring(shstrtab, ".gosymcounts");
                elfstr[ElfStrGosymtab] = addstring(shstrtab, ".gosymtab");
                elfstr[ElfStrGopclntab] = addstring(shstrtab, ".gopclntab");
+                dwarfaddshstrings(shstrtab);
        }
        elfstr[ElfStrShstrtab] = addstring(shstrtab, ".shstrtab");
 
@@ -649,8 +651,13 @@ asmb(void)
                lputl(symsize);
                lputl(lcsize);
                cflush();
-       }
-       else if(dlm){
+                if(!debug['s']) {
+                        seek(cout, symo+8+symsize+lcsize, 0);
+                        if(debug['v'])
+                               Bprint(&bso, "%5.2f dwarf\n", cputime());
+                        dwarfemitdebugsections();
+               }
+       } else if(dlm){
                seek(cout, HEADR+textsize+datsize, 0);
                asmdyn();
                cflush();
@@ -1042,6 +1049,8 @@ asmb(void)
                        sh->size = w;
                        sh->addralign = 1;
                        sh->addr = symdatva + 8 + symsize;
+
+                        dwarfaddheaders();
                }
 
                sh = newElfShstrtab(elfstr[ElfStrShstrtab]);
@@ -1118,6 +1127,13 @@ cflush(void)
        cbc = sizeof(buf.cbuf);
 }
 
+/* Current position in file */
+vlong
+cpos(void)
+{
+        return seek(cout, 0, 1) + sizeof(buf.cbuf) - cbc;
+}
+
 void
 datblk(int32 s, int32 n)
 {
index 6473cc5013c152f4a37ed306e57f38ffb3671dad..32ead12efba327aa274103ba1e8cb5fc9177cccf 100644 (file)
@@ -345,6 +345,7 @@ Prog*       brloop(Prog*);
 void   cflush(void);
 void   ckoff(Sym*, int32);
 Prog*  copyp(Prog*);
+vlong   cpos(void);
 double cputime(void);
 void   datblk(int32, int32);
 void   diag(char*, ...);
index 9067e94707999a70ad1d5c8574047ea760b4143b..241b4d6b7f1199eb9e3e088245f861c28ebeb634 100644 (file)
@@ -33,6 +33,7 @@
 #include       "../ld/lib.h"
 #include       "../ld/elf.h"
 #include       "../ld/macho.h"
+#include       "../ld/dwarf.h"
 #include       "../ld/pe.h"
 #include       <ar.h>
 
@@ -604,6 +605,7 @@ loop:
                                histfrogp++;
                        } else
                                collapsefrog(s);
+                        dwarfaddfrag(s->value, s->name);
                }
                goto loop;
        }
index d14fddb50f73091c726c888496b02bed12f3becf..e889ef739becc82fa637c8304df1a2ec455be8a8 100644 (file)
@@ -2,11 +2,11 @@
 // 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        "../ld/dwarf.h"
-#include        "../ld/dwarf_defs.h"
-#include        "../ld/elf.h"
+#include       "l.h"
+#include       "lib.h"
+#include       "../ld/dwarf.h"
+#include       "../ld/dwarf_defs.h"
+#include       "../ld/elf.h"
 
 /*
  * Offsets and sizes of the .debug_* sections in the cout file.
@@ -37,8 +37,9 @@ struct DWAttrForm {
 // index into the abbrevs table below.
 enum
 {
-        DW_ABRV_NULL,
-        DW_ABRV_COMPUNIT,
+       DW_ABRV_NULL,
+       DW_ABRV_COMPUNIT,
+       DW_ABRV_FUNCTION,
        DW_NABRV
 };
 
@@ -48,18 +49,26 @@ struct DWAbbrev {
        uint8 children;
        DWAttrForm attr[30];
 } abbrevs[DW_NABRV] = {
-        /* The mandatory DW_ABRV_NULL entry. */
-        { 0 },
+       /* The mandatory DW_ABRV_NULL entry. */
+       { 0 },
        /* COMPUNIT */
        {
                DW_TAG_compile_unit, DW_CHILDREN_yes,
-                DW_AT_name,      DW_FORM_string,
-                DW_AT_language,  DW_FORM_data1,
-                DW_AT_low_pc,    DW_FORM_addr,
-                DW_AT_high_pc,   DW_FORM_addr,
-                DW_AT_stmt_list, DW_FORM_data4,
-                0, 0
-        },
+               DW_AT_name,      DW_FORM_string,
+               DW_AT_language,  DW_FORM_data1,
+               DW_AT_low_pc,    DW_FORM_addr,
+               DW_AT_high_pc,   DW_FORM_addr,
+               DW_AT_stmt_list, DW_FORM_data4,
+               0, 0
+       },
+       /* FUNCTION */
+       {
+               DW_TAG_subprogram, DW_CHILDREN_no,
+               DW_AT_name,      DW_FORM_string,
+               DW_AT_low_pc,    DW_FORM_addr,
+               DW_AT_high_pc,   DW_FORM_addr,
+               0, 0
+       },
 };
 
 /*
@@ -72,19 +81,19 @@ struct DWAbbrev {
 
 typedef struct DWAttr DWAttr;
 struct DWAttr {
-        DWAttr *link;
-        uint8 atr;  // DW_AT_
-        uint8 cls;  // DW_CLS_
-        vlong value;
-        char *data;
+       DWAttr *link;
+       uint8 atr;  // DW_AT_
+       uint8 cls;  // DW_CLS_
+       vlong value;
+       char *data;
 };
 
 typedef struct DWDie DWDie;
 struct DWDie {
-        int abbrev;
-        DWDie *link;
-        DWDie *child;
-        DWAttr *attr;
+       int abbrev;
+       DWDie *link;
+       DWDie *child;
+       DWAttr *attr;
 };
 
 // top level compilation unit DIE's
@@ -93,33 +102,45 @@ static DWDie *dwinfo;
 static DWDie*
 newdie(DWDie *link, int abbrev)
 {
-        DWDie *die;
+       DWDie *die;
 
-        die = mal(sizeof *die);
-        die->abbrev = abbrev;
-        die->link = link;
-        return die;
+       die = mal(sizeof *die);
+       die->abbrev = abbrev;
+       die->link = link;
+       return die;
 }
 
 static DWAttr*
 newattr(DWDie *die, uint8 attr, int cls, vlong value, char *data)
 {
-        DWAttr *a;
-
-        a = mal(sizeof *a);
-        a->link = die->attr;
-        die->attr = a;
-        a->atr = attr;
-        a->cls = cls;
-        a->value = value;
-        a->data = data;
-        return a;
+       DWAttr *a;
+
+       a = mal(sizeof *a);
+       a->link = die->attr;
+       die->attr = a;
+       a->atr = attr;
+       a->cls = cls;
+       a->value = value;
+       a->data = data;
+       return a;
+}
+
+static void addrput(vlong addr)
+{
+       switch(PtrSize) {
+       case 4:
+               LPUT(addr);
+               break;
+       case 8:
+               VPUT(addr);
+               break;
+       }
 }
 
 static void
 uleb128put(uvlong v)
 {
-        uint8 c;
+       uint8 c;
 
        do {
                c = v & 0x7f;
@@ -132,116 +153,116 @@ uleb128put(uvlong v)
 static void
 sleb128put(vlong v)
 {
-        uint8 c, s;
-
-        do {
-                c = v & 0x7f;
-                s = c & 0x40;
-                v >>= 7;
-                if ((v != -1 || !s) && (v != 0 || s))
-                        c |= 0x80;
-                cput(c);
-        } while(c & 0x80);
+       uint8 c, s;
+
+       do {
+               c = v & 0x7f;
+               s = c & 0x40;
+               v >>= 7;
+               if ((v != -1 || !s) && (v != 0 || s))
+                       c |= 0x80;
+               cput(c);
+       } while(c & 0x80);
 };
 
 static void
 putattr(int form, int cls, vlong value, char *data)
 {
-        switch(form) {
-        case DW_FORM_addr:     // address
-                VPUT(value);
-                break;
-
-        case DW_FORM_block1:   // block
-                value &= 0xff;
-                cput(value);
-                while(value--)
-                        cput(*data++);
-                break;
-
-        case DW_FORM_block2:   // block
-                value &= 0xffff;
-                WPUT(value);
-                while(value--)
-                        cput(*data++);
-                break;
-
-        case DW_FORM_block4:   // block
-                value &= 0xffffffff;
-                LPUT(value);
-                while(value--)
-                        cput(*data++);
-                break;
-
-        case DW_FORM_block:    // block
-                uleb128put(value);
-                while(value--)
-                        cput(*data++);
-                break;
-
-        case DW_FORM_data1:    // constant
-                cput(value);
-                break;
-
-        case DW_FORM_data2:    // constant
-                WPUT(value);
-                break;
-
-        case DW_FORM_data4:    // constant, lineptr, loclistptr, macptr, rangelistptr
-                LPUT(value);
-                break;
-
-        case DW_FORM_data8:    // constant, lineptr, loclistptr, macptr, rangelistptr
-                VPUT(value);
-                break;
-
-        case DW_FORM_sdata:    // constant
-                sleb128put(value);
-                break;
-
-        case DW_FORM_udata:    // constant
-                uleb128put(value);
-                break;
-
-        case DW_FORM_string:   // string
-                strnput(data, value+1);
-                break;
-
-        case DW_FORM_flag:     // flag
-                cput(value?1:0);
-                break;
-
-        case DW_FORM_strp:     // string
-        case DW_FORM_ref_addr: // reference
-        case DW_FORM_ref1:     // reference
-        case DW_FORM_ref2:     // reference
-        case DW_FORM_ref4:     // reference
-        case DW_FORM_ref8:     // reference
-        case DW_FORM_ref_udata:        // reference
-        case DW_FORM_indirect: // (see Section 7.5.3)
-        default:
-                diag("Unsupported atribute form %d / class %d", form, cls);
-                errorexit();
-        }
+       switch(form) {
+       case DW_FORM_addr:      // address
+               addrput(value);
+               break;
+
+       case DW_FORM_block1:    // block
+               value &= 0xff;
+               cput(value);
+               while(value--)
+                       cput(*data++);
+               break;
+
+       case DW_FORM_block2:    // block
+               value &= 0xffff;
+               WPUT(value);
+               while(value--)
+                       cput(*data++);
+               break;
+
+       case DW_FORM_block4:    // block
+               value &= 0xffffffff;
+               LPUT(value);
+               while(value--)
+                       cput(*data++);
+               break;
+
+       case DW_FORM_block:     // block
+               uleb128put(value);
+               while(value--)
+                       cput(*data++);
+               break;
+
+       case DW_FORM_data1:     // constant
+               cput(value);
+               break;
+
+       case DW_FORM_data2:     // constant
+               WPUT(value);
+               break;
+
+       case DW_FORM_data4:     // constant, lineptr, loclistptr, macptr, rangelistptr
+               LPUT(value);
+               break;
+
+       case DW_FORM_data8:     // constant, lineptr, loclistptr, macptr, rangelistptr
+               VPUT(value);
+               break;
+
+       case DW_FORM_sdata:     // constant
+               sleb128put(value);
+               break;
+
+       case DW_FORM_udata:     // constant
+               uleb128put(value);
+               break;
+
+       case DW_FORM_string:    // string
+               strnput(data, value+1);
+               break;
+
+       case DW_FORM_flag:      // flag
+               cput(value?1:0);
+               break;
+
+       case DW_FORM_strp:      // string
+       case DW_FORM_ref_addr:  // reference
+       case DW_FORM_ref1:      // reference
+       case DW_FORM_ref2:      // reference
+       case DW_FORM_ref4:      // reference
+       case DW_FORM_ref8:      // reference
+       case DW_FORM_ref_udata: // reference
+       case DW_FORM_indirect:  // (see Section 7.5.3)
+       default:
+               diag("Unsupported atribute form %d / class %d", form, cls);
+               errorexit();
+       }
 }
 
 static void
 putattrs(int abbrev, DWAttr* attr)
 {
-        DWAttr *attrs[DW_AT_recursive + 1];
-        DWAttrForm* af;
-
-        memset(attrs, 0, sizeof attrs);
-        for( ; attr; attr = attr->link)
-                attrs[attr->atr] = attr;
-        for(af = abbrevs[abbrev].attr; af->attr; af++)
-                if (attrs[af->attr])
-                        putattr(af->form,
-                                attrs[af->attr]->cls,
-                                attrs[af->attr]->value,
-                                attrs[af->attr]->data);
-                else
-                        putattr(af->form, 0, 0, 0);
+       DWAttr *attrs[DW_AT_recursive + 1];
+       DWAttrForm* af;
+
+       memset(attrs, 0, sizeof attrs);
+       for( ; attr; attr = attr->link)
+               attrs[attr->atr] = attr;
+       for(af = abbrevs[abbrev].attr; af->attr; af++)
+               if (attrs[af->attr])
+                       putattr(af->form,
+                               attrs[af->attr]->cls,
+                               attrs[af->attr]->value,
+                               attrs[af->attr]->data);
+               else
+                       putattr(af->form, 0, 0, 0);
 }
 
 static void putdie(DWDie* die);
@@ -249,35 +270,46 @@ static void putdie(DWDie* die);
 static void
 putdies(DWDie* die)
 {
-        for(; die; die = die->link)
-                putdie(die);
+       for(; die; die = die->link)
+               putdie(die);
 }
 
 static void
 putdie(DWDie* die)
 {
-        uleb128put(die->abbrev);
-        putattrs(die->abbrev, die->attr);
-        if (abbrevs[die->abbrev].children) {
-                putdies(die->child);
-                cput(0);
-        }
+       uleb128put(die->abbrev);
+       putattrs(die->abbrev, die->attr);
+       if (abbrevs[die->abbrev].children) {
+               putdies(die->child);
+               cput(0);
+       }
 }
 
 static void
 reverselist(DWDie** list)
 {
-        DWDie *curr, * prev;
-
-        curr = *list;
-        prev = 0;
-        while(curr) {
-                DWDie* next = curr->link;
-                curr->link = prev;
-                prev = curr;
-                curr = next;
-        }
-        *list = prev;
+       DWDie *curr, * prev;
+
+       curr = *list;
+       prev = 0;
+       while(curr) {
+               DWDie* next = curr->link;
+               curr->link = prev;
+               prev = curr;
+               curr = next;
+       }
+       *list = prev;
+}
+
+static void
+reversetree(DWDie** list)
+{
+        DWDie *die;
+
+        reverselist(list);
+        if (*list != nil && abbrevs[(*list)->abbrev].children)
+                for (die = *list; die != nil; die = die->link)
+                        reversetree(&die->child);
 }
 
 /*
@@ -290,7 +322,7 @@ static int ftabsize;
 void
 dwarfaddfrag(int n, char *frag)
 {
-        int s;
+       int s;
 
        if (n >= ftabsize) {
                s = ftabsize;
@@ -308,19 +340,19 @@ dwarfaddfrag(int n, char *frag)
 static char *
 decodez(char *s)
 {
-        int len, o;
-        char *ss, *f;
-        char *r, *rb, *re;
+       int len, o;
+       char *ss, *f;
+       char *r, *rb, *re;
 
        len = 0;
        ss = s + 1;     // first is 0
-        while((o = ((uint8)ss[0] << 8) | (uint8)ss[1]) != 0) {
+       while((o = ((uint8)ss[0] << 8) | (uint8)ss[1]) != 0) {
                if (o < 0 || o >= ftabsize) {
                        diag("corrupt z entry");
                        return 0;
                }
                f = ftab[o];
-               if (!f) {
+               if (f == nil) {
                        diag("corrupt z entry");
                        return 0;
                }
@@ -351,60 +383,60 @@ decodez(char *s)
  * The line history itself
  */
 
-static char **histfile;    // [0] holds the empty string.
+static char **histfile;           // [0] holds the empty string.
 static int  histfilesize;
 static int  histfilecap;
 
 static void
 clearhistfile(void)
 {
-  int i;
+       int i;
 
-  // [0] holds the empty string.
-  for (i = 1; i < histfilesize; i++)
-          free(histfile[i]);
-  histfilesize = 0;
+       // [0] holds the empty string.
+       for (i = 1; i < histfilesize; i++)
+               free(histfile[i]);
+       histfilesize = 0;
 }
 
 static int
 addhistfile(char *zentry)
 {
-  char *fname;
-
-  if (histfilesize == histfilecap) {
-          histfilecap = 2 * histfilecap + 2;
-          histfile = realloc(histfile, histfilecap * sizeof(char*));
-  }
-  if (histfilesize == 0)
-          histfile[histfilesize++] = "<eof>";
-
-  fname = decodez(zentry);
-  if (fname == 0)
-          return -1;
-  // Don't fill with duplicates (check only top one).
-  if (strcmp(fname, histfile[histfilesize-1]) == 0) {
-          free(fname);
-          return histfilesize - 1;
-  }
-  histfile[histfilesize++] = fname;
-  return histfilesize - 1;
+       char *fname;
+
+       if (histfilesize == histfilecap) {
+               histfilecap = 2 * histfilecap + 2;
+               histfile = realloc(histfile, histfilecap * sizeof(char*));
+       }
+       if (histfilesize == 0)
+               histfile[histfilesize++] = "<eof>";
+
+       fname = decodez(zentry);
+       if (fname == 0)
+               return -1;
+       // Don't fill with duplicates (check only top one).
+       if (strcmp(fname, histfile[histfilesize-1]) == 0) {
+               free(fname);
+               return histfilesize - 1;
+       }
+       histfile[histfilesize++] = fname;
+       return histfilesize - 1;
 }
 
 // Go's runtime C sources are sane, and Go sources nest only 1 level,
 // so 16 should be plenty.
 static struct {
-        int file;
-        vlong line;
+       int file;
+       vlong line;
 } includestack[16];
 static int includetop;
 static vlong absline;
 
 typedef struct Linehist Linehist;
 struct Linehist {
-        Linehist *link;
-        vlong absline;
-        vlong line;
-        int file;
+       Linehist *link;
+       vlong absline;
+       vlong line;
+       int file;
 };
 
 static Linehist *linehist;
@@ -412,101 +444,101 @@ static Linehist *linehist;
 static void
 checknesting(void)
 {
-        int i;
-
-        if (includetop < 0) {
-                diag("corrupt z stack");
-                errorexit();
-        }
-        if (includetop >= nelem(includestack)) {
-                diag("nesting too deep");
-                for (i = 0; i < nelem(includestack); i++)
-                        diag("\t%s", histfile[includestack[i].file]);
-                errorexit();
-        }
+       int i;
+
+       if (includetop < 0) {
+               diag("corrupt z stack");
+               errorexit();
+       }
+       if (includetop >= nelem(includestack)) {
+               diag("nesting too deep");
+               for (i = 0; i < nelem(includestack); i++)
+                       diag("\t%s", histfile[includestack[i].file]);
+               errorexit();
+       }
 }
 
 /* find z and Z entries in the Auto list (of a Prog), and reset the history stack */
 static char *
 inithist(Auto *a)
 {
-        char *unitname;
-        Linehist *lh;
+       char *unitname;
+       Linehist *lh;
 
        for (; a; a = a->link)
                if (a->type == D_FILE)
-                        break;
-        if (a==nil)
-                return 0;
-
-        // We have a new history.  They are guaranteed to come completely
-        // at the beginning of the compilation unit.
-        if (a->aoffset != 1) {
-                diag("stray 'z' with offset %d", a->aoffset);
-                return 0;
-        }
-
-        unitname = decodez(a->asym->name);
-
-        // Clear the history.
-        clearhistfile();
-        includetop = 0;
-        includestack[includetop].file = 0;
-        includestack[includetop].line = -1;
-        absline = 0;
-        while (linehist != nil) {
-                lh = linehist->link;
-                free(linehist);
-                linehist = lh;
-        }
-
-        // Construct the new one.
-        for (; a; a = a->link) {
-                if (a->type == D_FILE) {  // 'z'
-                        int f = addhistfile(a->asym->name);
-                        if (f < 0) {       // pop file
-                                includetop--;
-                                checknesting();
-                        } else if(f != includestack[includetop].file) { // pushed a new file
-                                includestack[includetop].line += a->aoffset - absline;
-                                includetop++;
-                                checknesting();
-                                includestack[includetop].file = f;
-                                includestack[includetop].line = 1;
-
-                        }
-                        absline = a->aoffset;
-                } else if (a->type == D_FILE1) {  // 'Z'
-                        // We could just fixup the current
-                        // linehist->line, but there doesn't appear to
-                        // be a guarantee that every 'Z' is preceded
-                        // by it's own 'z', so do the safe thing and
-                        // update the stack and push a new Linehist
-                        // entry
-                        includestack[includetop].line =  a->aoffset;
-                } else
-                        continue;
-                if (linehist == 0 || linehist->absline != absline) {
-                        Linehist* lh = malloc(sizeof *lh);
-                        lh->link = linehist;
-                        lh->absline = absline;
-                        linehist = lh;
-                }
-                linehist->file = includestack[includetop].file;
-                linehist->line = includestack[includetop].line;
-        }
-        return unitname;
+                       break;
+       if (a==nil)
+               return 0;
+
+       // We have a new history.  They are guaranteed to come completely
+       // at the beginning of the compilation unit.
+       if (a->aoffset != 1) {
+               diag("stray 'z' with offset %d", a->aoffset);
+               return 0;
+       }
+
+       unitname = decodez(a->asym->name);
+
+       // Clear the history.
+       clearhistfile();
+       includetop = 0;
+       includestack[includetop].file = 0;
+       includestack[includetop].line = -1;
+       absline = 0;
+       while (linehist != nil) {
+               lh = linehist->link;
+               free(linehist);
+               linehist = lh;
+       }
+
+       // Construct the new one.
+       for (; a; a = a->link) {
+               if (a->type == D_FILE) {  // 'z'
+                       int f = addhistfile(a->asym->name);
+                       if (f < 0) {       // pop file
+                               includetop--;
+                               checknesting();
+                       } else if(f != includestack[includetop].file) { // pushed a new file
+                               includestack[includetop].line += a->aoffset - absline;
+                               includetop++;
+                               checknesting();
+                               includestack[includetop].file = f;
+                               includestack[includetop].line = 1;
+
+                       }
+                       absline = a->aoffset;
+               } else if (a->type == D_FILE1) {  // 'Z'
+                       // We could just fixup the current
+                       // linehist->line, but there doesn't appear to
+                       // be a guarantee that every 'Z' is preceded
+                       // by it's own 'z', so do the safe thing and
+                       // update the stack and push a new Linehist
+                       // entry
+                       includestack[includetop].line =  a->aoffset;
+               } else
+                       continue;
+               if (linehist == 0 || linehist->absline != absline) {
+                       Linehist* lh = malloc(sizeof *lh);
+                       lh->link = linehist;
+                       lh->absline = absline;
+                       linehist = lh;
+               }
+               linehist->file = includestack[includetop].file;
+               linehist->line = includestack[includetop].line;
+       }
+       return unitname;
 }
 
 static Linehist *
 searchhist(vlong absline)
 {
-        Linehist *lh;
+       Linehist *lh;
 
-        for (lh = linehist; lh; lh = lh->link)
-                if (lh->absline <= absline)
-                        break;
-        return lh;
+       for (lh = linehist; lh; lh = lh->link)
+               if (lh->absline <= absline)
+                       break;
+       return lh;
 }
 
 static void
@@ -516,7 +548,7 @@ writeabbrev(void)
 
        abbrevo = cpos();
        for (i = 1; i < DW_NABRV; i++) {
-                // See section 7.5.3
+               // See section 7.5.3
                uleb128put(i);
                uleb128put(abbrevs[i].tag);
                cput(abbrevs[i].children);
@@ -526,7 +558,7 @@ writeabbrev(void)
                strnput((char *) abbrevs[i].attr,
                        (n + 1) * sizeof(DWAttrForm));
        }
-        cput(0);
+       cput(0);
        abbrevsize = cpos() - abbrevo;
 }
 
@@ -534,10 +566,10 @@ writeabbrev(void)
 static int
 guesslang(char *s)
 {
-        if(strlen(s) >= 3 && strcmp(s+strlen(s)-3, ".go") == 0)
-                return DW_LANG_Go;
+       if(strlen(s) >= 3 && strcmp(s+strlen(s)-3, ".go") == 0)
+               return DW_LANG_Go;
 
-        return DW_LANG_C;
+       return DW_LANG_C;
 }
 
 /*
@@ -546,30 +578,30 @@ guesslang(char *s)
  */
 
 enum {
-        LINE_BASE = -1,
-        LINE_RANGE = 4,
-        OPCODE_BASE = 5
+       LINE_BASE = -1,
+       LINE_RANGE = 4,
+       OPCODE_BASE = 5
 };
 
 static void
 putpclcdelta(vlong delta_pc, vlong delta_lc)
 {
-        if (LINE_BASE <= delta_lc && delta_lc < LINE_BASE+LINE_RANGE) {
-                vlong opcode = OPCODE_BASE + (delta_lc - LINE_BASE) + (LINE_RANGE * delta_pc);
-                if (OPCODE_BASE <= opcode && opcode < 256) {
-                        cput(opcode);
-                        return;
-                }
-        }
-
-        if (delta_pc) {
-          cput(DW_LNS_advance_pc);
-          sleb128put(delta_pc);
-        }
-
-        cput(DW_LNS_advance_line);
-        sleb128put(delta_lc);
-        cput(DW_LNS_copy);
+       if (LINE_BASE <= delta_lc && delta_lc < LINE_BASE+LINE_RANGE) {
+               vlong opcode = OPCODE_BASE + (delta_lc - LINE_BASE) + (LINE_RANGE * delta_pc);
+               if (OPCODE_BASE <= opcode && opcode < 256) {
+                       cput(opcode);
+                       return;
+               }
+       }
+
+       if (delta_pc) {
+         cput(DW_LNS_advance_pc);
+         sleb128put(delta_pc);
+       }
+
+       cput(DW_LNS_advance_line);
+       sleb128put(delta_lc);
+       cput(DW_LNS_copy);
 }
 
 
@@ -581,132 +613,143 @@ putpclcdelta(vlong delta_pc, vlong delta_lc)
 static void
 flushunit(vlong pc, vlong unitstart)
 {
-        vlong here;
-
-        if (dwinfo != 0 && pc != 0) {
-                newattr(dwinfo, DW_AT_high_pc, DW_CLS_ADDRESS, pc, 0);
-        }
-
-        if (unitstart >= 0) {
-                cput(0);  // start extended opcode
-                uleb128put(1);
-                cput(DW_LNE_end_sequence);
-                cflush();
-
-                here = cpos();
-                seek(cout, unitstart, 0);
-                LPUT(here - unitstart - sizeof(int32));
-                cflush();
-                seek(cout, here, 0);
-        }
+       vlong here;
+
+       if (dwinfo != 0 && pc != 0) {
+               newattr(dwinfo, DW_AT_high_pc, DW_CLS_ADDRESS, pc, 0);
+       }
+
+       if (unitstart >= 0) {
+               cput(0);  // start extended opcode
+               uleb128put(1);
+               cput(DW_LNE_end_sequence);
+               cflush();
+
+               here = cpos();
+               seek(cout, unitstart, 0);
+               LPUT(here - unitstart - sizeof(int32));
+               cflush();
+               seek(cout, here, 0);
+       }
 }
 
 static void
 writelines(void)
 {
-        Prog *p, *q;
-        Sym *s;
-        char *unitname;
-        vlong unitstart;
-        vlong pc, lc, llc, lline;
-        int currfile;
-        int i;
-        Linehist *lh;
-
-        unitstart = -1;
-        pc = 0;
-        lc = 1;
-        llc = 1;
-        currfile = -1;
-        lineo = cpos();
-
-        for (p = textp; p != P; p = p->pcond) {
+       Prog *p, *q;
+       Sym *s;
+       char *unitname;
+       vlong unitstart;
+       vlong pc, lc, llc, lline;
+       int currfile;
+       int i;
+       Linehist *lh;
+
+       unitstart = -1;
+       pc = 0;
+       lc = 1;
+       llc = 1;
+       currfile = -1;
+       lineo = cpos();
+
+       for (p = textp; p != P; p = p->pcond) {
                s = p->from.sym;
                if (s == nil || s->type != STEXT) {
-                        diag("->pcond was supposed to loop over STEXT: %P", p);
-                        continue;
-                }
-
-                // Look for history stack.  If we find one,
-                // we're entering a new compilation unit
-                if ((unitname = inithist(p->to.autom)) != 0) {
-                        flushunit(pc, unitstart);
-                        unitstart = cpos();
-                        if(debug['v'] > 1) {
-                                print("dwarf writelines found %s\n", unitname);
-                                Linehist* lh;
-                                for (lh = linehist; lh; lh = lh->link)
-                                        print("\t%8lld: [%4lld]%s\n",
-                                              lh->absline, lh->line, histfile[lh->file]);
-                        }
-                        dwinfo = newdie(dwinfo, DW_ABRV_COMPUNIT);
-                        newattr(dwinfo, DW_AT_name, DW_CLS_STRING, strlen(unitname), unitname);
-                        newattr(dwinfo, DW_AT_language, DW_CLS_CONSTANT, guesslang(unitname), 0);
-                        newattr(dwinfo, DW_AT_stmt_list,  DW_CLS_PTR, unitstart - lineo, 0);
-                        newattr(dwinfo, DW_AT_low_pc,  DW_CLS_ADDRESS, p->pc, 0);
-                        // 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 later.
-                        WPUT(3);   // version
-                        LPUT(11);  // header_length (*)
-                        cput(1);   // minimum_instruction_length
-                        cput(1);   // default_is_stmt
-                        cput(LINE_BASE);     // line_base
-                        cput(LINE_RANGE);    // line_range
-                        cput(OPCODE_BASE);   // opcode_base (we only use 1..4)
-                        cput(0);   // standard_opcode_lengths[1]
-                        cput(1);   // standard_opcode_lengths[2]
-                        cput(1);   // standard_opcode_lengths[3]
-                        cput(1);   // standard_opcode_lengths[4]
-                        cput(0);   // include_directories  (empty)
-                        cput(0);   // file_names (empty) (emitted by DW_LNE's below)
-                        for (i=1; i < histfilesize; i++) {
-                                cput(0);  // start extended opcode
-                                uleb128put(1 + strlen(histfile[i]) + 4);
-                                cput(DW_LNE_define_file);
-                                strnput(histfile[i], strlen(histfile[i]) + 4);
-                                // 4 zeros: the string termination + 3 fields.
-                        }
-                        pc = p->pc;
-                        currfile = 1;
-                        lc = 1;
-                        llc = 1;
-                        cput(0);  // start extended opcode
-                        uleb128put(1 + sizeof pc);
-                        cput(DW_LNE_set_address);
-                        VPUT(pc);
-                }
-                if (!p->from.sym->reachable)
-                        continue;
-                if (unitstart < 0) {
-                        diag("Reachable code before seeing any history: %P", p);
-                        continue;
-                }
-                for(q = p; q != P && (q == p || q->as != ATEXT); q = q->link) {
-                        lh = searchhist(q->line);
-                        if (!lh) {
-                                diag("corrupt history or bad absolute line: %P", q);
-                                continue;
-                        }
-                        lline = lh->line + q->line - lh->absline;
-                        if (debug['v'] > 1)
-                                print("%6llux %s[%lld] %P\n", q->pc, histfile[lh->file], lline, q);
-                        // Only emit a line program statement if line has changed.
-                        if (q->line == lc)
-                                continue;
-                        if (currfile != lh->file) {
-                                currfile = lh->file;
-                                cput(DW_LNS_set_file);
-                                uleb128put(currfile);
-                        }
-                        putpclcdelta(q->pc - pc, lline - llc);
-                        pc  = q->pc;
-                        lc  = q->line;
-                        llc = lline;
-                }
-        }
-        flushunit(pc, unitstart);
-        linesize = cpos() - lineo;
+                       diag("->pcond was supposed to loop over STEXT: %P", p);
+                       continue;
+               }
+
+               // Look for history stack.  If we find one,
+               // we're entering a new compilation unit
+               if ((unitname = inithist(p->to.autom)) != 0) {
+                       flushunit(pc, unitstart);
+                       unitstart = cpos();
+                       if(debug['v'] > 1) {
+                               print("dwarf writelines found %s\n", unitname);
+                               Linehist* lh;
+                               for (lh = linehist; lh; lh = lh->link)
+                                       print("\t%8lld: [%4lld]%s\n",
+                                             lh->absline, lh->line, histfile[lh->file]);
+                       }
+                       dwinfo = newdie(dwinfo, DW_ABRV_COMPUNIT);
+                       newattr(dwinfo, DW_AT_name, DW_CLS_STRING, strlen(unitname), unitname);
+                       newattr(dwinfo, DW_AT_language, DW_CLS_CONSTANT, guesslang(unitname), 0);
+                       newattr(dwinfo, DW_AT_stmt_list,  DW_CLS_PTR, unitstart - lineo, 0);
+                       newattr(dwinfo, DW_AT_low_pc,  DW_CLS_ADDRESS, p->pc, 0);
+                       // 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 later.
+                       WPUT(3);   // version
+                       LPUT(11);  // header_length (*)
+                       cput(1);   // minimum_instruction_length
+                       cput(1);   // default_is_stmt
+                       cput(LINE_BASE);     // line_base
+                       cput(LINE_RANGE);    // line_range
+                       cput(OPCODE_BASE);   // opcode_base (we only use 1..4)
+                       cput(0);   // standard_opcode_lengths[1]
+                       cput(1);   // standard_opcode_lengths[2]
+                       cput(1);   // standard_opcode_lengths[3]
+                       cput(1);   // standard_opcode_lengths[4]
+                       cput(0);   // include_directories  (empty)
+                       cput(0);   // file_names (empty) (emitted by DW_LNE's below)
+                       for (i=1; i < histfilesize; i++) {
+                               cput(0);  // start extended opcode
+                               uleb128put(1 + strlen(histfile[i]) + 4);
+                               cput(DW_LNE_define_file);
+                               strnput(histfile[i], strlen(histfile[i]) + 4);
+                               // 4 zeros: the string termination + 3 fields.
+                       }
+
+                       pc = p->pc;
+                       currfile = 1;
+                       lc = 1;
+                       llc = 1;
+
+                       cput(0);  // start extended opcode
+                       uleb128put(1 + PtrSize);
+                       cput(DW_LNE_set_address);
+                       addrput(pc);
+               }
+               if (!p->from.sym->reachable)
+                       continue;
+               if (unitstart < 0) {
+                       diag("reachable code before seeing any history: %P", p);
+                       continue;
+               }
+
+               dwinfo->child = newdie(dwinfo->child, DW_ABRV_FUNCTION);
+               newattr(dwinfo->child, DW_AT_name, DW_CLS_STRING, strlen(s->name), s->name);
+               newattr(dwinfo->child, DW_AT_low_pc, DW_CLS_ADDRESS, p->pc, 0);
+               if (debug['v'] > 1)
+                 print("frame offset: %d\n", p->to.offset);
+//             newattr(dwinfo->child, DW_AT_return_addr,  DW_CLS_BLOCK, p->to.offset, 0);
+
+               for(q = p; q != P && (q == p || q->as != ATEXT); q = q->link) {
+                       lh = searchhist(q->line);
+                       if (lh == nil) {
+                               diag("corrupt history or bad absolute line: %P", q);
+                               continue;
+                       }
+                       lline = lh->line + q->line - lh->absline;
+                       if (debug['v'] > 1)
+                               print("%6llux %s[%lld] %P\n", q->pc, histfile[lh->file], lline, q);
+                       // Only emit a line program statement if line has changed.
+                       if (q->line == lc)
+                               continue;
+                       if (currfile != lh->file) {
+                               currfile = lh->file;
+                               cput(DW_LNS_set_file);
+                               uleb128put(currfile);
+                       }
+                       putpclcdelta(q->pc - pc, lline - llc);
+                       pc  = q->pc;
+                       lc  = q->line;
+                       llc = lline;
+               }
+               newattr(dwinfo->child, DW_AT_high_pc, DW_CLS_ADDRESS, pc, 0);
+       }
+       flushunit(pc, unitstart);
+       linesize = cpos() - lineo;
 }
 
 /*
@@ -715,41 +758,42 @@ writelines(void)
 static void
 writeinfo(void)
 {
-        DWDie *compunit;
-        vlong unitstart;
+       DWDie *compunit;
+       vlong unitstart;
 
-        reverselist(&dwinfo);
+       reversetree(&dwinfo);
 
-        infoo = cpos();
+       infoo = cpos();
 
-        for (compunit = dwinfo; compunit; compunit = compunit->link) {
-                unitstart = cpos();
+       for (compunit = dwinfo; compunit; compunit = compunit->link) {
+               unitstart = cpos();
 
-                // Write .debug_info Compilation Unit Header (sec 7.5.1)
-                // Fields marked with (*) must be changed for 64-bit dwarf
-                LPUT(0);   // unit_length (*), will be filled in later.
-                WPUT(3);   // version
-                LPUT(0);   // debug_abbrev_offset (*)
-                cput(8);   // address_size
+               // Write .debug_info Compilation Unit Header (sec 7.5.1)
+               // Fields marked with (*) must be changed for 64-bit dwarf
+               LPUT(0);   // unit_length (*), will be filled in later.
+               WPUT(3);   // version
+               LPUT(0);   // debug_abbrev_offset (*)
+               cput(PtrSize);   // address_size
 
-                putdie(compunit);
+               putdie(compunit);
 
-                cflush();
-                vlong here = cpos();
-                seek(cout, unitstart, 0);
-                LPUT(here - unitstart - sizeof(int32));
-                cflush();
-                seek(cout, here, 0);
-        }
+               cflush();
+               vlong here = cpos();
+               seek(cout, unitstart, 0);
+               LPUT(here - unitstart - sizeof(int32));
+               cflush();
+               seek(cout, here, 0);
+       }
 
-        cflush();
-        infosize = cpos() - infoo;
+       cflush();
+       infosize = cpos() - infoo;
 }
 
 /*
  *  Elf sections.
  */
-enum {
+enum
+{
        ElfStrDebugAbbrev,
        ElfStrDebugAranges,
        ElfStrDebugFrame,