From 48ba82a9755eae5da6e24d1381ea3bcf72ebb9ef Mon Sep 17 00:00:00 2001 From: epetrich Date: Thu, 13 May 2004 22:10:41 +0000 Subject: [PATCH] * src/hc08/gen.c (hc08_emitDebuggerSymbol), * src/hc08/main.c, * src/mcs51/gen.c (mcs51_emitDebuggerSymbol), * src/mcs51/main.c, * src/ds390/gen.c (ds390_emitDebuggerSymbol), * src/ds390/main.c, * src/z80/gen.c (z80_emitDebuggerSymbol), * src/z80/main.c, * src/pic/gen.c (pic14_emitDebuggerSymbol), * src/pic/main.c, * src/pic16/gen.c (pic14_emitDebuggerSymbol), * src/pic16/main.c, * src/avr/gen.c (avr_emitDebuggerSymbol), * src/avr/main.c, * src/xa51/gen.c (xa51_emitDebuggerSymbol), * src/xa51/main.c, * src/SDCCdebug.c (emitDebuggerSymbol), * src/SDCCdebug.h, * src/port.h: added a debugger struct to the port struct. Added a callback for defining debugger symbols * src/SDCCast.c (createLabel), * src/SDCC.y (labeled_statement): mark all compiler generated labels with isitmp = 1 * src/SDCCicode.h, * src/SDCCicode.c (geniCodeFunctionBody): added a link from the FUNCTION iCode back to the ast for the function * src/hc08/ralloc.c (hc08_assignRegisters), * src/hc08/ralloc.h: define a regs struct for the stack pointer. Removed unneeded fields from the regs struct. * src/hc08/gen.c (transferRegReg, genFunction, genEndFunction): use the pushReg() & pullReg() functions instead of emitcode() * src/hc08/gen.c (genLabel, genhc08Code), * src/SDCCdebug.h: Added additional debugger hooks needed for DWARF * src/cdbFile.c (cdbWriteLabel, cdbWriteScope): Added stubs for unneeded debugger hooks * src/hc08/gen.c (genEndFunction, genhc08Code), * src/hc08/gen.h, * src/mcs51/gen.c (genEndFunction, gen51Code), * src/mcs51/gen.h, * src/ds390/gen.c (genEndFunction, gen390Code), * src/ds390/gen.h, * src/z80/gen.c (genEndFunction, genZ80Code), * src/z80/gen.h, * src/z80/z80.h, * src/pic/gen.c (genEndFunction, genpic14Code), * src/pic/gen.h, * src/pic16/gen.c (genEndFunction, genpic16Code), * src/pic16/gen.h, * src/avr/gen.c (genEndFunction, genAVRCode), * src/avr/gen.h, * src/xa51/gen.c (genEndFunction, genXA51Code), * src/xa51/gen.h, * src/cdbFile.c (cdbWriteFunction, cdbWriteEndFunction): moved cdb specific code to cdbFile.c and out of the backend code generators * as/hc08/lkmain.c (main): removed OMF51 support from link-hc08 * as/hc08/lkarea.c (lnkarea): areas with NOLOAD attribute default starting address is now 0 * as/hc08/asm.h, * as/hc08/m08pst.c, * as/hc08/asmain.c (asmbl): implemented the .sleb128 and .uleb128 assembler directive for DWARF support * as/hc08/lkelf.c (elf): only increment address when rtflg[] set * src/src.dsp, * src/Makefile.in, * src/SDCCdwarf2.c: preliminary DWARF (ver 2) debugger data generator git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@3305 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- as/hc08/asm.h | 3 +- as/hc08/asmain.c | 31 + as/hc08/lkarea.c | 7 +- as/hc08/lkelf.c | 3 +- as/hc08/lkmain.c | 2 +- as/hc08/m08pst.c | 2 + src/Makefile.in | 2 +- src/SDCC.y | 3 +- src/SDCCast.c | 1 + src/SDCCdwarf2.c | 3032 +++++++++++++++++++++++++++++++++++++++++++++ src/SDCCdwarf2.h | 425 +++++++ src/SDCCicode.c | 2 + src/SDCCicode.h | 1 + src/avr/gen.h | 3 +- src/cdbFile.c | 117 +- src/ds390/gen.h | 1 + src/hc08/gen.h | 1 + src/hc08/ralloc.c | 22 +- src/hc08/ralloc.h | 8 +- src/mcs51/gen.h | 1 + src/pic/gen.h | 1 + src/pic16/gen.h | 1 + src/src.dsp | 8 + src/xa51/gen.h | 2 + src/z80/gen.h | 1 + src/z80/z80.h | 1 + 26 files changed, 3656 insertions(+), 25 deletions(-) create mode 100644 src/SDCCdwarf2.c create mode 100644 src/SDCCdwarf2.h diff --git a/as/hc08/asm.h b/as/hc08/asm.h index 948992a4..c7b1b6c7 100644 --- a/as/hc08/asm.h +++ b/as/hc08/asm.h @@ -332,7 +332,8 @@ struct sym #define S_ASCIS 26 /* .ascis */ #define S_FLAT24 27 /* .flat24 */ #define S_OPTSDCC 28 /* .optsdcc */ - +#define S_ULEB128 29 /* .uleb128 */ +#define S_SLEB128 30 /* .sleb128 */ /* * The tsym structure is a linked list of temporary diff --git a/as/hc08/asmain.c b/as/hc08/asmain.c index cb987f55..2ed786af 100644 --- a/as/hc08/asmain.c +++ b/as/hc08/asmain.c @@ -740,6 +740,37 @@ loop: } while ((c = getnb()) == ','); unget(c); break; + + case S_ULEB128: + case S_SLEB128: + do { + Addr_T val = absexpr(); + int bit = sizeof(val)*8 - 1; + int impliedBit; + + if (mp->m_type == S_ULEB128) { + impliedBit = 0; + } else { + impliedBit = (val & (1 << bit)) ? 1 : 0; + } + while ((bit>0) && (((val & (1 << bit)) ? 1 : 0) == impliedBit)) { + bit--; + } + if (mp->m_type == S_SLEB128) { + bit++; + } + while (bit>=0) { + if (bit<7) { + outab(val & 0x7f); + } else { + outab(0x80 | (val & 0x7f)); + } + bit -= 7; + val >>= 7; + } + } while ((c = getnb()) == ','); + unget(c); + break; case S_ASCII: case S_ASCIZ: diff --git a/as/hc08/lkarea.c b/as/hc08/lkarea.c index 42cdd4c1..5b8eaf85 100644 --- a/as/hc08/lkarea.c +++ b/as/hc08/lkarea.c @@ -350,7 +350,12 @@ lnkarea() * Relocatable sections */ if (ap->a_type == 0) { /* JLH */ - ap->a_addr = rloc[ locIndex ]; + if (ap->a_flag & A_NOLOAD) { + locIndex = 2; + ap->a_addr = 0; + } else { + ap->a_addr = rloc[ locIndex ]; + } ap->a_type = 1; } lnksect(ap); diff --git a/as/hc08/lkelf.c b/as/hc08/lkelf.c index edaad5bc..3cc602fd 100644 --- a/as/hc08/lkelf.c +++ b/as/hc08/lkelf.c @@ -753,7 +753,7 @@ elf (int i) } /* Copy the data into the image buffer */ - for (i = 2; i < rtcnt ; i++, address++) + for (i = 2; i < rtcnt ; i++) { if (rtflg[i]) { @@ -775,6 +775,7 @@ elf (int i) execStartLSBfound = 1; } } + address++; } } } diff --git a/as/hc08/lkmain.c b/as/hc08/lkmain.c index 882b5ca9..14003b7e 100644 --- a/as/hc08/lkmain.c +++ b/as/hc08/lkmain.c @@ -375,7 +375,7 @@ char *argv[]; } } //JCF: - CreateAOMF51(); + //CreateAOMF51(); #ifdef WIN32T Timer(1, "Linker execution time"); diff --git a/as/hc08/m08pst.c b/as/hc08/m08pst.c index 57f44e18..0da9cc9c 100644 --- a/as/hc08/m08pst.c +++ b/as/hc08/m08pst.c @@ -33,6 +33,8 @@ struct mne mne[] = { { NULL, "LOAD", S_ATYP, 0, A_LOAD }, { NULL, "NOLOAD", S_ATYP, 0, A_NOLOAD }, + { NULL, ".uleb128", S_ULEB128, 0, 0 }, + { NULL, ".sleb128", S_SLEB128, 0, 0 }, { NULL, ".byte", S_BYTE, 0, 1 }, { NULL, ".db", S_BYTE, 0, 1 }, { NULL, ".word", S_WORD, 0, 2 }, diff --git a/src/Makefile.in b/src/Makefile.in index 26478f8b..8dcdf7fe 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -27,7 +27,7 @@ OBJECTS = SDCCy.o SDCChasht.o SDCCmain.o \ SDCCicode.o SDCCbitv.o SDCCset.o SDCClabel.o \ SDCCBBlock.o SDCCloop.o SDCCcse.o SDCCcflow.o SDCCdflow.o \ SDCClrange.o SDCCptropt.o SDCCpeeph.o SDCCglue.o \ - asm.o SDCCmacro.o SDCCutil.o SDCCdebug.o cdbFile.o + asm.o SDCCmacro.o SDCCutil.o SDCCdebug.o cdbFile.o SDCCdwarf2.o SPECIAL = SDCCy.h ifeq ($(USE_ALT_LEX), 1) diff --git a/src/SDCC.y b/src/SDCC.y index 442e17e5..77182a48 100644 --- a/src/SDCC.y +++ b/src/SDCC.y @@ -1399,7 +1399,8 @@ critical_statement labeled_statement // : identifier ':' statement { $$ = createLabel($1,$3); } - : identifier ':' { $$ = createLabel($1,NULL); } + : identifier ':' { $$ = createLabel($1,NULL); + $1->isitmp = 0; } | CASE constant_expr ':' { if (STACK_EMPTY(swStk)) diff --git a/src/SDCCast.c b/src/SDCCast.c index f44ae1cc..a3fb39df 100644 --- a/src/SDCCast.c +++ b/src/SDCCast.c @@ -4446,6 +4446,7 @@ createLabel (symbol * label, ast * stmnt) else addSym (LabelTab, label, name, label->level, 0, 0); + label->isitmp = 1; label->islbl = 1; label->key = labelKey++; rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt); diff --git a/src/SDCCdwarf2.c b/src/SDCCdwarf2.c new file mode 100644 index 00000000..5a9c22c8 --- /dev/null +++ b/src/SDCCdwarf2.c @@ -0,0 +1,3032 @@ +/*------------------------------------------------------------------------- + SDCCdwarf2.c - generate DWARF2 debug information + + Written By - Erik Petrich . epetrich@users.sourceforge.net (2004) + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! +-------------------------------------------------------------------------*/ + + +#include "common.h" +#include "SDCCdwarf2.h" + +/************************************************************* + * + * + * + * + *************************************************************/ + +extern set *includeDirsSet; + +int dwOpenFile(char *file); +int dwCloseFile(void); +int dwWriteFunction(symbol *pSym, iCode *ic); +int dwWriteEndFunction(symbol *pSym, iCode *ic, int offset); +int dwWriteLabel(symbol *pSym, iCode *ic); +int dwWriteScope(iCode *ic); +int dwWriteSymbol(symbol *pSym); +int dwWriteType(structdef *sdef, int block, int inStruct, char *tag); +int dwWriteModule(char *name); +int dwWriteCLine(iCode *ic); +int dwWriteALine(char *module, int Line); +int dwWriteFrameAddress(char *variable, struct regs *reg, int offset); +int dwWriteBasicSymbol(symbol *sym, int isStructSym, int isFunc); + + +DEBUGFILE dwarf2DebugFile = + { + &dwOpenFile, + &dwCloseFile, + &dwWriteModule, + &dwWriteFunction, + &dwWriteEndFunction, + &dwWriteLabel, + &dwWriteScope, + &dwWriteSymbol, + &dwWriteType, + &dwWriteCLine, + &dwWriteALine, + &dwWriteFrameAddress + }; + +FILE *dwarf2FilePtr = NULL; +char *dwModuleName = NULL; +dwtag *dwRootTag = NULL; +dwtag *dwFuncTag = NULL; +dwtag *dwScopeTag = NULL; +hTab * dwAbbrevTable; +int dwAbbrevNum = 0; +hTab * dwTypeTagTable; +int dwRefNum = 0; +int dwScopeBlock = 0; +int dwScopeLevel = 0; +int dwDebugSymbol = 0; +//dwcfins * dwCIEins = NULL; +dwlocregion * dwFrameLastLoc = NULL; +dwloclist * dwRootLocList = NULL; +dwloclist * dwFrameLocList = NULL; +int dwLineBase = -5; +int dwLineRange = 15; +int dwLineOpcodeBase = 10; +set * dwFilenameSet = NULL; +dwline * dwLineFirst = NULL; +dwline * dwLineLast = NULL; + + +/*----------------------------------------------------------------------*/ +/* dwNewDebugSymbol - returns the name for a new debug symbol */ +/*----------------------------------------------------------------------*/ +static char * +dwNewDebugSymbol () +{ + char debugSym[SDCC_NAME_MAX]; + + sprintf (debugSym, "S%s$%s$%d", moduleName, currFunc->name, dwDebugSymbol); + dwDebugSymbol++; + return Safe_strdup (debugSym); +} + + +/*----------------------------------------------------------------------*/ +/* dwWriteByte - generate a single byte assembler constant in the form: */ +/* */ +/* .db label+offset ; comment */ +/* */ +/* The label and comment parameters are optional */ +/*----------------------------------------------------------------------*/ +static void +dwWriteByte (char * label, int offset, char * comment) +{ + tfprintf (dwarf2FilePtr, "\t!db\t"); + if (label) + { + if (offset) + fprintf (dwarf2FilePtr, "%s+%d", label, offset); + else + fprintf (dwarf2FilePtr, "%s", label); + } + else + fprintf (dwarf2FilePtr, "%d", offset); + + if (comment) + fprintf (dwarf2FilePtr, "\t;%s\n", comment); + else + fprintf (dwarf2FilePtr, "\n"); +} + +/*----------------------------------------------------------------------*/ +/* dwWriteHalf - generate a two byte assembler constant in the form: */ +/* */ +/* .dw label+offset ; comment */ +/* */ +/* The label and comment parameters are optional */ +/*----------------------------------------------------------------------*/ +static void +dwWriteHalf (char * label, int offset, char * comment) +{ + tfprintf (dwarf2FilePtr, "\t!dw\t"); + if (label) + { + if (offset) + fprintf (dwarf2FilePtr, "%s+%d", label, offset); + else + fprintf (dwarf2FilePtr, "%s", label); + } + else + fprintf (dwarf2FilePtr, "%d", offset); + + if (comment) + fprintf (dwarf2FilePtr, "\t;%s\n", comment); + else + fprintf (dwarf2FilePtr, "\n"); +} + +/*----------------------------------------------------------------------*/ +/* dwWriteWord - generate a four byte assembler constant in the form: */ +/* */ +/* .dd label+offset ; comment */ +/* */ +/* The label and comment parameters are optional */ +/*----------------------------------------------------------------------*/ +static void +dwWriteWord (char * label, int offset, char * comment) +{ + /* FIXME: need to implement !dd pseudo-op in the assember. In the */ + /* meantime, we use dw with zero padding and hope the values fit */ + /* in only 16 bits. */ +#if 0 + tfprintf (dwarf2FilePtr, "\t!dd\t"); + if (label) + { + if (offset) + fprintf (dwarf2FilePtr, "%s+%d", label, offset); + else + fprintf (dwarf2FilePtr, "%s", label); + } + else + fprintf (dwarf2FilePtr, "%d", offset); +#else + tfprintf (dwarf2FilePtr, "\t!dw\t"); + if (port->little_endian) + { + if (label) + { + if (offset) + fprintf (dwarf2FilePtr, "(%s+%d),0", label, offset); + else + fprintf (dwarf2FilePtr, "(%s),0", label); + } + else + fprintf (dwarf2FilePtr, "%d,%d", offset, offset >> 16); + } + else + { + if (label) + { + if (offset) + fprintf (dwarf2FilePtr, "0,(%s+%d)", label, offset); + else + fprintf (dwarf2FilePtr, "0,(%s)", label); + } + else + fprintf (dwarf2FilePtr, "%d,%d", offset >> 16, offset); + } +#endif + + if (comment) + fprintf (dwarf2FilePtr, "\t;%s\n", comment); + else + fprintf (dwarf2FilePtr, "\n"); +} + + +/*----------------------------------------------------------------------*/ +/* dwWriteULEB128 - generate an unsigned variable length assembler */ +/* constant in the form: */ +/* */ +/* .uleb128 label+offset ; comment */ +/* */ +/* The label and comment parameters are optional */ +/*----------------------------------------------------------------------*/ +static void +dwWriteULEB128 (char * label, int offset, char * comment) +{ + tfprintf (dwarf2FilePtr, "\t.uleb128\t"); + if (label) + { + if (offset) + fprintf (dwarf2FilePtr, "%s+%d", label, offset); + else + fprintf (dwarf2FilePtr, "%s", label); + } + else + fprintf (dwarf2FilePtr, "%d", offset); + + if (comment) + fprintf (dwarf2FilePtr, "\t;%s\n", comment); + else + fprintf (dwarf2FilePtr, "\n"); +} + +/*----------------------------------------------------------------------*/ +/* dwWriteSLEB128 - generate a signed variable length assembler */ +/* constant in the form: */ +/* */ +/* .sleb128 label+offset ; comment */ +/* */ +/* The label and comment parameters are optional */ +/*----------------------------------------------------------------------*/ +static void +dwWriteSLEB128 (char * label, int offset, char * comment) +{ + tfprintf (dwarf2FilePtr, "\t.sleb128\t"); + if (label) + { + if (offset) + fprintf (dwarf2FilePtr, "%s+%d", label, offset); + else + fprintf (dwarf2FilePtr, "%s", label); + } + else + fprintf (dwarf2FilePtr, "%d", offset); + + if (comment) + fprintf (dwarf2FilePtr, "\t;%s\n", comment); + else + fprintf (dwarf2FilePtr, "\n"); +} + + +/*----------------------------------------------------------------------*/ +/* dwSizeofULEB128 - return the size (in bytes) of an unsigned variable */ +/* length constant */ +/*----------------------------------------------------------------------*/ +static int +dwSizeofULEB128 (int unsigned value) +{ + int size = 0; + + do + { + value >>= 7; + size++; + } + while (value); + + return size; +} + +/*----------------------------------------------------------------------*/ +/* dwSizeofSLEB128 - return the size (in bytes) of a signed variable */ +/* length constant */ +/*----------------------------------------------------------------------*/ +static int +dwSizeofSLEB128 (int value) +{ + int size = 0; + int negative = (value < 0); + int sign; + + while (1) + { + size++; + sign = value & 0x40; + value >>= 7; + if (negative) + value |= (0x7f << (sizeof(int)*8 - 7)); + if ((value == 0 && !sign) || (value == -1 && sign)) + break; + } + + return size; +} + +/*----------------------------------------------------------------------*/ +/* dwWriteString - generate a string constant in the form: */ +/* */ +/* .ascii /string/ ; comment */ +/* */ +/* The comment parameter is optional. The string may contain any */ +/* non-null characters */ +/*----------------------------------------------------------------------*/ +static void +dwWriteString (char * string, char * comment) +{ + /* FIXME: need to safely handle nonalphanumeric data in string */ + + tfprintf (dwarf2FilePtr, "\t!ascii\n", string); + dwWriteByte (NULL, 0, comment); +} + + +/*----------------------------------------------------------------------*/ +/* dwWriteAddress - generate an assembler constant in the form: */ +/* */ +/* .dw label+offset ; comment */ +/* or .dd label+offset ; comment */ +/* */ +/* depending on how the relevant ABI defines the address size (may be */ +/* larger than the CPU's actual address size). The label and comment */ +/* parameters are optional */ +/*----------------------------------------------------------------------*/ +static void +dwWriteAddress (char * label, int offset, char * comment) +{ + switch (port->debugger.dwarf.addressSize) + { + case 2: + dwWriteHalf (label, offset, comment); + break; + case 4: + dwWriteWord (label, offset, comment); + break; + default: + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + "unsupported port->debugger.dwarf.addressSize"); + } +} + + +/*----------------------------------------------------------------------*/ +/* dwWriteHalfDelta - generate a two byte assembler constant in the */ +/* form: */ +/* */ +/* .dw offset+label1-label2 */ +/* */ +/* The offset parameter is optional */ +/*----------------------------------------------------------------------*/ +static void +dwWriteHalfDelta (char * label1, char * label2, int offset) +{ + if (offset) + tfprintf (dwarf2FilePtr, "\t!dw\t%d+%s-%s\n", offset, label1, label2); + else + tfprintf (dwarf2FilePtr, "\t!dw\t%s-%s\n", label1, label2); +} + +/*----------------------------------------------------------------------*/ +/* dwWriteWordDelta - generate a four byte assembler constant in the */ +/* form: */ +/* */ +/* .dd label1-label2 */ +/*----------------------------------------------------------------------*/ +static void +dwWriteWordDelta (char * label1, char * label2) +{ + /* FIXME: need to implement !dd pseudo-op; this hack only */ + /* works for positive offsets of less than 64k */ +#if 0 + tfprintf (dwarf2FilePtr, "\t!dd\t%s-%s\n", label1,label2); +#else + if (port->little_endian) + { + tfprintf (dwarf2FilePtr, "\t!dw\t%s-%s,%d\n", label1, label2, 0); + } + else + { + tfprintf (dwarf2FilePtr, "\t!dw\t%d,%s-%s\n", 0, label1, label2); + } +#endif +} + + +/* disabled to eliminiate unused function warning */ +#if 0 +/*----------------------------------------------------------------------*/ +/* dwWriteAddressDelta - generate an assembler constant in the form: */ +/* */ +/* .dw label1-label2 */ +/* or .dd label1-label2 */ +/* */ +/* depending on how the relevant ABI defines the address size (may be */ +/* larger than the CPU's actual address size) */ +/*----------------------------------------------------------------------*/ +static void +dwWriteAddressDelta (char * label1, char * label2) +{ + switch (port->debugger.dwarf.addressSize) + { + case 2: + dwWriteHalfDelta (label1, label2, 0); + break; + case 4: + dwWriteWordDelta (label1, label2); + break; + default: + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + "unsupported port->debugger.dwarf.addressSize"); + } +} + +/*----------------------------------------------------------------------*/ +/* dwWriteULEB128Delta - generate an unsigned variable byte assembler */ +/* constant in the form: */ +/* */ +/* .uleb128 offset+label1-label2 */ +/* */ +/* The offset parameter is optional */ +/*----------------------------------------------------------------------*/ +static void +dwWriteULEB128Delta (char * label1, char * label2, int offset) +{ + if (offset) + tfprintf (dwarf2FilePtr, "\t.uleb128\t%d+%s-%s\n", offset, label1, label2); + else + tfprintf (dwarf2FilePtr, "\t.uleb128\t%s-%s\n", label1, label2); +} +#endif + +/*------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* dwNewLoc - allocates a new location expression node */ +/*----------------------------------------------------------------------*/ +dwloc * +dwNewLoc (int opcode, char * label, int offset) +{ + dwloc * lp; + + lp = Safe_alloc (sizeof (dwloc)); + + lp->opcode = opcode; + lp->operand.label = label; + lp->operand.offset = offset; + + return lp; +} + +/*-------------------------------------------------------------------------*/ +/* dwSizeofLoc - returns the size (in bytes) of a chain of location */ +/* expression nodes as they would be encoded by dwWriteLoc() */ +/*-------------------------------------------------------------------------*/ +static int +dwSizeofLoc (dwloc * lp) +{ + int size = 0; + + while (lp) + { + size++; + switch (lp->opcode) + { + case DW_OP_addr: + size += port->debugger.dwarf.addressSize; + break; + + case DW_OP_deref_size: + case DW_OP_xderef_size: + case DW_OP_pick: + case DW_OP_const1u: + case DW_OP_const1s: + size += 1; + break; + + case DW_OP_skip: + case DW_OP_bra: + case DW_OP_const2u: + case DW_OP_const2s: + size += 2; + break; + + case DW_OP_const4u: + case DW_OP_const4s: + size += 4; + break; + + case DW_OP_const8u: + case DW_OP_const8s: + size += 8; + break; + + case DW_OP_piece: + case DW_OP_regx: + case DW_OP_plus_uconst: + size += dwSizeofULEB128 (lp->operand.offset); + break; + + case DW_OP_breg0: + case DW_OP_breg1: + case DW_OP_breg2: + case DW_OP_breg3: + case DW_OP_breg4: + case DW_OP_breg5: + case DW_OP_breg6: + case DW_OP_breg7: + case DW_OP_breg8: + case DW_OP_breg9: + case DW_OP_breg10: + case DW_OP_breg11: + case DW_OP_breg12: + case DW_OP_breg13: + case DW_OP_breg14: + case DW_OP_breg15: + case DW_OP_breg16: + case DW_OP_breg17: + case DW_OP_breg18: + case DW_OP_breg19: + case DW_OP_breg20: + case DW_OP_breg21: + case DW_OP_breg22: + case DW_OP_breg23: + case DW_OP_breg24: + case DW_OP_breg25: + case DW_OP_breg26: + case DW_OP_breg27: + case DW_OP_breg28: + case DW_OP_breg29: + case DW_OP_breg30: + case DW_OP_breg31: + case DW_OP_fbreg: + size += dwSizeofSLEB128 (lp->operand.offset); + break; + } + + lp = lp->next; + } + + return size; +} + +/*------------------------------------------------------------------------*/ +/* dwWriteLoc - writes a chain of location expression nodes */ +/*------------------------------------------------------------------------*/ +static void +dwWriteLoc (dwloc *lp) +{ + while (lp) + { + dwWriteByte (NULL, lp->opcode, NULL); + switch (lp->opcode) + { + case DW_OP_addr: + dwWriteAddress (lp->operand.label, lp->operand.offset, NULL); + break; + + case DW_OP_deref_size: + case DW_OP_xderef_size: + case DW_OP_pick: + case DW_OP_const1u: + case DW_OP_const1s: + dwWriteByte (NULL, lp->operand.offset, NULL); + break; + + case DW_OP_skip: + case DW_OP_bra: + case DW_OP_const2u: + case DW_OP_const2s: + dwWriteHalf (NULL, lp->operand.offset, NULL); + break; + + case DW_OP_const4u: + case DW_OP_const4s: + dwWriteWord (NULL, lp->operand.offset, NULL); + break; + + case DW_OP_piece: + case DW_OP_regx: + case DW_OP_plus_uconst: + dwWriteULEB128 (NULL, lp->operand.offset, NULL); + break; + + case DW_OP_breg0: + case DW_OP_breg1: + case DW_OP_breg2: + case DW_OP_breg3: + case DW_OP_breg4: + case DW_OP_breg5: + case DW_OP_breg6: + case DW_OP_breg7: + case DW_OP_breg8: + case DW_OP_breg9: + case DW_OP_breg10: + case DW_OP_breg11: + case DW_OP_breg12: + case DW_OP_breg13: + case DW_OP_breg14: + case DW_OP_breg15: + case DW_OP_breg16: + case DW_OP_breg17: + case DW_OP_breg18: + case DW_OP_breg19: + case DW_OP_breg20: + case DW_OP_breg21: + case DW_OP_breg22: + case DW_OP_breg23: + case DW_OP_breg24: + case DW_OP_breg25: + case DW_OP_breg26: + case DW_OP_breg27: + case DW_OP_breg28: + case DW_OP_breg29: + case DW_OP_breg30: + case DW_OP_breg31: + case DW_OP_fbreg: + dwWriteSLEB128 (NULL, lp->operand.offset, NULL); + break; + } + + lp = lp->next; + } +} + +/*----------------------------------------------------------------------*/ +/* dwNewLocList - allocates a new list of location expression node */ +/*----------------------------------------------------------------------*/ +static dwloclist * +dwNewLocList (void) +{ + dwloclist * llp; + + llp = Safe_alloc (sizeof (dwloclist)); + + return llp; +} + +/*----------------------------------------------------------------------*/ +/* dwSizeofLocRegion - returns the size (in bytes) of a chain of */ +/* location regions (inluding their location */ +/* expression nodes) as encoded by dwWriteLocLists */ +/*----------------------------------------------------------------------*/ +static int +dwSizeofLocRegion (dwlocregion * lrp) +{ + int size = 0; + + while (lrp) + { + size += 2 * port->debugger.dwarf.addressSize; + size += 2 + dwSizeofLoc (lrp->loc); + lrp = lrp->next; + } + + size += 2 * port->debugger.dwarf.addressSize; + return size; +} + +/*-----------------------------------------------------------------------*/ +/* dwAssignLocListAddresses - assign the address offsets of the location */ +/* lists so that they can be referenced from */ +/* the tag structure */ +/*-----------------------------------------------------------------------*/ +static void +dwAssignLocListAddresses (void) +{ + dwloclist * llp; + int address = 0; + + llp = dwRootLocList; + while (llp) + { + llp->baseOffset = address; + address += dwSizeofLocRegion (llp->region); + + llp = llp->next; + } +} + +/*-----------------------------------------------------------------------*/ +/* dwWriteLocLists - write all of the location lists in dwRootLocList to */ +/* the .debug_loc section */ +/*-----------------------------------------------------------------------*/ +static void +dwWriteLocLists (void) +{ + dwlocregion * lrp; + dwloclist * llp; + + tfprintf (dwarf2FilePtr, "\n\t!area\n", ".debug_loc (NOLOAD)"); + tfprintf (dwarf2FilePtr, "!slabeldef\n", "Ldebug_loc_start"); + + llp = dwRootLocList; + while (llp) + { + //fprintf (dwarf2FilePtr, "; baseOffset = 0x%x\n", llp->baseOffset); + lrp = llp->region; + while (lrp) + { + dwWriteAddress (lrp->startLabel, 0, NULL); + dwWriteAddress (lrp->endLabel, 0, NULL); + dwWriteHalf (NULL, dwSizeofLoc (lrp->loc), NULL); + dwWriteLoc (lrp->loc); + lrp = lrp ->next; + } + + dwWriteAddress (NULL, 0, NULL); + dwWriteAddress (NULL, 0, NULL); + + llp = llp->next; + } + +} + + +/*------------------------------------------------------------------------*/ + + +/*----------------------------------------------------------------------*/ +/* dwNewAttr - allocate a new tag attribute node */ +/*----------------------------------------------------------------------*/ +static dwattr * +dwNewAttr (int attr) +{ + dwattr * ap; + + ap = Safe_alloc ( sizeof (dwattr)); + ap->attr = attr; + + return ap; +} + +/*----------------------------------------------------------------------*/ +/* dwFreeAttr - deallocate a tag attribute node */ +/*----------------------------------------------------------------------*/ +static void +dwFreeAttr (dwattr * ap) +{ + Safe_free (ap); +} + + + +/*-------------------------------------------------------------------------*/ +/* dwNewAttrString - allocate a new tag attribute node with a string value */ +/*-------------------------------------------------------------------------*/ +static dwattr * +dwNewAttrString (int attr, char * string) +{ + dwattr * ap; + + ap = dwNewAttr (attr); + ap->form = DW_FORM_string; + ap->val.string = string; + return ap; +} + + +/*---------------------------------------------------------------------*/ +/* dwNewAttrConst - allocate a new tag attribute node with an unsigned */ +/* numeric constant value */ +/*---------------------------------------------------------------------*/ +static dwattr * +dwNewAttrConst (int attr, unsigned int data) +{ + dwattr * ap; + + ap = dwNewAttr (attr); + if (data <= 0xffu) + ap->form = DW_FORM_data1; + else if (data <= 0xffffu) + ap->form = DW_FORM_data2; + else + ap->form = DW_FORM_data4; + + ap->val.data = data; + return ap; +} + +/* disabled to eliminiate unused function warning */ +#if 0 +/*---------------------------------------------------------------------*/ +/* dwNewAttrSignedConst - allocate a new tag attribute node with a */ +/* signed numeric constant value */ +/*---------------------------------------------------------------------*/ +static dwattr * +dwNewAttrSignedConst (int attr, int data) +{ + dwattr * ap; + + ap = dwNewAttr (attr); + if (data <= 0x7f && data >= -0x80) + ap->form = DW_FORM_data1; + else if (data <= 0xffff && data >= -0x8000) + ap->form = DW_FORM_data2; + else + ap->form = DW_FORM_data4; + + ap->val.data = data; + return ap; +} +#endif + +/*---------------------------------------------------------------------*/ +/* dwNewAttrFlag - allocate a new tag attribute node with a boolean */ +/* flag value (zero/non-zero) */ +/*---------------------------------------------------------------------*/ +static dwattr * +dwNewAttrFlag (int attr, int data) +{ + dwattr * ap; + + ap = dwNewAttr (attr); + ap->form = DW_FORM_flag; + + ap->val.data = data; + return ap; +} + +/*---------------------------------------------------------------------*/ +/* dwNewAttrAddrSymbol - allocate a new tag attribute node with the */ +/* address of a C symbol plus an offset */ +/*---------------------------------------------------------------------*/ +static dwattr * +dwNewAttrAddrSymbol (int attr, symbol * sym, int offset) +{ + dwattr * ap; + + ap = dwNewAttr (attr); + ap->form = DW_FORM_addr; + + ap->val.symaddr.label = sym->rname; + ap->val.symaddr.offset = offset; + return ap; +} + +/*---------------------------------------------------------------------*/ +/* dwNewAttrAddrLabel - allocate a new tag attribute node with the */ +/* address of an assembler label plus an offset */ +/*---------------------------------------------------------------------*/ +static dwattr * +dwNewAttrAddrLabel (int attr, char * label, int offset) +{ + dwattr * ap; + + ap = dwNewAttr (attr); + ap->form = DW_FORM_addr; + + ap->val.symaddr.label = label; + ap->val.symaddr.offset = offset; + return ap; +} + +/*---------------------------------------------------------------------*/ +/* dwNewAttrTagRef - allocate a new tag attribute node that references */ +/* a tag node */ +/*---------------------------------------------------------------------*/ +static dwattr * +dwNewAttrTagRef (int attr, dwtag * tp) +{ + dwattr * ap; + + ap = dwNewAttr (attr); + ap->form = DW_FORM_ref4; + + ap->val.ref = tp; + return ap; +} + +/*---------------------------------------------------------------------*/ +/* dwNewAttrLocRef - allocate a new tag attribute node that references */ +/* a location list */ +/*---------------------------------------------------------------------*/ +static dwattr * +dwNewAttrLocRef (int attr, dwloclist * llp) +{ + dwattr * ap; + + ap = dwNewAttr (attr); + ap->form = DW_FORM_data4; + + ap->val.loclist = llp; + return ap; +} + +/*-----------------------------------------------------------------------*/ +/* dwNewAttrLabelRef - allocate a new tag attribute node that references */ +/* the address of an assembler label plus an offset */ +/*-----------------------------------------------------------------------*/ +static dwattr * +dwNewAttrLabelRef (int attr, char * label, int offset) +{ + dwattr * ap; + + ap = dwNewAttr (attr); + ap->form = DW_FORM_data4; + + ap->val.symaddr.label = label; + ap->val.symaddr.offset = offset; + return ap; +} + +/*---------------------------------------------------------------------*/ +/* dwNewAttrLoc - allocate a new tag attribute node for a chain of */ +/* location expression nodes */ +/*---------------------------------------------------------------------*/ +dwattr * +dwNewAttrLoc (int attr, dwloc * lp) +{ + dwattr * ap; + + ap = dwNewAttr (attr); + ap->form = DW_FORM_block1; + ap->val.loc = lp; + + return ap; +} + +/*---------------------------------------------------------------------*/ +/* dwWriteAttr - write a tag attribute node */ +/*---------------------------------------------------------------------*/ +static void +dwWriteAttr (dwattr * ap) +{ + + switch (ap->form) + { + case DW_FORM_addr: + dwWriteAddress (ap->val.symaddr.label, ap->val.symaddr.offset, NULL); + break; + + case DW_FORM_block: + dwWriteULEB128 (NULL, dwSizeofLoc (ap->val.loc), NULL); + dwWriteLoc (ap->val.loc); + break; + + case DW_FORM_block1: + dwWriteByte (NULL, dwSizeofLoc (ap->val.loc), NULL); + dwWriteLoc (ap->val.loc); + break; + + case DW_FORM_block2: + dwWriteHalf (NULL, dwSizeofLoc (ap->val.loc), NULL); + dwWriteLoc (ap->val.loc); + break; + + case DW_FORM_block4: + dwWriteWord (NULL, dwSizeofLoc (ap->val.loc), NULL); + dwWriteLoc (ap->val.loc); + break; + + case DW_FORM_data1: + case DW_FORM_flag: + dwWriteByte (NULL, ap->val.data, NULL); + break; + + case DW_FORM_data2: + dwWriteHalf (NULL, ap->val.data, NULL); + break; + + case DW_FORM_data4: + switch (ap->attr) + { + case DW_AT_stmt_list: + dwWriteWord (ap->val.symaddr.label, ap->val.symaddr.offset, NULL); + break; + case DW_AT_location: + case DW_AT_frame_base: + dwWriteWord (NULL, ap->val.loclist->baseOffset, NULL); + break; + default: + dwWriteWord (NULL, ap->val.data, NULL); + } + break; + + case DW_FORM_udata: + dwWriteULEB128 (NULL, ap->val.data, NULL); + break; + + case DW_FORM_sdata: + dwWriteSLEB128 (NULL, ap->val.data, NULL); + break; + + case DW_FORM_string: + dwWriteString (ap->val.string, NULL); + break; + + case DW_FORM_ref1: + dwWriteByte (NULL, ap->val.ref->baseOffset, NULL); + break; + + case DW_FORM_ref2: + dwWriteHalf (NULL, ap->val.ref->baseOffset, NULL); + break; + + case DW_FORM_ref4: + dwWriteWord (NULL, ap->val.ref->baseOffset, NULL); + break; + + default: + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + "unsupported DWARF form"); + exit (1); + } +} + +/*---------------------------------------------------------------------*/ +/* dwSizeofAttr - returns the size (in bytes) of a tag attribute node */ +/* as encoded by dwWriteAttr */ +/*---------------------------------------------------------------------*/ +static int +dwSizeofAttr (dwattr * ap) +{ + int size; + + switch (ap->form) + { + case DW_FORM_addr: + return port->debugger.dwarf.addressSize; + + case DW_FORM_block: + size = dwSizeofLoc (ap->val.loc); + return size + dwSizeofULEB128 (size); + + case DW_FORM_block1: + size = dwSizeofLoc (ap->val.loc); + return size + 1; + + case DW_FORM_block2: + size = dwSizeofLoc (ap->val.loc); + return size + 2; + + case DW_FORM_block4: + size = dwSizeofLoc (ap->val.loc); + return size + 4; + + case DW_FORM_data1: + case DW_FORM_flag: + return 1; + + case DW_FORM_data2: + return 2; + + case DW_FORM_data4: + return 4; + + case DW_FORM_udata: + return dwSizeofULEB128 (ap->val.data); + + case DW_FORM_sdata: + return dwSizeofSLEB128 (ap->val.data); + + case DW_FORM_string: + return 1 + strlen (ap->val.string); + + case DW_FORM_ref1: + return 1; + + case DW_FORM_ref2: + return 2; + + case DW_FORM_ref4: + return 4; + + default: + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + "unsupported DWARF form"); + exit (1); + } + +} + + +/*---------------------------------------------------------------------*/ +/* dwFindAttr - for a tag node, return a pointer to a particular */ +/* attribute node, or NULL if not found */ +/*---------------------------------------------------------------------*/ +static dwattr * +dwFindAttr (dwtag * tp, int attr) +{ + dwattr * ap; + + ap = tp->attribs; + while (ap) + { + if (ap->attr == attr) + return ap; + ap = ap->next; + } + + return NULL; +} + + + +/*------------------------------------------------------------------------*/ + + +/*----------------------------------------------------------------------*/ +/* dwNewTag - allocate a new tag node */ +/*----------------------------------------------------------------------*/ +static dwtag * +dwNewTag (int tag) +{ + dwtag * tp; + + tp = Safe_alloc ( sizeof (dwtag)); + tp->tag = tag; + + return tp; +} + +/*----------------------------------------------------------------------*/ +/* dwAddTagAttr - add an attribute to a tag */ +/*----------------------------------------------------------------------*/ +static void +dwAddTagAttr (dwtag * tp, dwattr * ap) +{ + dwattr * curap; + + if (!tp->attribs) + tp->attribs = ap; + else if (ap->attr < tp->attribs->attr) + { + ap->next = tp->attribs; + tp->attribs = ap; + } + else + { + curap = tp->attribs; + while (curap->next && curap->next->attr < ap->attr) + curap = curap->next; + ap->next = curap->next; + curap->next = ap; + } +} + +/*----------------------------------------------------------------------*/ +/* dwSetTagAttr - repleace an existing attribute of a tag with a new */ +/* attribute or add if non-existent */ +/*----------------------------------------------------------------------*/ +static void +dwSetTagAttr (dwtag *tp, dwattr * ap) +{ + dwattr * curap; + + curap = dwFindAttr (tp, ap->attr); + if (curap) + { + ap->next = curap->next; + *curap = *ap; + dwFreeAttr (ap); + } + else + dwAddTagAttr (tp, ap); +} + + +/*----------------------------------------------------------------------*/ +/* dwAddTagChild - add a tag as a child of another tag */ +/*----------------------------------------------------------------------*/ +static dwtag * +dwAddTagChild (dwtag * parent, dwtag * child) +{ + child->parent = parent; + if (parent->lastChild) + { + parent->lastChild->siblings = child; + parent->lastChild = child; + } + else + { + parent->firstChild = child; + parent->lastChild = child; + } + return parent; +} + +/*----------------------------------------------------------------------*/ +/* dwMatchTagAttr - returns true if two tags are equal in value, */ +/* attributes, and offspring status (the child tags */ +/* need not match, but they must both have children or */ +/* both not have children) */ +/*----------------------------------------------------------------------*/ +static int +dwMatchTagAttr (const void * tp1v, const void * tp2v) +{ + const dwtag * tp1 = tp1v; + const dwtag * tp2 = tp2v; + dwattr * ap1 = tp1->attribs; + dwattr * ap2 = tp2->attribs; + + if (!tp1 || !tp2) + return 0; + + if (tp1->tag != tp2->tag) + return 0; + + if (tp1->firstChild && !tp2->lastChild) + return 0; + if (!tp1->firstChild && tp2->lastChild) + return 0; + + while (ap1 && ap2) + { + if (ap1->attr != ap2->attr) + return 0; + if (ap1->form != ap2->form) + return 0; + + ap1 = ap1->next; + ap2 = ap2->next; + } + + return 1; +} + +/*----------------------------------------------------------------------*/ +/* dwHashTag - return a hash code for a tag based on its value and */ +/* attributes */ +/*----------------------------------------------------------------------*/ +static int +dwHashTag (dwtag * tp) +{ + dwattr * ap = tp->attribs; + int hash = tp->tag; + + while (ap) + { + hash = (hash << 6) ^ ((hash >> 11) & 0xff); + hash ^= (ap->attr) | (ap->form << 8); + + ap = ap->next; + } + if (hash<0) + return -hash; + else + return hash; +} + +/*----------------------------------------------------------------------*/ +/* dwTraverseTag - perform a depth-first preorder traversal of a tag */ +/* tree, calling the user function at each node. The */ +/* user function is also called with a NULL tag pointer */ +/* after the last sibling of each immediate family is */ +/* processed. */ +/*----------------------------------------------------------------------*/ +static int +dwTraverseTag (dwtag *tp, int (*somefunc)(dwtag *tp, void * info), void * info) +{ + int rvalue = 0; + + while (tp) + { + rvalue += (*somefunc)(tp, info); + if (tp->firstChild) + rvalue += dwTraverseTag (tp->firstChild, somefunc, info); + tp = tp->siblings; + } + rvalue += (*somefunc)(NULL, info); + + return rvalue; +} + +/*----------------------------------------------------------------------*/ +/* dwAssignAbbrev - find a matching abbreviation for a tag or create a */ +/* a new one and assign it */ +/*----------------------------------------------------------------------*/ +static int +dwAssignAbbrev (dwtag *tp, void *info) +{ + dwtag * oldtp; + int * anp = info; /* pointer to current abbreviation number */ + int key; + + if (!tp) + return 0; + + key = dwHashTag (tp) % dwAbbrevTable->size; + oldtp = hTabFindByKey (dwAbbrevTable, key, tp, dwMatchTagAttr); + if (oldtp) + { + tp->abbrev = oldtp->abbrev; + return 0; + } + else + { + tp->abbrev = ++(*anp); + hTabAddItemLong (&dwAbbrevTable, key, tp, tp); + return 1; + } +} + +/*-----------------------------------------------------------------------*/ +/* dwWriteAbbrevs - write the abbreviations to the .debug_abbrev section */ +/*-----------------------------------------------------------------------*/ +static void +dwWriteAbbrevs (void) +{ + dwtag * tp; + dwattr * ap; + int key; + + tfprintf (dwarf2FilePtr, "\n\t!area\n", ".debug_abbrev (NOLOAD)"); + tfprintf (dwarf2FilePtr, "!slabeldef\n", "Ldebug_abbrev"); + + tp = hTabFirstItem (dwAbbrevTable, &key); + for (; tp; tp = hTabNextItem (dwAbbrevTable, &key)) + { + dwWriteULEB128 (NULL, tp->abbrev, NULL); + dwWriteULEB128 (NULL, tp->tag, NULL); + dwWriteByte (NULL, tp->firstChild ? DW_CHILDREN_yes : DW_CHILDREN_no, + NULL); + ap = tp->attribs; + while (ap) + { + dwWriteULEB128 (NULL, ap->attr, NULL); + dwWriteULEB128 (NULL, ap->form, NULL); + ap = ap->next; + } + dwWriteULEB128 (NULL, 0, NULL); + dwWriteULEB128 (NULL, 0, NULL); + + } + dwWriteULEB128 (NULL, 0, NULL); + + hTabDeleteAll (dwAbbrevTable); +} + + + +/*-----------------------------------------------------------------------*/ +/* dwWriteTag - write the encoded tag information */ +/*-----------------------------------------------------------------------*/ +static int +dwWriteTag (dwtag *tp, void *info) +{ + dwattr * ap; + + if (!tp) + { + /* mark the end of this series of siblings */ + dwWriteULEB128 (NULL, 0, NULL); + return 0; + } + + //fprintf (dwarf2FilePtr, "; baseOffset = 0x%x\n", tp->baseOffset); + + /* write the tag abbreviation */ + dwWriteULEB128 (NULL, tp->abbrev, NULL); + + /* write the values of the attributes */ + ap = tp->attribs; + while (ap) + { + dwWriteAttr (ap); + ap = ap->next; + } + + return 1; +} + + +/*-----------------------------------------------------------------------*/ +/* dwWriteTags - write all the tags to the .debug_info section */ +/*-----------------------------------------------------------------------*/ +static void +dwWriteTags (void) +{ + tfprintf (dwarf2FilePtr, "\n\t!area\n", ".debug_info (NOLOAD)"); + + dwWriteWordDelta ("Ldebug_info_end", "Ldebug_info_start"); + + tfprintf (dwarf2FilePtr, "!slabeldef\n", "Ldebug_info_start"); + + dwWriteHalf (NULL, 2, NULL); /* DWARF version */ + + dwWriteWord ("Ldebug_abbrev", 0, NULL); + + dwWriteByte (NULL, port->debugger.dwarf.addressSize, NULL); + + dwTraverseTag (dwRootTag, dwWriteTag, NULL); + + dwWriteULEB128 (NULL, 0, NULL); + + tfprintf (dwarf2FilePtr, "!slabeldef\n", "Ldebug_info_end"); + +} + +/*-----------------------------------------------------------------------*/ +/* dwAssignTagAddress - assign the current address to the current tag. */ +/* Compute the next address based on the tag size */ +/*-----------------------------------------------------------------------*/ +static int +dwAssignTagAddress (dwtag *tp, void *info) +{ + int * tap = info; + dwattr * ap; + + if (!tp) + { + *tap += 1; + return 0; + } + + tp->baseOffset = *tap; + + *tap += dwSizeofULEB128 (tp->abbrev); + + ap = tp->attribs; + while (ap) + { + *tap += dwSizeofAttr (ap); + ap = ap->next; + } + + return 0; +} + +/*-----------------------------------------------------------------------*/ +/* dwAddSibAttr - if a tag has children and a sibling, add a sibling */ +/* attribute (it allows debuggers to jump to the sibling */ +/* and skip the child data) */ +/*-----------------------------------------------------------------------*/ +static int +dwAddSibAttr (dwtag *tp, void *info) +{ + if (!tp) + return 0; + if (tp == dwRootTag) + return 0; + + if (tp->firstChild && tp->siblings) + dwAddTagAttr (tp, dwNewAttrTagRef (DW_AT_sibling, tp->siblings)); + + return 0; +} + +/*-----------------------------------------------------------------------*/ +/* dwDeleteTagAttr - given a pointer to an attribute type, delete any */ +/* matching attribute */ +/*-----------------------------------------------------------------------*/ +static int +dwDeleteTagAttr (dwtag *tp, void *info) +{ + int attr = *((int *) info); + dwattr * ap; + + if (!tp) + return 0; + + ap = tp->attribs; + if (ap && ap->attr == attr) + { + tp->attribs = ap->next; + return 1; + } + + while (ap) + { + if (ap->next && ap->next->attr == attr) + { + ap->next = ap->next->next; + return 1; + } + ap = ap->next; + } + + return 0; +} + + +/*------------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------*/ +/* dwWritePubnames - write all the public names to the .debug_pubnames */ +/* section. Externally visible functions and variables */ +/* are considered to have public names. */ +/*-----------------------------------------------------------------------*/ +static void +dwWritePubnames (void) +{ + dwtag * tp; + dwattr * ap1; + dwattr * ap2; + + tfprintf (dwarf2FilePtr, "\n\t!area\n", ".debug_pubnames (NOLOAD)"); + + dwWriteWordDelta ("Ldebug_pubnames_end", "Ldebug_pubnames_start"); + + tfprintf (dwarf2FilePtr, "!slabeldef\n", "Ldebug_pubnames_start"); + + dwWriteHalf (NULL, 2, NULL); /* DWARF version */ + + dwWriteWord ("Ldebug_info_start-4", 0, NULL); + dwWriteWordDelta ("4+Ldebug_info_end", "Ldebug_info_start"); + + if (dwRootTag && dwRootTag->firstChild) + { + tp = dwRootTag->firstChild; + while (tp) + { + if (tp->tag == DW_TAG_variable || tp->tag == DW_TAG_subprogram) + { + /* If it has a name and is externally visible, it's a pubname */ + ap1 = dwFindAttr (tp, DW_AT_external); + ap2 = dwFindAttr (tp, DW_AT_name); + if (ap1 && ap1->val.data && ap2) + { + dwWriteWord (NULL, tp->baseOffset, NULL); + dwWriteString (ap2->val.string, NULL); + } + } + + tp = tp->siblings; + } + } + dwWriteWord (NULL, 0, NULL); + tfprintf (dwarf2FilePtr, "!slabeldef\n", "Ldebug_pubnames_end"); +} + +/*------------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------*/ +/* dwFindFileIndex - find the index of a filename in dwFilenameSet; if */ +/* it does not exist, it is added */ +/*-----------------------------------------------------------------------*/ +static int +dwFindFileIndex (char * filename) +{ + char * includeDir; + dwfile * srcfile; + int fileIndex = 1; + int dirIndex = 1; + + /* Just do a linear search for the file. There should be hardly */ + /* a penalty since 1) most calls search for the first file, and */ + /* 2) the file set is usually small (often just 1 item) */ + for (srcfile = setFirstItem (dwFilenameSet); + srcfile; + srcfile = setNextItem(dwFilenameSet), fileIndex++ ) + { + if (!strcmp (srcfile->name, filename)) + return fileIndex; + } + + for (includeDir = setFirstItem (includeDirsSet); + includeDir; + includeDir = setNextItem(includeDirsSet), dirIndex++ ) + { + if (!strncmp (includeDir, filename, strlen (includeDir)) + && strlen (filename) > strlen (includeDir)) + { + if (*(filename+strlen (includeDir)) == DIR_SEPARATOR_CHAR) + break; + } + } + if (!includeDir) + dirIndex = 0; + + srcfile = Safe_alloc (sizeof (dwfile)); + srcfile->name = filename; + srcfile->dirIndex = dirIndex; + srcfile->timestamp = 0; + srcfile->length = 0; + + addSet (&dwFilenameSet, srcfile); + return fileIndex; +} + +/*-----------------------------------------------------------------------*/ +/* dwWriteLineNumber - write line number (and related position info) to */ +/* address corespondence data for a single node */ +/*-----------------------------------------------------------------------*/ +static void +dwWriteLineNumber (dwline * lp) +{ + static int curFileIndex = 1; + static int curLine = 1; + static char * curLabel = NULL; + static int curOffset = 0; + int deltaLine = lp->line - curLine; + int deltaAddr = lp->offset - curOffset; + int deltaAddrValid = curLabel && lp->label && !strcmp (lp->label, curLabel); + + //fprintf (dwarf2FilePtr, "; line %d\n", lp->line); + if (lp->begin_sequence) + { + curFileIndex = 1; + curLine = 1; + curLabel = NULL; + curOffset = 0; + + if (lp->end_sequence) + return; + } + + if (lp->fileIndex != curFileIndex) + { + dwWriteByte (NULL, DW_LNS_set_file, NULL); + dwWriteULEB128 (NULL, lp->fileIndex, NULL); + curFileIndex = lp->fileIndex; + } + + if (lp->basic_block) + { + dwWriteByte (NULL, DW_LNS_set_basic_block, NULL); + } + + if (lp->begin_sequence) + { + dwWriteByte (NULL, 0, NULL); + dwWriteULEB128 (NULL, 1+port->debugger.dwarf.addressSize, NULL); + dwWriteByte (NULL, DW_LNE_set_address, NULL); + dwWriteAddress (lp->label, lp->offset, NULL); + curLabel = lp->label; + curOffset = lp->offset; + + dwWriteByte (NULL, DW_LNS_advance_line, NULL); + dwWriteULEB128 (NULL, lp->line - 1, NULL); + curLine = lp->line; + + dwWriteByte (NULL, DW_LNS_copy, NULL); + } + else if (lp->end_sequence) + { + if (deltaAddrValid) + { + dwWriteByte (NULL, DW_LNS_advance_pc, NULL); + dwWriteULEB128 (NULL, deltaAddr, NULL); + } + else + { + dwWriteByte (NULL, DW_LNS_fixed_advance_pc, NULL); + dwWriteHalfDelta (lp->label, curLabel, lp->offset-curOffset); + curLabel = lp->label; + curOffset = lp->offset; + } + + dwWriteByte (NULL, 0, NULL); + dwWriteULEB128 (NULL, 1, NULL); + dwWriteByte (NULL, DW_LNE_end_sequence, NULL); + } + else + { + int usedSpecial = 0; + + /* Metrowerks CW08 V3.0 gets confused by this. Just use the long */ + /* encoding until we can find a more compatible phrasing. */ + #if 0 + if (deltaLine >= dwLineBase && deltaLine < (dwLineBase+dwLineRange)) + { + int opcode; + + /* try to build a "special" opcode */ + opcode = dwLineOpcodeBase + (deltaLine - dwLineBase); + if (deltaAddrValid) + opcode += deltaAddr*dwLineRange; + + if (opcode >= dwLineOpcodeBase && opcode <= 255) + { + /* ok, we can use a "special" opcode */ + + /* If the deltaAddr value was symbolic, it can't be part */ + /* of the "special" opcode, so encode it seperately */ + if (!deltaAddrValid) + { + dwWriteByte (NULL, DW_LNS_advance_pc, NULL); + dwWriteULEB128Delta (lp->label, curLabel, lp->offset-curOffset); + curLabel = lp->label; + curOffset = lp->offset; + } + + /* Write the "special" opcode */ + dwWriteByte (NULL, opcode, NULL); + curLine = lp->line; + usedSpecial = 1; + } + } + #endif + + /* If we couldn't use the "special" opcode, we will have to */ + /* encode this the long way. */ + if (!usedSpecial) + { + dwWriteByte (NULL, DW_LNS_fixed_advance_pc, NULL); + dwWriteHalfDelta (lp->label, curLabel, lp->offset-curOffset); + curLabel = lp->label; + curOffset = lp->offset; + + dwWriteByte (NULL, DW_LNS_advance_line, NULL); + dwWriteULEB128 (NULL, deltaLine, NULL); + curLine = lp->line; + + dwWriteByte (NULL, DW_LNS_copy, NULL); + } + + } + +} + +/*-----------------------------------------------------------------------*/ +/* dwWriteLineNumbers - write all the source line number position data */ +/* to the .debug_line section */ +/*-----------------------------------------------------------------------*/ +static void +dwWriteLineNumbers (void) +{ + char * includeDir; + dwfile * srcfile; + dwline * lp; + + tfprintf (dwarf2FilePtr, "\n\t!area\n", ".debug_line (NOLOAD)"); + + dwWriteWordDelta ("Ldebug_line_end", "Ldebug_line_start"); + + tfprintf (dwarf2FilePtr, "!slabeldef\n", "Ldebug_line_start"); + + dwWriteHalf (NULL, 2, NULL); /* DWARF version */ + + dwWriteWordDelta ("Ldebug_line_stmt-6", "Ldebug_line_start"); + + dwWriteByte (NULL, 1, NULL); /* we track everything in 1 byte increments */ + + dwWriteByte (NULL, 1, NULL); /* assume every line is a new statement */ + + dwWriteByte (NULL, dwLineBase, NULL); + dwWriteByte (NULL, dwLineRange, NULL); + + dwWriteByte (NULL, 9+1, NULL); /* there are 9 standard opcodes */ + + dwWriteByte (NULL, 0, NULL); /* number of DW_LNS_copy arguments */ + dwWriteByte (NULL, 1, NULL); /* number of DW_LNS_advance_pc arguments */ + dwWriteByte (NULL, 1, NULL); /* number of DW_LNS_advance_line arguments */ + dwWriteByte (NULL, 1, NULL); /* number of DW_LNS_set_file arguments */ + dwWriteByte (NULL, 1, NULL); /* number of DW_LNS_set_column arguments */ + dwWriteByte (NULL, 0, NULL); /* number of DW_LNS_negate_stmt arguments */ + dwWriteByte (NULL, 0, NULL); /* number of DW_LNS_set_basic_block arguments */ + dwWriteByte (NULL, 0, NULL); /* number of DW_LNS_const_add_pc arguments */ + dwWriteByte (NULL, 1, NULL); /* number of DW_LNS_fixed_advance_pc arguments */ + + /* Write the list of source directories searched */ + for (includeDir = setFirstItem (includeDirsSet); + includeDir; + includeDir = setNextItem(includeDirsSet) ) + dwWriteString (includeDir, NULL); + dwWriteByte (NULL, 0, NULL); + + /* Write the list of source files used */ + for (srcfile = setFirstItem (dwFilenameSet); + srcfile; + srcfile = setNextItem(dwFilenameSet) ) + { + dwWriteString (srcfile->name, NULL); + dwWriteULEB128 (NULL, srcfile->dirIndex, NULL); + dwWriteULEB128 (NULL, srcfile->timestamp, NULL); + dwWriteULEB128 (NULL, srcfile->length, NULL); + } + dwWriteByte (NULL, 0, NULL); + + tfprintf (dwarf2FilePtr, "!slabeldef\n", "Ldebug_line_stmt"); + + lp = dwLineFirst; + if (lp) + lp->begin_sequence = 1; + while (lp) + { + dwWriteLineNumber (lp); + if (lp->end_sequence && lp->next) + lp->next->begin_sequence = 1; + lp = lp->next; + } + + tfprintf (dwarf2FilePtr, "!slabeldef\n", "Ldebug_line_end"); +} + +/*------------------------------------------------------------------------*/ + + +/* I have disabled all of this canonical frame address related code */ +/* until I better understand this part of the DWARF2 spec. -- EEP */ +#if 0 +static void +dwWriteCFAinstructions (dwcfins *ip) +{ + dwcfop * op = ip->first; + + while (op) + { + dwWriteByte (NULL, op->opcode, NULL); + switch (op->opcode >> 6) + { + case 0: + switch (op->opcode) + { + case DW_CFA_set_loc: + dwWriteAddress (NULL, op->label, op->operand1); + break; + + case DW_CFA_advance_loc1: + dwWriteByte (NULL, op->operand1, NULL); + break; + + case DW_CFA_advance_loc2: + dwWriteHalf (NULL, op->operand1, NULL); + break; + + case DW_CFA_advance_loc4: + dwWriteWord (NULL, op->operand1, NULL); + break; + + case DW_CFA_def_cfa: + case DW_CFA_register: + case DW_CFA_offset_extended: + dwWriteULEB128 (NULL, op->operand1, NULL); + dwWriteULEB128 (NULL, op->operand2, NULL); + break; + + case DW_CFA_undefined: + case DW_CFA_same_value: + case DW_CFA_def_cfa_register: + case DW_CFA_def_cfa_offset: + case DW_CFA_restore_extended: + dwWriteULEB128 (NULL, op->operand1, NULL); + break; + } + break; + + case DW_CFA_restore >> 6: + case DW_CFA_advance_loc >> 6: + break; + + case DW_CFA_offset >> 6: + dwWriteULEB128 (NULL, op->operand1, NULL); + break; + } + op = op->next; + } +} + +static int +dwSizeofCFAinstructions (dwcfins *ip) +{ + int size = 0; + dwcfop * op = ip->first; + + while (op) + { + size++; + switch (op->opcode >> 6) + { + case 0: + switch (op->opcode) + { + case DW_CFA_set_loc: + size += port->debugger.dwarf.addressSize; + break; + + case DW_CFA_advance_loc1: + size += 1; + break; + + case DW_CFA_advance_loc2: + size += 2; + break; + + case DW_CFA_advance_loc4: + size += 4; + break; + + case DW_CFA_def_cfa: + case DW_CFA_register: + case DW_CFA_offset_extended: + size += dwSizeofULEB128 (op->operand1); + size += dwSizeofULEB128 (op->operand2); + break; + + case DW_CFA_undefined: + case DW_CFA_same_value: + case DW_CFA_def_cfa_register: + case DW_CFA_def_cfa_offset: + case DW_CFA_restore_extended: + size += dwSizeofULEB128 (op->operand1); + break; + } + break; + + case DW_CFA_restore >> 6: + case DW_CFA_advance_loc >> 6: + break; + + case DW_CFA_offset >> 6: + size += dwSizeofULEB128 (op->operand1); + break; + } + op = op->next; + } + return size; +} + +static dwcfop * +dwNewCFop (int opcode) +{ + dwcfop * op; + + op = Safe_alloc (sizeof (dwcfop)); + op->opcode = opcode; + + return op; +} + +static dwcfins * +dwNewCFins (void) +{ + return (dwcfins *) Safe_alloc (sizeof (dwcfins)); +} + +static void +dwAddCFinsOp (dwcfins * ip, dwcfop *op) +{ + if (ip->last) + ip->last->next = op; + else + ip->first = op; + ip->last = op; +} + +static dwcfins * +dwGenCFIins (void) +{ + dwcfins * ip; + dwcfop * op; + int i; + + ip = dwNewCFins (); + + /* Define the CFA as the top of the stack at function start. */ + /* The return address is then at cfa+0 */ + op = dwNewCFop (DW_CFA_def_cfa); + op->operand1 = port->debugger.dwarf.regNumSP; + op->operand2 = port->debugger.dwarf.offsetSP; + dwAddCFinsOp (ip, op); + + op = dwNewCFop (DW_CFA_offset + port->debugger.dwarf.regNumRet); + op->operand1 = 0; + dwAddCFinsOp (ip, op); + + if (port->debugger.dwarf.cfiUndef) + for (i=0; i < port->debugger.dwarf.cfiUndef->size; i++) + { + if (bitVectBitValue (port->debugger.dwarf.cfiUndef, i)) + { + op = dwNewCFop (DW_CFA_undefined); + dwAddCFinsOp (ip, op); + } + } + + if (port->debugger.dwarf.cfiSame) + for (i=0; i < port->debugger.dwarf.cfiSame->size; i++) + { + if (bitVectBitValue (port->debugger.dwarf.cfiSame, i)) + { + op = dwNewCFop (DW_CFA_undefined); + dwAddCFinsOp (ip, op); + } + } + + return ip; +} + + +static void +dwWriteFDE (dwfde * fp) +{ + dwWriteWord (NULL, dwSizeofCFAinstructions(fp->ins) + 4 + + port->debugger.dwarf.addressSize * 2, NULL); + + dwWriteWord ("Ldebug_CIE_start-4", 0, NULL); + + dwWriteAddressDelta (fp->endLabel, fp->startLabel); + + dwWriteCFAinstructions (fp->ins); + +} + +static void +dwWriteFrames (void) +{ + tfprintf (dwarf2FilePtr, "\n\t!area\n", ".debug_frame (NOLOAD)"); + + /* FIXME: these two dw should be combined into a dd */ + tfprintf (dwarf2FilePtr, "\t!dw\t0\n"); + tfprintf (dwarf2FilePtr, "\t!dw\t%s\n", "Ldebug_CIE_end-Ldebug_CIE_start"); + + tfprintf (dwarf2FilePtr, "!slabeldef\n", "Ldebug_CIE_start"); + + tfprintf (dwarf2FilePtr, "\t!dw\t0xffff\n"); + tfprintf (dwarf2FilePtr, "\t!dw\t0xffff\n"); /* CIE_id */ + + tfprintf (dwarf2FilePtr, "\t!db\t%d\n",1); /* CIE version number */ + + tfprintf (dwarf2FilePtr, "\t!db\t%d\n",0); /* augmentation (none) */ + + dwWriteULEB128 (NULL, 1, NULL); /* code alignment factor */ + + dwWriteSLEB128 (NULL, (port->stack.direction > 0) ? -1 : 1, NULL); /* data alignment factor */ + + dwWriteByte (NULL, port->debugger.dwarf.regNumRet, NULL); + + if (!dwCIEins) + { + #if 0 + if (port->debugger.dwarf.genCFIins) + dwCIEins = port->debugger.dwarf.genCFIins (); + else + #endif + dwCIEins = dwGenCFIins (); + } + dwWriteCFAinstructions (dwCIEins); + + tfprintf (dwarf2FilePtr, "!slabeldef\n", "Ldebug_CIE_end"); +} +#endif + + + + +/*------------------------------------------------------------------------*/ + + + + +/*-----------------------------------------------------------------------*/ +/* dwHashType - return a hash code for a type chain */ +/*-----------------------------------------------------------------------*/ +static int +dwHashType (sym_link * type) +{ + int hash = 0; + + while (type) + { + hash = (hash << 5) ^ ((hash >> 8) & 0xff); + if (IS_DECL (type)) + { + hash ^= DCL_TYPE (type); + } + else + { + hash ^= SPEC_NOUN (type) + | (SPEC_CONST (type) << 4) + | (SPEC_VOLATILE (type) << 5) + | (SPEC_LONG (type) << 6); + } + + type = type->next; + } + + if (hash<0) + return -hash; + else + return hash; +} + +/*-----------------------------------------------------------------------*/ +/* dwMatchType - returns true if two types match exactly (including type */ +/* qualifiers) */ +/*-----------------------------------------------------------------------*/ +static int +dwMatchTypes (const void * type1v, const void * type2v) +{ + sym_link * type1 = (sym_link *)type1v; + sym_link * type2 = (sym_link *)type2v; + + if (!type1 || !type2) + return 0; + + while (type1 && type2) + { + if (IS_SPEC(type1)) + { + if (IS_SPEC (type2)) + { + if (SPEC_NOUN (type1) != SPEC_NOUN (type2)) + return 0; + if (SPEC_CONST (type1) != SPEC_CONST (type2)) + return 0; + if (SPEC_VOLATILE (type1) != SPEC_VOLATILE (type2)) + return 0; + if (SPEC_SHORT (type1) != SPEC_SHORT (type2)) + return 0; + if (SPEC_LONG (type1) != SPEC_LONG (type2)) + return 0; + if (SPEC_USIGN (type1) != SPEC_USIGN (type2)) + return 0; + } + else + return 0; + } + else + { + if (IS_DECL (type2)) + { + if (DCL_TYPE (type1) != DCL_TYPE (type2)) + return 0; + if (DCL_PTR_CONST (type1) != DCL_PTR_CONST (type2)) + return 0; + if (DCL_PTR_VOLATILE (type1) != DCL_PTR_VOLATILE (type2)) + return 0; + if (DCL_TYPE (type1) == ARRAY + && DCL_ELEM (type1) != DCL_ELEM (type2)) + return 0; + /* FIXME: need to match function pointer parameters */ + } + else + return 0; + } + + type1 = type1->next; + type2 = type2->next; + } + + if (!type1 && !type2) + return 1; + else + return 0; +} + +/*-----------------------------------------------------------------------*/ +/* dwTagFromType - returns the tag describing a type. If new tags need */ +/* to be created, they will be added under the specified */ +/* parent tag */ +/*-----------------------------------------------------------------------*/ +static dwtag * +dwTagFromType (sym_link * type, dwtag * parent) +{ + dwtag * oldtp; + dwtag * tp = NULL; + dwtag * modtp; + dwtag * subtp; + int key; + + key = dwHashType (type) % dwTypeTagTable->size; + oldtp = hTabFindByKey (dwTypeTagTable, key, type, dwMatchTypes); + if (oldtp) + return oldtp; + else + { + if (IS_DECL (type)) + { + switch (DCL_TYPE (type)) + { + case POINTER: + case FPOINTER: + case CPOINTER: + case GPOINTER: + case PPOINTER: + case IPOINTER: + case EEPPOINTER: + case UPOINTER: + tp = dwNewTag (DW_TAG_pointer_type); + if (type->next && !IS_VOID (type->next)) + { + subtp = dwTagFromType (type->next, parent); + dwAddTagAttr (tp, dwNewAttrTagRef (DW_AT_type, subtp)); + } + dwAddTagAttr (tp, dwNewAttrConst (DW_AT_byte_size, + getSize (type))); + dwAddTagChild (parent, tp); + if (DCL_PTR_VOLATILE (type)) + { + modtp = dwNewTag (DW_TAG_volatile_type); + dwAddTagAttr (modtp, dwNewAttrTagRef (DW_AT_type, tp)); + dwAddTagChild (parent, modtp); + tp = modtp; + } + if (DCL_PTR_CONST (type)) + { + modtp = dwNewTag (DW_TAG_const_type); + dwAddTagAttr (modtp, dwNewAttrTagRef (DW_AT_type, tp)); + dwAddTagChild (parent, modtp); + tp = modtp; + } + break; + + case ARRAY: + tp = dwNewTag (DW_TAG_array_type); + subtp = dwTagFromType (type->next, parent); + dwAddTagAttr (tp, dwNewAttrTagRef (DW_AT_type, subtp)); + if (!subtp->parent) + dwAddTagChild (tp, subtp); + if (DCL_ELEM (type)) + { + dwAddTagAttr (tp, dwNewAttrConst (DW_AT_byte_size, + getSize (type))); + subtp = dwNewTag (DW_TAG_subrange_type); + dwAddTagAttr (subtp, dwNewAttrConst (DW_AT_upper_bound, + DCL_ELEM (type)-1)); + dwAddTagChild (tp, subtp); + } + + break; + + case FUNCTION: + tp = dwNewTag (DW_TAG_subroutine_type); + if (type->next && !IS_VOID (type->next)) + { + subtp = dwTagFromType (type->next, parent); + dwAddTagAttr (tp, dwNewAttrTagRef (DW_AT_type, subtp)); + } + /* FIXME: need to handle function parameters */ + break; + + default: + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + "unknown DCL_TYPE"); + exit (1); + } + } + else + { + if (IS_STRUCT (type)) + { + struct structdef * sdp = SPEC_STRUCT (type); + symbol * field; + + tp = dwNewTag (sdp->type == STRUCT ? DW_TAG_structure_type + : DW_TAG_union_type); + if (*(sdp->tag)) + dwAddTagAttr (tp, dwNewAttrString (DW_AT_name, sdp->tag)); + + /* FIXME: should only specify the size if we know this */ + /* is a complete type */ + dwAddTagAttr (tp, dwNewAttrConst (DW_AT_byte_size, + getSize (type))); + field = sdp->fields; + while (field) + { + dwtag * memtp; + dwloc * lp; + + memtp = dwNewTag (DW_TAG_member); + if (*(field->name)) + dwAddTagAttr (memtp, dwNewAttrString (DW_AT_name, + field->name)); + subtp = dwTagFromType (field->type, tp); + dwAddTagAttr (memtp, dwNewAttrTagRef (DW_AT_type, subtp)); + if (!subtp->parent) + dwAddTagChild (parent, subtp); + + lp = dwNewLoc (DW_OP_plus_uconst, NULL, field->offset); + dwAddTagAttr (memtp, + dwNewAttrLoc (DW_AT_data_member_location, lp)); + + dwAddTagChild (tp, memtp); + + field = field->next; + } + } + else if (SPEC_VOLATILE (type) || SPEC_CONST (type)) + { + sym_link temptype = *type; + + SPEC_VOLATILE (&temptype) = 0; + SPEC_CONST (&temptype) = 0; + tp = dwTagFromType (&temptype, parent); + if (SPEC_VOLATILE (type)) + { + modtp = dwNewTag (DW_TAG_volatile_type); + dwAddTagAttr (modtp, dwNewAttrTagRef (DW_AT_type, tp)); + dwAddTagChild (parent, modtp); + tp = modtp; + } + if (SPEC_CONST (type)) + { + modtp = dwNewTag (DW_TAG_const_type); + dwAddTagAttr (modtp, dwNewAttrTagRef (DW_AT_type, tp)); + dwAddTagChild (parent, modtp); + tp = modtp; + } + } + else + { + switch (SPEC_NOUN (type)) + { + case V_INT: + tp = dwNewTag (DW_TAG_base_type); + if (SPEC_USIGN (type)) + { + dwAddTagAttr (tp, dwNewAttrConst (DW_AT_encoding, + DW_ATE_unsigned)); + if (SPEC_LONG (type)) + dwAddTagAttr (tp, dwNewAttrString (DW_AT_name, + "unsigned long")); + else + dwAddTagAttr (tp, dwNewAttrString (DW_AT_name, + "unsigned int")); + } + else + { + dwAddTagAttr (tp, dwNewAttrConst (DW_AT_encoding, + DW_ATE_signed)); + if (SPEC_LONG (type)) + dwAddTagAttr (tp, dwNewAttrString (DW_AT_name, "long")); + else + dwAddTagAttr (tp, dwNewAttrString (DW_AT_name, "int")); + } + dwAddTagAttr (tp, dwNewAttrConst (DW_AT_byte_size, + getSize (type))); + dwAddTagChild (dwRootTag, tp); + break; + + case V_FLOAT: + tp = dwNewTag (DW_TAG_base_type); + dwAddTagAttr (tp, dwNewAttrConst (DW_AT_encoding, + DW_ATE_float)); + dwAddTagAttr (tp, dwNewAttrString (DW_AT_name, "float")); + dwAddTagAttr (tp, dwNewAttrConst (DW_AT_byte_size, + getSize (type))); + dwAddTagChild (dwRootTag, tp); + break; + + case V_CHAR: + tp = dwNewTag (DW_TAG_base_type); + if (SPEC_USIGN (type)) + { + dwAddTagAttr (tp, dwNewAttrConst (DW_AT_encoding, + DW_ATE_unsigned_char)); + dwAddTagAttr (tp, dwNewAttrString (DW_AT_name, + "unsigned char")); + } + else + { + dwAddTagAttr (tp, dwNewAttrConst (DW_AT_encoding, + DW_ATE_signed)); + dwAddTagAttr (tp, dwNewAttrString (DW_AT_name, "char")); + } + dwAddTagAttr (tp, dwNewAttrConst (DW_AT_byte_size, + getSize (type))); + dwAddTagChild (dwRootTag, tp); + break; + + case V_VOID: + case V_BIT: + case V_BITFIELD: + case V_SBIT: + case V_DOUBLE: + default: + + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + "unhandled base type"); + printTypeChain (type, NULL); + exit (1); + + } + } + } + } + + hTabAddItemLong (&dwTypeTagTable, key, type, tp); + return tp; +} +/*------------------------------------------------------------------------*/ + + +/*-----------------------------------------------------------------------*/ +/* dwOpenFile - opens a temporary file for debugging information */ +/*-----------------------------------------------------------------------*/ +int dwOpenFile(char *file) +{ + dwarf2FilePtr = tempfile(); + if(!dwarf2FilePtr) return 0; + + dwTypeTagTable = newHashTable (128); + + return 1; +} + +/*-----------------------------------------------------------------------*/ +/* dwCloseFile - close (and deletes) the temporary file for debugging */ +/* information */ +/*-----------------------------------------------------------------------*/ +int dwCloseFile(void) +{ + if(!dwarf2FilePtr) return 0; + + fclose(dwarf2FilePtr); + + return 1; +} + + +/*-----------------------------------------------------------------------*/ +/* dwGenerateScopes - recursively traverse an ast, generating lexical */ +/* block tags for block scopes found */ +/*-----------------------------------------------------------------------*/ +static void +dwGenerateScopes (dwtag *tp, ast * tree) +{ + dwtag *subtp; + + if (!tree) + return; + + if (!IS_AST_OP (tree)) + return; + + if (tree->opval.op == BLOCK) + { + subtp = dwNewTag (DW_TAG_lexical_block); + if (tree->right) + { + dwAddTagAttr (subtp, dwNewAttrConst (DW_AT_user_block, tree->right->block)); + dwAddTagAttr (subtp, dwNewAttrConst (DW_AT_user_level, tree->right->level)); + + dwAddTagChild (tp, subtp); + } + dwGenerateScopes (subtp, tree->right); + } + else + { + dwGenerateScopes (tp, tree->left); + dwGenerateScopes (tp, tree->right); + } +} + +/*-----------------------------------------------------------------------*/ +/* dwFindScope - return the lexical block tag for a particular block */ +/* scope, or NULL if not found */ +/*-----------------------------------------------------------------------*/ +static dwtag * +dwFindScope (dwtag * tp, int block) +{ + dwtag * rettp; + dwattr * ap; + + if (!tp) + return NULL; + + while (tp) + { + if (tp->tag == DW_TAG_lexical_block) + { + ap = tp->attribs; + while (ap) + { + if (ap->attr == DW_AT_user_block) + { + if (ap->val.data == block) + return tp; + } + ap = ap->next; + } + + rettp = dwFindScope (tp->firstChild, block); + if (rettp) + return rettp; + } + tp = tp->siblings; + } + + return NULL; +} + +/*------------------------------------------------------------------------*/ +/* dwWriteSymbolInternal - create tag information for a variable or */ +/* parameter and place it in the correct position */ +/* within the tag tree */ +/*------------------------------------------------------------------------*/ +static int +dwWriteSymbolInternal (symbol *sym) +{ + dwtag * tp; + dwtag * subtp; + dwloc * lp; + dwtag * scopetp; + symbol * symloc; + dwtag * functp; + dwattr * funcap; + int inregs = 0; + + if (!sym->level) + scopetp = dwRootTag; + else + { + assert(sym->localof); + if (!sym->localof) + return 0; + + /* Find the tag for the function this symbol is defined in */ + functp = dwRootTag->firstChild; + while (functp) + { + if (functp->tag == DW_TAG_subprogram) + { + funcap = dwFindAttr (functp, DW_AT_name); + if (funcap && !strcmp (funcap->val.string, sym->localof->name)) + break; + } + functp = functp->siblings; + } + assert (functp); + if (!functp) + return 0; + + /* Find the correct scope within this function */ + scopetp = dwFindScope (functp->firstChild, sym->block); + if (!scopetp) + scopetp = functp; + } + + tp = dwNewTag (sym->_isparm ? DW_TAG_formal_parameter : DW_TAG_variable); + + dwAddTagAttr (tp, dwNewAttrString (DW_AT_name, sym->name)); + + /* Find the ultimate symbol holding the value. */ + /* Might be: */ + /* a) original symbol, */ + /* b) register equivalent, */ + /* c) spill location */ + symloc = sym; + if (!sym->allocreq && sym->reqv) + { + symloc = OP_SYMBOL (symloc->reqv); + if (symloc->isspilt && !symloc->remat) + symloc = symloc->usl.spillLoc; + else + inregs = 1; + } + + lp = NULL; + if (inregs && symloc->regs[0]) + { + dwloc * reglp; + dwloc * lastlp = NULL; + int regNum; + int i; + + /* register allocation */ + for (i = (port->little_endian ? 0 : symloc->nRegs-1); + (port->little_endian ? (i < symloc->nRegs) : (i >= 0)); + (port->little_endian ? i++ : i--)) + { + regNum = port->debugger.dwarf.regNum (symloc->regs[i]); + if (regNum >= 0 && regNum <= 31) + reglp = dwNewLoc (DW_OP_reg0 + regNum, NULL, 0); + else if (regNum >= 0) + reglp = dwNewLoc (DW_OP_regx, NULL, regNum); + else + { + /* We are forced to give up if the ABI for this port */ + /* does not define a number for this register */ + lp = NULL; + break; + } + + if (lastlp) + lastlp->next = reglp; + else + lp = reglp; + lastlp = reglp; + + if (symloc->nRegs != 1) + { + reglp = dwNewLoc (DW_OP_piece, NULL, 1); + lastlp->next = reglp; + lastlp = reglp; + } + } + } + else if (symloc->onStack) + { + /* stack allocation */ + lp = dwNewLoc (DW_OP_fbreg, NULL, sym->stack); + } + else + { + /* global allocation */ + lp = dwNewLoc (DW_OP_addr, sym->rname, 0); + } + + /* Only create the DW_AT_location if a known location exists. */ + /* It might not exist if the variable has been optimized away */ + /* or if the compiler has lost track of it (not good, but still */ + /* happens sometimes -- need to improve induction) */ + if (lp) + dwAddTagAttr (tp, dwNewAttrLoc (DW_AT_location, lp)); + + if (!IS_STATIC (sym->etype) && !sym->level) + dwAddTagAttr (tp, dwNewAttrFlag (DW_AT_external, 1)); + if (IS_EXTERN (sym->etype)) + dwAddTagAttr (tp, dwNewAttrFlag (DW_AT_declaration, 1)); + + subtp = dwTagFromType (sym->type, scopetp); + dwAddTagAttr (tp, dwNewAttrTagRef (DW_AT_type, subtp)); + if (!subtp->parent) + dwAddTagChild (scopetp, subtp); + + dwAddTagChild (scopetp, tp); + return 1; +} + + +/*-----------------------------------------------------------------------*/ +/* dwWriteFunction - generate a tag for a function. */ +/*-----------------------------------------------------------------------*/ +int dwWriteFunction(symbol *sym, iCode *ic) +{ + dwtag * tp; + value * args; + + if(!dwarf2FilePtr) return 0; + + dwFuncTag = tp = dwNewTag (DW_TAG_subprogram); + + dwAddTagAttr (dwFuncTag, dwNewAttrString (DW_AT_name, sym->name)); + + dwAddTagAttr (dwFuncTag, dwNewAttrAddrSymbol (DW_AT_low_pc, sym, 0)); + + if (FUNC_ISISR (sym->type)) + dwAddTagAttr (dwFuncTag, dwNewAttrConst (DW_AT_calling_convention, + DW_CC_nocall)); + + dwAddTagAttr (dwFuncTag, dwNewAttrFlag (DW_AT_external, + !IS_STATIC (sym->etype))); + + if (sym->type->next && !IS_VOID (sym->type->next)) + { + dwtag * subtp; + + subtp = dwTagFromType (sym->type->next, dwRootTag); + dwAddTagAttr (dwFuncTag, dwNewAttrTagRef (DW_AT_type, subtp)); + } + dwAddTagChild (dwRootTag, dwFuncTag); + + args = FUNC_ARGS(sym->type); + while (args) + { + dwWriteSymbolInternal (args->sym); + args = args->next; + } + if (FUNC_HASVARARGS (sym->type)) + { + dwAddTagChild (dwFuncTag, dwNewTag (DW_TAG_unspecified_parameters)); + } + + while (ic && ic->op != FUNCTION) + ic = ic->next; + if (ic && ic->op == FUNCTION && ic->tree && ic->tree->right) + { + dwGenerateScopes (dwFuncTag, ic->tree->right->left); + dwGenerateScopes (dwFuncTag, ic->tree->right->right); + } + + dwScopeTag = NULL; + dwScopeLevel = 0; + + return 1; +} + + +/*-----------------------------------------------------------------------*/ +/* dwWriteEndFunction - write attributes to the current function tag */ +/* that are only known after code generation is */ +/* complete */ +/*-----------------------------------------------------------------------*/ +int dwWriteEndFunction(symbol *sym, iCode *ic, int offset) +{ + char debugSym[SDCC_NAME_MAX]; + + if (ic) + { + dwWriteCLine (ic); + dwLineLast->offset += offset; + dwLineLast->end_sequence = 1; + } + + if (IS_STATIC (sym->etype)) + sprintf (debugSym, "XF%s$%s$0$0", moduleName, sym->name); + else + sprintf (debugSym, "XG$%s$0$0", sym->name); + emitDebuggerSymbol (debugSym); + + dwAddTagAttr (dwFuncTag, dwNewAttrAddrLabel (DW_AT_high_pc, + Safe_strdup(debugSym), + offset)); + + if (dwFrameLocList) + { + dwAddTagAttr (dwFuncTag, dwNewAttrLocRef (DW_AT_frame_base, + dwFrameLocList)); + + dwFrameLocList->next = dwRootLocList; + dwRootLocList = dwFrameLocList; + dwFrameLocList = NULL; + } + + return 1; +} + + +/*-----------------------------------------------------------------------*/ +/* dwWriteLabel - generate a tag for a source level label */ +/*-----------------------------------------------------------------------*/ +int dwWriteLabel(symbol *sym, iCode *ic) +{ + char debugSym[SDCC_NAME_MAX]; + dwtag * tp; + + /* ignore the compiler generated labels */ + if (sym->isitmp) + return 1; + + sprintf (debugSym, "L%s$%s$%s", moduleName, currFunc->name, sym->name); + emitDebuggerSymbol (debugSym); + + tp = dwNewTag (DW_TAG_label); + dwAddTagAttr (tp, dwNewAttrString (DW_AT_name, sym->name)); + dwAddTagAttr (tp, dwNewAttrAddrLabel (DW_AT_low_pc, + Safe_strdup (debugSym), 0)); + + dwAddTagChild (dwFuncTag, tp); + + return 1; +} + + +/*-----------------------------------------------------------------------*/ +/* dwWriteScope - add the starting and ending address attributes to a */ +/* a lexical block tag (created during dwWriteFunction) */ +/*-----------------------------------------------------------------------*/ +int dwWriteScope(iCode *ic) +{ + char * debugSym = NULL; + dwtag * scopetp; + dwattr * ap; + + scopetp = dwFindScope (dwFuncTag->firstChild, ic->block); + + if (dwScopeTag && ic->level <= dwScopeLevel) + { + debugSym = dwNewDebugSymbol (); + emitDebuggerSymbol (debugSym); + dwSetTagAttr (dwScopeTag, dwNewAttrAddrLabel (DW_AT_high_pc, debugSym, 0)); + + dwScopeTag = scopetp; + dwScopeLevel = ic->level; + } + if (scopetp) + { + ap = dwFindAttr (scopetp, DW_AT_low_pc); + if (ap) + return 1; + + if (!debugSym) + debugSym = dwNewDebugSymbol (); + emitDebuggerSymbol (debugSym); + dwAddTagAttr (scopetp, dwNewAttrAddrLabel (DW_AT_low_pc, debugSym, 0)); + + dwScopeTag = scopetp; + dwScopeLevel = ic->level; + } + + return 1; +} + +/*-----------------------------------------------------------------------*/ +/* dwWriteSymbol - generate tags for global variables. This is actually */ +/* called for all variables and parameters, but we */ +/* process the non-global variables elsewhere. */ +/*-----------------------------------------------------------------------*/ +int dwWriteSymbol(symbol *sym) +{ + if (IS_FUNC (sym->type)) + return 1; + + /* If it is an iTemp, then it is not a C source symbol; ignore it */ + if (sym->isitmp) + return 1; + + /* Ignore parameters; they must be handled specially so that they will */ + /* appear in the correct order */ + if (sym->_isparm) + return 1; + + return dwWriteSymbolInternal (sym); +} + + +/*-----------------------------------------------------------------------*/ +/* dwWriteType */ +/*-----------------------------------------------------------------------*/ +int dwWriteType(structdef *sdef, int block, int inStruct, char *tag) +{ + /* FIXME: needs implementation */ + return 1; +} + + +/*-----------------------------------------------------------------------*/ +/* dwWriteModule - generates the root tag for this compilation unit */ +/*-----------------------------------------------------------------------*/ +int dwWriteModule(char *name) +{ + dwtag * tp; + + if(!dwarf2FilePtr) return 0; + + tp = dwNewTag (DW_TAG_compile_unit); + dwAddTagAttr (tp, dwNewAttrString (DW_AT_producer, "SDCC version " + SDCC_VERSION_STR)); + dwAddTagAttr (tp, dwNewAttrConst (DW_AT_language, DW_LANG_C89)); + + dwAddTagAttr (tp, dwNewAttrString (DW_AT_name, fullSrcFileName)); + + dwAddTagAttr (tp, dwNewAttrLabelRef (DW_AT_stmt_list, + "Ldebug_line_start", -4)); + + dwRootTag = tp; + + return 1; +} + + +/*-----------------------------------------------------------------------*/ +/* dwWriteCLine - generates a line number/position to address record for */ +/* C source */ +/*-----------------------------------------------------------------------*/ +int dwWriteCLine(iCode *ic) +{ + dwline * lp; + char * debugSym; + + if(!dwarf2FilePtr) return 0; + + lp = Safe_alloc (sizeof (dwline)); + + lp->line = ic->lineno; + + debugSym = dwNewDebugSymbol (); + emitDebuggerSymbol (debugSym); + lp->label = debugSym; + lp->offset = 0; + + lp->fileIndex = dwFindFileIndex (ic->filename); + + if (!dwLineFirst) + dwLineFirst = lp; + else + dwLineLast->next = lp; + dwLineLast = lp; + + return 1; +} + + +/*-----------------------------------------------------------------------*/ +/* dwWriteFrameAddress - note the current position of the frame pointer */ +/* address. The base address can be specified by */ +/* either a register or pointer variable, leaving */ +/* the other as NULL. If both are NULL, there is */ +/* no current frame pointer address defined. */ +/*-----------------------------------------------------------------------*/ +int +dwWriteFrameAddress(char *variable, struct regs *reg, int offset) +{ + char * debugSym = NULL; + dwlocregion * lrp; + dwloc * lp; + int regNum; + + if(!dwarf2FilePtr) return 0; + + /* If there was a region open, close it */ + if (dwFrameLastLoc) + { + debugSym = dwNewDebugSymbol (); + emitDebuggerSymbol (debugSym); + + dwFrameLastLoc->endLabel = debugSym; + dwFrameLastLoc = NULL; + } + + if (!variable && !reg) + return 1; + + /* Create a new debugger symbol for the start of the region if */ + /* we can't recycle the symbol at the end of the previous */ + if (!debugSym) + { + debugSym = dwNewDebugSymbol (); + emitDebuggerSymbol (debugSym); + } + + lrp = Safe_alloc (sizeof (dwlocregion)); + lrp->startLabel = debugSym; + + if (variable) /* frame pointer based from a global variable */ + { + dwloc * lp; + + lrp->loc = dwNewLoc (DW_OP_addr, variable, 0); + lrp->loc->next = lp = dwNewLoc (DW_OP_deref_size, NULL, PTRSIZE); + if (offset) + { + lp->next = dwNewLoc (DW_OP_consts, NULL, offset); + lp->next->next = dwNewLoc (DW_OP_plus, NULL, 0); + } + } + else if (reg) /* frame pointer based from a register */ + { + regNum = port->debugger.dwarf.regNum (reg); + assert (regNum>=0); + + if (regNum>=0 && regNum<=31) + { + if (offset) + lrp->loc = dwNewLoc (DW_OP_breg0 + regNum, NULL, offset); + else + lrp->loc = dwNewLoc (DW_OP_reg0 + regNum, NULL, 0); + } + else + { + lrp->loc = lp = dwNewLoc (DW_OP_regx, NULL, regNum); + if (offset) + { + lp->next = dwNewLoc (DW_OP_consts, NULL, offset); + lp->next->next = dwNewLoc (DW_OP_plus, NULL, 0); + } + } + } + dwFrameLastLoc = lrp; + + if (!dwFrameLocList) + dwFrameLocList = dwNewLocList(); + lrp->next = dwFrameLocList->region; + dwFrameLocList->region = lrp; + + return 1; +} + + +/*-----------------------------------------------------------------------*/ +/* dwWriteALine - generates a line number/position to address record for */ +/* assembly source */ +/*-----------------------------------------------------------------------*/ +int dwWriteALine(char *module, int Line) +{ + if(!dwarf2FilePtr) return 0; + + return 1; +} + + + + +/*-----------------------------------------------------------------------*/ +/* dwarf2FinalizeFile - write all of the DWARF debugging data to the */ +/* debug file */ +/*-----------------------------------------------------------------------*/ +int +dwarf2FinalizeFile(void) +{ + int tagAddress = 11; + int abbrevNum = 0; + int attr; + + if(!dwarf2FilePtr) return 1; + + /* Write the .debug_line section */ + dwWriteLineNumbers (); + + /* Assign the location list addresses (for cross references) */ + dwAssignLocListAddresses (); + + /* Write the .debug_loc section */ + dwWriteLocLists (); + + /* Delete our scope related user attributes; they were only needed to help */ + /* build the tag tree and have no meaning to (and may confuse) debuggers */ + attr = DW_AT_user_block; + dwTraverseTag (dwRootTag, dwDeleteTagAttr, &attr); + attr = DW_AT_user_level; + dwTraverseTag (dwRootTag, dwDeleteTagAttr, &attr); + + /* Add a DW_AT_sibling attribute to all tags with children and siblings */ + dwTraverseTag (dwRootTag, dwAddSibAttr, NULL); + + /* Assign the tag abbreviations. The tags, attributes, and forms must */ + /* not change after this point. The attribute values may change as long */ + /* as the size of the value does not. */ + dwAbbrevTable = newHashTable (128); + dwTraverseTag (dwRootTag, dwAssignAbbrev, &abbrevNum); + + /* Assign the tag addresses (for cross references) */ + dwTraverseTag (dwRootTag, dwAssignTagAddress, &tagAddress); + + /* Write the .debug_abbrev section */ + dwWriteAbbrevs (); + + /* Write the .debug_info section */ + dwWriteTags (); + + /* Write the .debug_pubnames section */ + dwWritePubnames (); + + return 1; +} diff --git a/src/SDCCdwarf2.h b/src/SDCCdwarf2.h new file mode 100644 index 00000000..814912fa --- /dev/null +++ b/src/SDCCdwarf2.h @@ -0,0 +1,425 @@ +/*------------------------------------------------------------------------- + SDCCdwarf2.h - DWARF2 debugging constants + + Written By - Erik Petrich . epetrich@users.sourceforge.net (2004) + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! +-------------------------------------------------------------------------*/ + +#ifndef SDCCDWARF2_H +#define SDCCDWARF2_H + +#define DW_TAG_array_type 0x01 +#define DW_TAG_class_type 0x02 +#define DW_TAG_entry_point 0x03 +#define DW_TAG_enumeration_type 0x04 +#define DW_TAG_formal_parameter 0x05 +#define DW_TAG_imported_declaration 0x08 +#define DW_TAG_label 0x0a +#define DW_TAG_lexical_block 0x0b +#define DW_TAG_member 0x0d +#define DW_TAG_pointer_type 0x0f +#define DW_TAG_reference_type 0x10 +#define DW_TAG_compile_unit 0x11 +#define DW_TAG_string_type 0x12 +#define DW_TAG_structure_type 0x13 +#define DW_TAG_subroutine_type 0x15 +#define DW_TAG_typedef 0x16 +#define DW_TAG_union_type 0x17 +#define DW_TAG_unspecified_parameters 0x18 +#define DW_TAG_variant 0x19 +#define DW_TAG_common_block 0x1a +#define DW_TAG_common_inclusion 0x1b +#define DW_TAG_inheritance 0x1c +#define DW_TAG_inlined_subroutine 01x1d +#define DW_TAG_module 0x1e +#define DW_TAG_ptr_to_member_type 0x1f +#define DW_TAG_set_type 0x20 +#define DW_TAG_subrange_type 0x21 +#define DW_TAG_with_stmt 0x22 +#define DW_TAG_access_declaration 0x23 +#define DW_TAG_base_type 0x24 +#define DW_TAG_catch_block 0x25 +#define DW_TAG_const_type 0x26 +#define DW_TAG_constant 0x27 +#define DW_TAG_enumerator 0x28 +#define DW_TAG_file_type 0x29 +#define DW_TAG_friend 0x2a +#define DW_TAG_namelist 0x2b +#define DW_TAG_namelist_item 0x2c +#define DW_TAG_packed_type 0x2d +#define DW_TAG_subprogram 0x2e +#define DW_TAG_template_type_param 0x2f +#define DW_TAG_template_value_param 0x30 +#define DW_TAG_thrown_type 0x31 +#define DW_TAG_try_block 0x32 +#define DW_TAG_variant_part 0x33 +#define DW_TAG_variable 0x34 +#define DW_TAG_volatile_type 0x35 + +#define DW_CHILDREN_no 0 +#define DW_CHILDREN_yes 1 + +#define DW_LANG_C89 0x0001 + +#define DW_AT_sibling 0x01 +#define DW_AT_location 0x02 +#define DW_AT_name 0x03 +#define DW_AT_ordering 0x09 +#define DW_AT_byte_size 0x0b +#define DW_AT_bit_offset 0x0c +#define DW_AT_bit_size 0x0d +#define DW_AT_stmt_list 0x10 +#define DW_AT_low_pc 0x11 +#define DW_AT_high_pc 0x12 +#define DW_AT_language 0x13 +#define DW_AT_discr 0x15 +#define DW_AT_discr_value 0x16 +#define DW_AT_visibility 0x17 +#define DW_AT_import 0x18 +#define DW_AT_string_length 0x19 +#define DW_AT_common_reference 0x1a +#define DW_AT_comp_dir 0x1b +#define DW_AT_const_value 0x1c +#define DW_AT_containing_type 0x1d +#define DW_AT_default_value 0x1e +#define DW_AT_inline 0x20 +#define DW_AT_is_optional 0x21 +#define DW_AT_lower_bound 0x22 +#define DW_AT_producer 0x25 +#define DW_AT_prototyped 0x27 +#define DW_AT_return_addr 0x2a +#define DW_AT_start_scope 0x2c +#define DW_AT_stride_size 0x2e +#define DW_AT_upper_bound 0x2f +#define DW_AT_abstract_origin 0x31 +#define DW_AT_accessibility 0x32 +#define DW_AT_address_class 0x33 +#define DW_AT_artificial 0x34 +#define DW_AT_base_types 0x35 +#define DW_AT_calling_convention 0x36 +#define DW_AT_count 0x37 +#define DW_AT_data_member_location 0x38 +#define DW_AT_decl_column 0x39 +#define DW_AT_decl_file 0x3a +#define DW_AT_decl_line 0x3b +#define DW_AT_declaration 0x3c +#define DW_AT_discr_list 0x3d +#define DW_AT_encoding 0x3e +#define DW_AT_external 0x3f +#define DW_AT_frame_base 0x40 +#define DW_AT_friend 0x41 +#define DW_AT_identifier_case 0x42 +#define DW_AT_macro_info 0x43 +#define DW_AT_namelist_item 0x44 +#define DW_AT_priority 0x45 +#define DW_AT_segment 0x46 +#define DW_AT_specification 0x47 +#define DW_AT_static_link 0x48 +#define DW_AT_type 0x49 +#define DW_AT_use_location 0x4a +#define DW_AT_variable_parameter 0x4b +#define DW_AT_virtuality 0x4c +#define DW_AT_vtable_elem_location 0x4d +#define DW_AT_lo_user 0x2000 +#define DW_AT_hi_user 0x3fff + +#define DW_AT_user_block 0x2650 +#define DW_AT_user_level 0x2651 + +#define DW_FORM_addr 0x01 +#define DW_FORM_block2 0x03 +#define DW_FORM_block4 0x04 +#define DW_FORM_data2 0x05 +#define DW_FORM_data4 0x06 +#define DW_FORM_data8 0x07 +#define DW_FORM_string 0x08 +#define DW_FORM_block 0x09 +#define DW_FORM_block1 0x0a +#define DW_FORM_data1 0x0b +#define DW_FORM_flag 0x0c +#define DW_FORM_sdata 0x0d +#define DW_FORM_strp 0x0e +#define DW_FORM_udata 0x0f +#define DW_FORM_ref_addr 0x10 +#define DW_FORM_ref1 0x11 +#define DW_FORM_ref2 0x12 +#define DW_FORM_ref4 0x13 +#define DW_FORM_ref_udata 0x15 +#define DW_FORM_indirect 0x16 + +#define DW_OP_addr 0x03 +#define DW_OP_deref 0x06 +#define DW_OP_const1u 0x08 +#define DW_OP_const1s 0x09 +#define DW_OP_const2u 0x0a +#define DW_OP_const2s 0x0b +#define DW_OP_const4u 0x0c +#define DW_OP_const4s 0x0d +#define DW_OP_const8u 0x0e +#define DW_OP_const8s 0x0f +#define DW_OP_constu 0x10 +#define DW_OP_consts 0x11 +#define DW_OP_dup 0x12 +#define DW_OP_drop 0x13 +#define DW_OP_over 0x14 +#define DW_OP_pick 0x15 +#define DW_OP_swap 0x16 +#define DW_OP_rot 0x17 +#define DW_OP_xderef 0x18 +#define DW_OP_abs 0x19 +#define DW_OP_and 0x1a +#define DW_OP_div 0x1b +#define DW_OP_minus 0x1c +#define DW_OP_mod 0x1d +#define DW_OP_mul 0x1e +#define DW_OP_neg 0x1f +#define DW_OP_not 0x20 +#define DW_OP_or 0x21 +#define DW_OP_plus 0x22 +#define DW_OP_plus_uconst 0x23 +#define DW_OP_shl 0x24 +#define DW_OP_shr 0x25 +#define DW_OP_shra 0x26 +#define DW_OP_xor 0x27 +#define DW_OP_skip 0x2f +#define DW_OP_bra 0x28 +#define DW_OP_eq 0x29 +#define DW_OP_ge 0x2a +#define DW_OP_gt 0x2b +#define DW_OP_le 0x2c +#define DW_OP_lt 0x2d +#define DW_OP_ne 0x2e +#define DW_OP_lit0 0x30 +#define DW_OP_reg0 0x50 +#define DW_OP_breg0 0x70 +#define DW_OP_breg1 0x71 +#define DW_OP_breg2 0x72 +#define DW_OP_breg3 0x73 +#define DW_OP_breg4 0x74 +#define DW_OP_breg5 0x75 +#define DW_OP_breg6 0x76 +#define DW_OP_breg7 0x77 +#define DW_OP_breg8 0x78 +#define DW_OP_breg9 0x79 +#define DW_OP_breg10 0x7a +#define DW_OP_breg11 0x7b +#define DW_OP_breg12 0x7c +#define DW_OP_breg13 0x7d +#define DW_OP_breg14 0x7e +#define DW_OP_breg15 0x7f +#define DW_OP_breg16 0x80 +#define DW_OP_breg17 0x81 +#define DW_OP_breg18 0x82 +#define DW_OP_breg19 0x83 +#define DW_OP_breg20 0x84 +#define DW_OP_breg21 0x85 +#define DW_OP_breg22 0x86 +#define DW_OP_breg23 0x87 +#define DW_OP_breg24 0x88 +#define DW_OP_breg25 0x89 +#define DW_OP_breg26 0x8a +#define DW_OP_breg27 0x8b +#define DW_OP_breg28 0x8c +#define DW_OP_breg29 0x8d +#define DW_OP_breg30 0x8e +#define DW_OP_breg31 0x8f +#define DW_OP_regx 0x90 +#define DW_OP_fbreg 0x91 +#define DW_OP_bregx 0x92 +#define DW_OP_piece 0x93 +#define DW_OP_deref_size 0x94 +#define DW_OP_xderef_size 0x95 +#define DW_OP_nop 0x96 + +#define DW_ATE_address 0x1 +#define DW_ATE_boolean 0x2 +#define DW_ATE_complex_float 0x3 +#define DW_ATE_float 0x4 +#define DW_ATE_signed 0x5 +#define DW_ATE_signed_char 0x6 +#define DW_ATE_unsigned 0x7 +#define DW_ATE_unsigned_char 0x8 + +#define DW_CC_normal 0x1 +#define DW_CC_program 0x2 +#define DW_CC_nocall 0x3 + +#define DW_LNS_copy 1 +#define DW_LNS_advance_pc 2 +#define DW_LNS_advance_line 3 +#define DW_LNS_set_file 4 +#define DW_LNS_set_column 5 +#define DW_LNS_negate_stmt 6 +#define DW_LNS_set_basic_block 7 +#define DW_LNS_const_add_pc 8 +#define DW_LNS_fixed_advance_pc 9 + +#define DW_LNE_end_sequence 1 +#define DW_LNE_set_address 2 +#define DW_LNE_define_file 3 + +#define DW_MACINFO_define 1 +#define DW_MACINFO_undef 2 +#define DW_MACINFO_start_file 3 +#define DW_MACINFO_end_file 4 +#define DW_MACINFO_vendor_ext 255 + +#define DW_CFA_advance_loc (1 << 6) +#define DW_CFA_offset (2 << 6) +#define DW_CFA_restore (3 << 6) +#define DW_CFA_set_loc 0x01 +#define DW_CFA_advance_loc1 0x02 +#define DW_CFA_advance_loc2 0x03 +#define DW_CFA_advance_loc4 0x04 +#define DW_CFA_offset_extended 0x05 +#define DW_CFA_restore_extended 0x06 +#define DW_CFA_undefined 0x07 +#define DW_CFA_same_value 0x08 +#define DW_CFA_register 0x09 +#define DW_CFA_remember_state 0x0a +#define DW_CFA_restore_state 0x0b +#define DW_CFA_def_cfa 0x0c +#define DW_CFA_def_cfa_register 0x0d +#define DW_CFA_def_cfa_offset 0x0e +#define DW_CFA_nop 0x0f +#define DW_CFA_lo_user 0x1c +#define DW_CFA_hi_user 0x3f + + +typedef struct dwloc +{ + int opcode; + struct + { + symbol * sym; + char * label; + int offset; + } operand; + struct dwloc * next; +} dwloc; + +typedef struct dwlocregion +{ + char * startLabel; + char * endLabel; + dwloc * loc; + struct dwlocregion * next; +} dwlocregion; + +typedef struct dwloclist +{ + int baseOffset; + dwlocregion * region; + struct dwloclist * next; +} dwloclist; + +struct dwtag; + +typedef struct dwattr +{ + int attr; + int form; + union + { + struct + { + char * label; + int offset; + } symaddr; + struct + { + unsigned char * data; + int length; + } block; + int data; + char * string; + struct dwtag * ref; + struct dwloc * loc; + struct dwloclist * loclist; + } val; + struct dwattr * next; +} dwattr; + +typedef struct dwtag +{ + int tag; + int abbrev; + int baseOffset; + struct dwattr * attribs; + struct dwtag * parent; + struct dwtag * firstChild; + struct dwtag * lastChild; + struct dwtag * siblings; +} dwtag; + +typedef struct dwfile +{ + char * name; + int dirIndex; + int timestamp; + int length; +} dwfile; + +typedef struct dwline +{ + char * label; + int offset; + int fileIndex; + int line; + unsigned is_stmt:1; + unsigned basic_block:1; + unsigned end_sequence:1; + unsigned begin_sequence:1; + struct dwline * next; +} dwline; + +#if 0 +typedef struct dwblock +{ + unsigned char * data; + int length; + int alloc; +} dwblock; + +typedef struct dwcfop +{ + int opcode; + char * label; + int operand1; + int operand2; + struct dwcfop * next; +} dwcfop; + +typedef struct dwcfins +{ + dwcfop * first; + dwcfop * last; +} dwcfins; + +typedef struct dwfde +{ + char * startLabel; + char * endLabel; + dwcfins * ins; +} dwfde; +#endif + + +#endif diff --git a/src/SDCCicode.c b/src/SDCCicode.c index a704cbc4..fdc27804 100644 --- a/src/SDCCicode.c +++ b/src/SDCCicode.c @@ -3363,6 +3363,7 @@ geniCodeFunctionBody (ast * tree,int lvl) /* create a proc icode */ ic = newiCode (FUNCTION, func, NULL); lineno=ic->lineno = OP_SYMBOL (func)->lineDef; + ic->tree = tree; ADDTOCHAIN (ic); @@ -3378,6 +3379,7 @@ geniCodeFunctionBody (ast * tree,int lvl) /* now generate the end proc */ ic = newiCode (ENDFUNCTION, func, NULL); + ic->tree = tree; ADDTOCHAIN (ic); return; } diff --git a/src/SDCCicode.h b/src/SDCCicode.h index 3dc90c7a..3069ff10 100644 --- a/src/SDCCicode.h +++ b/src/SDCCicode.h @@ -191,6 +191,7 @@ typedef struct iCode int argreg; /* argument regno for SEND/RECEIVE */ int eBBlockNum; /* belongs to which eBBlock */ char riu; /* after ralloc, the registers in use */ + struct ast * tree; /* ast node for this iCode (if not NULL) */ } iCode; diff --git a/src/avr/gen.h b/src/avr/gen.h index 57158cee..89ca931d 100644 --- a/src/avr/gen.h +++ b/src/avr/gen.h @@ -73,7 +73,8 @@ typedef struct asmop } asmop; -void gen51Code (iCode *); +void genAVRCode (iCode *); +void avr_emitDebuggerSymbol (char *); extern char *fReturn8051[]; extern char *fReturn390[]; diff --git a/src/cdbFile.c b/src/cdbFile.c index ea9e5559..1e8e277b 100644 --- a/src/cdbFile.c +++ b/src/cdbFile.c @@ -12,12 +12,16 @@ int cdbOpenFile(char *file); int cdbCloseFile(void); -int cdbWriteFunction(symbol *pSym); +int cdbWriteFunction(symbol *pSym, iCode *ic); +int cdbWriteEndFunction(symbol *pSym, iCode *ic, int offset); +int cdbWriteLabel(symbol *pSym, iCode *ic); +int cdbWriteScope(iCode *ic); int cdbWriteSymbol(symbol *pSym); int cdbWriteType(structdef *sdef, int block, int inStruct, char *tag); int cdbWriteModule(char *name); -int cdbWriteCLine(char *module, int Line, int Level, int Block); +int cdbWriteCLine(iCode *ic); int cdbWriteALine(char *module, int Line); +int cdbWriteFrameAddress(char *variable, struct regs *reg, int offset); int cdbWriteBasicSymbol(symbol *sym, int isStructSym, int isFunc); void cdbTypeInfo (sym_link * type); @@ -28,10 +32,14 @@ DEBUGFILE cdbDebugFile = &cdbCloseFile, &cdbWriteModule, &cdbWriteFunction, + &cdbWriteEndFunction, + &cdbWriteLabel, + &cdbWriteScope, &cdbWriteSymbol, &cdbWriteType, &cdbWriteCLine, - &cdbWriteALine + &cdbWriteALine, + &cdbWriteFrameAddress }; FILE *cdbFilePtr = NULL; @@ -79,17 +87,92 @@ int cdbCloseFile(void) * *****************************************************************/ -int cdbWriteFunction(symbol *pSym) +int cdbWriteFunction(symbol *pSym, iCode *ic) { + char debugSym[INITIAL_INLINEASM]; + if (getenv("SDCC_DEBUG_FUNCTION_POINTERS")) fprintf (stderr, "cdbFile.c:cdbWriteFunction()\n"); if(!cdbFilePtr) return 0; + if (IS_STATIC (pSym->etype)) + sprintf (debugSym, "F%s$%s$0$0", moduleName, pSym->name); + else + sprintf (debugSym, "G$%s$0$0", pSym->name); + emitDebuggerSymbol (debugSym); + return cdbWriteBasicSymbol(pSym, FALSE, TRUE); } +/****************************************************************** + * + * + * + * + *****************************************************************/ + +int cdbWriteEndFunction(symbol *pSym, iCode *ic, int offset) +{ + char debugSym[INITIAL_INLINEASM]; + + if (getenv("SDCC_DEBUG_FUNCTION_POINTERS")) + fprintf (stderr, "cdbFile.c:cdbWriteEndFunction()\n"); + + if(!cdbFilePtr) return 0; + + if (ic) + { + sprintf (debugSym, "C$%s$%d$%d$%d", + FileBaseName (ic->filename), pSym->lastLine, + ic->level, ic->block); + emitDebuggerSymbol (debugSym); + } + + if (IS_STATIC (pSym->etype)) + sprintf (debugSym, "XF%s$%s$0$0", moduleName, pSym->name); + else + sprintf (debugSym, "XG$%s$0$0", pSym->name); + emitDebuggerSymbol (debugSym); + + return 1; +} + +/****************************************************************** + * + * + * + * + *****************************************************************/ + +int cdbWriteLabel(symbol *pSym, iCode *ic) +{ + if (getenv("SDCC_DEBUG_FUNCTION_POINTERS")) + fprintf (stderr, "cdbFile.c:cdbWriteLabel()\n"); + + if(!cdbFilePtr) return 0; + + return 1; +} + +/****************************************************************** + * + * + * + * + *****************************************************************/ + +int cdbWriteScope(iCode *ic) +{ + if (getenv("SDCC_DEBUG_FUNCTION_POINTERS")) + fprintf (stderr, "cdbFile.c:cdbWriteScope()\n"); + + if(!cdbFilePtr) return 0; + + return 1; +} + /****************************************************************** * * @@ -171,9 +254,16 @@ int cdbWriteModule(char *name) * * *****************************************************************/ -int cdbWriteCLine(char *module, int Line, int Level, int Block) +int cdbWriteCLine(iCode *ic) { + char debugSym[INITIAL_INLINEASM]; + if(!cdbFilePtr) return 0; + + sprintf (debugSym, "C$%s$%d$%d$%d", + FileBaseName (ic->filename), ic->lineno, + ic->level, ic->block); + emitDebuggerSymbol (debugSym); return 1; } @@ -192,6 +282,23 @@ int cdbWriteALine(char *module, int Line) return 1; } +/****************************************************************** + * + * + * + * + *****************************************************************/ + +int cdbWriteFrameAddress(char *variable, struct regs *reg, int offset) +{ + if (getenv("SDCC_DEBUG_FUNCTION_POINTERS")) + fprintf (stderr, "cdbFile.c:cdbWriteFrameAddress()\n"); + + if(!cdbFilePtr) return 0; + + return 1; +} + /****************************************************************** * * diff --git a/src/ds390/gen.h b/src/ds390/gen.h index 8f33d712..731847d1 100644 --- a/src/ds390/gen.h +++ b/src/ds390/gen.h @@ -81,6 +81,7 @@ typedef struct asmop asmop; void gen390Code (iCode *); +void ds390_emitDebuggerSymbol (char *); extern unsigned fReturnSizeDS390; diff --git a/src/hc08/gen.h b/src/hc08/gen.h index f1463a58..b8b09b6a 100644 --- a/src/hc08/gen.h +++ b/src/hc08/gen.h @@ -88,6 +88,7 @@ typedef struct asmop asmop; void genhc08Code (iCode *); +void hc08_emitDebuggerSymbol (char *); //extern char *fReturn8051[]; extern unsigned fReturnSizeHC08; diff --git a/src/hc08/ralloc.c b/src/hc08/ralloc.c index cec247d7..4669e852 100644 --- a/src/hc08/ralloc.c +++ b/src/hc08/ralloc.c @@ -61,21 +61,23 @@ int hc08_ptrRegReq; /* one byte pointer register required */ regs regshc08[] = { - {REG_GPR, A_IDX, REG_GPR, "a", "a", "0", 1, NULL, 0, 1}, - {REG_GPR, X_IDX, REG_GPR, "x", "x", "0", 2, NULL, 0, 1}, - {REG_GPR, H_IDX, REG_GPR, "h", "h", "0", 4, NULL, 0, 1}, - {REG_PTR, HX_IDX, REG_PTR, "hx", "hx", "0", 6, NULL, 0, 1}, - {REG_GPR, XA_IDX, REG_GPR, "xa", "xa", "0", 3, NULL, 0, 1}, - - {REG_CND, CND_IDX, REG_CND, "C", "C", "xreg", 0, NULL, 0, 1}, + {REG_GPR, A_IDX, "a", 1, NULL, 0, 1}, + {REG_GPR, X_IDX, "x", 2, NULL, 0, 1}, + {REG_GPR, H_IDX, "h", 4, NULL, 0, 1}, + {REG_PTR, HX_IDX, "hx", 6, NULL, 0, 1}, + {REG_GPR, XA_IDX, "xa", 3, NULL, 0, 1}, + + {REG_CND, CND_IDX, "C", 0, NULL, 0, 1}, + {0, SP_IDX, "sp", 0, NULL, 0, 1}, }; -int hc08_nRegs = 6; +int hc08_nRegs = 7; regs *hc08_reg_a; regs *hc08_reg_x; regs *hc08_reg_h; regs *hc08_reg_hx; regs *hc08_reg_xa; +regs *hc08_reg_sp; static void spillThis (symbol *); static void freeAllRegs (); @@ -3020,12 +3022,14 @@ hc08_assignRegisters (eBBlock ** ebbs, int count) setToNull ((void *) &_G.regAssigned); setToNull ((void *) &_G.totRegAssigned); hc08_ptrRegReq = _G.stackExtend = _G.dataExtend = 0; - hc08_nRegs = 5; + hc08_nRegs = 7; hc08_reg_a = hc08_regWithIdx(A_IDX); hc08_reg_x = hc08_regWithIdx(X_IDX); hc08_reg_h = hc08_regWithIdx(H_IDX); hc08_reg_hx = hc08_regWithIdx(HX_IDX); hc08_reg_xa = hc08_regWithIdx(XA_IDX); + hc08_reg_sp = hc08_regWithIdx(SP_IDX); + hc08_nRegs = 5; /* change assignments this will remove some live ranges reducing some register pressure */ diff --git a/src/hc08/ralloc.h b/src/hc08/ralloc.h index 878c9aac..ce77cbae 100644 --- a/src/hc08/ralloc.h +++ b/src/hc08/ralloc.h @@ -34,23 +34,22 @@ enum X_IDX, HX_IDX, XA_IDX, - CND_IDX + CND_IDX, + SP_IDX }; #define REG_PTR 0x01 #define REG_GPR 0x02 #define REG_CND 0x04 + /* definition for the registers */ typedef struct regs { short type; /* can have value REG_GPR, REG_PTR or REG_CND */ short rIdx; /* index into register table */ - short otype; char *name; /* name */ - char *dname; /* name when direct access needed */ - char *base; /* base address */ short mask; /* bitmask for pair allocation */ struct asmop *aop; /* last operand */ int aopofs; /* last operand offset */ @@ -63,6 +62,7 @@ extern regs *hc08_reg_x; extern regs *hc08_reg_h; extern regs *hc08_reg_hx; extern regs *hc08_reg_xa; +extern regs *hc08_reg_sp; regs *hc08_regWithIdx (int); void hc08_useReg (regs * reg); diff --git a/src/mcs51/gen.h b/src/mcs51/gen.h index ada89d6a..9988061d 100644 --- a/src/mcs51/gen.h +++ b/src/mcs51/gen.h @@ -79,6 +79,7 @@ typedef struct asmop asmop; void gen51Code (iCode *); +void mcs51_emitDebuggerSymbol (char *); //extern char *fReturn8051[]; extern unsigned fReturnSizeMCS51; diff --git a/src/pic/gen.h b/src/pic/gen.h index 4083c1ae..6c1e5e7f 100644 --- a/src/pic/gen.h +++ b/src/pic/gen.h @@ -139,6 +139,7 @@ void emitpcode(PIC_OPCODE poc, pCodeOp *pcop); void emitpLabel(int key); void pic14_emitcode (char *inst,char *fmt, ...); void DEBUGpic14_emitcode (char *inst,char *fmt, ...); +void pic14_emitDebuggerSymbol (char *); asmop *newAsmop (short type); bool pic14_sameRegs (asmop *aop1, asmop *aop2 ); char *aopGet (asmop *aop, int offset, bool bit16, bool dname); diff --git a/src/pic16/gen.h b/src/pic16/gen.h index e942384d..9c8c7e05 100644 --- a/src/pic16/gen.h +++ b/src/pic16/gen.h @@ -151,6 +151,7 @@ void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop); void pic16_emitpLabel(int key); void pic16_emitcode (char *inst,char *fmt, ...); void DEBUGpic16_emitcode (char *inst,char *fmt, ...); +void pic16_emitDebuggerSymbol (char *); bool pic16_sameRegs (asmop *aop1, asmop *aop2 ); char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname); diff --git a/src/src.dsp b/src/src.dsp index 2341e114..7c2e898e 100644 --- a/src/src.dsp +++ b/src/src.dsp @@ -243,6 +243,10 @@ SOURCE=.\SDCCval.c SOURCE=.\sdccy.c # End Source File +# Begin Source File + +SOURCE=.\SDCCdwarf2.c +# End Source File # End Group # Begin Group "Header Files" @@ -367,6 +371,10 @@ SOURCE=.\sdccy.h SOURCE=.\spawn.h # End Source File +# Begin Source File + +SOURCE=.\SDCCdwarf2.h +# End Source File # End Group # Begin Group "Regression Test" diff --git a/src/xa51/gen.h b/src/xa51/gen.h index 85f6e6bf..fec9e0c3 100755 --- a/src/xa51/gen.h +++ b/src/xa51/gen.h @@ -64,4 +64,6 @@ typedef struct asmop { #define AOP_SIZE(x) x->aop->size #define AOP_NAME(x) x->aop->name +void xa51_emitDebuggerSymbol (char *); + #endif diff --git a/src/z80/gen.h b/src/z80/gen.h index 40ccd0c9..2512bd65 100644 --- a/src/z80/gen.h +++ b/src/z80/gen.h @@ -92,6 +92,7 @@ typedef struct asmop asmop; void genZ80Code (iCode *); +void z80_emitDebuggerSymbol (char *); #endif diff --git a/src/z80/z80.h b/src/z80/z80.h index 043025f9..dd6cda26 100644 --- a/src/z80/z80.h +++ b/src/z80/z80.h @@ -3,6 +3,7 @@ */ #include "common.h" #include "ralloc.h" +#include "gen.h" #include "support.h" typedef enum -- 2.30.2