diff options
author | Charles Crayne <chuck@thor.crayne.org> | 2008-02-13 19:58:54 -0800 |
---|---|---|
committer | Charles Crayne <chuck@thor.crayne.org> | 2008-02-13 19:58:54 -0800 |
commit | f0b43d212e77012641524570dd55b925bbea9c15 (patch) | |
tree | 23f55f607c24a126dbccfc9e9f7a3dea3f76169e | |
parent | 978a25d3e987fd6c3629ebf030e0419d5ece7d68 (diff) | |
download | nasm-f0b43d212e77012641524570dd55b925bbea9c15.tar.gz nasm-f0b43d212e77012641524570dd55b925bbea9c15.tar.bz2 nasm-f0b43d212e77012641524570dd55b925bbea9c15.zip |
Upgrade dwarf3 support for elf64
Add support for multiple executable segments
-rw-r--r-- | output/outelf64.c | 237 |
1 files changed, 174 insertions, 63 deletions
diff --git a/output/outelf64.c b/output/outelf64.c index f3118e6..f5a0bb0 100644 --- a/output/outelf64.c +++ b/output/outelf64.c @@ -6,7 +6,6 @@ * redistributable under the license given in the file "LICENSE" * distributed in the NASM archive. */ - #include "compiler.h" #include <stdio.h> @@ -196,7 +195,7 @@ struct Section { struct SAA *data; uint64_t len, size; uint32_t nrelocs; - int32_t index; + int32_t index; /* index into sects array */ uint32_t type; /* SHT_PROGBITS or SHT_NOBITS */ uint64_t align; /* alignment: power of two */ uint64_t flags; /* section flags */ @@ -278,7 +277,7 @@ static void add_sectname(char *, char *); #define N_BINCL 0x82 #define N_EINCL 0xA2 #define N_SLINE 0x44 -#define TY_STABSSYMLIN 0x40 /* ouch */ +#define TY_STABSSYMLIN 0x40 /* internal call to debug_out */ struct stabentry { uint32_t n_strx; @@ -294,7 +293,8 @@ struct erel { struct symlininfo { int offset; - int section; /* section index */ + int section; /* index into sects[] */ + int segto; /* internal section number */ char *name; /* shallow-copied pointer of section name */ }; @@ -306,6 +306,16 @@ struct linelist { struct linelist *last; }; +struct sectlist { + struct SAA *psaa; + int section; + int line; + int offset; + int file; + struct sectlist *next; + struct sectlist *last; +}; + /* common debug variables */ static int currentline = 1; @@ -320,14 +330,13 @@ static int stablen, stabstrlen, stabrellen; /* dwarf debug variables */ static struct linelist *dwarf_flist = 0, *dwarf_clist = 0, *dwarf_elist = 0; -static int dwarf_immcall = 0, dwarf_numfiles = 0; +static struct sectlist *dwarf_fsect = 0, *dwarf_csect = 0, *dwarf_esect = 0; +static int dwarf_immcall = 0, dwarf_numfiles = 0, dwarf_nsections; static uint8_t *arangesbuf = 0, *arangesrelbuf = 0, *pubnamesbuf = 0, *infobuf = 0, *inforelbuf = 0, *abbrevbuf = 0, *linebuf = 0, *linerelbuf = 0, *framebuf = 0, *locbuf = 0; static int8_t line_base = -5, line_range = 14, opcode_base = 13; static int arangeslen, arangesrellen, pubnameslen, infolen, inforellen, abbrevlen, linelen, linerellen, framelen, loclen; -static int dwarf_line = 1, dwarf_offset = 0, dwarf_fileinx = 0; -static struct SAA *plinep; static char workbuf[1024]; @@ -354,6 +363,7 @@ void dwarf64_output(int, void *); void dwarf64_generate(void); void dwarf64_cleanup(void); void dwarf64_findfile(const char *); +void dwarf64_findsect(const int); void saa_wleb128u(struct SAA *, int); void saa_wleb128s(struct SAA *, int); @@ -406,7 +416,6 @@ static void elf_init(FILE * fp, efunc errfunc, ldfunc ldef, evalfunc eval) def_seg = seg_alloc(); - if (of_elf64.current_dfmt) of_elf64.current_dfmt->init(0,0,0,0); } static void elf_cleanup(int debuginfo) @@ -437,7 +446,7 @@ static void elf_cleanup(int debuginfo) of_elf64.current_dfmt->cleanup(); } } - +/* add entry to the elf .shstrtab section */ static void add_sectname(char *firsthalf, char *secondhalf) { int len = strlen(firsthalf) + strlen(secondhalf); @@ -807,7 +816,6 @@ static void elf_deflabel(char *name, int32_t segment, int64_t offset, static void elf_add_reloc(struct Section *sect, int32_t segment, int type) { struct Reloc *r; - r = *sect->tail = nasm_malloc(sizeof(struct Reloc)); sect->tail = &r->next; r->next = NULL; @@ -928,9 +936,12 @@ static void elf_out(int32_t segto, const void *data, static struct symlininfo sinfo; #if defined(DEBUG) && DEBUG>2 - fprintf(stderr, - " elf_out type: %x seg: %d bytes: %x data: %"PRIx64"\n", - (type >> 24), segment, size, *(int64_t *)data); + if (data) fprintf(stderr, + " elf_out line: %d type: %x seg: %d segto: %d bytes: %x data: %"PRIx64"\n", + currentline, type, segment, segto, size, *(int64_t *)data); + else fprintf(stderr, + " elf_out line: %d type: %x seg: %d segto: %d bytes: %x\n", + currentline, type, segment, segto, size); #endif /* @@ -959,10 +970,11 @@ static void elf_out(int32_t segto, const void *data, } } - /* again some stabs debugging stuff */ + /* invoke current debug_output routine */ if (of_elf64.current_dfmt) { sinfo.offset = s->len; sinfo.section = i; + sinfo.segto = segto; sinfo.name = s->name; of_elf64.current_dfmt->debug_output(TY_STABSSYMLIN, &sinfo); } @@ -1157,7 +1169,12 @@ static void elf_write(void) } else if (of_elf64.current_dfmt == &df_dwarf) { - /* in case the debug information is wanted, add these ten sections... */ + /* the dwarf debug standard specifies the following ten sections, + not all of which are currently implemented, + although all of them are defined. */ + #define debug_aranges nsections-10 + #define debug_info nsections-7 + #define debug_line nsections-4 add_sectname("", ".debug_aranges"); add_sectname(".rela", ".debug_aranges"); add_sectname("", ".debug_pubnames"); @@ -1279,7 +1296,7 @@ static void elf_write(void) arangeslen, 0, 0, 1, 0); p += strlen(p) + 1; elf_section_header(p - shstrtab, SHT_RELA, 0, arangesrelbuf, false, - arangesrellen, symtabsection, nsections - 10, 1, 24); + arangesrellen, symtabsection, debug_aranges, 1, 24); p += strlen(p) + 1; elf_section_header(p - shstrtab, SHT_PROGBITS, 0, pubnamesbuf, false, pubnameslen, 0, 0, 1, 0); @@ -1288,7 +1305,7 @@ static void elf_write(void) infolen, 0, 0, 1, 0); p += strlen(p) + 1; elf_section_header(p - shstrtab, SHT_RELA, 0, inforelbuf, false, - inforellen, symtabsection, nsections - 7, 1, 24); + inforellen, symtabsection, debug_info, 1, 24); p += strlen(p) + 1; elf_section_header(p - shstrtab, SHT_PROGBITS, 0, abbrevbuf, false, abbrevlen, 0, 0, 1, 0); @@ -1297,7 +1314,7 @@ static void elf_write(void) linelen, 0, 0, 1, 0); p += strlen(p) + 1; elf_section_header(p - shstrtab, SHT_RELA, 0, linerelbuf, false, - linerellen, symtabsection, nsections - 4, 1, 24); + linerellen, symtabsection, debug_line, 1, 24); p += strlen(p) + 1; elf_section_header(p - shstrtab, SHT_PROGBITS, 0, framebuf, false, framelen, 0, 0, 8, 0); @@ -1705,7 +1722,7 @@ void stabs64_output(int type, void *param) if (stabs_immcall) { s = (struct symlininfo *)param; if (!(sects[s->section]->flags & SHF_EXECINSTR)) - return; /* we are only interested in the text stuff */ + return; /* line info is only collected for executable sections */ numlinestabs++; el = (struct linelist *)nasm_malloc(sizeof(struct linelist)); el->info.offset = s->offset; @@ -1898,12 +1915,6 @@ void dwarf64_init(struct ofmt *of, void *id, FILE * fp, efunc error) (void)id; (void)fp; (void)error; - /* initialize line program SAA */ - plinep = saa_init(1L); - WSAACHAR(plinep,workbuf,DW_LNS_extended_op); - WSAACHAR(plinep,workbuf,9); /* operand length */ - WSAACHAR(plinep,workbuf,DW_LNE_set_address); - WSAADLONG(plinep,workbuf,0); /* Start Address */ } void dwarf64_linenum(const char *filename, int32_t linenumber, int32_t segto) @@ -1992,25 +2003,36 @@ void dwarf64_typevalue(int32_t type) lastsym->type = stype; } } +/* called from elf_out with type == TY_STABSSYMLIN */ void dwarf64_output(int type, void *param) { (void)type; int ln, aa, inx, maxln, soc; struct symlininfo *s; - + struct SAA *plinep; + + s = (struct symlininfo *)param; + /* line number info is only gathered for executable sections */ + if (!(sects[s->section]->flags & SHF_EXECINSTR)) + return; + /* Check if section index has changed */ + if (!(dwarf_csect && (dwarf_csect->section) == (s->section))) + { + dwarf64_findsect(s->section); + } /* do nothing unless line or file has changed */ if (dwarf_immcall) { - s = (struct symlininfo *)param; - ln = currentline - dwarf_line; - aa = s->offset - dwarf_offset; + ln = currentline - dwarf_csect->line; + aa = s->offset - dwarf_csect->offset; inx = dwarf_clist->line; + plinep = dwarf_csect->psaa; /* check for file change */ - if (!(inx == dwarf_fileinx)) + if (!(inx == dwarf_csect->file)) { WSAACHAR(plinep,workbuf,DW_LNS_set_file); WSAACHAR(plinep,workbuf,inx); - dwarf_fileinx = inx; + dwarf_csect->file = inx; } /* check for line change */ if (ln) @@ -2035,8 +2057,8 @@ void dwarf64_output(int type, void *param) saa_wleb128u(plinep,aa); } } - dwarf_line = currentline; - dwarf_offset = s->offset; + dwarf_csect->line = currentline; + dwarf_csect->offset = s->offset; } /* show change handled */ dwarf_immcall = 0; @@ -2049,18 +2071,45 @@ void dwarf64_generate(void) uint8_t *pbuf; int indx; struct linelist *ftentry; - struct SAA *paranges, *ppubnames, *pinfo, *pabbrev, *plines; - size_t saalen, linepoff; + struct SAA *paranges, *ppubnames, *pinfo, *pabbrev, *plines, *plinep; + struct SAA *parangesrel, *plinesrel; + struct sectlist *psect; + size_t saalen, linepoff, totlen, highaddr; - /* build aranges section */ + /* write epilogues for each line program range */ + /* and build aranges section */ paranges = saa_init(1L); + parangesrel = saa_init(1L); WSAASHORT(paranges,workbuf,3); /* dwarf version */ WSAALONG(paranges,workbuf,0); /* offset into info */ WSAACHAR(paranges,workbuf,8); /* pointer size */ WSAACHAR(paranges,workbuf,0); /* not segmented */ WSAALONG(paranges,workbuf,0); /* padding */ - WSAADLONG(paranges,workbuf,0x0000); /* 1st address */ - WSAADLONG(paranges,workbuf,0x108); /* 1st length */ + /* iterate though sectlist entries */ + psect = dwarf_fsect; + totlen = 0; + highaddr = 0; + for (indx = 0; indx < dwarf_nsections; indx++) + { + plinep = psect->psaa; + /* Line Number Program Epilogue */ + WSAACHAR(plinep,workbuf,2); /* std op 2 */ + WSAACHAR(plinep,workbuf,(sects[psect->section]->len)-psect->offset); + WSAACHAR(plinep,workbuf,DW_LNS_extended_op); + WSAACHAR(plinep,workbuf,1); /* operand length */ + WSAACHAR(plinep,workbuf,DW_LNE_end_sequence); + totlen += plinep->datalen; + /* range table relocation entry */ + WSAADLONG(parangesrel,workbuf, paranges->datalen + 4); + WSAADLONG(parangesrel,workbuf, ((uint64_t) (psect->section + 2) << 32) + R_X86_64_64); + WSAADLONG(parangesrel,workbuf, (uint64_t) 0); + /* range table entry */ + WSAADLONG(paranges,workbuf,0x0000); /* range start */ + WSAADLONG(paranges,workbuf,sects[psect->section]->len); /* range length */ + highaddr += sects[psect->section]->len; + /* done with this entry */ + psect = psect->next; + } WSAADLONG(paranges,workbuf,0); /* null address */ WSAADLONG(paranges,workbuf,0); /* null length */ saalen = paranges->datalen; @@ -2071,11 +2120,10 @@ void dwarf64_generate(void) saa_free(paranges); /* build rela.aranges section */ - arangesrellen = 24; + arangesrellen = saalen = parangesrel->datalen; arangesrelbuf = pbuf = nasm_malloc(arangesrellen); - WRITEDLONG(pbuf, 16); - WRITEDLONG(pbuf, (2L << 32) + R_X86_64_64); - WRITEDLONG(pbuf, (uint64_t) 0); + memcpy(pbuf, saa_rbytes(parangesrel, &saalen), saalen); + saa_free(parangesrel); /* build pubnames section */ ppubnames = saa_init(1L); @@ -2097,7 +2145,7 @@ void dwarf64_generate(void) WSAACHAR(pinfo,workbuf,8); /* pointer size */ WSAACHAR(pinfo,workbuf,1); /* abbrviation number LEB128u */ WSAADLONG(pinfo,workbuf,0); /* DW_AT_low_pc */ - WSAADLONG(pinfo,workbuf,108); /* DW_AT_high_pc */ + WSAADLONG(pinfo,workbuf,highaddr); /* DW_AT_high_pc */ WSAALONG(pinfo,workbuf,0); /* DW_AT_stmt_list */ strcpy(workbuf,elf_module); /* input file name */ saa_wbytes(pinfo, workbuf, (int32_t)(strlen(elf_module) + 1)); @@ -2116,10 +2164,10 @@ void dwarf64_generate(void) inforellen = 48; inforelbuf = pbuf = nasm_malloc(inforellen); WRITEDLONG(pbuf, 12); - WRITEDLONG(pbuf, (2L << 32) + R_X86_64_64); + WRITEDLONG(pbuf, (2LL << 32) + R_X86_64_64); WRITEDLONG(pbuf, (uint64_t) 0); WRITEDLONG(pbuf, 20); - WRITEDLONG(pbuf, (2L << 32) + R_X86_64_64); + WRITEDLONG(pbuf, (2LL << 32) + R_X86_64_64); WRITEDLONG(pbuf, (uint64_t) 0); /* build abbrev section */ @@ -2151,9 +2199,6 @@ void dwarf64_generate(void) memcpy(pbuf, saa_rbytes(pabbrev, &saalen), saalen); saa_free(pabbrev); - - - /* build line section */ /* prolog */ plines = saa_init(1L); @@ -2188,33 +2233,42 @@ void dwarf64_generate(void) ftentry = ftentry->next; } WSAACHAR(plines,workbuf,0); /* End of table */ - /* Line Number Program Epilogue */ - WSAACHAR(plinep,workbuf,2); /* std op 2 */ - WSAACHAR(plinep,workbuf,1); - WSAACHAR(plinep,workbuf,DW_LNS_extended_op); - WSAACHAR(plinep,workbuf,1); /* operand length */ - WSAACHAR(plinep,workbuf,DW_LNE_end_sequence); linepoff = plines->datalen; - linelen = linepoff + plinep->datalen + 10; + linelen = linepoff + totlen + 10; linebuf = pbuf = nasm_malloc(linelen); WRITELONG(pbuf,linelen-4); /* initial length */ WRITESHORT(pbuf,3); /* dwarf version */ WRITELONG(pbuf,linepoff); /* offset to line number program */ + /* write line header */ saalen = linepoff; memcpy(pbuf, saa_rbytes(plines, &saalen), saalen); pbuf += linepoff; saa_free(plines); - saalen = plinep->datalen; - memcpy(pbuf, saa_rbytes(plinep, &saalen), saalen); - saa_free(plinep); + /* concatonate line program ranges */ + linepoff += 13; + plinesrel = saa_init(1L); + psect = dwarf_fsect; + for (indx = 0; indx < dwarf_nsections; indx++) + { + WSAADLONG(plinesrel,workbuf, linepoff); + WSAADLONG(plinesrel,workbuf, ((uint64_t) (psect->section + 2) << 32) + R_X86_64_64); + WSAADLONG(plinesrel,workbuf, (uint64_t) 0); + plinep = psect->psaa; + saalen = plinep->datalen; + memcpy(pbuf, saa_rbytes(plinep, &saalen), saalen); + pbuf += saalen; + linepoff += saalen; + saa_free(plinep); + /* done with this entry */ + psect = psect->next; + } + /* build rela.lines section */ - linerellen = 24; + linerellen =saalen = plinesrel->datalen; linerelbuf = pbuf = nasm_malloc(linerellen); - WRITEDLONG(pbuf, linepoff + 13); - WRITEDLONG(pbuf, (2L << 32) + R_X86_64_64); - WRITEDLONG(pbuf, (uint64_t) 0); - + memcpy(pbuf, saa_rbytes(plinesrel, &saalen), saalen); + saa_free(plinesrel); /* build frame section */ framelen = 4; @@ -2295,6 +2349,63 @@ void dwarf64_findfile(const char * fname) } } } +/* */ +void dwarf64_findsect(const int index) +{ + int sinx; + struct sectlist *match; + struct SAA *plinep; + /* return if index is current section index */ + if (dwarf_csect && (dwarf_csect->section == index)) + { + return; + } + /* search for match */ + else + { + match = 0; + if (dwarf_fsect) + { + match = dwarf_fsect; + for (sinx = 0; sinx < dwarf_nsections; sinx++) + { + if ((match->section == index)) + { + dwarf_csect = match; + return; + } + match = match->next; + } + } + /* add entry to end of list */ + dwarf_csect = (struct sectlist *)nasm_malloc(sizeof(struct sectlist)); + dwarf_nsections++; + dwarf_csect->psaa = plinep = saa_init(1L); + dwarf_csect->line = 1; + dwarf_csect->offset = 0; + dwarf_csect->file = 1; + dwarf_csect->section = index; + dwarf_csect->next = 0; + /* set relocatable address at start of line program */ + WSAACHAR(plinep,workbuf,DW_LNS_extended_op); + WSAACHAR(plinep,workbuf,9); /* operand length */ + WSAACHAR(plinep,workbuf,DW_LNE_set_address); + WSAADLONG(plinep,workbuf,0); /* Start Address */ + /* if first entry */ + if (!dwarf_fsect) + { + dwarf_fsect = dwarf_esect = dwarf_csect; + dwarf_csect->last = 0; + } + /* chain to previous entry */ + else + { + dwarf_esect->next = dwarf_csect; + dwarf_esect = dwarf_csect; + } + } +} + /* write unsigned LEB128 value to SAA */ void saa_wleb128u(struct SAA *psaa, int value) { |