⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vms-dbg.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
#include <stdio.h>#include "as.h"#include "struc-symbol.h"#include "symbols.h"#include "objrecdef.h"#include <stab.h>/* This file contains many of the routines needed to output debugging info into * the object file that the VMS debugger needs to understand symbols.  These * routines are called very late in the assembly process, and thus we can be * fairly lax about changing things, since the GSD and the TIR sections have * already been output. *//* We need this info to cross correlate between the stabs def for a symbol and * the actual symbol def.  The actual symbol def contains the psect number and * offset, which is needed to declare a variable to the debugger for global * and static variables */struct VMS_Symbol {	struct VMS_Symbol *Next;	struct symbol *Symbol;	int Size;	int Psect_Index;	int Psect_Offset;	};extern struct VMS_Symbol *VMS_Symbols;enum advanced_type {BASIC,POINTER,ARRAY,ENUM,STRUCT,UNION,FUNCTION,VOID,UNKNOWN};/* this structure contains the information from the stabs directives, and the * information is filled in by VMS_typedef_parse.  Everything that is needed * to generate the debugging record for a given symbol is present here. * This could be done more efficiently, using nested struct/unions, but for now * I am happy that it works. */struct VMS_DBG_Symbol{	struct VMS_DBG_Symbol * next;	enum advanced_type advanced;	/* description of what this is */	int dbx_type;	/* this record is for this type */	int type2;	/* For advanced types this is the type referred to.				i.e. the type a pointer points to, or the type				of object that makes up an array */	int VMS_type;	/* Use this type when generating a variable def */	int index_min;	/* used for arrays - this will be present for all */	int index_max;	/* entries, but will be meaningless for non-arrays */	int data_size;	/* size in bytes of the data type.  For an array, this			   is the size of one element in the array */	int struc_numb; /* Number of the structure/union/enum - used for ref */};struct VMS_DBG_Symbol *VMS_Symbol_type_list={(struct VMS_DBG_Symbol*) NULL};/* we need this structure to keep track of forward references to * struct/union/enum that have not been defined yet.  When they are ultimately * defined, then we can go back and generate the TIR commands to make a back * reference. */struct forward_ref{	struct forward_ref * next;	int dbx_type;	int struc_numb;	char resolved;	};struct forward_ref * f_ref_root={(struct forward_ref*) NULL};static char * symbol_name;static structure_count=0;/* this routine converts a number string into an integer, and stops when it * sees an invalid character the return value is the address of the character  * just past the last character read.  No error is generated. */static char * cvt_integer(char* str,int * rtn){	int ival, neg;		neg = *str == '-' ? ++str, -1 : 1;		ival=0;	/* first get the number of the type for dbx */		while((*str <= '9') && (*str >= '0'))			ival = 10*ival + *str++ -'0';	*rtn = neg*ival;	return str;}/* this routine fixes the names that are generated by C++, ".this" is a good * example.  The period does not work for the debugger, since it looks like * the syntax for a structure element, and thus it gets mightily confused */static fix_name(char* pnt){	for( ;*pnt != 0; pnt++){	if(*pnt == '.') *pnt = '$';	};}/* this routine is used to compare the names of certain types to various * fixed types that are known by the debugger. */#define type_check(x)  !strcmp( symbol_name , x )/* When defining a structure, this routine is called to find the name of * the actual structure.  It is assumed that str points to the equal sign * in the definition, and it moves backward until it finds the start of the * name.  If it finds a 0, then it knows that this structure def is in the * outermost level, and thus symbol_name points to the symbol name. */static char* get_struct_name(char* str){	char* pnt;	pnt=str;	while((*pnt != ':') && (*pnt != '\0')) pnt--;	if(*pnt == '\0') return symbol_name;	*pnt-- = '\0';	while((*pnt != ';') && (*pnt != '=')) pnt--;	if(*pnt == ';') return pnt+1;	while((*pnt < '0') || (*pnt > '9')) pnt++;	while((*pnt >= '0') && (*pnt <= '9')) pnt++;	return pnt;}	/* search symbol list for type number dbx_type.  Return a pointer to struct */static struct VMS_DBG_Symbol* find_symbol(int dbx_type){	struct VMS_DBG_Symbol* spnt;	spnt=VMS_Symbol_type_list;	while (spnt!=(struct VMS_DBG_Symbol*) NULL){		if(spnt->dbx_type==dbx_type) break;		spnt=spnt->next;};	if(spnt==(struct VMS_DBG_Symbol*) NULL) return 0;/*Dunno what this is*/	return spnt;}/* Many good programmers cringe when they see a fixed size array - since I am * using this to generate the various descriptors for the data types present, * you might argue that the descriptor could overflow the array for a * complicated variable, and then I am in deep doo-doo.  My answer to this is * that the debugger records that we write have all sorts of length bytes * stored in them all over the place, and if we exceed 127 bytes (since the top * bit indicates data, rather than a command), we are dead anyhow.  So I figure * why not do this the easy way.  Besides, to get 128 bytes, you need something * like an array with 10 indicies, or something like *       char **************************************** var;  * Lets get real.  If some idiot writes programs like that he/she gets what * they deserve.  (It is possible to overflow the record with a somewhat * simpler example, like: int (*(*(*(*(*(* sarr6)[1])[1])[2])[3])[4])[5]; * but still...).  And if someone in the peanut gallery wants to know "What * does VAX-C do with something like this?", I will tell you.  It crashes. * At least this code has the good sense to convert it to *void. * In practice, I do not think that this presents too much of a problem, since * struct/union/enum all use defined types, which sort of terminate the * definition.  It occurs to me that we could possibly do the same thing with * arrays and pointers, but I don't know quite how it would be coded. * * And now back to the regularly scheduled program... */#define MAX_DEBUG_RECORD 128static char Local[MAX_DEBUG_RECORD]; /* buffer for variable descriptor */static int Lpnt;		/* index into Local */static char Asuffix[MAX_DEBUG_RECORD]; /* buffer for array descriptor */static int Apoint;	/* index into Asuffix */static char overflow;	/* flag to indicate we have written too much*/static int total_len;	/* used to calculate the total length of variable			descriptor plus array descriptor - used for len byte*/static int struct_number;	/* counter used to assign indexes to struct					unions and enums *//* this routine puts info into either Local or Asuffix, depending on the sign * of size.  The reason is that it is easier to build the variable descriptor * backwards, while the array descriptor is best built forwards.  In the end * they get put together, if there is not a struct/union/enum along the way */push(int value, int size){	char * pnt;	int i;	int size1;	long int val;	val=value;	pnt=(char*) &val;	size1 = size;	if (size < 0) {size1 = -size; pnt += size1-1;};	if(size < 0)	for(i=0;i<size1;i++) {		Local[Lpnt--] = *pnt--;		if(Lpnt < 0) {overflow = 1; Lpnt = 1;};}	else for(i=0;i<size1;i++){		 Asuffix[Apoint++] = *pnt++;		 if(Apoint >= MAX_DEBUG_RECORD) 			{overflow = 1; Apoint =MAX_DEBUG_RECORD-1;};}}/* this routine generates the array descriptor for a given array */static array_suffix(struct VMS_DBG_Symbol* spnt2){	struct VMS_DBG_Symbol * spnt;	struct VMS_DBG_Symbol * spnt1;	int rank;	int total_size;	int i;	rank=0;	spnt=spnt2;	while(spnt->advanced != ARRAY) {		spnt=find_symbol(spnt->type2);		if(spnt == (struct VMS_DBG_Symbol *) NULL) return;};	spnt1=spnt;	spnt1=spnt;	total_size= 1;	while(spnt1->advanced == ARRAY) {rank++;		total_size *= (spnt1->index_max - spnt1->index_min +1);		spnt1=find_symbol(spnt1->type2);};	total_size = total_size * spnt1->data_size;	push(spnt1->data_size,2);	if(spnt1->VMS_type == 0xa3) push(0,1);			else push(spnt1->VMS_type,1);	push(4,1);	for(i=0;i<6;i++) push(0,1);	push(0xc0,1);	push(rank,1);	push(total_size,4);	push(0,4);	spnt1=spnt;	while(spnt1->advanced == ARRAY) {		push(spnt1->index_max - spnt1->index_min+1,4);		spnt1=find_symbol(spnt1->type2);};	spnt1=spnt;	while(spnt1->advanced == ARRAY) {		push(spnt1->index_min,4);		push(spnt1->index_max,4);		spnt1=find_symbol(spnt1->type2);};}/* this routine generates the start of a variable descriptor based upon * a struct/union/enum that has yet to be defined.  We define this spot as * a new location, and save four bytes for the address.  When the struct is * finally defined, then we can go back and plug in the correct address*/static new_forward_ref(int dbx_type){	struct forward_ref* fpnt;	fpnt = (struct forward_ref*) malloc(sizeof(struct forward_ref));	fpnt->next = f_ref_root;	f_ref_root = fpnt;	fpnt->dbx_type = dbx_type;	fpnt->struc_numb = ++structure_count;	fpnt->resolved = 'N';	push(3,-1);	total_len = 5;	push(total_len,-2);	struct_number = - fpnt->struc_numb;}/* this routine generates the variable descriptor used to describe non-basic * variables.  It calls itself recursively until it gets to the bottom of it * all, and then builds the descriptor backwards.  It is easiest to do it this *way since we must periodically write length bytes, and it is easiest if we know *the value when it is time to write it. */static int gen1(struct VMS_DBG_Symbol * spnt,int array_suffix_len){	struct VMS_DBG_Symbol * spnt1;	int i;	switch(spnt->advanced){	case VOID:		push(DBG$C_VOID,-1);		total_len += 1;		push(total_len,-2);		return 0;	case BASIC:	case FUNCTION:		if(array_suffix_len == 0) {				push(spnt->VMS_type,-1);				push(DBG$C_BASIC,-1);						total_len = 2;				push(total_len,-2);				return 1;};		push(0,-4);		push(0xfa02,-2);				total_len = -2;		return 1;	case STRUCT:	case UNION:	case ENUM:		struct_number=spnt->struc_numb;		if(struct_number < 0) {			new_forward_ref(spnt->dbx_type);			return 1;		}		push(DBG$C_STRUCT,-1);		total_len = 5;		push(total_len,-2);		return 1;	case POINTER:		spnt1=find_symbol(spnt->type2);		i=1;		if(spnt1 == (struct VMS_DBG_Symbol *) NULL)				new_forward_ref(spnt->type2);		else  i=gen1(spnt1,0);		if(i){ /* (*void) is a special case, do not put pointer suffix*/		  push(DBG$C_POINTER,-1);		  total_len += 3;		  push(total_len,-2);		};		return 1;	case ARRAY:		spnt1=spnt;		while(spnt1->advanced == ARRAY)			{spnt1 = find_symbol(spnt1->type2);			if(spnt1 == (struct VMS_DBG_Symbol *) NULL) {			    printf("gcc-as warning(debugger output):");			    printf("Forward reference error, dbx type %d\n",					spnt->type2);			    return;}			};/* It is too late to generate forward references, so the user gets a message. * This should only happen on a compiler error */		i=gen1(spnt1,1);		i=Apoint;		array_suffix(spnt);		array_suffix_len = Apoint - i;		switch(spnt1->advanced){		case BASIC:		case FUNCTION:			break;		default:			push(0,-2);			total_len += 2;			push(total_len,-2);			push(0xfa,-1);			push(0x0101,-2);			push(DBG$C_COMPLEX_ARRAY,-1);		};		total_len += array_suffix_len + 8;		push(total_len,-2);				};}/* this generates a suffix for a variable.  If it is not a defined type yet, * then dbx_type contains the type we are expecting so we can generate a * forward reference.  This calls gen1 to build most of the descriptor, and * then it puts the icing on at the end.  It then dumps whatever is needed * to get a complete descriptor (i.e. struct reference, array suffix ). */static generate_suffix(struct VMS_DBG_Symbol * spnt,int dbx_type){	int ilen;	int i;	char pvoid[6] = {5,0xaf,0,1,0,5};	struct VMS_DBG_Symbol * spnt1;	Apoint=0;	Lpnt =MAX_DEBUG_RECORD-1;	total_len=0;	struct_number = 0;	overflow = 0;	if(spnt == (struct VMS_DBG_Symbol*) NULL)		new_forward_ref(dbx_type);	else{		if(spnt->VMS_type != 0xa3) return 0; /* no suffix needed */		gen1(spnt,0);	};	push(0x00af,-2);	total_len += 4;	push(total_len,-1);/* if the variable descriptor overflows the record, output a descriptor for * a pointer to void. */	if((total_len >= MAX_DEBUG_RECORD) || overflow) {		 printf(" Variable descriptor %d too complicated. Defined as *void ",spnt->dbx_type);		 VMS_Store_Immediate_Data(pvoid, 6, OBJ$C_DBG);		  return;		};			i=0;	while(Lpnt < MAX_DEBUG_RECORD-1) Local[i++] = Local[++Lpnt];	Lpnt = i; /* we use this for a reference to a structure that has already been defined */	if(struct_number > 0){		 VMS_Store_Immediate_Data(Local, Lpnt, OBJ$C_DBG);Lpnt=0;		 VMS_Store_Struct(struct_number);}; /* we use this for a forward reference to a structure that has yet to be*defined.  We store four bytes of zero to make room for the actual address once* it is known*/	if(struct_number < 0){		 struct_number = -struct_number;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -