📄 vms-dbg.c
字号:
VMS_Store_Immediate_Data(Local, Lpnt,OBJ$C_DBG);Lpnt=0; VMS_Def_Struct(struct_number); for(i=0;i<4;i++) Local[Lpnt++] = 0; VMS_Store_Immediate_Data(Local, Lpnt, OBJ$C_DBG);Lpnt=0; }; i=0; while(i<Apoint) Local[Lpnt++] = Asuffix[i++]; if(Lpnt != 0) VMS_Store_Immediate_Data(Local, Lpnt, OBJ$C_DBG); Lpnt=0; }/* This routine generates a symbol definition for a C sybmol for the debugger. * It takes a psect and offset for global symbols - if psect < 0, then this is * a local variable and the offset is relative to FP. In this case it can * be either a variable (Offset < 0) or a parameter (Offset > 0). */VMS_DBG_record(struct VMS_DBG_Symbol* spnt,int Psect,int Offset, char* Name){ char* pnt; int j; int maxlen; int i=0; if(Psect < 0) { /* this is a local variable, referenced to SP */ maxlen=7+strlen(Name); Local[i++] = maxlen; Local[i++]=spnt->VMS_type; if(Offset > 0) Local[i++] = DBG$C_FUNCTION_PARAMETER; else Local[i++] = DBG$C_LOCAL_SYM; pnt=(char*) &Offset; for(j=0;j<4;j++) Local[i++]=*pnt++; /* copy the offset */ } else { maxlen=7+strlen(Name); /* symbols fixed in memory */ Local[i++]=7+strlen(Name); Local[i++]=spnt->VMS_type; Local[i++]=1; VMS_Store_Immediate_Data(Local, i, OBJ$C_DBG); i=0; VMS_Set_Data(Psect,Offset,OBJ$C_DBG,0); } Local[i++]=strlen(Name); pnt=Name; fix_name(pnt); /* if there are bad characters in name, convert them */ while(*pnt!='\0') Local[i++]=*pnt++; VMS_Store_Immediate_Data(Local, i, OBJ$C_DBG); if(spnt->VMS_type == DBG$C_ADVANCED_TYPE) generate_suffix(spnt,0);}/* This routine parses the stabs entries in order to make the definition * for the debugger of local symbols and function parameters */int VMS_local_stab_Parse(symbolS * sp){ char *pnt; char *pnt1; char *str; struct VMS_DBG_Symbol* spnt; struct VMS_Symbol * vsp; int dbx_type; int VMS_type; dbx_type=0; str=sp->sy_nlist.n_un.n_name; pnt=(char*) strchr(str,':'); if(pnt==(char*) NULL) return; /* no colon present */ pnt1=pnt++; /* save this for later, and skip colon */ if(*pnt == 'c') return 0; /* ignore static constants *//* there is one little catch that we must be aware of. Sometimes function * parameters are optimized into registers, and the compiler, in its infiite * wisdom outputs stabs records for *both*. In general we want to use the * register if it is present, so we must search the rest of the symbols for * this function to see if this parameter is assigned to a register. */ { char *str1; char *pnt2; symbolS * sp1; if(*pnt == 'p'){ for(sp1 = sp->sy_next; sp1; sp1 = sp1->sy_next) { if ((sp1->sy_nlist.n_type & N_STAB) == 0) continue; if((unsigned char)sp1->sy_nlist.n_type == N_FUN) break; if((unsigned char)sp1->sy_nlist.n_type != N_RSYM) continue; str1=sp1->sy_nlist.n_un.n_name; /* and get the name */ pnt2=str; while(*pnt2 != ':') { if(*pnt2 != *str1) break; pnt2++; str1++;}; if((*str1 != ':') || (*pnt2 != ':') ) continue; return; /* they are the same! lets skip this one */ }; /* for *//* first find the dbx symbol type from list, and then find VMS type */ pnt++; /* skip p in case no register */ };/* if */ }; /* p block */ pnt = cvt_integer( pnt, &dbx_type); spnt = find_symbol(dbx_type); if(spnt==(struct VMS_DBG_Symbol*) NULL) return 0;/*Dunno what this is*/ *pnt1='\0'; VMS_DBG_record(spnt,-1,sp->sy_nlist.n_value,str); *pnt1=':'; /* and restore the string */ return 1;}/* this routine parses a stabs entry to find the information required to define * a variable. It is used for global and static variables. * Basically we need to know the address of the symbol. With older versions * of the compiler, const symbols are * treated differently, in that if they are global they are written into the * text psect. The global symbol entry for such a const is actually written * as a program entry point (Yuk!!), so if we cannot find a symbol in the list * of psects, we must search the entry points as well. static consts are even * harder, since they are never assigned a memory address. The compiler passes * a stab to tell us the value, but I am not sure what to do with it. */static gave_compiler_message = 0;static int VMS_stab_parse(symbolS * sp,char expected_type, int type1,int type2,int Text_Psect){ char *pnt; char *pnt1; char *str; symbolS * sp1; struct VMS_DBG_Symbol* spnt; struct VMS_Symbol * vsp; int dbx_type; int VMS_type; dbx_type=0; str=sp->sy_nlist.n_un.n_name; pnt=(char*) strchr(str,':'); if(pnt==(char*) NULL) return; /* no colon present */ pnt1=pnt; /* save this for later*/ pnt++; if(*pnt==expected_type){ pnt = cvt_integer(pnt+1,&dbx_type); spnt = find_symbol(dbx_type); if(spnt==(struct VMS_DBG_Symbol*) NULL) return 0;/*Dunno what this is*//* now we need to search the symbol table to find the psect and offset for * this variable. */ *pnt1='\0'; vsp=VMS_Symbols; while(vsp != (struct VMS_Symbol*) NULL) {pnt=vsp->Symbol->sy_nlist.n_un.n_name; if(pnt!=(char*) NULL) if(*pnt++ == '_') /* make sure name is the same, and make sure correct symbol type */ if((strlen(pnt) == strlen(str)) && (strcmp(pnt,str)==0) && ((vsp->Symbol->sy_type == type1) || (vsp->Symbol->sy_type == type2))) break; vsp=vsp->Next;}; if(vsp != (struct VMS_Symbol*) NULL){ VMS_DBG_record(spnt,vsp->Psect_Index,vsp->Psect_Offset,str); *pnt1=':'; /* and restore the string */ return 1;};/* the symbol was not in the symbol list, but it may be an "entry point" if it was a constant */ for(sp1 = symbol_rootP; sp1; sp1 = sp1->sy_next) { /* * Dispatch on STAB type */ if(sp1->sy_type != (N_TEXT | N_EXT) && sp1->sy_type!=N_TEXT) continue; pnt = sp1->sy_nlist.n_un.n_name; if(*pnt == '_') pnt++; if(strcmp(pnt,str) == 0){ if(!gave_compiler_message && expected_type=='G'){printf("***Warning - the assembly code generated by the compiler has placed\n");printf("global constant(s) in the text psect. These will not be available to\n");printf("other modules, since this is not the correct way to handle this. You\n");printf("have two options: 1) get a patched compiler that does not put global\n");printf("constants in the text psect, or 2) remove the 'const' keyword from\n");printf("definitions of global variables in your source module(s). Don't say\n");printf("I didn't warn you!");gave_compiler_message = 1;}; VMS_DBG_record(spnt, Text_Psect, sp1->sy_nlist.n_value, str); *pnt1=':'; *(sp1->sy_nlist.n_un.n_name) = 'L'; /* fool assembler to not output this * as a routine in the TBT */ return 1;}; }; }; *pnt1=':'; /* and restore the string */ return 0;}VMS_GSYM_Parse(symbolS * sp,int Text_Psect){ /* Global variables */ VMS_stab_parse(sp,'G',(N_UNDF | N_EXT),(N_DATA | N_EXT),Text_Psect);}VMS_LCSYM_Parse(symbolS * sp,int Text_Psect){/* Static symbols - uninitialized */ VMS_stab_parse(sp,'S',N_BSS,-1,Text_Psect);}VMS_STSYM_Parse(symbolS * sp,int Text_Psect){ /*Static symbols - initialized */ VMS_stab_parse(sp,'S',N_DATA,-1,Text_Psect);}/* for register symbols, we must figure out what range of addresses within the * psect are valid. We will use the brackets in the stab directives to give us * guidance as to the PC range that this variable is in scope. I am still not * completely comfortable with this but as I learn more, I seem to get a better * handle on what is going on. * Caveat Emptor. */VMS_RSYM_Parse(symbolS * sp,symbolS * Current_Routine,int Text_Psect){ char* pnt; char* pnt1; char* str; int dbx_type; struct VMS_DBG_Symbol* spnt; int j; int maxlen; int i=0; int bcnt=0; int Min_Offset=-1; /* min PC of validity */ int Max_Offset=0; /* max PC of validity */ symbolS * symbolP; for(symbolP = sp; symbolP; symbolP = symbolP->sy_next) { /* * Dispatch on STAB type */ switch((unsigned char)symbolP->sy_type) { case N_LBRAC: if(bcnt++==0) Min_Offset = symbolP->sy_nlist.n_value; break; case N_RBRAC: if(--bcnt==0) Max_Offset = symbolP->sy_nlist.n_value-1; break; } if((Min_Offset != -1) && (bcnt == 0)) break; if((unsigned char)symbolP->sy_type == N_FUN) break; }/* check to see that the addresses were defined. If not, then there were no * brackets in the function, and we must try to search for the next function * Since functions can be in any order, we should search all of the symbol list * to find the correct ending address. */ if(Min_Offset == -1){ int Max_Source_Offset; int This_Offset; Min_Offset = sp->sy_nlist.n_value; for(symbolP = symbol_rootP; symbolP; symbolP = symbolP->sy_next) { /* * Dispatch on STAB type */ This_Offset = symbolP->sy_nlist.n_value; switch(symbolP->sy_type) { case N_TEXT | N_EXT: if((This_Offset > Min_Offset) && (This_Offset < Max_Offset)) Max_Offset = This_Offset; break; case N_SLINE: if(This_Offset > Max_Source_Offset) Max_Source_Offset=This_Offset; } }/* if this is the last routine, then we use the PC of the last source line * as a marker of the max PC for which this reg is valid */ if(Max_Offset == 0x7fffffff) Max_Offset = Max_Source_Offset; }; dbx_type=0; str=sp->sy_nlist.n_un.n_name; pnt=(char*) strchr(str,':'); if(pnt==(char*) NULL) return; /* no colon present */ pnt1=pnt; /* save this for later*/ pnt++; if(*pnt!='r') return 0; pnt = cvt_integer( pnt+1, &dbx_type); spnt = find_symbol(dbx_type); if(spnt==(struct VMS_DBG_Symbol*) NULL) return 0;/*Dunno what this is yet*/ *pnt1='\0'; maxlen=25+strlen(sp->sy_nlist.n_un.n_name); Local[i++]=maxlen; Local[i++]=spnt->VMS_type; Local[i++]=0xfb; Local[i++]=strlen(sp->sy_nlist.n_un.n_name)+1; Local[i++]=0x00; Local[i++]=0x00; Local[i++]=0x00; Local[i++]=strlen(sp->sy_nlist.n_un.n_name); pnt=sp->sy_nlist.n_un.n_name; fix_name(pnt); /* if there are bad characters in name, convert them */ while(*pnt!='\0') Local[i++]=*pnt++; Local[i++]=0xfd; Local[i++]=0x0f; Local[i++]=0x00; Local[i++]=0x03; Local[i++]=0x01; VMS_Store_Immediate_Data(Local, i, OBJ$C_DBG); i=0; VMS_Set_Data(Text_Psect,Min_Offset,OBJ$C_DBG,1); VMS_Set_Data(Text_Psect,Max_Offset,OBJ$C_DBG,1); Local[i++]=0x03; Local[i++]=sp->sy_nlist.n_value; Local[i++]=0x00; Local[i++]=0x00; Local[i++]=0x00; VMS_Store_Immediate_Data(Local, i, OBJ$C_DBG); *pnt1=':'; if(spnt->VMS_type == DBG$C_ADVANCED_TYPE) generate_suffix(spnt,0);}/* this function examines a structure definition, checking all of the elements * to make sure that all of them are fully defined. The only thing that we * kick out are arrays of undefined structs, since we do not know how big * they are. All others we can handle with a normal forward reference. */static int forward_reference(char* pnt){ int i; struct VMS_DBG_Symbol * spnt; struct VMS_DBG_Symbol * spnt1; pnt = cvt_integer(pnt+1,&i); if(*pnt == ';') return 0; /* no forward references */ do{ pnt=(char*) strchr(pnt,':'); pnt = cvt_integer(pnt+1,&i); spnt = find_symbol(i); if(spnt == (struct VMS_DBG_Symbol*) NULL) return 0; while((spnt->advanced == POINTER) || (spnt->advanced == ARRAY)){ i=spnt->type2; spnt1 = find_symbol(spnt->type2); if((spnt->advanced == ARRAY) && (spnt1 == (struct VMS_DBG_Symbol*) NULL))return 1; if(spnt1 == (struct VMS_DBG_Symbol*) NULL) break; spnt=spnt1; }; pnt = cvt_integer(pnt+1,&i); pnt = cvt_integer(pnt+1,&i); }while(*++pnt != ';'); return 0; /* no forward refences found */}/* This routine parses the stabs directives to find any definitions of dbx type * numbers. It makes a note of all of them, creating a structure element * of VMS_DBG_Symbol that describes it. This also generates the info for the * debugger that describes the struct/union/enum, so that further references * to these data types will be by number * We have to process pointers right away, since there can be references * to them later in the same stabs directive. We cannot have forward * references to pointers, (but we can have a forward reference to a pointer to * a structure/enum/union) and this is why we process them immediately. * After we process the pointer, then we search for defs that are nested even * deeper. */static int VMS_typedef_parse(char* str){ char* pnt; char* pnt1; char* pnt2; int i; int dtype; struct forward_ref * fpnt; int i1,i2,i3; int convert_integer; struct VMS_DBG_Symbol* spnt; struct VMS_DBG_Symbol* spnt1;/* check for any nested def's */ pnt=(char*)strchr(str+1,'='); if((pnt != (char*) NULL) && (*(str+1) != '*')) if(VMS_typedef_parse(pnt) == 1 ) return 1;/* now find dbx_type of entry */ pnt=str-1; if(*pnt == 'c'){ /* check for static constants */ *str = '\0'; /* for now we ignore them */ return 0;}; while((*pnt <= '9')&& (*pnt >= '0')) pnt--; pnt++; /* and get back to the number */ cvt_integer(pnt,&i1); spnt = find_symbol(i1);/* first we see if this has been defined already, due to a forward reference*/ if(spnt == (struct VMS_DBG_Symbol*) NULL) { if(VMS_Symbol_type_list==(struct VMS_DBG_Symbol*) NULL) {spnt=(struct VMS_DBG_Symbol*) malloc(sizeof(struct VMS_DBG_Symbol)); spnt->next = (struct VMS_DBG_Symbol*) NULL; VMS_Symbol_type_list=spnt;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -