+++ /dev/null
-/* This file is vms-dbg.c
-
- Copyright (C) 1987-1992 Free Software Foundation, Inc.
-
- This file is part of GAS, the GNU Assembler.
-
- GAS 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.
-
- GAS 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 GAS; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#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 128
- static 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;
- 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 = symbol_next(sp); sp1; sp1 = symbol_next(sp1)) {
- 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 = symbol_next(sp1)) {
- /*
- * 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 = symbol_next(symbolP)) {
- /*
- * 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 = symbol_next(symbolP)) {
- /*
- * 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;}
- else
- {spnt=(struct VMS_DBG_Symbol*) malloc(sizeof(struct VMS_DBG_Symbol));
- spnt->next=VMS_Symbol_type_list;
- VMS_Symbol_type_list = spnt;};
- spnt->dbx_type = i1; /* and save the type */
- };
- /* for structs and unions, do a partial parse, otherwise we sometimes get
- * circular definitions that are impossible to resolve. We read enough info
- * so that any reference to this type has enough info to be resolved
- */
- pnt=str + 1; /* point to character past equal sign */
- if((*pnt == 'u') || (*pnt == 's')){
- };
- if((*pnt <= '9') && (*pnt >= '0')){
- if(type_check("void")){ /* this is the void symbol */
- *str='\0';
- spnt->advanced = VOID;
- return 0;};
- printf("gcc-as warning(debugger output):");
- printf(" %d is an unknown untyped variable.\n",spnt->dbx_type);
- return 1; /* do not know what this is */
- };
- /* now define this module*/
- pnt=str + 1; /* point to character past equal sign */
- switch (*pnt){
- case 'r':
- spnt->advanced= BASIC;
- if(type_check("int")) {
- spnt->VMS_type=DBG$C_SLINT; spnt->data_size=4;}
- else if(type_check("long int")) {
- spnt->VMS_type=DBG$C_SLINT; spnt->data_size=4;}
- else if(type_check("unsigned int")) {
- spnt->VMS_type=DBG$C_ULINT; spnt->data_size = 4;}
- else if(type_check("long unsigned int")) {
- spnt->VMS_type=DBG$C_ULINT; spnt->data_size = 4;}
- else if(type_check("short int")) {
- spnt->VMS_type=DBG$C_SSINT; spnt->data_size = 2;}
- else if(type_check("short unsigned int")) {
- spnt->VMS_type=DBG$C_USINT; spnt->data_size = 2;}
- else if(type_check("char")) {
- spnt->VMS_type=DBG$C_SCHAR; spnt->data_size = 1;}
- else if(type_check("signed char")) {
- spnt->VMS_type=DBG$C_SCHAR; spnt->data_size = 1;}
- else if(type_check("unsigned char")) {
- spnt->VMS_type=DBG$C_UCHAR; spnt->data_size = 1;}
- else if(type_check("float")) {
- spnt->VMS_type=DBG$C_REAL4; spnt->data_size = 4;}
- else if(type_check("double")) {
- spnt->VMS_type=DBG$C_REAL8; spnt->data_size = 8;}
- pnt1=(char*) strchr(str,';')+1;
- break;
- case 's':
- case 'u':
- if(*pnt == 's') spnt->advanced= STRUCT;
- else spnt->advanced= UNION;
- spnt->VMS_type = DBG$C_ADVANCED_TYPE;
- pnt1 = cvt_integer(pnt+1,&spnt->data_size);
- if(forward_reference(pnt)) {
- spnt->struc_numb = -1;
- return 1;
- }
- spnt->struc_numb = ++structure_count;
- pnt1--;
- pnt=get_struct_name(str);
- VMS_Def_Struct(spnt->struc_numb);
- fpnt = f_ref_root;
- while(fpnt != (struct forward_ref*) NULL){
- if(fpnt->dbx_type == spnt->dbx_type) {
- fpnt->resolved = 'Y';
- VMS_Set_Struct(fpnt->struc_numb);
- VMS_Store_Struct(spnt->struc_numb);};
- fpnt = fpnt->next;};
- VMS_Set_Struct(spnt->struc_numb);
- i=0;
- Local[i++] = 11+strlen(pnt);
- Local[i++] = DBG$C_STRUCT_START;
- Local[i++] = 0x80;
- for(i1=0;i1<4;i1++) Local[i++] = 0x00;
- Local[i++] = strlen(pnt);
- pnt2=pnt;
- while(*pnt2 != '\0') Local[i++] = *pnt2++;
- i2=spnt->data_size * 8; /* number of bits */
- pnt2=(char*) &i2;
- for(i1=0;i1<4;i1++) Local[i++] = *pnt2++;
- VMS_Store_Immediate_Data(Local, i, OBJ$C_DBG); i=0;
- if(pnt != symbol_name) {
- pnt += strlen(pnt);
- *pnt=':';}; /* replace colon for later */
- while(*++pnt1 != ';'){
- pnt=(char*) strchr(pnt1,':');
- *pnt='\0';
- pnt2=pnt1;
- pnt1 = cvt_integer(pnt+1,&dtype);
- pnt1 = cvt_integer(pnt1+1,&i2);
- pnt1 = cvt_integer(pnt1+1,&i3);
- if((dtype == 1) && (i3 != 32)) { /* bitfield */
- Apoint = 0;
- push(19+strlen(pnt2),1);
- push(0xfa22,2);
- push(1+strlen(pnt2),4);
- push(strlen(pnt2),1);
- while(*pnt2 != '\0') push(*pnt2++,1);
- push(i3,2); /* size of bitfield */
- push(0x0d22,2);
- push(0x00,4);
- push(i2,4); /* start position */
- VMS_Store_Immediate_Data(Asuffix,Apoint,OBJ$C_DBG);
- Apoint=0;
- }else{
- Local[i++] = 7+strlen(pnt2);
- spnt1 = find_symbol(dtype);
- /* check if this is a forward reference */
- if(spnt1 != (struct VMS_DBG_Symbol*) NULL)
- Local[i++] = spnt1->VMS_type;
- else
- Local[i++] = DBG$C_ADVANCED_TYPE;
- Local[i++] = DBG$C_STRUCT_ITEM;
- pnt=(char*) &i2;
- for(i1=0;i1<4;i1++) Local[i++] = *pnt++;
- Local[i++] = strlen(pnt2);
- while(*pnt2 != '\0') Local[i++] = *pnt2++;
- VMS_Store_Immediate_Data(Local, i, OBJ$C_DBG); i=0;
- if(spnt1 == (struct VMS_DBG_Symbol*) NULL)
- generate_suffix(spnt1,dtype);
- else if(spnt1->VMS_type == DBG$C_ADVANCED_TYPE)
- generate_suffix(spnt1,0);
- };
- };
- pnt1++;
- Local[i++] = 0x01; /* length byte */
- Local[i++] = DBG$C_STRUCT_END;
- VMS_Store_Immediate_Data(Local, i, OBJ$C_DBG); i=0;
- break;
- case 'e':
- spnt->advanced= ENUM;
- spnt->VMS_type = DBG$C_ADVANCED_TYPE;
- spnt->struc_numb = ++structure_count;
- spnt->data_size=4;
- VMS_Def_Struct(spnt->struc_numb);
- fpnt = f_ref_root;
- while(fpnt != (struct forward_ref*) NULL){
- if(fpnt->dbx_type == spnt->dbx_type) {
- fpnt->resolved = 'Y';
- VMS_Set_Struct(fpnt->struc_numb);
- VMS_Store_Struct(spnt->struc_numb);};
- fpnt = fpnt->next;};
- VMS_Set_Struct(spnt->struc_numb);
- i=0;
- Local[i++] = 3+strlen(symbol_name);
- Local[i++] = DBG$C_ENUM_START;
- Local[i++] = 0x20;
- Local[i++] = strlen(symbol_name);
- pnt2=symbol_name;
- while(*pnt2 != '\0') Local[i++] = *pnt2++;
- VMS_Store_Immediate_Data(Local, i, OBJ$C_DBG); i=0;
- while(*++pnt != ';') {
- pnt1=(char*) strchr(pnt,':');
- *pnt1++='\0';
- pnt1 = cvt_integer(pnt1,&i1);
- Local[i++] = 7+strlen(pnt);
- Local[i++] = DBG$C_ENUM_ITEM;
- Local[i++] = 0x00;
- pnt2=(char*) &i1;
- for(i2=0;i2<4;i2++) Local[i++] = *pnt2++;
- Local[i++] = strlen(pnt);
- pnt2=pnt;
- while(*pnt != '\0') Local[i++] = *pnt++;
- VMS_Store_Immediate_Data(Local, i, OBJ$C_DBG); i=0;
- pnt= pnt1; /* Skip final semicolon */
- };
- Local[i++] = 0x01; /* len byte */
- Local[i++] = DBG$C_ENUM_END;
- VMS_Store_Immediate_Data(Local, i, OBJ$C_DBG); i=0;
- pnt1=pnt + 1;
- break;
- case 'a':
- spnt->advanced= ARRAY;
- spnt->VMS_type = DBG$C_ADVANCED_TYPE;
- pnt=(char*)strchr(pnt,';'); if (pnt == (char*) NULL) return 1;
- pnt1 = cvt_integer(pnt+1,&spnt->index_min);
- pnt1 = cvt_integer(pnt1+1,&spnt->index_max);
- pnt1 = cvt_integer(pnt1+1,&spnt->type2);
- break;
- case 'f':
- spnt->advanced= FUNCTION;
- spnt->VMS_type = DBG$C_FUNCTION_ADDR;
- /* this masquerades as a basic type*/
- spnt->data_size=4;
- pnt1 = cvt_integer(pnt+1,&spnt->type2);
- break;
- case '*':
- spnt->advanced= POINTER;
- spnt->VMS_type = DBG$C_ADVANCED_TYPE;
- spnt->data_size=4;
- pnt1 = cvt_integer(pnt+1,&spnt->type2);
- pnt=(char*)strchr(str+1,'=');
- if((pnt != (char*) NULL))
- if(VMS_typedef_parse(pnt) == 1 ) return 1;
- break;
- default:
- spnt->advanced= UNKNOWN;
- spnt->VMS_type = 0;
- printf("gcc-as warning(debugger output):");
- printf(" %d is an unknown type of variable.\n",spnt->dbx_type);
- return 1; /* unable to decipher */
- };
- /* this removes the evidence of the definition so that the outer levels of
- parsing do not have to worry about it */
- pnt=str;
- while (*pnt1 != '\0') *pnt++ = *pnt1++;
- *pnt = '\0';
- return 0;
-}
-
-
-/*
- * This is the root routine that parses the stabs entries for definitions.
- * it calls VMS_typedef_parse, which can in turn call itself.
- * We need to be careful, since sometimes there are forward references to
- * other symbol types, and these cannot be resolved until we have completed
- * the parse.
- */
-int VMS_LSYM_Parse(){
- char *pnt;
- char *pnt1;
- char *pnt2;
- char *str;
- char fixit[10];
- int incomplete,i,pass,incom1;
- struct VMS_DBG_Symbol* spnt;
- struct VMS_Symbol * vsp;
- struct forward_ref * fpnt;
- symbolS * sp;
- pass=0;
- incomplete = 0;
- do{
- incom1=incomplete;
- incomplete = 0;
- for(sp = symbol_rootP; sp; sp = symbol_next(sp)) {
- /*
- * Deal with STAB symbols
- */
- if ((sp->sy_nlist.n_type & N_STAB) != 0) {
- /*
- * Dispatch on STAB type
- */
- switch((unsigned char)sp->sy_nlist.n_type) {
- case N_GSYM:
- case N_LCSYM:
- case N_STSYM:
- case N_PSYM:
- case N_RSYM:
- case N_LSYM:
- case N_FUN: /*sometimes these contain typedefs*/
- str=sp->sy_nlist.n_un.n_name;
- symbol_name = str;
- pnt=(char*)strchr(str,':');
- if(pnt== (char*) NULL) break;
- *pnt='\0';
- pnt1=pnt+1;
- pnt2=(char*)strchr(pnt1,'=');
- if(pnt2 == (char*) NULL){
- *pnt=':'; /* replace colon */
- break;}; /* no symbol here */
- incomplete += VMS_typedef_parse(pnt2);
- *pnt=':'; /* put back colon so variable def code finds dbx_type*/
- break;
- } /*switch*/
- } /* if */
- } /*for*/
- pass++;
- } while((incomplete != 0) && (incomplete != incom1 ));
- /* repeat until all refs resolved if possible */
- /* if(pass > 1) printf(" Required %d passes\n",pass);*/
- if(incomplete != 0){
- printf("gcc-as warning(debugger output):");
- printf("Unable to resolve %d circular references.\n",incomplete);
- };
- fpnt = f_ref_root;
- symbol_name="\0";
- while(fpnt != (struct forward_ref*) NULL){
- if(fpnt->resolved != 'Y') {
- if( find_symbol(fpnt->dbx_type) !=
- (struct VMS_DBG_Symbol*) NULL){
- printf("gcc-as warning(debugger output):");
- printf("Forward reference error, dbx type %d\n",
- fpnt->dbx_type);
- break;};
- fixit[0]=0;
- sprintf(&fixit[1],"%d=s4;",fpnt->dbx_type);
- pnt2=(char*)strchr(&fixit[1],'=');
- VMS_typedef_parse(pnt2);
- };
- fpnt = fpnt->next;};
-}
-
-static symbolS* Current_Routine;
-static int Text_Psect;
-
-static Define_Local_Symbols(symbolS* s1,symbolS* s2){
- symbolS * symbolP1;
- for(symbolP1 = symbol_next(s1); symbolP1 != s2; symbolP1 = symbol_next(symbolP1)) {
- if (symbolP1 == (symbolS *)NULL) return;
- if (symbolP1->sy_nlist.n_type == N_FUN) return;
- /*
- * Deal with STAB symbols
- */
- if ((symbolP1->sy_nlist.n_type & N_STAB) != 0) {
- /*
- * Dispatch on STAB type
- */
- switch((unsigned char)symbolP1->sy_nlist.n_type) {
- case N_LSYM:
- case N_PSYM:
- VMS_local_stab_Parse(symbolP1);
- break;
- case N_RSYM:
- VMS_RSYM_Parse(symbolP1,Current_Routine,Text_Psect);
- break;
- } /*switch*/
- } /* if */
- } /* for */
-}
-
-static symbolS* Define_Routine(symbolS* symbolP,int Level){
- symbolS * sstart;
- symbolS * symbolP1;
- char str[10];
- char * pnt;
- int rcount = 0;
- int Offset;
- sstart = symbolP;
- for(symbolP1 = symbol_next(symbolP); symbolP1; symbolP1 = symbol_next(symbolP1)) {
- if (symbolP1->sy_nlist.n_type == N_FUN) break;
- /*
- * Deal with STAB symbols
- */
- if ((symbolP1->sy_nlist.n_type & N_STAB) != 0) {
- /*
- * Dispatch on STAB type
- */
- if((unsigned char)symbolP1->sy_nlist.n_type == N_FUN) break;
- switch((unsigned char)symbolP1->sy_nlist.n_type) {
- case N_LBRAC:
- if(Level != 0) {
- pnt = str +sprintf(str,"$%d",rcount++);
- *pnt = '\0';
- VMS_TBT_Block_Begin(symbolP1,Text_Psect,str);
- };
- Offset = symbolP1->sy_nlist.n_value;
- Define_Local_Symbols(sstart,symbolP1);
- symbolP1 =
- Define_Routine(symbolP1,Level+1);
- if(Level != 0)
- VMS_TBT_Block_End(symbolP1->sy_nlist.n_value -
- Offset);
- sstart=symbolP1;
- break;
- case N_RBRAC:
- return symbolP1;
- } /*switch*/
- } /* if */
- } /* for */
- /* we end up here if there were no brackets in this function. Define
- everything */
- Define_Local_Symbols(sstart,(symbolS *) 0);
-}
-
-VMS_DBG_Define_Routine(symbolS* symbolP,symbolS* Curr_Routine,int Txt_Psect){
- Current_Routine = Curr_Routine;
- Text_Psect = Txt_Psect;
- Define_Routine(symbolP,0);
-}
-
-/* end of vms-dbg.c */
+++ /dev/null
-/* vms.c -- Write out a VAX/VMS object file
-
- Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc.
-
- This file is part of GAS, the GNU Assembler.
-
- GAS 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.
-
- GAS 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 GAS; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/* Written by David L. Kashtan */
-#include <ctype.h>
-#include <stdio.h>
-
-#include "as.h"
-#include "subsegs.h"
-#include "obstack.h"
-#include "struc-symbol.h"
-#include "write.h"
-#include "symbols.h"
-
-#ifdef VMS /* THIS MODULE IS FOR VMS ONLY */
-
-#include <stab.h>
-#include "objrecdef.h" /* Define VMS Object record lang. */
-#include <vms/fabdef.h> /* Define File Access Block */
-#include <vms/namdef.h> /* Define NAM Block */
-#include <vms/xabdef.h> /* Define XAB */
-#include <vms/xabdatdef.h> /* Define Date XAB */
-#include <vms/xabfhcdef.h> /* Define File Header XAB */
-
-const pseudo_typeS obj_pseudo_table[] = {
-{ "const", s_const, 0 },
-
-}; /* obj_pseudo_table */
-
-/*
- * Version string of the compiler that produced the code we are
- * assembling. (And this assembler, if we do not have compiler info.)
- */
-extern char version_string[];
-char *compiler_version_string;
-
-extern char *myname;
-static symbolS *Entry_Point_Symbol = 0; /* Pointer to "_main" */
-
-/*
- * We augment the "gas" symbol structure with this
- */
-struct VMS_Symbol {
- struct VMS_Symbol *Next;
-struct symbol *Symbol;
-int Size;
-int Psect_Index;
-int Psect_Offset;
-};
-struct VMS_Symbol *VMS_Symbols = 0;
-
-/* we need this to keep track of the various input files, so that we can
- * give the debugger the correct source line
- */
-
-struct input_file{
- struct input_file* next;
-struct input_file* same_file_fpnt;
-int file_number;
-int max_line;
-int min_line;
-int offset;
-char flag;
-char * name;
-symbolS * spnt;
-};
-
-static struct input_file * file_root = (struct input_file*)NULL;
-
- struct input_file * find_file(symbolS *);
-
- \f
- /*
- * If the procedure "main()" exists we have to add the instruction
- * "jsb c$main_args" at the beginning to be compatible with VAX-11 "C".
- */
- VMS_Check_For_Main()
-{
- register symbolS *symbolP;
-#ifdef HACK_DEC_C_STARTUP /* JF */
- register struct frchain *frchainP;
- register fragS *fragP;
- register fragS **prev_fragPP;
- register struct fix *fixP;
- register fragS *New_Frag;
- int i;
-#endif HACK_DEC_C_STARTUP
-
- symbolP = (struct symbol *)symbol_find("_main");
- if (symbolP && (symbolP->sy_nlist.n_type == (N_TEXT | N_EXT))) {
-#ifdef HACK_DEC_C_STARTUP
- if( !flagseen['+']) {
-#endif
- /*
- * Remember the entry point symbol
- */
- Entry_Point_Symbol = symbolP;
-#ifdef HACK_DEC_C_STARTUP
- } else {
- /*
- * Scan all the fragment chains for the one with "_main"
- * (Actually we know the fragment from the symbol, but we need
- * the previous fragment so we can change its pointer)
- */
- frchainP = frchain_root;
- while(frchainP) {
- /*
- * Scan all the fragments in this chain, remembering
- * the "previous fragment"
- */
- prev_fragPP = &frchainP->frch_root;
- fragP = frchainP->frch_root;
- while(fragP && (fragP != frchainP->frch_last)) {
- /*
- * Is this the fragment?
- */
- if (fragP == symbolP->sy_frag) {
- /*
- * Yes: Modify the fragment by replacing
- * it with a new fragment.
- */
- New_Frag = (fragS *)
- xmalloc(sizeof(*New_Frag) +
- fragP->fr_fix +
- fragP->fr_var +
- 5);
- /*
- * The fragments are the same except
- * that the "fixed" area is larger
- */
- *New_Frag = *fragP;
- New_Frag->fr_fix += 6;
- /*
- * Copy the literal data opening a hole
- * 2 bytes after "_main" (i.e. just after
- * the entry mask). Into which we place
- * the JSB instruction.
- */
- New_Frag->fr_literal[0] = fragP->fr_literal[0];
- New_Frag->fr_literal[1] = fragP->fr_literal[1];
- New_Frag->fr_literal[2] = 0x16; /* Jsb */
- New_Frag->fr_literal[3] = 0xef;
- New_Frag->fr_literal[4] = 0;
- New_Frag->fr_literal[5] = 0;
- New_Frag->fr_literal[6] = 0;
- New_Frag->fr_literal[7] = 0;
- for(i = 2; i < fragP->fr_fix + fragP->fr_var; i++)
- New_Frag->fr_literal[i+6] =
- fragP->fr_literal[i];
- /*
- * Now replace the old fragment with the
- * newly generated one.
- */
- *prev_fragPP = New_Frag;
- /*
- * Remember the entry point symbol
- */
- Entry_Point_Symbol = symbolP;
- /*
- * Scan the text area fixup structures
- * as offsets in the fragment may have
- * changed
- */
- for(fixP = text_fix_root; fixP; fixP = fixP->fx_next) {
- /*
- * Look for references to this
- * fragment.
- */
- if (fixP->fx_frag == fragP) {
- /*
- * Change the fragment
- * pointer
- */
- fixP->fx_frag = New_Frag;
- /*
- * If the offset is after
- * the entry mask we need
- * to account for the JSB
- * instruction we just
- * inserted.
- */
- if (fixP->fx_where >= 2)
- fixP->fx_where += 6;
- }
- }
- /*
- * Scan the symbols as offsets in the
- * fragment may have changed
- */
- for(symbolP = symbol_rootP;
- symbolP;
- symbolP = symbol_next(symbolP)) {
- /*
- * Look for references to this
- * fragment.
- */
- if (symbolP->sy_frag == fragP) {
- /*
- * Change the fragment
- * pointer
- */
- symbolP->sy_frag = New_Frag;
- /*
- * If the offset is after
- * the entry mask we need
- * to account for the JSB
- * instruction we just
- * inserted.
- */
- if (symbolP->sy_nlist.n_value >= 2)
- symbolP->sy_nlist.n_value += 6;
- }
- }
- /*
- * Make a symbol reference to
- * "_c$main_args" so we can get
- * its address inserted into the
- * JSB instruction.
- */
- symbolP = (symbolS *)xmalloc(sizeof(*symbolP));
- symbolP->sy_nlist.n_un.n_name = "_c$main_args";
- symbolP->sy_nlist.n_type = N_UNDF;
- symbolP->sy_nlist.n_other = 0;
- symbolP->sy_nlist.n_desc = 0;
- symbolP->sy_nlist.n_value = 0;
- symbolP->sy_name_offset = 0;
- symbolP->sy_number = 0;
- symbolP->sy_frag = New_Frag;
- symbolP->sy_forward = 0;
- /* this actually inserts at the beginning of the list */
- symbol_append(symbol_rootP, symbolP, &symbol_rootP, &symbol_lastP);
-
- symbol_rootP = symbolP;
- /*
- * Generate a text fixup structure
- * to get "_c$main_args" stored into the
- * JSB instruction.
- */
- fixP = (struct fix *)xmalloc(sizeof(*fixP));
- fixP->fx_frag = New_Frag;
- fixP->fx_where = 4;
- fixP->fx_addsy = symbolP;
- fixP->fx_subsy = 0;
- fixP->fx_offset = 0;
- fixP->fx_size = sizeof(long);
- fixP->fx_pcrel = 1;
- fixP->fx_next = text_fix_root;
- text_fix_root = fixP;
- /*
- * Now make sure we exit from the loop
- */
- frchainP = 0;
- break;
- }
- /*
- * Try the next fragment
- */
- prev_fragPP = &fragP->fr_next;
- fragP = fragP->fr_next;
- }
- /*
- * Try the next fragment chain
- */
- if (frchainP) frchainP=frchainP->frch_next;
- }
- }
-#endif /* HACK_DEC_C_STARTUP */
- }
-}
-\f
-/*
- * Write a VAX/VMS object file (everything else has been done!)
- */
-VMS_write_object_file(text_siz, data_siz, text_frag_root, data_frag_root)
- unsigned text_siz;
- unsigned data_siz;
- struct frag *text_frag_root;
- struct frag *data_frag_root;
-{
- register fragS * fragP;
- register symbolS * symbolP;
- register symbolS * sp;
- register struct fix * fixP;
- register struct VMS_Symbol * vsp;
- int Local_Initialized_Data_Size = 0;
- int Psect_Number = 0; /* Psect Index Number */
- int Text_Psect = -1; /* Text Psect Index */
- int Data_Psect = -2; /* Data Psect Index JF: Was -1 */
- int Bss_Psect = -3; /* Bss Psect Index JF: Was -1 */
-
- /*
- * Create the VMS object file
- */
- Create_VMS_Object_File();
- /*
- * Write the module header records
- */
- Write_VMS_MHD_Records();
- \f
- /*
- * Generate the VMS object file records
- * 1st GSD then TIR records
- */
-
- /******* Global Symbol Dictionary *******/
- /*
- * Define the Text Psect
- */
- if (text_siz > 0) {
- Text_Psect = Psect_Number++;
- VMS_Psect_Spec("$code",text_siz,"TEXT");
- }
- /*
- * Define the BSS Psect
- */
- if (local_bss_counter > 0) {
- Bss_Psect = Psect_Number++;
- VMS_Psect_Spec("$uninitialized_data",local_bss_counter,"DATA");
- }
- /*
- * Now scan the symbols and emit the appropriate GSD records
- */
- for (sp = symbol_rootP; sp; sp = symbol_next(sp)) {
- /*
- * Dispatch on symbol type
- */
- switch(sp->sy_type) {
- /*
- * Global uninitialized data
- */
- case N_UNDF | N_EXT:
- /*
- * Make a VMS data symbol entry
- */
- vsp = (struct VMS_Symbol *)
- xmalloc(sizeof(*vsp));
- vsp->Symbol = sp;
- vsp->Size = sp->sy_nlist.n_value;
- vsp->Psect_Index = Psect_Number++;
- vsp->Psect_Offset = 0;
- vsp->Next = VMS_Symbols;
- VMS_Symbols = vsp;
- sp->sy_number = (int)vsp;
- /*
- * Make the psect for this data
- */
- if(sp->sy_nlist.n_other)
- VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,
- vsp->Size,
- "CONST");
- else
- VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,
- vsp->Size,
- "COMMON");
-#ifdef NOT_VAX_11_C_COMPATIBLE
- /*
- * Place a global symbol at the
- * beginning of the Psect
- */
- VMS_Global_Symbol_Spec(sp->sy_nlist.n_un.n_name,
- vsp->Psect_Index,
- 0,
- 1);
-#endif NOT_VAX_11_C_COMPATIBLE
- break;
- /*
- * Local uninitialized data
- */
- case N_BSS:
- /*
- * Make a VMS data symbol entry
- */
- vsp = (struct VMS_Symbol *)
- xmalloc(sizeof(*vsp));
- vsp->Symbol = sp;
- vsp->Size = 0;
- vsp->Psect_Index = Bss_Psect;
- vsp->Psect_Offset =
- sp->sy_nlist.n_value -
- bss_address_frag . fr_address;
- vsp->Next = VMS_Symbols;
- VMS_Symbols = vsp;
- sp->sy_number = (int)vsp;
- break;
- /*
- * Global initialized data
- */
- case N_DATA | N_EXT:
- /*
- * Make a VMS data symbol entry
- */
- vsp = (struct VMS_Symbol *)
- xmalloc(sizeof(*vsp));
- vsp->Symbol = sp;
- vsp->Size = VMS_Initialized_Data_Size(sp,
- text_siz + data_siz);
- vsp->Psect_Index = Psect_Number++;
- vsp->Psect_Offset = 0;
- vsp->Next = VMS_Symbols;
- VMS_Symbols = vsp;
- sp->sy_number = (int)vsp;
- /*
- * Make its psect
- */
- if(sp->sy_nlist.n_other)
- VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,
- vsp->Size,
- "CONST");
- else
- VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,
- vsp->Size,
- "COMMON");
-#ifdef NOT_VAX_11_C_COMPATIBLE
- /*
- * Place a global symbol at the
- * beginning of the Psect
- */
- VMS_Global_Symbol_Spec(sp->sy_nlist.n_un.n_name,
- vsp->Psect_Index,
- 0,
- 1);
-#endif NOT_VAX_11_C_COMPATIBLE
- break;
- /*
- * Local initialized data
- */
- case N_DATA:
- /*
- * Make a VMS data symbol entry
- */
- vsp = (struct VMS_Symbol *)
- xmalloc(sizeof(*vsp));
- vsp->Symbol = sp;
- vsp->Size =
- VMS_Initialized_Data_Size(sp,
- text_siz + data_siz);
- vsp->Psect_Index = Data_Psect;
- vsp->Psect_Offset =
- Local_Initialized_Data_Size;
- Local_Initialized_Data_Size += vsp->Size;
- vsp->Next = VMS_Symbols;
- VMS_Symbols = vsp;
- sp->sy_number = (int)vsp;
- break;
- /*
- * Global Text definition
- */
- case N_TEXT | N_EXT: {
- unsigned short Entry_Mask;
-
- /*
- * Get the entry mask
- */
- fragP = sp->sy_frag;
- Entry_Mask = (fragP->fr_literal[0] & 0xff) +
- ((fragP->fr_literal[1] & 0xff)
- << 8);
- /*
- * Define the Procedure entry pt.
- */
- VMS_Procedure_Entry_Pt(sp->sy_nlist.n_un.n_name,
- Text_Psect,
- sp->sy_nlist.n_value,
- Entry_Mask);
- break;
- }
- /*
- * Local Text definition
- */
- case N_TEXT:
- /*
- * Make a VMS data symbol entry
- */
- if(Text_Psect != -1) {
- vsp = (struct VMS_Symbol *)
- xmalloc(sizeof(*vsp));
- vsp->Symbol = sp;
- vsp->Size = 0;
- vsp->Psect_Index = Text_Psect;
- vsp->Psect_Offset = sp->sy_nlist.n_value;
- vsp->Next = VMS_Symbols;
- VMS_Symbols = vsp;
- sp->sy_number = (int)vsp;
- }
- break;
- /*
- * Global Reference
- */
- case N_UNDF:
- /*
- * Make a GSD global symbol reference
- * record.
- */
- VMS_Global_Symbol_Spec(sp->sy_nlist.n_un.n_name,
- 0,
- 0,
- 0);
- break;
- /*
- * Anything else
- */
- default:
- /*
- * Ignore STAB symbols
- * Including .stabs emitted by g++
- */
- if ((sp->sy_type & N_STAB) != 0 || sp->sy_nlist.n_type==22)
- break;
- /*
- * Error
- */
- if(sp->sy_nlist.n_type !=22)
- printf(" ERROR, unknown type (%d)\n",
- sp->sy_nlist.n_type);
- break;
- }
- }
- /*
- * Define the Data Psect
- */
- if ((data_siz > 0) && (Local_Initialized_Data_Size > 0)) {
- /*
- * Do it
- */
- Data_Psect = Psect_Number++;
- VMS_Psect_Spec("$data",
- Local_Initialized_Data_Size,
- "DATA");
- /*
- * Scan the VMS symbols and fill in the data psect
- */
- for (vsp = VMS_Symbols; vsp; vsp = vsp->Next) {
- /*
- * Only look for undefined psects
- */
- if (vsp->Psect_Index < 0) {
- /*
- * And only initialized data
- */
- if (vsp->Symbol->sy_nlist.n_type == N_DATA)
- vsp->Psect_Index = Data_Psect;
- }
- }
- }
- \f
- /******* Text Information and Relocation Records *******/
- /*
- * Write the text segment data
- */
- if (text_siz > 0) {
- /*
- * Scan the text fragments
- */
- for(fragP = text_frag_root; fragP; fragP = fragP->fr_next) {
- /*
- * Stop if we get to the data fragments
- */
- if (fragP == data_frag_root) break;
- /*
- * Ignore fragments with no data
- */
- if ((fragP->fr_fix == 0) && (fragP->fr_var == 0))
- continue;
- /*
- * Go the the appropriate offset in the
- * Text Psect.
- */
- VMS_Set_Psect(Text_Psect,fragP->fr_address,OBJ$C_TIR);
- /*
- * Store the "fixed" part
- */
- if (fragP->fr_fix)
- VMS_Store_Immediate_Data(fragP->fr_literal,
- fragP->fr_fix,
- OBJ$C_TIR);
- /*
- * Store the "variable" part
- */
- if (fragP->fr_var && fragP->fr_offset)
- VMS_Store_Repeated_Data(fragP->fr_offset,
- fragP->fr_literal+
- fragP->fr_fix,
- fragP->fr_var,
- OBJ$C_TIR);
- }
- /*
- * Now we go through the text segment fixups and
- * generate TIR records to fix up addresses within
- * the Text Psect
- */
- for(fixP = text_fix_root; fixP; fixP = fixP->fx_next) {
- /*
- * We DO handle the case of "Symbol - Symbol" as
- * long as it is in the same segment.
- */
- if (fixP->fx_subsy && fixP->fx_addsy) {
- int i;
-
- /*
- * They need to be in the same segment
- */
- if (fixP->fx_subsy->sy_type !=
- fixP->fx_addsy->sy_type)
- error("Fixup data addsy and subsy didn't have the same type");
- /*
- * And they need to be in one that we
- * can check the psect on
- */
- if (((fixP->fx_addsy->sy_type & ~N_EXT) != N_DATA) &&
- ((fixP->fx_addsy->sy_type & ~N_EXT) != N_TEXT))
- error("Fixup data addsy and subsy didn't have an appropriate type");
- /*
- * This had better not be PC relative!
- */
- if (fixP->fx_pcrel)
- error("Fixup data was erroneously \"pcrel\"");
- /*
- * Subtract their values to get the
- * difference.
- */
- i = fixP->fx_addsy->sy_value -
- fixP->fx_subsy->sy_value;
- /*
- * Now generate the fixup object records
- * Set the psect and store the data
- */
- VMS_Set_Psect(Text_Psect,
- fixP->fx_where +
- fixP->fx_frag->fr_address,
- OBJ$C_TIR);
- VMS_Store_Immediate_Data(&i,
- fixP->fx_size,
- OBJ$C_TIR);
- /*
- * Done
- */
- continue;
- }
- /*
- * Size will HAVE to be "long"
- */
- if (fixP->fx_size != sizeof(long))
- error("Fixup datum was not a longword");
- /*
- * Symbol must be "added" (if it is ever
- * subtracted we can
- * fix this assumption)
- */
- if (fixP->fx_addsy == 0)
- error("Fixup datum was not \"fixP->fx_addsy\"");
- /*
- * Store the symbol value in a PIC fashion
- */
- VMS_Store_PIC_Symbol_Reference(fixP->fx_addsy,
- fixP->fx_offset,
- fixP->fx_pcrel,
- Text_Psect,
- fixP->fx_where +
- fixP->fx_frag->fr_address,
- OBJ$C_TIR);
- /*
- * Check for indirect address reference,
- * which has to be fixed up (as the linker
- * will screw it up with TIR$C_STO_PICR).
- */
- if (fixP->fx_pcrel)
- VMS_Fix_Indirect_Reference(Text_Psect,
- fixP->fx_where +
- fixP->fx_frag->fr_address,
- fixP->fx_frag,
- text_frag_root);
- }
- }
- /*
- * Store the Data segment:
- *
- * Since this is REALLY hard to do any other way,
- * we actually manufacture the data segment and
- * the store the appropriate values out of it.
- */
- if (data_siz > 0) {
- char *Data_Segment;
-
- /*
- * Allocate the data segment
- */
- Data_Segment = (char *)xmalloc(data_siz);
- /*
- * Run through the data fragments, filling in the segment
- */
- for(fragP = data_frag_root; fragP; fragP = fragP->fr_next) {
- register long int count;
- register char * fill_literal;
- register long int fill_size;
- int i;
-
- i = fragP->fr_address - text_siz;
- if (fragP->fr_fix)
- bcopy(fragP->fr_literal,
- Data_Segment + i,
- fragP->fr_fix);
- i += fragP->fr_fix;
-
- fill_literal= fragP -> fr_literal + fragP -> fr_fix;
- fill_size = fragP -> fr_var;
- for (count = fragP -> fr_offset; count; count --) {
- if (fill_size)
- bcopy(fill_literal,
- Data_Segment + i,
- fill_size);
- i += fill_size;
- }
- }
- /*
- * Now we can run through all the data symbols
- * and store the data
- */
- for(vsp = VMS_Symbols; vsp; vsp = vsp->Next) {
- /*
- * Ignore anything other than data symbols
- */
- if ((vsp->Symbol->sy_nlist.n_type & ~N_EXT) != N_DATA)
- continue;
- /*
- * Set the Psect + Offset
- */
- VMS_Set_Psect(vsp->Psect_Index,
- vsp->Psect_Offset,
- OBJ$C_TIR);
- /*
- * Store the data
- */
- VMS_Store_Immediate_Data(Data_Segment +
- vsp->Symbol->sy_nlist.n_value -
- text_siz,
- vsp->Size,
- OBJ$C_TIR);
- }
- /*
- * Now we go through the data segment fixups and
- * generate TIR records to fix up addresses within
- * the Data Psects
- */
- for(fixP = data_fix_root; fixP; fixP = fixP->fx_next) {
- /*
- * Find the symbol for the containing datum
- */
- for(vsp = VMS_Symbols; vsp; vsp = vsp->Next) {
- /*
- * Only bother with Data symbols
- */
- sp = vsp->Symbol;
- if ((sp->sy_nlist.n_type & ~N_EXT) != N_DATA)
- continue;
- /*
- * Ignore symbol if After fixup
- */
- if (sp->sy_nlist.n_value >
- (fixP->fx_where +
- fixP->fx_frag->fr_address))
- continue;
- /*
- * See if the datum is here
- */
- if ((sp->sy_nlist.n_value + vsp->Size) <=
- (fixP->fx_where +
- fixP->fx_frag->fr_address))
- continue;
- /*
- * We DO handle the case of "Symbol - Symbol" as
- * long as it is in the same segment.
- */
- if (fixP->fx_subsy && fixP->fx_addsy) {
- int i;
-
- /*
- * They need to be in the same segment
- */
- if (fixP->fx_subsy->sy_type !=
- fixP->fx_addsy->sy_type)
- error("Fixup data addsy and subsy didn't have the same type");
- /*
- * And they need to be in one that we
- * can check the psect on
- */
- if (((fixP->fx_addsy->sy_type & ~N_EXT) != N_DATA) &&
- ((fixP->fx_addsy->sy_type & ~N_EXT) != N_TEXT))
- error("Fixup data addsy and subsy didn't have an appropriate type");
- /*
- * This had better not be PC relative!
- */
- if (fixP->fx_pcrel)
- error("Fixup data was erroneously \"pcrel\"");
- /*
- * Subtract their values to get the
- * difference.
- */
- i = fixP->fx_addsy->sy_value -
- fixP->fx_subsy->sy_value;
- /*
- * Now generate the fixup object records
- * Set the psect and store the data
- */
- VMS_Set_Psect(vsp->Psect_Index,
- fixP->fx_frag->fr_address +
- fixP->fx_where -
- vsp->Symbol->sy_value +
- vsp->Psect_Offset,
- OBJ$C_TIR);
- VMS_Store_Immediate_Data(&i,
- fixP->fx_size,
- OBJ$C_TIR);
- /*
- * Done
- */
- break;
- }
- /*
- * Size will HAVE to be "long"
- */
- if (fixP->fx_size != sizeof(long))
- error("Fixup datum was not a longword");
- /*
- * Symbol must be "added" (if it is ever
- * subtracted we can
- * fix this assumption)
- */
- if (fixP->fx_addsy == 0)
- error("Fixup datum was not \"fixP->fx_addsy\"");
- /*
- * Store the symbol value in a PIC fashion
- */
- VMS_Store_PIC_Symbol_Reference(
- fixP->fx_addsy,
- fixP->fx_offset,
- fixP->fx_pcrel,
- vsp->Psect_Index,
- fixP->fx_frag->fr_address +
- fixP->fx_where -
- vsp->Symbol->sy_value +
- vsp->Psect_Offset,
- OBJ$C_TIR);
- /*
- * Done
- */
- break;
- }
-
- }
- }
- \f
- /*
- * Write the Traceback Begin Module record
- */
- VMS_TBT_Module_Begin();
- /*
- * Scan the symbols and write out the routines
- * (this makes the assumption that symbols are in
- * order of ascending text segment offset)
- */
-{
- struct symbol *Current_Routine = 0;
- int Current_Line_Number = 0;
- int Current_Offset = -1;
- struct input_file * Current_File;
-
- /* Output debugging info for global variables and static variables that are not
- * specific to one routine. We also need to examine all stabs directives, to
- * find the definitions to all of the advanced data types, and this is done by
- * VMS_LSYM_Parse. This needs to be done before any definitions are output to
- * the object file, since there can be forward references in the stabs
- * directives. When through with parsing, the text of the stabs directive
- * is altered, with the definitions removed, so that later passes will see
- * directives as they would be written if the type were already defined.
- *
- * We also look for files and include files, and make a list of them. We
- * examine the source file numbers to establish the actual lines that code was
- * generated from, and then generate offsets.
- */
- VMS_LSYM_Parse();
- for(symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
- /*
- * Deal with STAB symbols
- */
- if ((symbolP->sy_nlist.n_type & N_STAB) != 0) {
- /*
- * Dispatch on STAB type
- */
- switch((unsigned char)symbolP->sy_nlist.n_type) {
- case N_SLINE:
- if(symbolP->sy_nlist.n_desc > Current_File->max_line)
- Current_File->max_line = symbolP->sy_nlist.n_desc;
- if(symbolP->sy_nlist.n_desc < Current_File->min_line)
- Current_File->min_line = symbolP->sy_nlist.n_desc;
- break;
- case N_SO:
- Current_File =find_file(symbolP);
- Current_File->flag = 1;
- Current_File->min_line = 1;
- break;
- case N_SOL:
- Current_File = find_file(symbolP);
- break;
- case N_GSYM:
- VMS_GSYM_Parse(symbolP,Text_Psect);
- break;
- case N_LCSYM:
- VMS_LCSYM_Parse(symbolP,Text_Psect);
- break;
- case N_FUN: /* For static constant symbols */
- case N_STSYM:
- VMS_STSYM_Parse(symbolP,Text_Psect);
- break;
- }
- }
- }
-
- /* now we take a quick sweep through the files and assign offsets
- to each one. This will essentially be the starting line number to the
- debugger for each file. Output the info for the debugger to specify the
- files, and then tell it how many lines to use */
-{
- int File_Number = 0;
- int Debugger_Offset = 0;
- int file_available;
- Current_File = file_root;
- for(Current_File = file_root; Current_File; Current_File = Current_File->next){
- if(Current_File == (struct input_file*) NULL) break;
- if(Current_File->max_line == 0) continue;
- if((strncmp(Current_File->name,"GNU_GXX_INCLUDE:",16) == 0) &&
- !flagseen['D']) continue;
- if((strncmp(Current_File->name,"GNU_CC_INCLUDE:",15) == 0) &&
- !flagseen['D']) continue;
- /* show a few extra lines at the start of the region selected */
- if(Current_File->min_line > 2) Current_File->min_line -= 2;
- Current_File->offset = Debugger_Offset - Current_File->min_line + 1;
- Debugger_Offset += Current_File->max_line - Current_File->min_line + 1;
- if(Current_File->same_file_fpnt != (struct input_file *) NULL)
- Current_File->file_number =Current_File->same_file_fpnt->file_number;
- else {
- Current_File->file_number = ++File_Number;
- file_available = VMS_TBT_Source_File(Current_File->name,
- Current_File->file_number);
- if(!file_available) {Current_File->file_number = 0;
- File_Number--;
- continue;};
- };
- VMS_TBT_Source_Lines(Current_File->file_number,
- Current_File->min_line,
- Current_File->max_line-Current_File->min_line+1);
- }; /* for */
-}; /* scope */
-Current_File = (struct input_file*) NULL;
-
- for(symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
- /*
- * Deal with text symbols
- */
- if ((symbolP->sy_nlist.n_type & ~N_EXT) == N_TEXT) {
- /*
- * Ignore symbols starting with "L",
- * as they are local symbols
- */
- if (symbolP->sy_nlist.n_un.n_name[0] == 'L') continue;
- /*
- * If there is a routine start defined,
- * terminate it.
- */
- if (Current_Routine) {
- /*
- * End the routine
- */
- VMS_TBT_Routine_End(text_siz,Current_Routine);
- }
- /*
- * Store the routine begin traceback info
- */
- if(Text_Psect != -1) {
- VMS_TBT_Routine_Begin(symbolP,Text_Psect);
- Current_Routine = symbolP;
- }
- /* Output local symbols, i.e. all symbols that are associated with a specific
- * routine. We output them now so the debugger recognizes them as local to
- * this routine.
- */
- { symbolS * symbolP1;
- char* pnt;
- char* pnt1;
- for(symbolP1 = Current_Routine; symbolP1; symbolP1 = symbol_next(symbolP1)) {
- if ((symbolP1->sy_nlist.n_type & N_STAB) == 0) continue;
- if (symbolP1->sy_nlist.n_type != N_FUN) continue;
- pnt=symbolP->sy_nlist.n_un.n_name;
- pnt1=symbolP1->sy_nlist.n_un.n_name;
- if(*pnt++ != '_') continue;
- while(*pnt++ == *pnt1++) {};
- if((*(--pnt) == '\0') && (*(--pnt1) == ':')) break;
- };
- if(symbolP1 != (symbolS *) NULL)
- VMS_DBG_Define_Routine(symbolP1,Current_Routine,Text_Psect);
- } /* local symbol block */
- /*
- * Done
- */
- continue;
- }
- /*
- * Deal with STAB symbols
- */
- if ((symbolP->sy_nlist.n_type & N_STAB) != 0) {
- /*
- * Dispatch on STAB type
- */
- switch((unsigned char)symbolP->sy_nlist.n_type) {
- /*
- * Line number
- */
- case N_SLINE:
- /* Offset the line into the correct portion
- * of the file */
- if(Current_File->file_number == 0) break;
- /* Sometimes the same offset gets several source
- * lines assigned to it.
- * We should be selective about which lines
- * we allow, we should prefer lines that are
- * in the main source file when debugging
- * inline functions. */
- if((Current_File->file_number != 1) &&
- symbolP->sy_nlist.n_value ==
- Current_Offset) break;
- /* calculate actual debugger source line */
- symbolP->sy_nlist.n_desc
- += Current_File->offset;
- /*
- * If this is the 1st N_SLINE, setup
- * PC/Line correlation. Otherwise
- * do the delta PC/Line. If the offset
- * for the line number is not +ve we need
- * to do another PC/Line correlation
- * setup
- */
- if (Current_Offset == -1) {
- VMS_TBT_Line_PC_Correlation(
- symbolP->sy_nlist.n_desc,
- symbolP->sy_nlist.n_value,
- Text_Psect,
- 0);
- } else {
- if ((symbolP->sy_nlist.n_desc -
- Current_Line_Number) <= 0) {
- /*
- * Line delta is not +ve, we
- * need to close the line and
- * start a new PC/Line
- * correlation.
- */
- VMS_TBT_Line_PC_Correlation(0,
- symbolP->sy_nlist.n_value -
- Current_Offset,
- 0,
- -1);
- VMS_TBT_Line_PC_Correlation(
- symbolP->sy_nlist.n_desc,
- symbolP->sy_nlist.n_value,
- Text_Psect,
- 0);
- } else {
- /*
- * Line delta is +ve, all is well
- */
- VMS_TBT_Line_PC_Correlation(
- symbolP->sy_nlist.n_desc -
- Current_Line_Number,
- symbolP->sy_nlist.n_value -
- Current_Offset,
- 0,
- 1);
- }
- }
- /*
- * Update the current line/PC
- */
- Current_Line_Number = symbolP->sy_nlist.n_desc;
- Current_Offset = symbolP->sy_nlist.n_value;
- /*
- * Done
- */
- break;
- /*
- * Source file
- */
- case N_SO:
- /*
- * Remember that we had a source file
- * and emit the source file debugger
- * record
- */
- Current_File =
- find_file(symbolP);
- break;
- /* We need to make sure that we are really in the actual source file when
- * we compute the maximum line number. Otherwise the debugger gets really
- * confused */
- case N_SOL:
- Current_File =
- find_file(symbolP);
- break;
- }
- }
- }
- /*
- * If there is a routine start defined,
- * terminate it (and the line numbers)
- */
- if (Current_Routine) {
- /*
- * Terminate the line numbers
- */
- VMS_TBT_Line_PC_Correlation(0,
- text_siz - Current_Routine->sy_nlist.n_value,
- 0,
- -1);
- /*
- * Terminate the routine
- */
- VMS_TBT_Routine_End(text_siz,Current_Routine);
- }
-}
-/*
- * Write the Traceback End Module TBT record
- */
-VMS_TBT_Module_End();
-\f
-/*
- * Write the End Of Module record
- */
-if (Entry_Point_Symbol == 0)
- Write_VMS_EOM_Record(-1,0);
-else
- Write_VMS_EOM_Record(Text_Psect,
- Entry_Point_Symbol->sy_nlist.n_value);
-\f
-/*
- * All done, close the object file
- */
-Close_VMS_Object_File();
-}
-
-\f
-/****** VMS OBJECT FILE HACKING ROUTINES *******/
-
-
-/*
- * Global data (Object records limited to 512 bytes by VAX-11 "C" runtime)
- */
-static int VMS_Object_File_FD; /* File Descriptor for object file */
-static char Object_Record_Buffer[512]; /* Buffer for object file records */
-static int Object_Record_Offset; /* Offset to end of data */
-static int Current_Object_Record_Type; /* Type of record in above */
-
-/*
- * Macros for placing data into the object record buffer
- */
-#define PUT_LONG(val) *((long *)(Object_Record_Buffer + \
- Object_Record_Offset)) = val; \
- Object_Record_Offset += sizeof(long)
-
-#define PUT_SHORT(val) *((short *)(Object_Record_Buffer + \
- Object_Record_Offset)) = val; \
- Object_Record_Offset += sizeof(short)
-
-#define PUT_CHAR(val) Object_Record_Buffer[Object_Record_Offset++] = val
-
-#define PUT_COUNTED_STRING(cp) {\
- register char *p = cp; \
- PUT_CHAR(strlen(p)); \
- while(*p) PUT_CHAR(*p++);}
-
-/*
- * Macro for determining if a Name has psect attributes attached
- * to it.
- */
-#define PSECT_ATTRIBUTES_STRING "$$PsectAttributes_"
-#define PSECT_ATTRIBUTES_STRING_LENGTH 18
-
-#define HAS_PSECT_ATTRIBUTES(Name) \
-(strncmp((Name[0] == '_' ? Name + 1 : Name), \
- PSECT_ATTRIBUTES_STRING, \
- PSECT_ATTRIBUTES_STRING_LENGTH) == 0)
-
-\f
-/*
- * Create the VMS object file
- */
-Create_VMS_Object_File()
-{
-#ifdef eunice
- VMS_Object_File_FD = creat(out_file_name, 0777, "var");
-#else eunice
- VMS_Object_File_FD = creat(out_file_name, 0, "rfm=var");
-#endif eunice
- /*
- * Deal with errors
- */
- if (VMS_Object_File_FD < 0) {
- char Error_Line[256];
-
- sprintf(Error_Line,"Couldn't create VMS object file \"%s\"",
- out_file_name);
- error(Error_Line);
- }
- /*
- * Initialize object file hacking variables
- */
- Object_Record_Offset = 0;
- Current_Object_Record_Type = -1;
-}
-
-\f
-/*
- * Declare a particular type of object file record
- */
-Set_VMS_Object_File_Record(Type)
- int Type;
-{
- /*
- * If the type matches, we are done
- */
- if (Type == Current_Object_Record_Type) return;
- /*
- * Otherwise: flush the buffer
- */
- Flush_VMS_Object_Record_Buffer();
- /*
- * Set the new type
- */
- Current_Object_Record_Type = Type;
-}
-
-\f
-/*
- * Flush the object record buffer to the object file
- */
-Flush_VMS_Object_Record_Buffer()
-{
- int i;
-
- /*
- * If the buffer is empty, we are done
- */
- if (Object_Record_Offset == 0) return;
- /*
- * Write the data to the file
- */
- i= write(VMS_Object_File_FD,
- Object_Record_Buffer,
- Object_Record_Offset);
- if (i != Object_Record_Offset)
- error("I/O error writing VMS object file");
- /*
- * The buffer is now empty
- */
- Object_Record_Offset = 0;
-}
-
-\f
-/*
- * Close the VMS Object file
- */
-Close_VMS_Object_File()
-{
- close(VMS_Object_File_FD);
-}
-
-\f
-/*
- * Write the MHD (Module Header) records
- */
-Write_VMS_MHD_Records()
-{
- register char *cp,*cp1;
- register int i;
- struct {int Size; char *Ptr;} Descriptor;
- char Module_Name[256];
- char Now[17];
-
- /*
- * We are writing a module header record
- */
- Set_VMS_Object_File_Record(OBJ$C_HDR);
- /*
- * ***************************
- * *MAIN MODULE HEADER RECORD*
- * ***************************
- *
- * Store record type and header type
- */
- PUT_CHAR(OBJ$C_HDR);
- PUT_CHAR(MHD$C_MHD);
- /*
- * Structure level is 0
- */
- PUT_CHAR(OBJ$C_STRLVL);
- /*
- * Maximum record size is size of the object record buffer
- */
- PUT_SHORT(sizeof(Object_Record_Buffer));
- /*
- * Get module name (the FILENAME part of the object file)
- */
- cp = out_file_name;
- cp1 = Module_Name;
- while(*cp) {
- if ((*cp == ']') || (*cp == '>') ||
- (*cp == ':') || (*cp == '/')) {
- cp1 = Module_Name;
- cp++;
- continue;
- }
- *cp1++ = islower(*cp) ? toupper(*cp++) : *cp++;
- }
- *cp1 = 0;
- /*
- * Limit it to 31 characters and store in the object record
- */
- while(--cp1 >= Module_Name)
- if (*cp1 == '.') *cp1 = 0;
- if (strlen(Module_Name) > 31) {
- if(flagseen['+'])
- printf("%s: Module name truncated: %s\n", myname, Module_Name);
- Module_Name[31] = 0;
- }
- PUT_COUNTED_STRING(Module_Name);
- /*
- * Module Version is "V1.0"
- */
- PUT_COUNTED_STRING("V1.0");
- /*
- * Creation time is "now" (17 chars of time string)
- */
- Descriptor.Size = 17;
- Descriptor.Ptr = Now;
- sys$asctim(0,&Descriptor,0,0);
- for(i = 0; i < 17; i++) PUT_CHAR(Now[i]);
- /*
- * Patch time is "never" (17 zeros)
- */
- for(i = 0; i < 17; i++) PUT_CHAR(0);
- /*
- * Flush the record
- */
- Flush_VMS_Object_Record_Buffer();
- /*
- * *************************
- * *LANGUAGE PROCESSOR NAME*
- * *************************
- *
- * Store record type and header type
- */
- PUT_CHAR(OBJ$C_HDR);
- PUT_CHAR(MHD$C_LNM);
- /*
- * Store language processor name and version
- * (not a counted string!)
- */
- cp = compiler_version_string;
- if (cp == 0) {
- cp ="GNU AS V";
- while(*cp) PUT_CHAR(*cp++);
- cp = strchr(&version_string,'.');
- while(*cp != ' ') cp--; cp++;
- };
- while(*cp >= 32) PUT_CHAR(*cp++);
- /*
- * Flush the record
- */
- Flush_VMS_Object_Record_Buffer();
-}
-
-\f
-/*
- * Write the EOM (End Of Module) record
- */
-Write_VMS_EOM_Record(Psect, Offset)
- int Psect;
- int Offset;
-{
- /*
- * We are writing an end-of-module record
- */
- Set_VMS_Object_File_Record(OBJ$C_EOM);
- /*
- * Store record Type
- */
- PUT_CHAR(OBJ$C_EOM);
- /*
- * Store the error severity (0)
- */
- PUT_CHAR(0);
- /*
- * Store the entry point, if it exists
- */
- if (Psect >= 0) {
- /*
- * Store the entry point Psect
- */
- PUT_CHAR(Psect);
- /*
- * Store the entry point Psect offset
- */
- PUT_LONG(Offset);
- }
- /*
- * Flush the record
- */
- Flush_VMS_Object_Record_Buffer();
-}
-
-\f
-/* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/
-
-static int
- hash_string (ptr)
-unsigned char *ptr;
-{
- register unsigned char *p = ptr;
- register unsigned char *end = p + strlen(ptr);
- register unsigned char c;
- register int hash = 0;
-
- while (p != end)
- {
- c = *p++;
- hash = ((hash<<3) + (hash<<15) + (hash>>28) + c);
- }
- return hash;
-}
-
-/*
- * Generate a Case-Hacked VMS symbol name (limited to 31 chars)
- */
-VMS_Case_Hack_Symbol(In,Out)
- register char *In;
- register char *Out;
-{
- long int init = 0;
- long int result;
- char *pnt;
- char *new_name;
- char *old_name;
- register int i;
- int destructor = 0; /*hack to allow for case sens in a destructor*/
- int truncate = 0;
- int Case_Hack_Bits = 0;
- int Saw_Dollar = 0;
- static char Hex_Table[16] =
- {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
-
- /*
- * Kill any leading "_"
- */
- if (*In == '_') In++;
-
- new_name=Out; /* save this for later*/
-
- if((In[0]=='_')&&(In[1]=='$')&&(In[2]=='_'))
- destructor=1;
-
- /* We may need to truncate the symbol, save the hash for later*/
- if(strlen(In)>23) result = hash_string(In);
- /*
- * Is there a Psect Attribute to skip??
- */
- if (HAS_PSECT_ATTRIBUTES(In)) {
- /*
- * Yes: Skip it
- */
- In += PSECT_ATTRIBUTES_STRING_LENGTH;
- while(*In) {
- if ((In[0] == '$') && (In[1] == '$')) {
- In += 2;
- break;
- }
- In++;
- }
- }
-
- old_name=In;
- /* if(strlen(In) > 31 && flagseen['+'])
- printf("%s: Symbol name truncated: %s\n",myname,In);*/
- /*
- * Do the case conversion
- */
- i = 23; /* Maximum of 23 chars */
- while(*In && (--i >= 0)) {
- Case_Hack_Bits <<= 1;
- if (*In == '$') Saw_Dollar = 1;
- if ((destructor==1)&&(i==21)) Saw_Dollar = 0;
- if (isupper(*In)) {
- *Out++ = *In++;
- Case_Hack_Bits |= 1;
- } else {
- *Out++ = islower(*In) ? toupper(*In++) : *In++;
- }
- }
- /*
- * If we saw a dollar sign, we don't do case hacking
- */
- if(flagseen['h'] || Saw_Dollar)
- Case_Hack_Bits = 0;
-
- /*
- * If we have more than 23 characters and everything is lowercase
- * we can insert the full 31 characters
- */
- if (*In) {
- /*
- * We have more than 23 characters
- * If we must add the case hack, then we have truncated the str
- */
- pnt=Out;
- truncate=1;
- if (Case_Hack_Bits == 0) {
- /*
- * And so far they are all lower case:
- * Check up to 8 more characters
- * and ensure that they are lowercase
- */
- if(flagseen['h'])
- i=8;
- else
- for(i = 0; (In[i] != 0) && (i < 8); i++)
- if (isupper(In[i]) && !Saw_Dollar)
- break;
- if(In[i]==0)
- truncate=0;
-
- if ((i >= 8) || (In[i] == 0)) {
- /*
- * They are: Copy up to 31 characters
- * to the output string
- */
- i = 8;
- while((--i >= 0) && (*In))
- *Out++ = islower(*In) ?
- toupper(*In++) :
- *In++;
- }
- }
- }
- /*
- * If there were any uppercase characters in the name we
- * take on the case hacking string
- */
-
- /* Old behavior for regular GNU-C compiler */
- if (!flagseen['+'])
- truncate=0;
- if ((Case_Hack_Bits != 0)||(truncate==1)) {
- if(truncate==0) {
- *Out++ = '_';
- for(i = 0; i < 6; i++) {
- *Out++ = Hex_Table[Case_Hack_Bits & 0xf];
- Case_Hack_Bits >>= 4;
- }
- *Out++ = 'X';
- } else {
- Out=pnt; /*Cut back to 23 characters maximum */
- *Out++ = '_';
- for( i=0; i < 7; i++) {
- init = result & 0x01f;
- if (init < 10)
- *Out++='0'+init;
- else
- *Out++ = 'A'+init-10;
- result = result >> 5;
- }
- }
- } /*Case Hack */
- /*
- * Done
- */
- *Out = 0;
- if( truncate==1 && flagseen['+'] && flagseen['H'])
- printf("%s: Symbol %s replaced by %s\n",myname,old_name,new_name);
-}
-
-\f
-/*
- * Scan a symbol name for a psect attribute specification
- */
-VMS_Modify_Psect_Attributes(Name, Attribute_Pointer)
- char *Name;
- int *Attribute_Pointer;
-{
- register int i;
- register char *cp;
- int Negate;
- static struct {
- char *Name;
- int Value;
- } Attributes[] = {
- {"PIC", GPS$M_PIC},
-{"LIB", GPS$M_LIB},
-{"OVR", GPS$M_OVR},
-{"REL", GPS$M_REL},
-{"GBL", GPS$M_GBL},
-{"SHR", GPS$M_SHR},
-{"EXE", GPS$M_EXE},
-{"RD", GPS$M_RD},
-{"WRT", GPS$M_WRT},
-{"VEC", GPS$M_VEC},
-{0, 0}};
-
-/*
- * Kill leading "_"
- */
-if (*Name == '_') Name++;
- /*
- * Check for a PSECT attribute list
- */
- if (!HAS_PSECT_ATTRIBUTES(Name)) return; /* If not, return */
- /*
- * Skip the attribute list indicator
- */
- Name += PSECT_ATTRIBUTES_STRING_LENGTH;
- /*
- * Process the attributes ("_" separated, "$" terminated)
- */
- while(*Name != '$') {
- /*
- * Assume not negating
- */
- Negate = 0;
- /*
- * Check for "NO"
- */
- if ((Name[0] == 'N') && (Name[1] == 'O')) {
- /*
- * We are negating (and skip the NO)
- */
- Negate = 1;
- Name += 2;
- }
- /*
- * Find the token delimiter
- */
- cp = Name;
- while(*cp && (*cp != '_') && (*cp != '$')) cp++;
- /*
- * Look for the token in the attribute list
- */
- for(i = 0; Attributes[i].Name; i++) {
- /*
- * If the strings match, set/clear the attr.
- */
- if (strncmp(Name, Attributes[i].Name, cp - Name) == 0) {
- /*
- * Set or clear
- */
- if (Negate)
- *Attribute_Pointer &=
- ~Attributes[i].Value;
- else
- *Attribute_Pointer |=
- Attributes[i].Value;
- /*
- * Done
- */
- break;
- }
- }
- /*
- * Now skip the attribute
- */
- Name = cp;
- if (*Name == '_') Name++;
-}
-/*
- * Done
- */
-return;
-}
-
-\f
-/*
- * Define a psect
- */
-VMS_Psect_Spec(Name, Size, Type)
- char *Name;
- int Size;
- char *Type;
-{
- char Local[32];
- int Psect_Attributes;
-
- /*
- * We are writing a GSD record
- */
- Set_VMS_Object_File_Record(OBJ$C_GSD);
- /*
- * If the buffer is empty we must insert the GSD record type
- */
- if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_GSD);
- /*
- * We are writing a PSECT definition subrecord
- */
- PUT_CHAR(GSD$C_PSC);
- /*
- * Psects are always LONGWORD aligned
- */
- PUT_CHAR(2);
- /*
- * Generate the appropriate PSECT flags given the PSECT type
- */
- if (strcmp(Type,"COMMON") == 0) {
- /*
- * Common block psects are: PIC,OVR,REL,GBL,SHR,RD,WRT
- */
- Psect_Attributes = (GPS$M_PIC|GPS$M_OVR|GPS$M_REL|GPS$M_GBL|
- GPS$M_SHR|GPS$M_RD|GPS$M_WRT);
- } else if (strcmp(Type,"CONST") == 0) {
- /*
- * Common block psects are: PIC,OVR,REL,GBL,SHR,RD
- */
- Psect_Attributes = (GPS$M_PIC|GPS$M_OVR|GPS$M_REL|GPS$M_GBL|
- GPS$M_SHR|GPS$M_RD);
- } else if (strcmp(Type,"DATA") == 0) {
- /*
- * The Data psects are PIC,REL,RD,WRT
- */
- Psect_Attributes =
- (GPS$M_PIC|GPS$M_REL|GPS$M_RD|GPS$M_WRT);
- } else if (strcmp(Type,"TEXT") == 0) {
- /*
- * The Text psects are PIC,REL,SHR,EXE,RD
- */
- Psect_Attributes =
- (GPS$M_PIC|GPS$M_REL|GPS$M_SHR|
- GPS$M_EXE|GPS$M_RD);
- } else {
- /*
- * Error: Unknown psect type
- */
- error("Unknown VMS psect type");
- }
- /*
- * Modify the psect attributes according to any attribute string
- */
- if (HAS_PSECT_ATTRIBUTES(Name))
- VMS_Modify_Psect_Attributes(Name,&Psect_Attributes);
- /*
- * Specify the psect attributes
- */
- PUT_SHORT(Psect_Attributes);
- /*
- * Specify the allocation
- */
- PUT_LONG(Size);
- /*
- * Finally, the psect name
- */
- VMS_Case_Hack_Symbol(Name,Local);
- PUT_COUNTED_STRING(Local);
- /*
- * Flush the buffer if it is more than 75% full
- */
- if (Object_Record_Offset >
- (sizeof(Object_Record_Buffer)*3/4))
- Flush_VMS_Object_Record_Buffer();
-}
-
-\f
-/*
- * Define a global symbol
- */
-VMS_Global_Symbol_Spec(Name, Psect_Number, Psect_Offset, Defined)
- char *Name;
- int Psect_Number;
- int Psect_Offset;
-{
- char Local[32];
-
- /*
- * We are writing a GSD record
- */
- Set_VMS_Object_File_Record(OBJ$C_GSD);
- /*
- * If the buffer is empty we must insert the GSD record type
- */
- if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_GSD);
- /*
- * We are writing a Global symbol definition subrecord
- */
- if (Psect_Number <= 255) {
- PUT_CHAR(GSD$C_SYM);
- } else {
- PUT_CHAR(GSD$C_SYMW);
- }
- /*
- * Data type is undefined
- */
- PUT_CHAR(0);
- /*
- * Switch on Definition/Reference
- */
- if (Defined) {
- /*
- * Definition:
- * Flags = "RELOCATABLE" and "DEFINED"
- */
- PUT_SHORT(GSY$M_DEF|GSY$M_REL);
- /*
- * Psect Number
- */
- if (Psect_Number <= 255) {
- PUT_CHAR(Psect_Number);
- } else {
- PUT_SHORT(Psect_Number);
- }
- /*
- * Offset
- */
- PUT_LONG(Psect_Offset);
- } else {
- /*
- * Reference:
- * Flags = "RELOCATABLE"
- */
- PUT_SHORT(GSY$M_REL);
- }
- /*
- * Finally, the global symbol name
- */
- VMS_Case_Hack_Symbol(Name,Local);
- PUT_COUNTED_STRING(Local);
- /*
- * Flush the buffer if it is more than 75% full
- */
- if (Object_Record_Offset >
- (sizeof(Object_Record_Buffer)*3/4))
- Flush_VMS_Object_Record_Buffer();
-}
-
-\f
-/*
- * Define a procedure entry pt/mask
- */
-VMS_Procedure_Entry_Pt(Name, Psect_Number, Psect_Offset, Entry_Mask)
- char *Name;
- int Psect_Number;
- int Psect_Offset;
- int Entry_Mask;
-{
- char Local[32];
-
- /*
- * We are writing a GSD record
- */
- Set_VMS_Object_File_Record(OBJ$C_GSD);
- /*
- * If the buffer is empty we must insert the GSD record type
- */
- if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_GSD);
- /*
- * We are writing a Procedure Entry Pt/Mask subrecord
- */
- if (Psect_Number <= 255) {
- PUT_CHAR(GSD$C_EPM);
- } else {
- PUT_CHAR(GSD$C_EPMW);
- }
- /*
- * Data type is undefined
- */
- PUT_CHAR(0);
- /*
- * Flags = "RELOCATABLE" and "DEFINED"
- */
- PUT_SHORT(GSY$M_DEF|GSY$M_REL);
- /*
- * Psect Number
- */
- if (Psect_Number <= 255) {
- PUT_CHAR(Psect_Number);
- } else {
- PUT_SHORT(Psect_Number);
- }
- /*
- * Offset
- */
- PUT_LONG(Psect_Offset);
- /*
- * Entry mask
- */
- PUT_SHORT(Entry_Mask);
- /*
- * Finally, the global symbol name
- */
- VMS_Case_Hack_Symbol(Name,Local);
- PUT_COUNTED_STRING(Local);
- /*
- * Flush the buffer if it is more than 75% full
- */
- if (Object_Record_Offset >
- (sizeof(Object_Record_Buffer)*3/4))
- Flush_VMS_Object_Record_Buffer();
-}
-
-\f
-/*
- * Set the current location counter to a particular Psect and Offset
- */
-VMS_Set_Psect(Psect_Index, Offset, Record_Type)
- int Psect_Index;
- int Offset;
- int Record_Type;
-{
- /*
- * We are writing a "Record_Type" record
- */
- Set_VMS_Object_File_Record(Record_Type);
- /*
- * If the buffer is empty we must insert the record type
- */
- if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
- /*
- * Stack the Psect base + Longword Offset
- */
- if (Psect_Index < 255) {
- PUT_CHAR(TIR$C_STA_PL);
- PUT_CHAR(Psect_Index);
- } else {
- PUT_CHAR(TIR$C_STA_WPL);
- PUT_SHORT(Psect_Index);
- }
- PUT_LONG(Offset);
- /*
- * Set relocation base
- */
- PUT_CHAR(TIR$C_CTL_SETRB);
- /*
- * Flush the buffer if it is more than 75% full
- */
- if (Object_Record_Offset >
- (sizeof(Object_Record_Buffer)*3/4))
- Flush_VMS_Object_Record_Buffer();
-}
-
-/*
- * Make a data reference
- */
-VMS_Set_Data(Psect_Index, Offset, Record_Type,Force)
- int Psect_Index;
- int Offset;
- int Record_Type;
- int Force;
-{
- /*
- * We are writing a "Record_Type" record
- */
- Set_VMS_Object_File_Record(Record_Type);
- /*
- * If the buffer is empty we must insert the record type
- */
- if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
- /*
- * Stack the Psect base + Longword Offset
- */
- if(Force==1){
- if(Psect_Index>127){
- PUT_CHAR(TIR$C_STA_WPL);
- PUT_SHORT(Psect_Index);
- PUT_LONG(Offset);}
- else {
- PUT_CHAR(TIR$C_STA_PL);
- PUT_CHAR(Psect_Index);
- PUT_LONG(Offset);}
- } else {if(Offset>32767){
- PUT_CHAR(TIR$C_STA_WPL);
- PUT_SHORT(Psect_Index);
- PUT_LONG(Offset);}
- else if(Offset>127){
- PUT_CHAR(TIR$C_STA_WPW);
- PUT_SHORT(Psect_Index);
- PUT_SHORT(Offset);}
- else{
- PUT_CHAR(TIR$C_STA_WPB);
- PUT_SHORT(Psect_Index);
- PUT_CHAR(Offset);};};
- /*
- * Set relocation base
- */
- PUT_CHAR(TIR$C_STO_PIDR);
- /*
- * Flush the buffer if it is more than 75% full
- */
- if (Object_Record_Offset >
- (sizeof(Object_Record_Buffer)*3/4))
- Flush_VMS_Object_Record_Buffer();
-}
-
-/*
- * Make a debugger reference to a struct, union or enum.
- */
-VMS_Store_Struct(int Struct_Index)
-{
- /*
- * We are writing a "OBJ$C_DBG" record
- */
- Set_VMS_Object_File_Record(OBJ$C_DBG);
- /*
- * If the buffer is empty we must insert the record type
- */
- if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_DBG);
- PUT_CHAR(TIR$C_STA_UW);
- PUT_SHORT(Struct_Index);
- PUT_CHAR(TIR$C_CTL_STKDL);
- PUT_CHAR(TIR$C_STO_L);
- /*
- * Flush the buffer if it is more than 75% full
- */
- if (Object_Record_Offset >
- (sizeof(Object_Record_Buffer)*3/4))
- Flush_VMS_Object_Record_Buffer();
-}
-
-/*
- * Make a debugger reference to partially define a struct, union or enum.
- */
-VMS_Def_Struct(int Struct_Index)
-{
- /*
- * We are writing a "OBJ$C_DBG" record
- */
- Set_VMS_Object_File_Record(OBJ$C_DBG);
- /*
- * If the buffer is empty we must insert the record type
- */
- if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_DBG);
- PUT_CHAR(TIR$C_STA_UW);
- PUT_SHORT(Struct_Index);
- PUT_CHAR(TIR$C_CTL_DFLOC);
- /*
- * Flush the buffer if it is more than 75% full
- */
- if (Object_Record_Offset >
- (sizeof(Object_Record_Buffer)*3/4))
- Flush_VMS_Object_Record_Buffer();
-}
-
-VMS_Set_Struct(int Struct_Index)
-{/* see previous functions for comments */
- Set_VMS_Object_File_Record(OBJ$C_DBG);
- if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_DBG);
- PUT_CHAR(TIR$C_STA_UW);
- PUT_SHORT(Struct_Index);
- PUT_CHAR(TIR$C_CTL_STLOC);
- if (Object_Record_Offset >
- (sizeof(Object_Record_Buffer)*3/4))
- Flush_VMS_Object_Record_Buffer();
-}
-\f
-/*
- * Store immediate data in current Psect
- */
-VMS_Store_Immediate_Data(Pointer, Size, Record_Type)
- register char *Pointer;
- int Size;
- int Record_Type;
-{
- register int i;
-
- /*
- * We are writing a "Record_Type" record
- */
- Set_VMS_Object_File_Record(Record_Type);
- /*
- * We can only store 128 bytes at a time
- */
- while(Size > 0) {
- /*
- * Store a maximum of 128 bytes
- */
- i = (Size > 128) ? 128 : Size;
- Size -= i;
- /*
- * If we cannot accommodate this record, flush the
- * buffer.
- */
- if ((Object_Record_Offset + i + 1) >=
- sizeof(Object_Record_Buffer))
- Flush_VMS_Object_Record_Buffer();
- /*
- * If the buffer is empty we must insert record type
- */
- if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
- /*
- * Store the count
- */
- PUT_CHAR(-i & 0xff);
- /*
- * Store the data
- */
- while(--i >= 0) PUT_CHAR(*Pointer++);
- /*
- * Flush the buffer if it is more than 75% full
- */
- if (Object_Record_Offset >
- (sizeof(Object_Record_Buffer)*3/4))
- Flush_VMS_Object_Record_Buffer();
- }
-}
-
-\f
-/*
- * Store repeated immediate data in current Psect
- */
-VMS_Store_Repeated_Data(Repeat_Count,Pointer, Size, Record_Type)
- int Repeat_Count;
- register char *Pointer;
- int Size;
- int Record_Type;
-{
-
- /*
- * Ignore zero bytes/words/longwords
- */
- if ((Size == sizeof(char)) && (*Pointer == 0)) return;
- if ((Size == sizeof(short)) && (*(short *)Pointer == 0)) return;
- if ((Size == sizeof(long)) && (*(long *)Pointer == 0)) return;
- /*
- * If the data is too big for a TIR$C_STO_RIVB sub-record
- * then we do it manually
- */
- if (Size > 255) {
- while(--Repeat_Count >= 0)
- VMS_Store_Immediate_Data(Pointer,Size,Record_Type);
- return;
- }
- /*
- * We are writing a "Record_Type" record
- */
- Set_VMS_Object_File_Record(Record_Type);
- /*
- * If the buffer is empty we must insert record type
- */
- if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
- /*
- * Stack the repeat count
- */
- PUT_CHAR(TIR$C_STA_LW);
- PUT_LONG(Repeat_Count);
- /*
- * And now the command and its data
- */
- PUT_CHAR(TIR$C_STO_RIVB);
- PUT_CHAR(Size);
- while(--Size >= 0) PUT_CHAR(*Pointer++);
- /*
- * Flush the buffer if it is more than 75% full
- */
- if (Object_Record_Offset >
- (sizeof(Object_Record_Buffer)*3/4))
- Flush_VMS_Object_Record_Buffer();
-}
-
-\f
-/*
- * Store a Position Independent Reference
- */
-VMS_Store_PIC_Symbol_Reference(Symbol, Offset, PC_Relative,
- Psect, Psect_Offset, Record_Type)
- struct symbol *Symbol;
- int Offset;
- int PC_Relative;
- int Psect;
- int Psect_Offset;
- int Record_Type;
-{
- register struct VMS_Symbol *vsp =
- (struct VMS_Symbol *)(Symbol->sy_number);
- char Local[32];
-
- /*
- * We are writing a "Record_Type" record
- */
- Set_VMS_Object_File_Record(Record_Type);
- /*
- * If the buffer is empty we must insert record type
- */
- if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
- /*
- * Set to the appropriate offset in the Psect
- */
- if (PC_Relative) {
- /*
- * For a Code reference we need to fix the operand
- * specifier as well (so back up 1 byte)
- */
- VMS_Set_Psect(Psect, Psect_Offset - 1, Record_Type);
- } else {
- /*
- * For a Data reference we just store HERE
- */
- VMS_Set_Psect(Psect, Psect_Offset, Record_Type);
- }
- /*
- * Make sure we are still generating a "Record Type" record
- */
- if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
- /*
- * Dispatch on symbol type (so we can stack its value)
- */
- switch(Symbol->sy_nlist.n_type) {
- /*
- * Global symbol
- */
-#ifdef NOT_VAX_11_C_COMPATIBLE
- case N_UNDF | N_EXT:
- case N_DATA | N_EXT:
-#endif NOT_VAX_11_C_COMPATIBLE
- case N_UNDF:
- case N_TEXT | N_EXT:
- /*
- * Get the symbol name (case hacked)
- */
- VMS_Case_Hack_Symbol(Symbol->sy_nlist.n_un.n_name,Local);
- /*
- * Stack the global symbol value
- */
- PUT_CHAR(TIR$C_STA_GBL);
- PUT_COUNTED_STRING(Local);
- if (Offset) {
- /*
- * Stack the longword offset
- */
- PUT_CHAR(TIR$C_STA_LW);
- PUT_LONG(Offset);
- /*
- * Add the two, leaving the result on the stack
- */
- PUT_CHAR(TIR$C_OPR_ADD);
- }
- break;
- /*
- * Uninitialized local data
- */
- case N_BSS:
- /*
- * Stack the Psect (+offset)
- */
- if (vsp->Psect_Index < 255) {
- PUT_CHAR(TIR$C_STA_PL);
- PUT_CHAR(vsp->Psect_Index);
- } else {
- PUT_CHAR(TIR$C_STA_WPL);
- PUT_SHORT(vsp->Psect_Index);
- }
- PUT_LONG(vsp->Psect_Offset + Offset);
- break;
- /*
- * Local text
- */
- case N_TEXT:
- /*
- * Stack the Psect (+offset)
- */
- if (vsp->Psect_Index < 255) {
- PUT_CHAR(TIR$C_STA_PL);
- PUT_CHAR(vsp->Psect_Index);
- } else {
- PUT_CHAR(TIR$C_STA_WPL);
- PUT_SHORT(vsp->Psect_Index);
- }
- PUT_LONG(Symbol->sy_nlist.n_value);
- break;
- /*
- * Initialized local or global data
- */
- case N_DATA:
-#ifndef NOT_VAX_11_C_COMPATIBLE
- case N_UNDF | N_EXT:
- case N_DATA | N_EXT:
-#endif NOT_VAX_11_C_COMPATIBLE
- /*
- * Stack the Psect (+offset)
- */
- if (vsp->Psect_Index < 255) {
- PUT_CHAR(TIR$C_STA_PL);
- PUT_CHAR(vsp->Psect_Index);
- } else {
- PUT_CHAR(TIR$C_STA_WPL);
- PUT_SHORT(vsp->Psect_Index);
- }
- PUT_LONG(vsp->Psect_Offset + Offset);
- break;
- }
- /*
- * Store either a code or data reference
- */
- PUT_CHAR(PC_Relative ? TIR$C_STO_PICR : TIR$C_STO_PIDR);
- /*
- * Flush the buffer if it is more than 75% full
- */
- if (Object_Record_Offset >
- (sizeof(Object_Record_Buffer)*3/4))
- Flush_VMS_Object_Record_Buffer();
-}
-
-\f
-/*
- * Check in the text area for an indirect pc-relative reference
- * and fix it up with addressing mode 0xff [PC indirect]
- *
- * THIS SHOULD BE REPLACED BY THE USE OF TIR$C_STO_PIRR IN THE
- * PIC CODE GENERATING FIXUP ROUTINE.
- */
-VMS_Fix_Indirect_Reference(Text_Psect, Offset, fragP, text_frag_root)
- int Text_Psect;
- int Offset;
- register fragS *fragP;
- struct frag *text_frag_root;
-{
- /*
- * The addressing mode byte is 1 byte before the address
- */
- Offset--;
- /*
- * Is it in THIS frag??
- */
- if ((Offset < fragP->fr_address) ||
- (Offset >= (fragP->fr_address + fragP->fr_fix))) {
- /*
- * We need to search for the fragment containing this
- * Offset
- */
- for(fragP = text_frag_root; fragP; fragP = fragP->fr_next) {
- if ((Offset >= fragP->fr_address) &&
- (Offset < (fragP->fr_address + fragP->fr_fix)))
- break;
- }
- /*
- * If we couldn't find the frag, things are BAD!!
- */
- if (fragP == 0)
- error("Couldn't find fixup fragment when checking for indirect reference");
- }
- /*
- * Check for indirect PC relative addressing mode
- */
- if (fragP->fr_literal[Offset - fragP->fr_address] == (char)0xff) {
- static char Address_Mode = 0xff;
-
- /*
- * Yes: Store the indirect mode back into the image
- * to fix up the damage done by STO_PICR
- */
- VMS_Set_Psect(Text_Psect,Offset,OBJ$C_TIR);
- VMS_Store_Immediate_Data(&Address_Mode,1,OBJ$C_TIR);
- }
-}
-
-\f
-/*
- * Write the Traceback Module Begin record
- */
-VMS_TBT_Module_Begin()
-{
- register char *cp,*cp1;
- int Size;
- char Module_Name[256];
- char Local[256];
-
- /*
- * Get module name (the FILENAME part of the object file)
- */
- cp = out_file_name;
- cp1 = Module_Name;
- while(*cp) {
- if ((*cp == ']') || (*cp == '>') ||
- (*cp == ':') || (*cp == '/')) {
- cp1 = Module_Name;
- cp++;
- continue;
- }
- *cp1++ = islower(*cp) ? toupper(*cp++) : *cp++;
- }
- *cp1 = 0;
- /*
- * Limit it to 31 characters
- */
- while(--cp1 >= Module_Name)
- if (*cp1 == '.') *cp1 = 0;
- if (strlen(Module_Name) > 31) {
- if(flagseen['+'])
- printf("%s: Module name truncated: %s\n",myname, Module_Name);
- Module_Name[31] = 0;
- }
- /*
- * Arrange to store the data locally (leave room for size byte)
- */
- cp = Local+1;
- /*
- * Begin module
- */
- *cp++ = DST$C_MODBEG;
- /*
- * Unused
- */
- *cp++ = 0;
- /*
- * Language type == "C"
- */
- *(long *)cp = DST$C_C;
- cp += sizeof(long);
- /*
- * Store the module name
- */
- *cp++ = strlen(Module_Name);
- cp1 = Module_Name;
- while(*cp1) *cp++ = *cp1++;
- /*
- * Now we can store the record size
- */
- Size = (cp - Local);
- Local[0] = Size-1;
- /*
- * Put it into the object record
- */
- VMS_Store_Immediate_Data(Local, Size, OBJ$C_TBT);
-}
-
-\f
-/*
- * Write the Traceback Module End record
- */
-VMS_TBT_Module_End()
-{
- char Local[2];
-
- /*
- * End module
- */
- Local[0] = 1;
- Local[1] = DST$C_MODEND;
- /*
- * Put it into the object record
- */
- VMS_Store_Immediate_Data(Local, 2, OBJ$C_TBT);
-}
-
-\f
-/*
- * Write the Traceback Routine Begin record
- */
-VMS_TBT_Routine_Begin(symbolP, Psect)
- struct symbol *symbolP;
- int Psect;
-{
- register char *cp,*cp1;
- char *Name;
- int Offset;
- int Size;
- char Local[512];
-
- /*
- * Strip the leading "_" from the name
- */
- Name = symbolP->sy_nlist.n_un.n_name;
- if (*Name == '_') Name++;
- /*
- * Get the text psect offset
- */
- Offset = symbolP->sy_nlist.n_value;
- /*
- * Calculate the record size
- */
- Size = 1+1+4+1+strlen(Name);
- /*
- * Record Size
- */
- Local[0] = Size;
- /*
- * Begin Routine
- */
- Local[1] = DST$C_RTNBEG;
- /*
- * Uses CallS/CallG
- */
- Local[2] = 0;
- /*
- * Store the data so far
- */
- VMS_Store_Immediate_Data(Local, 3, OBJ$C_TBT);
- /*
- * Make sure we are still generating a OBJ$C_TBT record
- */
- if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_TBT);
- /*
- * Now get the symbol address
- */
- PUT_CHAR(TIR$C_STA_WPL);
- PUT_SHORT(Psect);
- PUT_LONG(Offset);
- /*
- * Store the data reference
- */
- PUT_CHAR(TIR$C_STO_PIDR);
- /*
- * Store the counted string as data
- */
- cp = Local;
- cp1 = Name;
- Size = strlen(cp1) + 1;
- *cp++ = Size - 1;
- while(*cp1) *cp++ = *cp1++;
- VMS_Store_Immediate_Data(Local, Size, OBJ$C_TBT);
-}
-
-\f
-/*
- * Write the Traceback Routine End record
- * We *must* search the symbol table to find the next routine, since
- * the assember has a way of reassembling the symbol table OUT OF ORDER
- * Thus the next routine in the symbol list is not necessarily the
- * next one in memory. For debugging to work correctly we must know the
- * size of the routine.
- */
-VMS_TBT_Routine_End(Max_Size,sp)
- int Max_Size;
- symbolS *sp;
-{
- symbolS *symbolP;
- int Size = 0x7fffffff;
- char Local[16];
-
-
- for(symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
- if ((symbolP->sy_nlist.n_type & ~N_EXT) == N_TEXT) {
- if (symbolP->sy_nlist.n_un.n_name[0] == 'L') continue;
- if((symbolP->sy_nlist.n_value > sp->sy_nlist.n_value) &&
- (symbolP->sy_nlist.n_value < Size ))
- Size = symbolP->sy_nlist.n_value;
- /* check if gcc_compiled. has size of zero */
- if((symbolP->sy_nlist.n_value == sp->sy_nlist.n_value) &&
- sp != symbolP &&
- !strcmp(sp->sy_nlist.n_un.n_name,"gcc_compiled."))
- Size = symbolP->sy_nlist.n_value;
-
- };
- };
- if(Size == 0x7fffffff) Size = Max_Size;
- Size -= sp->sy_nlist.n_value; /* and get the size of the routine */
- /*
- * Record Size
- */
- Local[0] = 6;
- /*
- * End of Routine
- */
- Local[1] = DST$C_RTNEND;
- /*
- * Unused
- */
- Local[2] = 0;
- /*
- * Size of routine
- */
- *((long *)(Local+3)) = Size;
- /*
- * Store the record
- */
- VMS_Store_Immediate_Data(Local,7, OBJ$C_TBT);
-}
-/*
- * Write the Traceback Block End record
- */
-VMS_TBT_Block_Begin(symbolP, Psect, Name)
- struct symbol *symbolP;
- int Psect;
- char* Name;
-{
- register char *cp,*cp1;
- int Offset;
- int Size;
- char Local[512];
- /*
- * Begin block
- */
- Size = 1+1+4+1+strlen(Name);
- /*
- * Record Size
- */
- Local[0] = Size;
- /*
- * Begin Block - We simulate with a phony routine
- */
- Local[1] = DST$C_BLKBEG;
- /*
- * Uses CallS/CallG
- */
- Local[2] = 0;
- /*
- * Store the data so far
- */
- VMS_Store_Immediate_Data(Local, 3, OBJ$C_DBG);
- /*
- * Make sure we are still generating a OBJ$C_DBG record
- */
- if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_DBG);
- /*
- * Now get the symbol address
- */
- PUT_CHAR(TIR$C_STA_WPL);
- PUT_SHORT(Psect);
- /*
- * Get the text psect offset
- */
- Offset = symbolP->sy_nlist.n_value;
- PUT_LONG(Offset);
- /*
- * Store the data reference
- */
- PUT_CHAR(TIR$C_STO_PIDR);
- /*
- * Store the counted string as data
- */
- cp = Local;
- cp1 = Name;
- Size = strlen(cp1) + 1;
- *cp++ = Size - 1;
- while(*cp1) *cp++ = *cp1++;
- VMS_Store_Immediate_Data(Local, Size, OBJ$C_DBG);
-}
-
-\f
-/*
- * Write the Traceback Block End record
- */
-VMS_TBT_Block_End(int Size)
-{
- char Local[16];
-
- /*
- * End block - simulate with a phony end routine
- */
- Local[0] = 6;
- Local[1] = DST$C_BLKEND;
- *((long *)(Local+3)) = Size;
- /*
- * Unused
- */
- Local[2] = 0;
- VMS_Store_Immediate_Data(Local,7, OBJ$C_DBG);
-}
-
-
-\f
-/*
- * Write a Line number / PC correlation record
- */
-VMS_TBT_Line_PC_Correlation(Line_Number, Offset, Psect, Do_Delta)
- int Line_Number;
- int Offset;
- int Psect;
- int Do_Delta;
-{
- register char *cp;
- char Local[64];
-
- /*
- * If not delta, set our PC/Line number correlation
- */
- if (Do_Delta == 0) {
- /*
- * Size
- */
- Local[0] = 1+1+2+1+4;
- /*
- * Line Number/PC correlation
- */
- Local[1] = DST$C_LINE_NUM;
- /*
- * Set Line number
- */
- Local[2] = DST$C_SET_LINE_NUM;
- *((unsigned short *)(Local+3)) = Line_Number-1;
- /*
- * Set PC
- */
- Local[5] = DST$C_SET_ABS_PC;
- VMS_Store_Immediate_Data(Local, 6, OBJ$C_TBT);
- /*
- * Make sure we are still generating a OBJ$C_TBT record
- */
- if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_TBT);
- if (Psect < 255) {
- PUT_CHAR(TIR$C_STA_PL);
- PUT_CHAR(Psect);
- } else {
- PUT_CHAR(TIR$C_STA_WPL);
- PUT_SHORT(Psect);
- }
- PUT_LONG(Offset);
- PUT_CHAR(TIR$C_STO_PIDR);
- /*
- * Do a PC offset of 0 to register the line number
- */
- Local[0] = 2;
- Local[1] = DST$C_LINE_NUM;
- Local[2] = 0; /* Increment PC by 0 and register line # */
- VMS_Store_Immediate_Data(Local, 3, OBJ$C_TBT);
- } else {
- /*
- * If Delta is negative, terminate the line numbers
- */
- if (Do_Delta < 0) {
- Local[0] = 1+1+4;
- Local[1] = DST$C_LINE_NUM;
- Local[2] = DST$C_TERM_L;
- *((long *)(Local+3)) = Offset;
- VMS_Store_Immediate_Data(Local, 7, OBJ$C_TBT);
- /*
- * Done
- */
- return;
- }
- /*
- * Do a PC/Line delta
- */
- cp = Local+1;
- *cp++ = DST$C_LINE_NUM;
- if (Line_Number > 1) {
- /*
- * We need to increment the line number
- */
- if (Line_Number-1 <= 255) {
- *cp++ = DST$C_INCR_LINUM;
- *cp++ = Line_Number-1;
- } else {
- *cp++ = DST$C_INCR_LINUM_W;
- *(short *)cp = Line_Number-1;
- cp += sizeof(short);
- }
- }
- /*
- * Increment the PC
- */
- if (Offset <= 128) {
- *cp++ = -Offset;
- } else {
- if (Offset < 0x10000) {
- *cp++ = DST$C_DELTA_PC_W;
- *(short *)cp = Offset;
- cp += sizeof(short);
- } else {
- *cp++ = DST$C_DELTA_PC_L;
- *(long *)cp = Offset;
- cp += sizeof(long);
- }
- }
- Local[0] = cp - (Local+1);
- VMS_Store_Immediate_Data(Local,cp - Local, OBJ$C_TBT);
- }
-}
-
-\f
-/*
- * Describe a source file to the debugger
- */
-VMS_TBT_Source_File(Filename, ID_Number)
- char *Filename;
- int ID_Number;
-{
- register char *cp,*cp1;
- int Status,i;
- char Local[512];
- static struct FAB Fab;
- static struct NAM Nam;
- static struct XABDAT Date_Xab;
- static struct XABFHC File_Header_Xab;
- char Es_String[255],Rs_String[255];
-
- /*
- * Setup the Fab
- */
- Fab.fab$b_bid = FAB$C_BID;
- Fab.fab$b_bln = sizeof(Fab);
- Fab.fab$l_nam = (&Nam);
- Fab.fab$l_xab = (struct XAB *)&Date_Xab;
- /*
- * Setup the Nam block so we can find out the FULL name
- * of the source file.
- */
- Nam.nam$b_bid = NAM$C_BID;
- Nam.nam$b_bln = sizeof(Nam);
- Nam.nam$l_rsa = Rs_String;
- Nam.nam$b_rss = sizeof(Rs_String);
- Nam.nam$l_esa = Es_String;
- Nam.nam$b_ess = sizeof(Es_String);
- /*
- * Setup the Date and File Header Xabs
- */
- Date_Xab.xab$b_cod = XAB$C_DAT;
- Date_Xab.xab$b_bln = sizeof(Date_Xab);
- Date_Xab.xab$l_nxt = (char *)&File_Header_Xab;
- File_Header_Xab.xab$b_cod = XAB$C_FHC;
- File_Header_Xab.xab$b_bln = sizeof(File_Header_Xab);
- /* ((struct XAB *)&Date_Xab)->xab$b_cod = XAB$C_DAT; */
- /* ((struct XAB *)&Date_Xab)->xab$b_bln = sizeof(Date_Xab); */
- /* ((struct XAB *)&Date_Xab)->xab$l_nxt = (struct XAB *)&File_Header_Xab; */
- /* ((struct XAB *)&File_Header_Xab)->xab$b_cod = XAB$C_FHC; */
- /* ((struct XAB *)&File_Header_Xab)->xab$b_bln = sizeof(File_Header_Xab); */
- /*
- * Get the file information
- */
- Fab.fab$l_fna = Filename;
- Fab.fab$b_fns = strlen(Filename);
- Status = sys$open(&Fab);
- if (!(Status & 1)) {
- printf("gas: Couldn't find source file \"%s\", Error = %%X%x\n",
- Filename, Status);
- return(0);
- }
- sys$close(&Fab);
- /*
- * Calculate the size of the resultant string
- */
- i = Nam.nam$b_rsl;
- /*
- * Size of record
- */
- Local[0] = 1+1+1+1+1+2+8+4+2+1+1+i+1;
- /*
- * Source declaration
- */
- Local[1] = DST$C_SOURCE;
- /*
- * Make formfeeds count as source records
- */
- Local[2] = DST$C_SRC_FORMFEED;
- /*
- * Declare source file
- */
- Local[3] = DST$C_SRC_DECLFILE;
- Local[4] = 1+2+8+4+2+1+1+i+1;
- cp = Local+5;
- /*
- * Flags
- */
- *cp++ = 0;
- /*
- * File ID
- */
- *(short *)cp = ID_Number;
- cp += sizeof(short);
- /*
- * Creation Date
- */
- *(long *)cp = ((long *) &Date_Xab.xab$q_cdt)[0];
- cp += sizeof(long);
- *(long *)cp = ((long *) &Date_Xab.xab$q_cdt)[1];
- cp += sizeof(long);
- /*
- * End of file block
- */
- *(long *)cp = File_Header_Xab.xab$l_ebk;
- cp += sizeof(long);
- /*
- * First free byte
- */
- *(short *)cp = File_Header_Xab.xab$w_ffb;
- cp += sizeof(short);
- /*
- * Record format
- */
- *cp++ = File_Header_Xab.xab$b_rfo;
- /*
- * Filename
- */
- *cp++ = i;
- cp1 = Rs_String;
- while(--i >= 0) *cp++ = *cp1++;
- /*
- * Library module name (none)
- */
- *cp++ = 0;
- /*
- * Done
- */
- VMS_Store_Immediate_Data(Local,cp - Local, OBJ$C_TBT);
-}
-
-\f
-/*
- * Give the number of source lines to the debugger
- */
-VMS_TBT_Source_Lines(ID_Number,Starting_Line_Number,Number_Of_Lines)
- int ID_Number;
- int Starting_Line_Number;
- int Number_Of_Lines;
-{
- char *cp,*cp1;
- char Local[16];
-
- /*
- * Size of record
- */
- Local[0] = 1+1+2+1+4+1+2;
- /*
- * Source declaration
- */
- Local[1] = DST$C_SOURCE;
- /*
- * Set Source File
- */
- cp = Local+2;
- *cp++ = DST$C_SRC_SETFILE;
- /*
- * File ID Number
- */
- *(short *)cp = ID_Number;
- cp += sizeof(short);
- /*
- * Set record number
- */
- *cp++ = DST$C_SRC_SETREC_L;
- *(long *)cp = Starting_Line_Number;
- cp += sizeof(long);
- /*
- * Define lines
- */
- *cp++ = DST$C_SRC_DEFLINES_W;
- *(short *)cp = Number_Of_Lines;
- cp += sizeof(short);
- /*
- * Done
- */
- VMS_Store_Immediate_Data(Local, cp-Local, OBJ$C_TBT);
-}
-
-\f
-/*
- * Given the pointer to a symbol we calculate how big the data at the
- * symbol is. We do this by looking for the next symbol (local or
- * global) which will indicate the start of another datum.
- */
-int VMS_Initialized_Data_Size(sp, End_Of_Data)
- register struct symbol *sp;
- int End_Of_Data;
-{
- register struct symbol *sp1,*Next_Symbol;
-
- /*
- * Find the next symbol
- * it delimits this datum
- */
- Next_Symbol = 0;
- for (sp1 = symbol_rootP; sp1; sp1 = symbol_next(sp1)) {
- /*
- * The data type must match
- */
- if ((sp1->sy_nlist.n_type & ~N_EXT) != N_DATA) continue;
- /*
- * The symbol must be AFTER this symbol
- */
- if (sp1->sy_nlist.n_value <= sp->sy_nlist.n_value) continue;
- /*
- * We ignore THIS symbol
- */
- if (sp1 == sp) continue;
- /*
- * If there is already a candidate selected for the
- * next symbol, see if we are a better candidate
- */
- if (Next_Symbol) {
- /*
- * We are a better candidate if we are "closer"
- * to the symbol
- */
- if (sp1->sy_nlist.n_value >
- Next_Symbol->sy_nlist.n_value)
- continue;
- /*
- * Win: Make this the candidate
- */
- Next_Symbol = sp1;
- } else {
- /*
- * This is the 1st candidate
- */
- Next_Symbol = sp1;
- }
- }
- /*
- * Calculate its size
- */
- return(Next_Symbol ?
- (Next_Symbol->sy_nlist.n_value -
- sp->sy_nlist.n_value) :
- (End_Of_Data - sp->sy_nlist.n_value));
-}
-
-\f
-
-/* this routine locates a file in the list of files. If an entry does not
- * exist, one is created. For include files, a new entry is always created
- * such that inline functions can be properly debugged */
-struct input_file *
- find_file(sp)
-symbolS * sp;
-{
- struct input_file * same_file;
- struct input_file * fpnt;
- same_file = (struct input_file*) NULL;
- for(fpnt = file_root; fpnt; fpnt = fpnt->next){
- if(fpnt == (struct input_file*) NULL) break;
- if(fpnt->spnt == sp) return fpnt;
- };
- for(fpnt = file_root; fpnt; fpnt = fpnt->next){
- if(fpnt == (struct input_file*) NULL) break;
- if (strcmp(sp->sy_nlist.n_un.n_name,fpnt->name) == 0){
- if(fpnt->flag == 1)return fpnt;
- same_file = fpnt;
- break;
- };
- };
- fpnt = (struct input_file*) malloc(sizeof(struct input_file));
- if(file_root == (struct input_file*) NULL) file_root = fpnt;
- else {
- struct input_file * fpnt1;
- for(fpnt1 = file_root; fpnt1->next; fpnt1 = fpnt1->next);
- fpnt1->next = fpnt;
- };
- fpnt->next = (struct input_file*) NULL;
- fpnt->name = sp->sy_nlist.n_un.n_name;
- fpnt->min_line = 0x7fffffff;
- fpnt->max_line = 0;
- fpnt->offset = 0;
- fpnt->flag = 0;
- fpnt->file_number = 0;
- fpnt->spnt = sp;
- fpnt->same_file_fpnt = same_file;
- return fpnt;
-}
-
-\f
-/*
- * This is a hacked _doprnt() for VAX-11 "C". It understands that
- * it is ONLY called by as_fatal(Format, Args) with a pointer to the
- * "Args" argument. From this we can make it all work right!
- */
-#ifndef eunice
-_doprnt(Format, a, f)
- char *Format;
- FILE *f;
- char **a;
-{
- int Nargs = ((int *)a)[-2]; /* This understands as_fatal() */
-
- switch(Nargs) {
- default: fprintf(f,"_doprnt error on \"%s\"!!",Format); break;
- case 1: fprintf(f,Format); break;
- case 2: fprintf(f,Format,a[0]); break;
- case 3: fprintf(f,Format,a[0],a[1]); break;
- case 4: fprintf(f,Format,a[0],a[1],a[2]); break;
- case 5: fprintf(f,Format,a[0],a[1],a[2],a[3]); break;
- case 6: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4]); break;
- case 7: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5]); break;
- case 8: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5],a[6]); break;
- case 9: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7]); break;
- case 10: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]); break;
- }
-}
-
-#endif /* eunice */
-
-#endif /* VMS */
-
-char const_flag = 0;
-void s_const();
-
-void
- s_const()
-{
- register int temp;
-
- temp = get_absolute_expression ();
- subseg_new (SEG_DATA, (subsegT)temp);
- const_flag = 1;
- demand_empty_rest_of_line();
-}
-
-obj_crawl_symbol_chain() {
- /* JF deal with forward references first. . . */
- for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
- if (symbolP->sy_forward) {
- symbolP->sy_value += symbolP->sy_forward->sy_value + symbolP->sy_forward->sy_frag->fr_address;
-#ifdef OBJ_COFF
- if(SF_GET_GET_SEGMENT(symbolP) &&
- S_GET_SEGMENT(symbolP) == SEG_UNKNOWN)
- S_SET_SEGMENT(symbolP, S_GET_SEGMENT(symbolP->sy_forward));
-#endif /* OBJ_COFF */
- symbolP->sy_forward=0;
- } /* if it has a forward reference */
- } /* walk the symbol chain */
-
-{ /* crawl symbol table */
- register int symbol_number = 0;
-
-#if defined(OBJ_COFF)
-{ /* OBJ_COFF version */
- lineno* lineP;
- symbolS* symbol_externP = (symbolS*)0;
- symbolS* symbol_extern_lastP = (symbolS*)0;
-
- /* The symbol list should be ordered according to the following sequence
- * order :
- * . .file symbol
- * . debug entries for functions
- * . fake symbols for .text .data and .bss
- * . defined symbols
- * . undefined symbols
- * But this is not mandatory. The only important point is to put the
- * undefined symbols at the end of the list.
- */
-
- if (symbol_rootP == NULL
- || S_GET_STORAGE_CLASS(symbol_rootP) != C_FILE) {
- c_dot_file_symbol("fake");
- } /* Is there a .file symbol ? If not insert one at the beginning. */
-
- /*
- * Build up static symbols for .text, .data and .bss
- */
- dot_text_symbol = (symbolS*)
- c_section_symbol(".text",
- 0,
- H_GET_TEXT_SIZE(&headers),
- 0/*text_relocation_number*/,
- 0/*text_lineno_number*/);
-
- dot_data_symbol = (symbolS*)
- c_section_symbol(".data",
- H_GET_TEXT_SIZE(&headers),
- H_GET_DATA_SIZE(&headers),
- 0/*data_relocation_number*/,
- 0); /* There are no data lineno
- entries */
-
- dot_bss_symbol = (symbolS*)
- c_section_symbol(".bss",
- H_GET_TEXT_SIZE(&headers) + H_GET_DATA_SIZE(&headers),
- H_GET_BSS_SIZE(&headers),
- 0, /* No relocation for a bss section. */
- 0); /* There are no bss lineno entries */
-
- /* FIXME late night before delivery, I don't know why the chain is
- broken, but I can guess. So! Let's force them to be knit properly
- at this point. */
-
- /* as john pointed out, this wasn't right. Instead, we'll check here to
- make sure that the list is doubly linked. */
-
-#if defined(DEBUG) && defined(SYMBOLS_NEED_BACKPOINTERS)
- for (symbolP = symbol_rootP; symbol_next(symbolP); symbolP = symbol_next(symbolP)) {
- know(symbolP->sy_next->sy_previous == symbolP);
- } /* walk the symbol chain */
-#endif /* DEBUG and SYMBOLS_NEED_BACKPOINTERS */
- symbolP = symbol_rootP;
-
- if (symbolP) {
- while(symbolP) {
- /* If the symbol has a tagndx entry, resolve it */
- if(SF_GET_TAGGED(symbolP)) {
- SA_SET_SYM_TAGNDX(symbolP,
- ((symbolS*)SA_GET_SYM_TAGNDX(symbolP))->sy_number);
- }
- /* Debug symbol do not need all this rubbish */
- if(!SF_GET_DEBUG(symbolP)) {
- symbolS* real_symbolP;
- /* L* and C_EFCN symbols never merge. */
- if(!SF_GET_LOCAL(symbolP) &&
- (real_symbolP =
- symbol_find_base(S_GET_NAME(symbolP), DO_NOT_STRIP)) &&
- real_symbolP != symbolP) {
- /* FIXME where do dups come from? xoxorich. */
- /* Move the debug data from the debug symbol to the
- real symbol. Do NOT do the oposite (i.e. move from
- real symbol to symbol and remove real symbol from the
- list.) Because some pointers refer to the real symbol
- whereas no pointers refer to the symbol. */
- c_symbol_merge(symbolP, real_symbolP);
- /* Replace the current symbol by the real one */
- /* The symbols will never be the last or the first
- because : 1st symbol is .file and 3 last symbols are
- .text, .data, .bss */
- symbol_remove(real_symbolP, &symbol_rootP, &symbol_lastP);
- symbol_insert(real_symbolP, symbolP, &symbol_rootP, &symbol_lastP);
- symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
- symbolP = real_symbolP;
- }
- if(flagseen['R'] && S_IS_DATA(symbolP))
- S_SET_TEXT(symbolP);
-
- symbolP->sy_value += symbolP->sy_frag->fr_address;
-
- if(!S_IS_DEFINED(symbolP))
- S_SET_EXTERNAL(symbolP);
- else if(S_GET_STORAGE_CLASS(symbolP) == C_NULL)
- S_SET_STORAGE_CLASS(symbolP, C_STAT);
-
- /* Mainly to speed up if not -g */
- if(SF_GET_PROCESS(symbolP)) {
- /* Handle the nested blocks auxiliary info. */
- if(S_GET_STORAGE_CLASS(symbolP) == C_BLOCK) {
- if(!strcmp(S_GET_NAME(symbolP), ".bb"))
- stack_push(block_stack, (char *) &symbolP);
- else { /* .eb */
- register symbolS* begin_symbolP;
- begin_symbolP = *(symbolS**)stack_pop(block_stack);
- if(begin_symbolP == (symbolS*)0)
- as_warn("mismatched .eb");
- else
- SA_SET_SYM_ENDNDX(begin_symbolP, symbol_number);
- }
- }
- /* If we are able to identify the type of a function, and we
- are out of a function (last_functionP == 0) then, the
- function symbol will be associated with an auxiliary
- entry. */
- if(last_functionP == (symbolS*)0 &&
- SF_GET_FUNCTION(symbolP)) {
- last_functionP = symbolP;
- S_SET_NUMBER_AUXILIARY(symbolP, 1);
- /* Clobber possible stale .dim information. */
- memset(&symbolP->sy_auxent[0], '\0', sizeof(union auxent));
- }
- /* The C_FCN doesn't need any additional information.
- I don't even know if this is needed for sdb. But the
- standard assembler generates it, so...
- */
- if(S_GET_STORAGE_CLASS(symbolP) == C_EFCN) {
- if(last_functionP == (symbolS*)0)
- as_fatal("C_EFCN symbol out of scope");
- SA_SET_SYM_FSIZE(last_functionP,
- (long)(symbolP->sy_value -
- last_functionP->sy_value));
- SA_SET_SYM_ENDNDX(last_functionP, symbol_number);
- last_functionP = (symbolS*)0;
- }
- }
- } else {
- /* First descriptor of a structure must point to the next
- slot outside the structure description. */
- if(SF_GET_TAG(symbolP))
- last_tagP = symbolP;
- else if(S_GET_STORAGE_CLASS(symbolP) == C_EOS)
- /* +2 take in account the current symbol */
- SA_SET_SYM_ENDNDX(last_tagP, symbol_number+2);
- }
-
- /* We must put the external symbols apart. The loader
- does not bomb if we do not. But the references in
- the endndx field for a .bb symbol are not corrected
- if an external symbol is removed between .bb and .be.
- I.e in the following case :
- [20] .bb endndx = 22
- [21] foo external
- [22] .be
- ld will move the symbol 21 to the end of the list but
- endndx will still be 22 instead of 21. */
- {
- register symbolS* thisP = symbolP;
-
- symbolP = symbol_next(thisP);
- /* remove C_EFCN and LOCAL (L...) symbols */
- if (SF_GET_LOCAL(thisP)) {
- symbol_remove(thisP, &symbol_rootP, &symbol_lastP);
- } else {
- if(S_GET_STORAGE_CLASS(thisP) == C_EXT &&
- !SF_GET_FUNCTION(thisP)) {
- /* Remove from the list */
- symbol_remove(thisP, &symbol_rootP, &symbol_lastP);
- symbol_clear_list_pointers(thisP);
- /* Move at the end of the list */
- if (symbol_extern_lastP == (symbolS*)0)
- symbol_externP = thisP;
- else
- symbol_append(thisP, symbol_extern_lastP);
- symbol_extern_lastP = thisP;
- } else {
- if(SF_GET_STRING(thisP)) {
- thisP->sy_name_offset = string_byte_count;
- string_byte_count += strlen(S_GET_NAME(thisP)) + 1;
- } else
- thisP->sy_name_offset = 0;
- thisP->sy_number = symbol_number;
- symbol_number += 1 + S_GET_NUMBER_AUXILIARY(thisP);
- }
- }
- }
- }
-
- /* this actually appends the entire extern chain */
- symbol_append(symbol_externP, symbol_lastP);
- symbolP = symbol_externP;
- while(symbolP) {
- if(SF_GET_STRING(symbolP)) {
- symbolP->sy_name_offset = string_byte_count;
- string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
- } else
- symbolP->sy_name_offset = 0;
- symbolP->sy_number = symbol_number;
- symbol_number += 1 + S_GET_NUMBER_AUXILIARY(symbolP);
- symbolP = symbol_next(symbolP);
- }
- }
-
- /* FIXME I'm counting line no's here so we know what to put in the section
- headers, and I'm resolving the addresses since I'm not sure how to
- do it later. I am NOT resolving the linno's representing functions.
- Their symbols need a fileptr pointing to this linno when emitted.
- Thus, I resolve them on emit. xoxorich. */
-
- for (lineP = lineno_rootP; lineP; lineP = lineP->next) {
- if (lineP->line.l_lnno) {
- lineP->line.l_addr.l_paddr += ((fragS*)lineP->frag)->fr_address;
- } else {
- ;
- }
- text_lineno_number++;
- } /* for each line number */
-} /* OBJ_COFF version */
-#elif defined(OBJ_AOUT) | defined(OBJ_BOUT)
-{ /* OBJ_AOUT version */
- symbolPP = & symbol_rootP; /* -> last symbol chain link. */
- while ((symbolP = *symbolPP) != NULL)
- {
- if (flagseen['R'] && S_IS_DATA(symbolP)) {
- S_SET_TEXT(symbolP);
- } /* if pusing data into text */
-
- symbolP -> sy_value += symbolP -> sy_frag -> fr_address;
-
- /* OK, here is how we decide which symbols go out into the
- brave new symtab. Symbols that do are:
-
- * symbols with no name (stabd's?)
- * symbols with debug info in their N_TYPE
-
- Symbols that don't are:
- * symbols that are registers
- * symbols with \1 as their 3rd character (numeric labels)
- * "local labels" as defined by S_LOCAL_NAME(name)
- if the -L switch was passed to gas.
-
- All other symbols are output. We complain if a deleted
- symbol was marked external. */
-
-
- if (1
- && !S_IS_REGISTER(symbolP)
-#ifndef VMS /* Under VMS we need to keep local symbols */
- && ( !S_GET_NAME(symbolP)
- || S_IS_DEBUG(symbolP)
-#ifdef TC_I960
- /* FIXME this ifdef seems highly dubious to me. xoxorich. */
- || !S_IS_DEFINED(symbolP)
- || S_IS_EXTERNAL(symbolP)
-#endif /* TC_I960 */
- || (S_GET_NAME(symbolP)[0] != '\001' && (flagseen ['L'] || ! S_LOCAL_NAME(symbolP))))
-#endif /* not VMS */
- )
- {
-#ifndef VMS
- symbolP->sy_number = symbol_number++;
-
- /* The + 1 after strlen account for the \0 at the
- end of each string */
- if (!S_IS_STABD(symbolP)) {
- /* Ordinary case. */
- symbolP->sy_name_offset = string_byte_count;
- string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
- }
- else /* .Stabd case. */
-#endif /* not VMS */
- symbolP->sy_name_offset = 0;
- symbolPP = &(symbol_next(symbolP));
- } else {
- if (S_IS_EXTERNAL(symbolP) || !S_IS_DEFINED(symbolP)) {
- as_bad ("Local symbol %s never defined", name);
- } /* oops. */
-
-#ifndef VMS
- /* Unhook it from the chain */
- *symbolPP = symbol_next(symbolP);
-#endif /* VMS */
- } /* if this symbol should be in the output */
- } /* for each symbol */
-} /* OBJ_AOUT version */
-#else
-cant_crawl_symbol_table();
-#endif
-H_SET_STRING_SIZE(&headers,string_byte_count);
-H_SET_SYMBOL_TABLE_SIZE(&headers, symbol_number);
-} /* crawl symbol table */
-
-/* JF deal with forward references first. . . */
-for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
- if (symbolP->sy_forward) {
- symbolP->sy_value += symbolP->sy_forward->sy_value + symbolP->sy_forward->sy_frag->fr_address;
-#ifdef OBJ_COFF
- if(SF_GET_GET_SEGMENT(symbolP) &&
- S_GET_SEGMENT(symbolP) == SEG_UNKNOWN)
- S_SET_SEGMENT(symbolP, S_GET_SEGMENT(symbolP->sy_forward));
-#endif /* OBJ_COFF */
- symbolP->sy_forward=0;
- } /* if it has a forward reference */
-} /* walk the symbol chain */
-
-{ /* crawl symbol table */
- register int symbol_number = 0;
-
-#if defined(OBJ_COFF)
-{ /* OBJ_COFF version */
- lineno* lineP;
- symbolS* symbol_externP = (symbolS*)0;
- symbolS* symbol_extern_lastP = (symbolS*)0;
-
- /* The symbol list should be ordered according to the following sequence
- * order :
- * . .file symbol
- * . debug entries for functions
- * . fake symbols for .text .data and .bss
- * . defined symbols
- * . undefined symbols
- * But this is not mandatory. The only important point is to put the
- * undefined symbols at the end of the list.
- */
-
- if (symbol_rootP == NULL
- || S_GET_STORAGE_CLASS(symbol_rootP) != C_FILE) {
- c_dot_file_symbol("fake");
- } /* Is there a .file symbol ? If not insert one at the beginning. */
-
- /*
- * Build up static symbols for .text, .data and .bss
- */
- dot_text_symbol = (symbolS*)
- c_section_symbol(".text",
- 0,
- H_GET_TEXT_SIZE(&headers),
- 0/*text_relocation_number*/,
- 0/*text_lineno_number*/);
-
- dot_data_symbol = (symbolS*)
- c_section_symbol(".data",
- H_GET_TEXT_SIZE(&headers),
- H_GET_DATA_SIZE(&headers),
- 0/*data_relocation_number*/,
- 0); /* There are no data lineno
- entries */
-
- dot_bss_symbol = (symbolS*)
- c_section_symbol(".bss",
- H_GET_TEXT_SIZE(&headers) + H_GET_DATA_SIZE(&headers),
- H_GET_BSS_SIZE(&headers),
- 0, /* No relocation for a bss section. */
- 0); /* There are no bss lineno entries */
-
- /* FIXME late night before delivery, I don't know why the chain is
- broken, but I can guess. So! Let's force them to be knit properly
- at this point. */
-
- /* as john pointed out, this wasn't right. Instead, we'll check here to
- make sure that the list is doubly linked. */
-
-#if defined(DEBUG) && defined(SYMBOLS_NEED_BACKPOINTERS)
- for (symbolP = symbol_rootP; symbol_next(symbolP); symbolP = symbol_next(symbolP)) {
- know(symbolP->sy_next->sy_previous == symbolP);
- } /* walk the symbol chain */
-#endif /* DEBUG and SYMBOLS_NEED_BACKPOINTERS */
- symbolP = symbol_rootP;
-
- if (symbolP) {
- while(symbolP) {
- /* If the symbol has a tagndx entry, resolve it */
- if(SF_GET_TAGGED(symbolP)) {
- SA_SET_SYM_TAGNDX(symbolP,
- ((symbolS*)SA_GET_SYM_TAGNDX(symbolP))->sy_number);
- }
- /* Debug symbol do not need all this rubbish */
- if(!SF_GET_DEBUG(symbolP)) {
- symbolS* real_symbolP;
- /* L* and C_EFCN symbols never merge. */
- if(!SF_GET_LOCAL(symbolP) &&
- (real_symbolP =
- symbol_find_base(S_GET_NAME(symbolP), DO_NOT_STRIP)) &&
- real_symbolP != symbolP) {
- /* FIXME where do dups come from? xoxorich. */
- /* Move the debug data from the debug symbol to the
- real symbol. Do NOT do the oposite (i.e. move from
- real symbol to symbol and remove real symbol from the
- list.) Because some pointers refer to the real symbol
- whereas no pointers refer to the symbol. */
- c_symbol_merge(symbolP, real_symbolP);
- /* Replace the current symbol by the real one */
- /* The symbols will never be the last or the first
- because : 1st symbol is .file and 3 last symbols are
- .text, .data, .bss */
- symbol_remove(real_symbolP, &symbol_rootP, &symbol_lastP);
- symbol_insert(real_symbolP, symbolP, &symbol_rootP, &symbol_lastP);
- symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
- symbolP = real_symbolP;
- }
- if(flagseen['R'] && S_IS_DATA(symbolP))
- S_SET_TEXT(symbolP);
-
- symbolP->sy_value += symbolP->sy_frag->fr_address;
-
- if(!S_IS_DEFINED(symbolP))
- S_SET_EXTERNAL(symbolP);
- else if(S_GET_STORAGE_CLASS(symbolP) == C_NULL)
- S_SET_STORAGE_CLASS(symbolP, C_STAT);
-
- /* Mainly to speed up if not -g */
- if(SF_GET_PROCESS(symbolP)) {
- /* Handle the nested blocks auxiliary info. */
- if(S_GET_STORAGE_CLASS(symbolP) == C_BLOCK) {
- if(!strcmp(S_GET_NAME(symbolP), ".bb"))
- stack_push(block_stack, (char *) &symbolP);
- else { /* .eb */
- register symbolS* begin_symbolP;
- begin_symbolP = *(symbolS**)stack_pop(block_stack);
- if(begin_symbolP == (symbolS*)0)
- as_warn("mismatched .eb");
- else
- SA_SET_SYM_ENDNDX(begin_symbolP, symbol_number);
- }
- }
- /* If we are able to identify the type of a function, and we
- are out of a function (last_functionP == 0) then, the
- function symbol will be associated with an auxiliary
- entry. */
- if(last_functionP == (symbolS*)0 &&
- SF_GET_FUNCTION(symbolP)) {
- last_functionP = symbolP;
- S_SET_NUMBER_AUXILIARY(symbolP, 1);
- /* Clobber possible stale .dim information. */
- memset(&symbolP->sy_auxent[0], '\0', sizeof(union auxent));
- }
- /* The C_FCN doesn't need any additional information.
- I don't even know if this is needed for sdb. But the
- standard assembler generates it, so...
- */
- if(S_GET_STORAGE_CLASS(symbolP) == C_EFCN) {
- if(last_functionP == (symbolS*)0)
- as_fatal("C_EFCN symbol out of scope");
- SA_SET_SYM_FSIZE(last_functionP,
- (long)(symbolP->sy_value -
- last_functionP->sy_value));
- SA_SET_SYM_ENDNDX(last_functionP, symbol_number);
- last_functionP = (symbolS*)0;
- }
- }
- } else {
- /* First descriptor of a structure must point to the next
- slot outside the structure description. */
- if(SF_GET_TAG(symbolP))
- last_tagP = symbolP;
- else if(S_GET_STORAGE_CLASS(symbolP) == C_EOS)
- /* +2 take in account the current symbol */
- SA_SET_SYM_ENDNDX(last_tagP, symbol_number+2);
- }
-
- /* We must put the external symbols apart. The loader
- does not bomb if we do not. But the references in
- the endndx field for a .bb symbol are not corrected
- if an external symbol is removed between .bb and .be.
- I.e in the following case :
- [20] .bb endndx = 22
- [21] foo external
- [22] .be
- ld will move the symbol 21 to the end of the list but
- endndx will still be 22 instead of 21. */
- {
- register symbolS* thisP = symbolP;
-
- symbolP = symbol_next(thisP);
- /* remove C_EFCN and LOCAL (L...) symbols */
- if (SF_GET_LOCAL(thisP)) {
- symbol_remove(thisP, &symbol_rootP, &symbol_lastP);
- } else {
- if(S_GET_STORAGE_CLASS(thisP) == C_EXT &&
- !SF_GET_FUNCTION(thisP)) {
- /* Remove from the list */
- symbol_remove(thisP, &symbol_rootP, &symbol_lastP);
- symbol_clear_list_pointers(thisP);
- /* Move at the end of the list */
- if (symbol_extern_lastP == (symbolS*)0)
- symbol_externP = thisP;
- else
- symbol_append(thisP, symbol_extern_lastP);
- symbol_extern_lastP = thisP;
- } else {
- if(SF_GET_STRING(thisP)) {
- thisP->sy_name_offset = string_byte_count;
- string_byte_count += strlen(S_GET_NAME(thisP)) + 1;
- } else
- thisP->sy_name_offset = 0;
- thisP->sy_number = symbol_number;
- symbol_number += 1 + S_GET_NUMBER_AUXILIARY(thisP);
- }
- }
- }
- }
-
- /* this actually appends the entire extern chain */
- symbol_append(symbol_externP, symbol_lastP);
- symbolP = symbol_externP;
- while(symbolP) {
- if(SF_GET_STRING(symbolP)) {
- symbolP->sy_name_offset = string_byte_count;
- string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
- } else
- symbolP->sy_name_offset = 0;
- symbolP->sy_number = symbol_number;
- symbol_number += 1 + S_GET_NUMBER_AUXILIARY(symbolP);
- symbolP = symbol_next(symbolP);
- }
- }
-
- /* FIXME I'm counting line no's here so we know what to put in the section
- headers, and I'm resolving the addresses since I'm not sure how to
- do it later. I am NOT resolving the linno's representing functions.
- Their symbols need a fileptr pointing to this linno when emitted.
- Thus, I resolve them on emit. xoxorich. */
-
- for (lineP = lineno_rootP; lineP; lineP = lineP->next) {
- if (lineP->line.l_lnno) {
- lineP->line.l_addr.l_paddr += ((fragS*)lineP->frag)->fr_address;
- } else {
- ;
- }
- text_lineno_number++;
- } /* for each line number */
-} /* OBJ_COFF version */
-#elif defined(OBJ_AOUT) | defined(OBJ_BOUT)
-{ /* OBJ_AOUT version */
- symbolPP = & symbol_rootP; /* -> last symbol chain link. */
- while ((symbolP = *symbolPP) != NULL)
- {
- if (flagseen['R'] && S_IS_DATA(symbolP)) {
- S_SET_TEXT(symbolP);
- } /* if pusing data into text */
-
- symbolP -> sy_value += symbolP -> sy_frag -> fr_address;
-
- /* OK, here is how we decide which symbols go out into the
- brave new symtab. Symbols that do are:
-
- * symbols with no name (stabd's?)
- * symbols with debug info in their N_TYPE
-
- Symbols that don't are:
- * symbols that are registers
- * symbols with \1 as their 3rd character (numeric labels)
- * "local labels" as defined by S_LOCAL_NAME(name)
- if the -L switch was passed to gas.
-
- All other symbols are output. We complain if a deleted
- symbol was marked external. */
-
-
- if (1
- && !S_IS_REGISTER(symbolP)
-#ifndef VMS /* Under VMS we need to keep local symbols */
- && ( !S_GET_NAME(symbolP)
- || S_IS_DEBUG(symbolP)
-#ifdef TC_I960
- /* FIXME this ifdef seems highly dubious to me. xoxorich. */
- || !S_IS_DEFINED(symbolP)
- || S_IS_EXTERNAL(symbolP)
-#endif /* TC_I960 */
- || (S_GET_NAME(symbolP)[0] != '\001' && (flagseen ['L'] || ! S_LOCAL_NAME(symbolP))))
-#endif /* not VMS */
- )
- {
-#ifndef VMS
- symbolP->sy_number = symbol_number++;
-
- /* The + 1 after strlen account for the \0 at the
- end of each string */
- if (!S_IS_STABD(symbolP)) {
- /* Ordinary case. */
- symbolP->sy_name_offset = string_byte_count;
- string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
- }
- else /* .Stabd case. */
-#endif /* not VMS */
- symbolP->sy_name_offset = 0;
- symbolPP = &(symbol_next(symbolP));
- } else {
- if (S_IS_EXTERNAL(symbolP) || !S_IS_DEFINED(symbolP)) {
- as_bad ("Local symbol %s never defined", name);
- } /* oops. */
-
-#ifndef VMS
- /* Unhook it from the chain */
- *symbolPP = symbol_next(symbolP);
-#endif /* VMS */
- } /* if this symbol should be in the output */
- } /* for each symbol */
-} /* OBJ_AOUT version */
-#else
-cant_crawl_symbol_table();
-#endif
-H_SET_STRING_SIZE(&headers,string_byte_count);
-H_SET_SYMBOL_TABLE_SIZE(&headers, symbol_number);
-} /* crawl symbol table */
-
-} /* obj_crawl_symbol_chain() */
-
-/* end of vms.c */