📄 dbg386.c
字号:
/*
Copyright 1994-2003 Free Software Foundation, Inc.
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 of the License, 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, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
This program is derived from the cc68k complier by
Matthew Brandt (mattb@walkingdog.net)
You may contact the author of this derivative at:
mailto::camille@bluegrass.net
or by snail mail at:
David Lindauer
850 Washburn Ave Apt 99
Louisville, KY 40222
*/
#include <stdio.h>
#include <string.h>
#include "lists.h"
#include "expr.h"
#include "c.h"
#include "ccerr.h"
#include "cvinfo.h"
#include "gen386.h"
#include "diag.h"
extern int packdata[], packlevel;
extern int global_flag;
extern int prm_debug, prm_cplusplus;
extern char version[];
extern char outfile[];
extern SYM *currentfunc;
extern EMIT_TAB segs[];
extern int startlab, retlab;
extern int packdata[], packlevel;
extern int outcode_base_address;
extern int lineno;
extern HASHREC **gsyms;
int dbgblocknum;
DBGBLOCK *DbgBlocks[2048];
int intrinsxlate[] =
{
T_BOOL08, T_CHAR, T_UCHAR, T_INT8, T_SHORT, T_USHORT, T_INT4, T_UINT4,
T_INT4, T_UINT4, T_INT8, T_UINT8, T_REAL32, T_REAL64, T_REAL80,
T_IMAGINARY32, T_IMAGINARY64, T_IMAGINARY80, T_CPLX32, T_CPLX64, T_CPLX80, T_VOID
};
int debug_outputtype(TYP *type);
static void emitsym(char *buf);
static void out_sym_header(void);
static DBGBLOCK *dbgblock, *currentblock;
static int nexttype, funcSyms, blockSyms, symSize;
static int lastfuncoffset;
void dbginit(void)
{
int v = CV_SIGNATURE_32BIT;
nexttype = CV_FIRST_NONPRIM;
if (prm_debug)
{
emit(typeseg, &v, 4);
emit(symseg, &v, 4);
}
lastfuncoffset = 0;
}
//-------------------------------------------------------------------------
static int emittype(char *buf)
{
int v = 0, len;
len = *((short*)buf) + 2;
if (len % 4)
{
*(int*)(buf + len) = 0;
*(short*)buf += 4-len % 4;
len += 4-len % 4;
}
emit(typeseg, buf, len);
}
//-------------------------------------------------------------------------
static void emitsym(char *buf)
{
int v = 0, len;
len = *((short*)buf) + 2;
if (len % 4)
{
*(int*)(buf + len) = 0;
*(short*)buf += 4-len % 4;
len += 4-len % 4;
}
emit(symseg, buf, len);
}
//-------------------------------------------------------------------------
static int isintrins(TYP *type, int allowptr)
{
int v;
if (type->typeindex && *type->typeindex)
{
return *type->typeindex; /* its in the table or an intrinsic that has
been looked up */
}
if (allowptr && type->type == bt_pointer)
{
if (type->val_flag &VARARRAY)
return 0;
// will be handled separately
if (type->btp == bt_pointer && (type->btp->val_flag &VARARRAY))
return 0;
if (v = isintrins(type, FALSE))
if (v < CV_FIRST_NONPRIM && !(type->cflags &(DF_CONST | DF_VOL)))
return v | (CV_TM_NPTR32 << CV_MSHIFT);
}
else if (allowptr && type->type == bt_farpointer)
{
if (v = isintrins(type, FALSE))
if (v < CV_FIRST_NONPRIM && !(type->cflags &(DF_CONST | DF_VOL)))
return v | (CV_TM_FPTR32 << CV_MSHIFT);
}
else if (allowptr && type->type == bt_segpointer)
{
v = CV_SP_SEGMENT << CV_SSHIFT;
}
else
{
if (type->type < sizeof(intrinsxlate) / sizeof(int) && type->type !=
bt_enum)
return intrinsxlate[type->type];
// relies on the type table being ordered
}
return 0;
}
//-------------------------------------------------------------------------
int numeric_leaf(char *buf, unsigned int size)
{
if (size < LF_NUMERIC)
{
*(short*)buf = size;
return 2;
}
else
{
*(short*)buf = LF_LONG;
*(int*)(buf + 2) = size;
return 6;
}
}
//-------------------------------------------------------------------------
int debug_outputpointer(TYP *type)
{
char buf[100];
int val;
if (!type->val_flag)
{
lfPointer *ptr = buf + 2;
val = debug_outputtype(type->btp);
if (CV_IS_PRIMITIVE(val) && CV_MODE(val) == CV_TM_DIRECT)
{
if (type->type == bt_pointer)
val = CV_NEWMODE(val, CV_TM_NPTR32);
else
val = CV_NEWMODE(val, CV_TM_FPTR32);
}
else
{
memset(buf, 0, 100);
ptr->u.leaf = LF_POINTER;
if (type->type == bt_pointer)
ptr->u.attr.ptrtype = CV_PTR_NEAR32;
else
ptr->u.attr.ptrtype = CV_PTR_FAR32;
ptr->u.attr.ptrmode = CV_PTR_MODE_PTR;
ptr->u.attr.isflat32 = TRUE;
ptr->u.attr.isvolatile = !!(type->cflags &DF_VOL);
ptr->u.attr.isconst = !!(type->cflags &DF_CONST);
ptr->u.utype = val;
*(short*)buf = sizeof(lfPointer); // we are cheating here
emittype(buf);
val = nexttype++;
}
}
else
{
int indexes[100];
int i = 0, len;
lfArray *ptr = buf + 2;
if (type->val_flag &VARARRAY)
{
varjoin: ptr->leaf = LF_VARARRAY;
// LF_VARARRAY is NOT one of the original types
type = type->btp;
while (type->esize)
type = type->btp;
}
else if (type->btp == bt_pointer && (type->btp->val_flag &VARARRAY))
{
type = type->btp;
goto varjoin;
}
else
{
ptr->leaf = LF_ARRAY;
type = type->btp;
}
val = debug_outputtype(type);
ptr->elemtype = val;
ptr->idxtype = T_INT4;
len = numeric_leaf(ptr->data, type->size);
// size of base type for vararray
len = sizeof(lfArray) - 1+len;
*(short*)buf = len;
emittype(buf);
val = nexttype++;
}
return val;
}
//-------------------------------------------------------------------------
int debug_outputref(TYP *type)
{
char buf[100];
int val = debug_outputtype(type->btp);
lfPointer *ptr = buf + 2;
ptr->u.leaf = LF_POINTER;
ptr->u.attr.ptrtype = CV_PTR_NEAR32;
ptr->u.attr.ptrmode = CV_PTR_MODE_REF;
ptr->u.attr.isflat32 = TRUE;
ptr->u.attr.isvolatile = !!(type->cflags &DF_VOL);
ptr->u.attr.isconst = !!(type->cflags &DF_CONST);
ptr->u.utype = val;
*(short*)buf[0] = sizeof(lfPointer);
emittype(buf);
val = nexttype++;
return val;
}
//-------------------------------------------------------------------------
static int putname(char *buf, char *name)
{
char internal[256];
int len;
unmangle(internal, name);
len = strlen(internal);
*buf++ = len++;
strcpy(buf, internal);
return len;
}
//-------------------------------------------------------------------------
static int outputFields(SYM *field, int *count)
{
char buffer[1024], *p = buffer + 4;
int val = 0;
memset(buffer, 0, 1024);
while (field)
{
if (field->tp->type != bt_defunc)
{
char qbuf[256];
int len;
lfMember *ptr = qbuf;
memset(qbuf, 0, 256);
ptr->leaf = LF_MEMBER;
ptr->index = debug_outputtype(field->tp);
len = numeric_leaf(ptr->offset, field->value.i);
len += putname(ptr->offset + len, field->name) + sizeof(lfMember) -
1;
if (len % 4)
{
qbuf[len] = 0xf0 + 4-len % 4;
len += 4-len % 4;
}
if (p - buffer + len < 1024-sizeof(lfIndex))
{
memcpy(p, qbuf, len);
p += len;
(*count)++;
}
else
{
lfIndex *ptr = p;
val = outputFields(field, count);
ptr->leaf = LF_INDEX;
ptr->index = val;
p += sizeof(lfIndex);
break;
}
}
field = field->next;
}
*(short*)(buffer + 2) = LF_FIELDLIST;
*(short*)buffer = p - buffer - 2;
emittype(buffer);
return nexttype++;
}
//-------------------------------------------------------------------------
static int debug_outputnamesym(TYP *type, int idx)
{
char buf[256];
if (type->sp->name)
{
UDTSYM *us = buf;
us->reclen = sizeof(UDTSYM) + putname(us->name, type->sp->name);
us->rectyp = S_UDT;
us->typind = idx;
emitsym(buf);
}
}
//-------------------------------------------------------------------------
static int debug_outputstruct(TYP *type)
{
char buf[256];
int thetype = nexttype++;
int count = 0, len;
int val, offset, typeofs, countofs;
memset(buf, 0, 256);
offset = segs[typeseg].last->filled + segs[typeseg].last->address;
/* fill in the type now to prevent recursion */
if (!type->typeindex)
{
global_flag++;
type->typeindex = xalloc(sizeof(int));
global_flag--;
}
*type->typeindex = thetype;
if (type->type == bt_union)
{
lfUnion *ptr = buf + 2;
ptr->leaf = LF_UNION;
ptr->count = 0;
ptr->property.packed = type->alignment < 2;
ptr->field = 0;
len = numeric_leaf(ptr->data, type->size);
len += putname(ptr->data + len, type->sp->name);
len += sizeof(lfUnion) - 1;
typeofs = (char*) &ptr->field - (char*)ptr + 2;
countofs = (char*) &ptr->count - (char*)ptr + 2;
}
else
{
lfClass *ptr = buf + 2;
ptr->leaf = type->type == bt_class ? LF_CLASS : LF_STRUCTURE;
ptr->count = 0;
ptr->property.packed = type->alignment < 2;
ptr->field = 0;
len = numeric_leaf(ptr->data, type->size);
len += putname(ptr->data + len, type->sp->name);
len += sizeof(lfClass) - 1;
typeofs = (char*) &ptr->field - (char*)ptr + 2;
countofs = (char*) &ptr->count - (char*)ptr + 2;
}
*(short*)buf = len;
emittype(buf);
val = outputFields(type->lst.head, &count);
/* have to go back after the fact and fill in the type and count */
write_to_seg(typeseg, offset + typeofs, &val, sizeof(CV_typ_t));
write_to_seg(typeseg, offset + countofs, &count, sizeof(unsigned short));
debug_outputnamesym(type, thetype);
return thetype;
}
//-------------------------------------------------------------------------
static int enumfields(SYM *field, int *count)
{
char buffer[1024], *p = buffer + 4;
int val = 0;
memset(buffer, 0, 1024);
while (field)
{
char qbuf[256];
int len;
lfEnumerate *ptr = qbuf;
memset(qbuf, 0, 256);
ptr->leaf = LF_ENUMERATE;
len = numeric_leaf(ptr->value, field->value.i);
len += putname(ptr->value + len, field->name);
len += sizeof(lfEnumerate) - 1;
if (len % 4)
{
qbuf[len] = 0xf0 + 4-len % 4;
len += 4-len % 4;
}
if (p - buffer + len < 1024-sizeof(lfIndex))
{
memcpy(p, qbuf, len);
p += len;
(*count)++;
}
else
{
lfIndex *ptr = p;
val = enumfields(field, count);
ptr->leaf = LF_INDEX;
ptr->index = val;
p += sizeof(lfIndex);
break;
}
field = field->enumlist;
}
*(short*)(buffer + 2) = LF_FIELDLIST;
*(short*)buffer = p - buffer - 2;
emittype(buffer);
return nexttype++;
}
//-------------------------------------------------------------------------
int debug_outputenum(TYP *type)
{
char buf[256];
lfEnum *enu = buf + 2;
int count = 0, val, len;
memset(buf, 0, 256);
val = enumfields(type->enumlist, &count);
enu->leaf = LF_ENUM;
enu->utype = T_INT4;
enu->count = count;
enu->field = val;
putname(enu->Name, type->sp->name);
len = *enu->Name + 1+sizeof(lfEnum) - 1;
*(short*)buf = len;
emittype(buf);
debug_outputnamesym(type, nexttype);
return nexttype++;
}
//-------------------------------------------------------------------------
int debug_outputtypell(TYP *type)
{
int val = 0;
if (val = isintrins(type, TRUE))
{
if (!type->typeindex)
{
global_flag++;
type->typeindex = xalloc(sizeof(int));
global_flag--;
}
return *type->typeindex = val;
}
switch (type->type)
{
case bt_pointer:
val = debug_outputpointer(type);
break;
case bt_ref:
val = debug_outputref(type);
break;
case bt_struct:
val = debug_outputstruct(type);
break;
case bt_union:
val = debug_outputstruct(type);
break;
case bt_class:
val = debug_outputstruct(type);
break;
case bt_enum:
val = debug_outputenum(type);
break;
case bt_func:
/* function ptr */
/* FIXME - should do something more elaborate than this but don't know what
* and need to work on something else
*/
val = T_VOID;
break;
default:
DIAG("debug_outputtype: unhandled type");
break;
}
if (!type->typeindex)
type->typeindex = xalloc(sizeof(int));
return *type->typeindex = val;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -