home *** CD-ROM | disk | FTP | other *** search
- #include "c.h"
- #include "cv.h"
-
- typedef struct tagLocal {
- char data[50];
- short len;
- } LocalVariable;
-
- LocalVariable LocalsTable[256];
- static ProcList *LastProc;
- ProcList *ProceduresList;
- static int DebugSymbolPtr = 0;
- DataList *DataSymbolsInfo;
- static DataList *LastDataSymbolsInfo;
- DataList *DataTypesInfo;
- static DataList *LastDataTypesInfo;
- static int AddToEmittedTypes(Type ty,int cvType);
- int AddNewType(char *data,int len,char *name);
- int AddArrayType(Type ty,char *name);
- int BuildPointerType(int xrefIdx);
- static int Typesidx = 0;
- static int GetTypeInternal(Type ty,char *name);
-
- void PutInSymbolBuffer(char *data,int len)
- {
- if (DebugSymbolPtr > 255) return;
- if (len < 50) {
- memcpy(LocalsTable[DebugSymbolPtr].data,data,len);
- LocalsTable[DebugSymbolPtr].len = len;
- DebugSymbolPtr++;
- }
- }
-
- void PutSymbolRecord(int type,char *data,int len,char *name)
- {
- char tmprec[256];
- int i;
-
- for (i=4; i<len+4;i++) {
- tmprec[i] = data[i-4];
- }
- tmprec[i++] = strlen(name);
- while (*name) {
- tmprec[i++] = *name++;
- }
- *((unsigned short *)tmprec) = i-2;
- *((unsigned short *)(tmprec+2)) = type;
- PutInSymbolBuffer(tmprec,i);
- }
-
- int BuildFunctionPointerRecord(Type ty,char *name)
- {
- Type *tp;
- int nrOfArgs,len,idx,result;
- unsigned short *data;
- char tmpbuffer[12],*p;
-
- nrOfArgs = 0;
- tp = ty->type->u.f.proto;
- if (tp) {
- while (*tp) {
- nrOfArgs++;
- tp++;
- }
- }
- len = 3 + nrOfArgs;
- len = len * sizeof(short);
- data = (unsigned short *)malloc(len);
- data[0] = len-2;
- data[1] = LF_ARGLIST;
- data[2] = nrOfArgs;
- tp = ty->type->u.f.proto;
- idx = 3;
- if (tp) {
- while (*tp) {
- data[idx++] = GetTypeInternal(*tp,"");
- tp++;
- }
- }
- result = AddNewType((char *)data,len,name);
- free(data);
- p = tmpbuffer;
- *(unsigned short *)p = 10;
- p += 2;
- *(unsigned short *)p = 0x8; /* Procedure */
- p += 2;
- *(unsigned short *)p = 116; /* ??? */
- p += 2;
- *p++ = 0; /* no special call flags */
- *p++ = 0; /* reserved */
- *(unsigned short *)p = nrOfArgs;
- p += 2;
- *(unsigned short *)p = Typesidx+4096 - 1;
- result = AddNewType(tmpbuffer,12,name);
- return(BuildPointerType(4096+result));
- }
-
-
- static int GetTypeInternal(Type ty,char *name)
- {
- int st;
-
- switch (ty->op) {
- case CHAR:
- if (ty->u.sym->name[0] == 'u')
- return(0x20);
- return(0x10);
- case DOUBLE:
- return(0x41);
- case FLOAT:
- return(0x40);
- case STRUCT:
- return(AddToEmittedTypes(ty,LF_STRUCTURE));
- case ENUM:
- return(0x74); /* signed int */
- case INT:
- case UNSIGNED:
- if (ty->u.sym->name[0] == 'u')
- return(0x75);
- return(0x74); /* signed int */
- case SHORT:
- if (ty->u.sym->name[0] == 'u')
- return(0x73);
- return(0x72); /* signed int */
- case FUNCTION:
- if (ty->type)
- return GetTypeInternal(ty->type,name);
- break;
- case LONGLONG:
- return 0x76;
- case ARRAY:
- return(AddArrayType(ty,name));
- case UNION:
- return(AddToEmittedTypes(ty,LF_UNION));
- case POINTER:
-
- assert(ty->type);
- redo:
- st = ty->type->op;
- switch(st) {
- case CONST:
- ty = ty->type;
- goto redo;
- case CHAR:
- return(0x470);
- case DOUBLE:
- return(0x441);
- case FLOAT:
- return(0x440);
- case STRUCT:
- return(AddToEmittedTypes(ty,LF_STRUCTURE));
- case UNION:
- return(AddToEmittedTypes(ty,LF_UNION));
- case ENUM:
- case INT:
- if (ty->type->type && ty->type->type->u.sym->name &&
- ty->type->u.sym->name[0] == 'u')
- return(0x475);
- return(0x474);
- case UNSIGNED:
- if (ty->type->type == NULL) return(0x475);
- break;
- case SHORT:
- if (ty->type->type && ty->type->type->u.sym->name &&
- ty->type->u.sym->name[0] == 'u')
- return(0x473);
- return(0x472);
- case LONGLONG:
- return 0x476;
- case VOID:
- return(0x403);
- case FUNCTION:
- return(4096+BuildFunctionPointerRecord(ty,name));
- break;
- case ARRAY:
- return 4096 + BuildPointerType(AddArrayType(ty->type,name));
- case POINTER:
- return 4096 + BuildPointerType(GetTypeInternal(ty->type,name));
- default:
- warning("Unknown type %s (%d) when generating debug info\n",name,st);
- break;
-
- }
- break;
- }
- return(0);
- }
-
- int GetType(Symbol p)
- {
- return(GetTypeInternal(p->type,p->name));
- }
- /*
- 17 EAX
- 18 ECX
- 19 EDX
- 20 EBX
- 21 ESP
- 22 EBP
- 23 ESI
- 24 EDI
- */
- static int FindRegisterNumber(char *regName)
- {
- if (regName[2] == 'a') return 17;
- else if (regName[2] == 'b') return 20;
- else if (regName[2] == 'c') return 18;
- else if (regName[2] == 's') return 23;
- else if (regName[2] == 'd' && regName[3] == 'x')
- return 19;
- else if (regName[2] == 'd' && regName[3] == 'i')
- return 24;
- return 0;
- }
-
- void GenLocalDebugInfo(Symbol p)
- {
- struct autoDataInfo info;
- int regNumber;
- char buf[150],*pt;
- int i;
-
- if (glevel == 0) return;
- if (p->x.offset == 0 && p->x.regnode) {
- /*
- This symbol record describes a symbol that has been enregistered. Provisions
- for enabling future implementation tracking of a symbol into and out of
- registers is provided in this symbol. When the symbol processor is examining
- a register symbol, the length field of the symbol is compared with the offset of
- the byte following the symbol name field. If these are the same, there is no
- register tracking information. If the length and offset are different, the byte
- following the end of the symbol name is examined. If the byte is zero, there is
- no register tracking information following the symbol. If the byte is not zero,
- then the byte indexes into the list of stack machine implementations and styles
- of register tracking. Microsoft does not currently emit or process register
- tracking information.
- 2 2 2 2 * *
- length S_REGISTER @type register name tracking
-
- @type The type of the symbol
- register Enumerate of the registers in which the symbol value is stored.
- This field is treated as two bytes. The high order byte specifies the register
- in which the high order part of the value is stored. The low byte specifies
- the register for the low order part of the value. If the value is not stored
- in two registers then high order register field contains the enumerate value
- for no register. For register enumeration values, see Section 6. The
- register index enumeration is specific to the processor model for the module.
- name Length-prefixed name of the symbol stored in the register
- tracking Register tracking information. Format unspecified.
- 32-bit registers
-
- 17 EAX
- 18 ECX
- 19 EDX
- 20 EBX
- 21 ESP
- 22 EBP
- 23 ESI
- 24 EDI
-
- */
- regNumber = FindRegisterNumber(p->x.name);
- pt = buf + 2;
- *(unsigned short *)pt = S_REGISTER;
- pt += 2;
- *(unsigned short *)pt = GetType(p);
- pt += 2;
- *(unsigned short *)pt = regNumber;
- pt += 2;
- pt = PutLengthPrefixedName(pt,p->name);
- *pt++ = 0;
- i = pt - buf;
- if (i & 1) {
- *pt++ = 0;
- }
- i = pt - buf;
- pt = buf;
- *(unsigned short *)pt = i-2;
- PutInSymbolBuffer(buf,i);
- return;
- }
- else
- info.offset = p->x.offset;
- info.type = GetType(p);
- PutSymbolRecord(S_BPREL32,(char *)&info,6,p->name);
- }
- void GenBlockDebugInfo(Code cp)
- {
- Symbol *p = cp->u.block.locals;
- for (; *p; p++) {
- GenLocalDebugInfo(*p);
- }
- }
-
- ProcList *newProcList(char *name)
- {
- ProcList *result;
- result = (ProcList *)malloc(sizeof(ProcList));
- memset(result,0,sizeof(ProcList));
- result->procInfo.u.Name = malloc(strlen(name)+1);
- strcpy(result->procInfo.u.Name,name);
- return(result);
- }
- DataList *newDataList(int len,char *name)
- {
- DataList *result;
-
- result = malloc(sizeof(DataList));
- result->Next = NULL;
- result->data = malloc(len);
- result->len = len;
- result->Name = name;
- return(result);
- }
-
- #if 0
- int FindArgListType(int nrOfArguments,unsigned short *typesVector)
- {
- ProcList *pl;
-
- pl = ProceduresList;
- while (pl) {
- if (pl->NrOfArguments == nrOfArguments) {
- if (pl->FunctionRecord) {
- if (!memcmp(pl->FunctionRecord->data+6,typesVector,nrOfArguments*sizeof(short))) {
- return(pl->procInfo.procType);
- }
- }
- }
- pl = pl->Next;
- }
- return(-1);
- }
- #endif
-
- static int BuildFunctionType(ProcList *pl,Symbol f)
- {
- char tmpbuffer[12],*p;
-
- p = tmpbuffer;
- *(unsigned short *)p = 10;
- p += 2;
- *(unsigned short *)p = 0x8; /* Procedure */
- p += 2;
- *(unsigned short *)p = GetTypeInternal(f->type,f->x.name);
- p += 2;
- *p++ = 0; /* no special call flags */
- *p++ = 0; /* reserved */
- *(unsigned short *)p = pl->NrOfArguments;
- p += 2;
- *(unsigned short *)p = Typesidx+4096 - 1;
- return(AddNewType(tmpbuffer,12,pl->FunctionRecord->Name));
- }
-
- void WriteFunctionTypeRecord(Symbol f,int nrOfArguments,unsigned short *typesVector)
- {
- int len,topad;
- unsigned short *data;
-
- // ti = FindArgListType(nrOfArguments,typesVector);
- #if 0
- if (ti != -1) {
- LastProc->procInfo.procType = ti;
- LastProc->FunctionRecord = NULL;
- return;
- }
- #endif
- len = 3 + nrOfArguments;
- topad = 0;
- len = len * sizeof(short);
- data = (unsigned short *)malloc(len);
- data[0] = len-2;
- data[1] = LF_ARGLIST;
- data[2] = nrOfArguments;
- memcpy(&data[3],typesVector,nrOfArguments * sizeof(short));
- if (topad) {
- unsigned char *p;
-
- p = (unsigned char *)data + len - 2;
- *p++ = (unsigned char)0xF2;
- *p++ = (unsigned char)0xF1;
- }
- LastProc->FunctionRecord = newDataList(len,f->x.name);
- LastProc->FunctionRecord->data = (char *)data;
- LastProc->FunctionRecord->len = len;
- /* This points to the type index record */
- LastProc->procInfo.procType = 4096 + Typesidx+1;
- if (LastProc->procInfo.procType > 8000) {
- fprintf(stderr,"bad synch in debug info\n");
- }
- AddNewType(LastProc->FunctionRecord->data,LastProc->FunctionRecord->len,f->x.name);
- BuildFunctionType(LastProc,f);
- }
-
- void WriteLocalsDebugInfo(Symbol f,int lineno)
- {
- int i,len,nrOfArguments;
- char *p,*pname;
- Symbol *Arguments,sym;
- struct autoDataInfo info;
- unsigned short *typesVector;
-
- if (glevel == 0) return;
- Arguments = f->u.f.callee;
- nrOfArguments = 0;
- while (*Arguments) {
- Arguments++;
- nrOfArguments++;
- }
- if (nrOfArguments)
- typesVector = (unsigned short *)malloc(sizeof(short)*nrOfArguments);
- else
- typesVector = NULL;
- Arguments = f->u.f.callee;
- for (i=0;i<nrOfArguments;i++) {
- sym = *Arguments++;
- info.offset = sym->x.offset;
- info.type = GetType(sym);
- PutSymbolRecord(S_BPREL32,(char *)&info,6,sym->name);
- typesVector[i] = info.type;
- }
- for (i=0,len=0;i<DebugSymbolPtr;i++) {
- len += LocalsTable[i].len;
- }
- pname = f->x.name;
- /* maybe use f->name? */
- if (ProceduresList == NULL) {
- ProceduresList = newProcList(pname);
- LastProc = ProceduresList;
- }
- else {
- LastProc->Next = newProcList(pname);
- LastProc = LastProc->Next;
- }
- LastProc->data = malloc(len);
- p = LastProc->data;
- for (i=0; i<DebugSymbolPtr;i++) {
- memcpy(p,LocalsTable[i].data,LocalsTable[i].len);
- p += LocalsTable[i].len;
- }
- LastProc->len = len;
- LastProc->Sym = f;
- DebugSymbolPtr = 0;
- LastProc->NrOfArguments = nrOfArguments;
- WriteFunctionTypeRecord(f,nrOfArguments,typesVector);
- free(typesVector);
- }
-
- char *PutLengthPrefixedName(char *dst,char *src)
- {
- if (src == NULL) src = "_unnamed";
- *dst++ = strlen(src);
- while (*src) {
- *dst++ = *src++;
- }
- return(dst);
- }
-
- DataList *AddToCVData(char *data,int len,char *name)
- {
- if (DataSymbolsInfo == NULL) {
- DataSymbolsInfo = newDataList(len,name);
- LastDataSymbolsInfo = DataSymbolsInfo;
- }
- else {
- LastDataSymbolsInfo->Next = newDataList(len,name);
- LastDataSymbolsInfo = LastDataSymbolsInfo->Next;
- }
- memcpy(LastDataSymbolsInfo->data,data,len);
- return(LastDataSymbolsInfo);
-
- }
-
- int AddNewType(char *data,int len,char *name)
- {
- if (DataTypesInfo == NULL) {
- DataTypesInfo = newDataList(len,name);
- LastDataTypesInfo = DataTypesInfo;
- }
- else {
- LastDataTypesInfo->Next = newDataList(len,name);
- LastDataTypesInfo = LastDataTypesInfo->Next;
- }
- memcpy(LastDataTypesInfo->data,data,len);
- return(Typesidx++);
-
- }
-
- extern int NrOfTypes;
- /*
- (0x0406) Data Member
- This leaf specifies nonstatic data members of a class.
-
- 2 2 2 * *
- LF_MEMBER @type attribute offset name
-
- @type Index to type record for field
- attribute Member attribute bit field
- offset Numeric leaf specifying the offset of field in the structure
- name Length-prefixed name of the member field
- */
- int BuildFieldList(Field flist,int count)
- {
- char *buffer,*p;
- int memberType,len,result,padCount;
-
- p = buffer = malloc(16000);
- *(unsigned short *)p = 0;
- p += 2;
- *(unsigned short *)p = 0x204;
- p += 2;
- while (flist) {
- *(unsigned short *)p = LF_MEMBER; /* (0x406) */
- p += 2;
- memberType = GetTypeInternal(flist->type,flist->name);
- *(unsigned short *)p = memberType;
- p += 2;
- *(unsigned short *)p = 0;
- p += 2;
- *(unsigned short *)p = flist->offset;
- p += 2;
- p = PutLengthPrefixedName(p,flist->name);
- flist = flist->link;
- len = (p - buffer);
- /*
- Because of the requirement for natural alignment, there may be padding
- between elements of the field list. As a program walks down the field
- list, the address of the next subfield is calculated by adding the length
- of the previous field to the address of the previous field. The byte at
- the new address is examined and if it is greater than 0xf0, the low four
- bits are extracted and added to the address to find the address of the next
- subfield. These padding fields are not included in the count field of the
- class, structure, union, or enumeration type records.
- */
- padCount = len % 4;
- if (padCount) {
- padCount = 4 - padCount;
- *p++ = (char)(0xF0 | padCount--);
- while (padCount > 0) {
- *p++ = (char)(0xF0|padCount--);
- }
- }
- }
- len = p - buffer;
- p = buffer;
- *(unsigned short *)p = len-2;
- result = AddNewType(buffer,len,"");
- free(buffer);
- return(result);
- }
- char *PutNumericValue(char *dst,int size)
- {
- if (size < 0x8000) {
- *(unsigned short *)dst = size;
- dst += 2;
- }
- else {
- *(unsigned short *)dst = LF_LONG;
- dst += 2;
- *(unsigned long *)dst = size;
- dst += 4;
- }
- return(dst);
- }
-
- /*
- (0x0004) Classes and Structures
- The format for structures and classes is as follows:
-
- 2 2 2 2 2 2 * *
-
- leaf count @field property @dList @vshape length name
-
- leaf LF_CLASS or LF_STRUCTURE
- count Number of elements in the class or structure. This count includes direct,
- virtual, and indirect virtual bases, and methods including overloads, data
- members, static data members, friends, and so on.
- @field Type index of the field list for this class.
- property Property bit field
-
- packed :1 Structure is packed
- ctor :1 Class has constructors and/or destructors
- overops :1 Class has overloaded operators
- isnested :1 Class is a nested class
- cnested :1 Class contains nested classes
- opassign :1 Class has overloaded assignment
- opcast :1 Class has casting methods
- fwdref :1 Class/structure is a forward (incomplete) reference
- scoped :1 This is a scoped definition
- reserved :8
- @dList Type index of the derivation list. This is output by the compiler as
- 0x0000 and is filled in by the CVPACK utility to a LF_DERIVED record
- containing the type indices of those classes which immediately inherit
- the current class. A zero index indicates that no derivation information
- is available. A LF_NULL index indicates that the class is not inherited
- by other classes.
- @vshape Type index of the virtual function table shape descriptor
- length Numeric leaf specifying size in bytes of the structure
- name Length-prefixed name this type
-
- (0x0005) Structures
- Structures have the same format as classes. Structure type records are used
- exclusively by the C compiler. The C++ compiler emits both class and structure
- records depending upon the declaration.
- */
- int BuildStructType(Type ty,int cvType)
- {
- char *name;
- Field flist;
- int size = ty->size;
- int count,len,padCount,result;
- Symbol sym;
- char buffer[200],*p;
-
- sym = ty->u.sym;
- name = sym->name;
- flist = sym->u.s.flist;
- count = 0;
- while (flist) {
- count++;
- flist = flist->link;
- }
- flist = sym->u.s.flist;
- memset(buffer,0,200);
- p = buffer + 2;
- *(unsigned short *)p = cvType;
- p += 2;
- *(unsigned short *)p = count;
- p += 2;
- *(unsigned short *)p = 0;
- p += 2;
- if (cvType == LF_STRUCTURE) {
- /* ignore for the moment the problem of knowing if
- this structure is packed */
- p += 2;
- /* leave the derived field as zero */
- p += 2;
- /* no virtual functions */
- p += 2;
- }
- else if (cvType == LF_UNION) {
- /* Property bit field undocumented */
- p += 2;
- }
- p = PutNumericValue(p,size);
- *p++ = strlen(name);
- while (*name) {
- *p++ = *name++;
- }
- len = (p-buffer);
- padCount = len % 4;
- if (padCount) {
- padCount = 4 - padCount;
- *p++ = (char)(0xF0 | padCount--);
- while (padCount > 0) {
- *p++ = (char)(0xF0|padCount--);
- }
- }
- len = (p - buffer)-2;
- p = buffer;
- *(unsigned short *)p = len;
- result = AddNewType(buffer,len+2,sym->name);
- p = LastDataTypesInfo->data + 6;
- *(unsigned short *)p = BuildFieldList(flist,count)+4096;
- return(result);
- }
-
- int BuildPointerType(int xrefIdx)
- {
- char buffer[8];
- short *p;
-
- p = (short *)buffer;
- p[0] = 6;
- p[1] = LF_POINTER;
- p[2] = 0xA; /* near 32 bit pointer */
- p[3] = xrefIdx;
- return(AddNewType(buffer,8,""));
- }
- static int AddToEmittedTypes(Type typ,int cvType)
- {
- DataList *save;
-
- if (typ == NULL) return(0);
- if (typ->op == POINTER) {
- Type ty;
-
- ty = typ->type;
- assert(ty);
- if (ty->x.marked == 0) {
- if (ty->op != STRUCT && ty->op != UNION) {
- return(0);
- }
- ty->x.typeno = Typesidx;
- ty->x.marked = 1;
- save = LastDataTypesInfo ;
- if (ty->op == STRUCT) {
- BuildStructType(ty,LF_STRUCTURE);
- }
- else if (ty->op == UNION) {
- BuildStructType(ty,LF_UNION);
- }
- else return(0);
- }
- if (ty->x.pointerEmitted) {
- return(ty->x.pointerIndex+4096);
- }
- ty->x.pointerEmitted = 1;
- ty->x.pointerIndex = BuildPointerType(ty->x.typeno+4096);
- return(ty->x.pointerIndex+4096);
- }
- if (typ->x.marked == 0) {
- if (typ->op != STRUCT && typ->op != UNION) {
- return(0);
- }
- typ->x.typeno = Typesidx;
- typ->x.marked = 1;
- save = LastDataTypesInfo;
- if (typ->op == STRUCT) {
- BuildStructType(typ,LF_STRUCTURE);
- }
- else if (typ->op == UNION) {
- BuildStructType(typ,LF_UNION);
- }
- }
- return(typ->x.typeno+4096);
- }
- /*
- (0x0003) Simple Array
-
- 2 2 2 * *
-
- LF_ARRAY @elemtype @idxtype length name
-
- @elemtype Type index of each array element
- @idxtype Type index of indexing variable
- length Length of array in bytes
- name Length-prefixed name of array
-
- */
- int AddArrayType(Type ty,char *name)
- {
- int len,result;
- char buf[256],*p,*n;
-
- assert(ty->type);
- p = buf;
- p += 2;
- *(unsigned short *)p = LF_ARRAY;
- p += 2;
- n = NULL;
- if (ty->type->u.sym)
- n = ty->type->u.sym->name;
- if (n == NULL) n = "";
- *(unsigned short *)p = GetTypeInternal(ty->type,n);
- p += 2;
- *(unsigned short *)p = 0x74; /* index is signed int... */
- p += 2;
- p = PutNumericValue(p,ty->size);
- p = PutLengthPrefixedName(p,name);
- len = p - buf;
- *(unsigned short *)buf = len - 2;
- result = AddNewType(buf,len,name);
- return result+4096;
-
- }
-