From b433552ebc20ed8669dac61c7a46f438c1bf3627 Mon Sep 17 00:00:00 2001 From: Luuk van Dijk Date: Mon, 30 Aug 2010 22:20:38 +0200 Subject: [PATCH] 8l: emit DWARF in ELF. R=rsc, r, ken2 CC=golang-dev https://golang.org/cl/2004046 --- src/cmd/6l/asm.c | 3 +- src/cmd/6l/l.h | 2 +- src/cmd/8l/Makefile | 5 +- src/cmd/8l/asm.c | 20 +- src/cmd/8l/l.h | 1 + src/cmd/8l/obj.c | 2 + src/cmd/ld/dwarf.c | 864 +++++++++++++++++++++++--------------------- 7 files changed, 481 insertions(+), 416 deletions(-) diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c index db11f14efb5..af615e69386 100644 --- a/src/cmd/6l/asm.c +++ b/src/cmd/6l/asm.c @@ -641,8 +641,7 @@ asmb(void) dwarfemitdebugsections(); } - } else - if(dlm){ + } else if(dlm){ seek(cout, HEADR+textsize+datsize, 0); asmdyn(); cflush(); diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h index 9a77658c3da..a8428865a77 100644 --- a/src/cmd/6l/l.h +++ b/src/cmd/6l/l.h @@ -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); diff --git a/src/cmd/8l/Makefile b/src/cmd/8l/Makefile index 2b509b36139..49064ca6a65 100644 --- a/src/cmd/8l/Makefile +++ b/src/cmd/8l/Makefile @@ -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\ diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c index a7f894aa281..277fba37abb 100644 --- a/src/cmd/8l/asm.c +++ b/src/cmd/8l/asm.c @@ -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) { diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h index 6473cc5013c..32ead12efba 100644 --- a/src/cmd/8l/l.h +++ b/src/cmd/8l/l.h @@ -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*, ...); diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c index 9067e947079..241b4d6b7f1 100644 --- a/src/cmd/8l/obj.c +++ b/src/cmd/8l/obj.c @@ -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 @@ -604,6 +605,7 @@ loop: histfrogp++; } else collapsefrog(s); + dwarfaddfrag(s->value, s->name); } goto loop; } diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c index d14fddb50f7..e889ef739be 100644 --- a/src/cmd/ld/dwarf.c +++ b/src/cmd/ld/dwarf.c @@ -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; + 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; + 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; + 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); + 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; + 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_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_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_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_block: // block + uleb128put(value); + while(value--) + cput(*data++); + break; - case DW_FORM_data1: // constant - cput(value); - break; + case DW_FORM_data1: // constant + cput(value); + break; - case DW_FORM_data2: // constant - WPUT(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_data4: // constant, lineptr, loclistptr, macptr, rangelistptr + LPUT(value); + break; - case DW_FORM_data8: // constant, lineptr, loclistptr, macptr, rangelistptr - VPUT(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_sdata: // constant + sleb128put(value); + break; - case DW_FORM_udata: // constant - uleb128put(value); - break; + case DW_FORM_udata: // constant + uleb128put(value); + break; - case DW_FORM_string: // string - strnput(data, value+1); - break; + case DW_FORM_string: // string + strnput(data, value+1); + break; - case DW_FORM_flag: // flag - cput(value?1:0); - 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(); - } + 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; + 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); + 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; + DWDie *curr, * prev; - curr = *list; - prev = 0; - while(curr) { - DWDie* next = curr->link; - curr->link = prev; - prev = curr; - curr = next; - } - *list = 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; + char *fname; - if (histfilesize == histfilecap) { - histfilecap = 2 * histfilecap + 2; - histfile = realloc(histfile, histfilecap * sizeof(char*)); - } - if (histfilesize == 0) - histfile[histfilesize++] = ""; + if (histfilesize == histfilecap) { + histfilecap = 2 * histfilecap + 2; + histfile = realloc(histfile, histfilecap * sizeof(char*)); + } + if (histfilesize == 0) + histfile[histfilesize++] = ""; - 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; + 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; + 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(); - } + 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; + 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; - } + // 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); + 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; - } + // 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; + // 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; + } + 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 (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); - } + if (delta_pc) { + cput(DW_LNS_advance_pc); + sleb128put(delta_pc); + } - cput(DW_LNS_advance_line); - sleb128put(delta_lc); - cput(DW_LNS_copy); + 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; + vlong here; - if (dwinfo != 0 && pc != 0) { - newattr(dwinfo, DW_AT_high_pc, DW_CLS_ADDRESS, pc, 0); - } + 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(); + 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); - } + 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; + 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(); + unitstart = -1; + pc = 0; + lc = 1; + llc = 1; + currfile = -1; + lineo = cpos(); - for (p = textp; p != P; p = p->pcond) { + 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; - } + 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; + // 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,