#define WANT_VMS_OBJ_DEFS
#include "as.h"
#include "config.h"
#include "safe-ctype.h"
#include "subsegs.h"
#include "obstack.h"
#include <fcntl.h>
#define error as_fatal
#ifdef VMS
#include <fab.h>
#include <nam.h>
#include <xab.h>
extern int sys$open(), sys$close(), sys$asctim();
#endif
char *compiler_version_string;
extern int flag_hash_long_names;
extern int flag_one;
extern int flag_show_after_trunc;
extern int flag_no_hash_mixed_case;
char vms_name_mapping = 0;
static symbolS *Entry_Point_Symbol = 0;
struct VMS_Symbol
{
struct VMS_Symbol *Next;
symbolS *Symbol;
int Size;
int Psect_Index;
int Psect_Offset;
};
struct VMS_Symbol *VMS_Symbols = 0;
struct VMS_Symbol *Ctors_Symbols = 0;
struct VMS_Symbol *Dtors_Symbols = 0;
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;
enum ps_type
{
ps_TEXT, ps_DATA, ps_COMMON, ps_CONST, ps_CTORS, ps_DTORS
};
enum advanced_type
{
BASIC, POINTER, ARRAY, ENUM, STRUCT, UNION, FUNCTION, VOID, ALIAS, UNKNOWN
};
struct VMS_DBG_Symbol
{
struct VMS_DBG_Symbol *next;
enum advanced_type advanced;
int dbx_type;
int type2;
int VMS_type;
int index_min;
int index_max;
int data_size;
int struc_numb;
};
#define SYMTYPLST_SIZE (1<<4)
#define SYMTYP_HASH(x) ((unsigned) (x) & (SYMTYPLST_SIZE - 1))
struct VMS_DBG_Symbol *VMS_Symbol_type_list[SYMTYPLST_SIZE];
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;
#define type_check(X) !strcmp (symbol_name, X)
static const char *symbol_name;
static int structure_count = 0;
static int final_pass;
static int struct_number;
static int vax_g_doubles = 0;
static int Current_Environment = -1;
static char Module_Name[255+1];
#define MAX_DEBUG_RECORD 128
static char Local[MAX_DEBUG_RECORD];
static char Asuffix[MAX_DEBUG_RECORD];
static int Lpnt;
static int Apoint;
static char overflow;
static int total_len;
static int gave_compiler_message = 0;
static int VMS_Object_File_FD;
static char Object_Record_Buffer[512];
static size_t Object_Record_Offset;
static int Current_Object_Record_Type;
#ifdef VMS
#define COPY_LONG(dest,val) ( *(long *) (dest) = (val) )
#define COPY_SHORT(dest,val) ( *(short *) (dest) = (val) )
#else
#define COPY_LONG(dest,val) md_number_to_chars ((dest), (val), 4)
#define COPY_SHORT(dest,val) md_number_to_chars ((dest), (val), 2)
#endif
#define PUT_LONG(val) \
( COPY_LONG (&Object_Record_Buffer[Object_Record_Offset], (val)), \
Object_Record_Offset += 4 )
#define PUT_SHORT(val) \
( COPY_SHORT (&Object_Record_Buffer[Object_Record_Offset], (val)), \
Object_Record_Offset += 2 )
#define PUT_CHAR(val) (Object_Record_Buffer[Object_Record_Offset++] = (val))
#define PUT_COUNTED_STRING(cp) \
do \
{ \
const char *p = (cp); \
\
PUT_CHAR ((char) strlen (p)); \
while (*p) \
PUT_CHAR (*p++); \
} \
while (0)
#define PSECT_ATTRIBUTES_STRING "$$PsectAttributes_"
#define PSECT_ATTRIBUTES_STRING_LENGTH 18
#define HAS_PSECT_ATTRIBUTES(Name) \
(strncmp ((*Name == '_' ? Name + 1 : Name), \
PSECT_ATTRIBUTES_STRING, \
PSECT_ATTRIBUTES_STRING_LENGTH) == 0)
const short seg_N_TYPE[] =
{
N_ABS,
N_TEXT,
N_DATA,
N_BSS,
N_UNDF,
N_UNDF,
N_UNDF,
N_UNDF,
N_UNDF,
N_UNDF,
N_REGISTER,
};
const segT N_TYPE_seg[N_TYPE + 2] =
{
SEG_UNKNOWN,
SEG_GOOF,
SEG_ABSOLUTE,
SEG_GOOF,
SEG_TEXT,
SEG_GOOF,
SEG_DATA,
SEG_GOOF,
SEG_BSS,
SEG_GOOF,
SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
SEG_REGISTER,
SEG_GOOF,
};
unsigned char const_flag = IN_DEFAULT_SECTION;
static void
s_const (int arg)
{
arg = get_absolute_expression ();
subseg_set (SEG_DATA, (subsegT) arg);
const_flag = 1;
demand_empty_rest_of_line ();
}
const pseudo_typeS obj_pseudo_table[] =
{
{"const", s_const, 0},
{0, 0, 0},
};
int
vms_resolve_symbol_redef (symbolS *sym)
{
if (SEGMENT_TO_SYMBOL_TYPE ((int) now_seg) == (N_UNDF | N_EXT)
&& frag_now_fix () == 0)
{
as_warn (_("compiler emitted zero-size common symbol `%s' already defined"),
S_GET_NAME (sym));
return 1;
}
if (S_IS_EXTERNAL (sym) && S_IS_DEFINED (sym) && S_GET_VALUE (sym) == 0)
{
as_warn (_("compiler redefined zero-size common symbol `%s'"),
S_GET_NAME (sym));
sym->sy_frag = frag_now;
S_SET_OTHER (sym, const_flag);
S_SET_VALUE (sym, frag_now_fix ());
sym->sy_symbol.n_type |= SEGMENT_TO_SYMBOL_TYPE ((int) now_seg);
return 1;
}
return 0;
}
void
vms_check_for_special_label (symbolS *symbolP)
{
if ((const_flag & IN_DEFAULT_SECTION) != 0)
{
char *sym_name = S_GET_NAME (symbolP);
if (*sym_name == '_')
++sym_name;
if (!strcmp (sym_name, "__vax_g_doubles"))
vax_g_doubles = 1;
#if 0
else if (!strcmp (sym_name, "__vax_d_doubles"))
vax_g_doubles = 0;
#endif
#if 0
else if (!strcmp (sym_name, "gcc_compiled."))
flag_one = 1;
else if (!strcmp (sym_name, "__gnu_language_cplusplus"))
flag_hash_long_names = 1;
#endif
}
}
void
obj_read_begin_hook (void)
{
}
void
obj_crawl_symbol_chain (object_headers *headers)
{
symbolS *symbolP;
symbolS **symbolPP;
int symbol_number = 0;
symbolPP = &symbol_rootP;
while ((symbolP = *symbolPP) != NULL)
{
resolve_symbol_value (symbolP);
if (!S_IS_REGISTER (symbolP))
{
symbolP->sy_number = symbol_number++;
symbolP->sy_name_offset = 0;
symbolPP = &symbolP->sy_next;
}
else
{
if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP))
as_bad (_("Local symbol %s never defined"),
S_GET_NAME (symbolP));
*symbolPP = symbol_next (symbolP);
}
}
H_SET_STRING_SIZE (headers, string_byte_count);
H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number);
}
static void
Create_VMS_Object_File (void)
{
#ifdef eunice
VMS_Object_File_FD = creat (out_file_name, 0777, "var");
#else
#ifndef VMS
VMS_Object_File_FD = creat (out_file_name, 0777);
#else
VMS_Object_File_FD = creat (out_file_name, 0, "rfm=var",
"ctx=bin", "mbc=16", "deq=64", "fop=tef",
"shr=nil");
#endif
#endif
if (VMS_Object_File_FD < 0)
as_fatal (_("Couldn't create VMS object file \"%s\""), out_file_name);
Object_Record_Offset = 0;
Current_Object_Record_Type = -1;
}
static void
Flush_VMS_Object_Record_Buffer (void)
{
if (Object_Record_Offset == 0)
return;
#ifndef VMS
{
char RecLen[2];
md_number_to_chars (RecLen, Object_Record_Offset, 2);
if (write (VMS_Object_File_FD, RecLen, 2) != 2)
error (_("I/O error writing VMS object file (length prefix)"));
if ((Object_Record_Offset & 1) != 0)
Object_Record_Buffer[Object_Record_Offset++] = '\0';
}
#endif
if ((size_t) write (VMS_Object_File_FD, Object_Record_Buffer,
Object_Record_Offset) != Object_Record_Offset)
error (_("I/O error writing VMS object file"));
Object_Record_Offset = 0;
}
static void
Set_VMS_Object_File_Record (int Type)
{
if (Type == Current_Object_Record_Type)
return;
Flush_VMS_Object_Record_Buffer ();
Current_Object_Record_Type = Type;
}
static void
Close_VMS_Object_File (void)
{
Set_VMS_Object_File_Record (-1);
#ifndef VMS
{
char RecLen[2];
int minus_one = -1;
md_number_to_chars (RecLen, minus_one, 2);
write (VMS_Object_File_FD, RecLen, 2);
}
#else
#endif
close (VMS_Object_File_FD);
}
static void
vms_tir_stack_psect (int Psect_Index, int Offset, int Force)
{
int psect_width, offset_width;
psect_width = ((unsigned) Psect_Index > 255) ? 2 : 1;
offset_width = (Force || Offset > 32767 || Offset < -32768) ? 4
: (Offset > 127 || Offset < -128) ? 2 : 1;
#define Sta_P(p,o) (((o)<<1) | ((p)-1))
switch (Sta_P(psect_width,offset_width))
{
case Sta_P(1,1): PUT_CHAR (TIR_S_C_STA_PB);
PUT_CHAR ((char) (unsigned char) Psect_Index);
PUT_CHAR ((char) Offset);
break;
case Sta_P(1,2): PUT_CHAR (TIR_S_C_STA_PW);
PUT_CHAR ((char) (unsigned char) Psect_Index);
PUT_SHORT (Offset);
break;
case Sta_P(1,4): PUT_CHAR (TIR_S_C_STA_PL);
PUT_CHAR ((char) (unsigned char) Psect_Index);
PUT_LONG (Offset);
break;
case Sta_P(2,1): PUT_CHAR (TIR_S_C_STA_WPB);
PUT_SHORT (Psect_Index);
PUT_CHAR ((char) Offset);
break;
case Sta_P(2,2): PUT_CHAR (TIR_S_C_STA_WPW);
PUT_SHORT (Psect_Index);
PUT_SHORT (Offset);
break;
case Sta_P(2,4): PUT_CHAR (TIR_S_C_STA_WPL);
PUT_SHORT (Psect_Index);
PUT_LONG (Offset);
break;
}
#undef Sta_P
}
static void
VMS_Store_Immediate_Data (const char *Pointer, int Size, int Record_Type)
{
int i;
Set_VMS_Object_File_Record (Record_Type);
while (Size > 0)
{
i = (Size > 128) ? 128 : Size;
Size -= i;
if ((Object_Record_Offset + i + 1) >= sizeof Object_Record_Buffer)
Flush_VMS_Object_Record_Buffer ();
if (Object_Record_Offset == 0)
PUT_CHAR (Record_Type);
PUT_CHAR ((char) (-i & 0xff));
while (--i >= 0)
PUT_CHAR (*Pointer++);
}
if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
Flush_VMS_Object_Record_Buffer ();
}
static void
VMS_Set_Data (int Psect_Index, int Offset, int Record_Type, int Force)
{
Set_VMS_Object_File_Record (Record_Type);
if (Object_Record_Offset == 0)
PUT_CHAR (Record_Type);
vms_tir_stack_psect (Psect_Index, Offset, Force);
PUT_CHAR (TIR_S_C_STO_PIDR);
if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
Flush_VMS_Object_Record_Buffer ();
}
static void
VMS_Store_Struct (int Struct_Index)
{
Set_VMS_Object_File_Record (OBJ_S_C_DBG);
if (Object_Record_Offset == 0)
PUT_CHAR (OBJ_S_C_DBG);
PUT_CHAR (TIR_S_C_STA_UW);
PUT_SHORT (Struct_Index);
PUT_CHAR (TIR_S_C_CTL_STKDL);
PUT_CHAR (TIR_S_C_STO_L);
if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
Flush_VMS_Object_Record_Buffer ();
}
static void
VMS_Def_Struct (int Struct_Index)
{
Set_VMS_Object_File_Record (OBJ_S_C_DBG);
if (Object_Record_Offset == 0)
PUT_CHAR (OBJ_S_C_DBG);
PUT_CHAR (TIR_S_C_STA_UW);
PUT_SHORT (Struct_Index);
PUT_CHAR (TIR_S_C_CTL_DFLOC);
if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
Flush_VMS_Object_Record_Buffer ();
}
static void
VMS_Set_Struct (int Struct_Index)
{
Set_VMS_Object_File_Record (OBJ_S_C_DBG);
if (Object_Record_Offset == 0)
PUT_CHAR (OBJ_S_C_DBG);
PUT_CHAR (TIR_S_C_STA_UW);
PUT_SHORT (Struct_Index);
PUT_CHAR (TIR_S_C_CTL_STLOC);
if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
Flush_VMS_Object_Record_Buffer ();
}
static void
VMS_TBT_Module_Begin (void)
{
char *cp, *cp1;
int Size;
char Local[256];
cp = &Local[1];
*cp++ = DST_S_C_MODBEG;
*cp++ = 0;
COPY_LONG (cp, DST_S_C_C);
cp += 4;
*cp++ = (char) strlen (Module_Name);
cp1 = Module_Name;
while (*cp1)
*cp++ = *cp1++;
Size = (cp - Local);
Local[0] = Size - 1;
VMS_Store_Immediate_Data (Local, Size, OBJ_S_C_TBT);
}
static void
VMS_TBT_Module_End (void)
{
char Local[2];
Local[0] = 1;
Local[1] = DST_S_C_MODEND;
VMS_Store_Immediate_Data (Local, 2, OBJ_S_C_TBT);
}
static void
VMS_TBT_Routine_Begin (symbolS *symbolP, int Psect)
{
char *cp, *cp1;
char *Name;
int Offset;
int Size;
char Local[512];
Name = S_GET_NAME (symbolP);
if (*Name == '_')
Name++;
Offset = S_GET_VALUE (symbolP);
Size = 1 + 1 + 4 + 1 + strlen (Name);
Local[0] = Size;
Local[1] = DST_S_C_RTNBEG;
Local[2] = 0;
VMS_Store_Immediate_Data (Local, 3, OBJ_S_C_TBT);
if (Object_Record_Offset == 0)
PUT_CHAR (OBJ_S_C_TBT);
vms_tir_stack_psect (Psect, Offset, 0);
PUT_CHAR (TIR_S_C_STO_PIDR);
cp = Local;
cp1 = Name;
Size = strlen (cp1) + 1;
*cp++ = Size - 1;
while (*cp1)
*cp++ = *cp1++;
VMS_Store_Immediate_Data (Local, Size, OBJ_S_C_TBT);
}
static void
VMS_TBT_Routine_End (int Max_Size, symbolS *sp)
{
symbolS *symbolP;
unsigned long Size = 0x7fffffff;
char Local[16];
valueT sym_value, sp_value = S_GET_VALUE (sp);
for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
{
if (!S_IS_DEBUG (symbolP) && S_GET_TYPE (symbolP) == N_TEXT)
{
if (*S_GET_NAME (symbolP) == 'L')
continue;
sym_value = S_GET_VALUE (symbolP);
if (sym_value > sp_value && sym_value < Size)
Size = sym_value;
#if 0
else
if (sym_value == sp_value &&
sp != symbolP &&
(!strcmp (S_GET_NAME (sp), "gcc_compiled.") ||
!strcmp (S_GET_NAME (sp), "gcc2_compiled.")))
Size = sym_value;
#endif
}
}
if (Size == 0x7fffffff)
Size = Max_Size;
Size -= sp_value;
Local[0] = 6;
Local[1] = DST_S_C_RTNEND;
Local[2] = 0;
COPY_LONG (&Local[3], Size);
VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_TBT);
}
static void
VMS_TBT_Block_Begin (symbolS *symbolP, int Psect, char *Name)
{
char *cp, *cp1;
int Offset;
int Size;
char Local[512];
Size = 1 + 1 + 4 + 1 + strlen (Name);
Local[0] = Size;
Local[1] = DST_S_C_BLKBEG;
Local[2] = 0;
VMS_Store_Immediate_Data (Local, 3, OBJ_S_C_DBG);
if (Object_Record_Offset == 0)
PUT_CHAR (OBJ_S_C_DBG);
PUT_CHAR (TIR_S_C_STA_WPL);
PUT_SHORT (Psect);
Offset = S_GET_VALUE (symbolP);
PUT_LONG (Offset);
PUT_CHAR (TIR_S_C_STO_PIDR);
cp = Local;
cp1 = Name;
Size = strlen (cp1) + 1;
*cp++ = Size - 1;
while (*cp1)
*cp++ = *cp1++;
VMS_Store_Immediate_Data (Local, Size, OBJ_S_C_DBG);
}
static void
VMS_TBT_Block_End (valueT Size)
{
char Local[16];
Local[0] = 6;
Local[1] = DST_S_C_BLKEND;
Local[2] = 0;
COPY_LONG (&Local[3], Size);
VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_DBG);
}
static void
VMS_TBT_Line_PC_Correlation (int Line_Number, int Offset,
int Psect, int Do_Delta)
{
char *cp;
char Local[64];
if (Do_Delta == 0)
{
cp = &Local[1];
*cp++ = DST_S_C_LINE_NUM;
if (Line_Number - 1 <= 255)
{
*cp++ = DST_S_C_SET_LINUM_B;
*cp++ = (char) (Line_Number - 1);
}
else if (Line_Number - 1 <= 65535)
{
*cp++ = DST_S_C_SET_LINE_NUM;
COPY_SHORT (cp, Line_Number - 1), cp += 2;
}
else
{
*cp++ = DST_S_C_SET_LINUM_L;
COPY_LONG (cp, Line_Number - 1), cp += 4;
}
*cp++ = DST_S_C_SET_ABS_PC;
Local[0] = cp - &Local[1];
Local[0] += 4;
VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT);
if (Object_Record_Offset == 0)
PUT_CHAR (OBJ_S_C_TBT);
vms_tir_stack_psect (Psect, Offset, 0);
PUT_CHAR (TIR_S_C_STO_PIDR);
Local[0] = 2;
Local[1] = DST_S_C_LINE_NUM;
Local[2] = 0;
VMS_Store_Immediate_Data (Local, 3, OBJ_S_C_TBT);
}
else
{
if (Do_Delta < 0)
{
Local[0] = 1 + 1 + 4;
Local[1] = DST_S_C_LINE_NUM;
Local[2] = DST_S_C_TERM_L;
COPY_LONG (&Local[3], Offset);
VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_TBT);
return;
}
cp = &Local[1];
*cp++ = DST_S_C_LINE_NUM;
if (Line_Number > 1)
{
if (Line_Number - 1 <= 255)
{
*cp++ = DST_S_C_INCR_LINUM;
*cp++ = Line_Number - 1;
}
else if (Line_Number - 1 <= 65535)
{
*cp++ = DST_S_C_INCR_LINUM_W;
COPY_SHORT (cp, Line_Number - 1), cp += 2;
}
else
{
*cp++ = DST_S_C_INCR_LINUM_L;
COPY_LONG (cp, Line_Number - 1), cp += 4;
}
}
if (Offset <= 128)
{
*cp++ = (char) -Offset;
}
else if (Offset <= 65535)
{
*cp++ = DST_S_C_DELTA_PC_W;
COPY_SHORT (cp, Offset), cp += 2;
}
else
{
*cp++ = DST_S_C_DELTA_PC_L;
COPY_LONG (cp, Offset), cp += 4;
}
Local[0] = cp - &Local[1];
VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT);
}
}
static int
VMS_TBT_Source_File (char *Filename, int ID_Number)
{
char *cp;
int len, rfo, ffb, ebk;
char cdt[8];
char Local[512];
#ifdef VMS
unsigned Status;
struct FAB fab;
struct NAM nam;
struct XABDAT xabdat;
struct XABFHC xabfhc;
char resultant_string_buffer[255 + 1];
memset ((char *) &fab, 0, sizeof fab);
fab.fab$b_bid = FAB$C_BID;
fab.fab$b_bln = (unsigned char) sizeof fab;
fab.fab$l_fna = Filename;
fab.fab$b_fns = (unsigned char) strlen (Filename);
fab.fab$l_nam = (char *) &nam;
fab.fab$l_xab = (char *) &xabdat;
memset ((char *) &nam, 0, sizeof nam);
nam.nam$b_bid = NAM$C_BID;
nam.nam$b_bln = (unsigned char) sizeof nam;
nam.nam$l_rsa = resultant_string_buffer;
nam.nam$b_rss = (unsigned char) (sizeof resultant_string_buffer - 1);
memset ((char *) &xabdat, 0, sizeof xabdat);
xabdat.xab$b_cod = XAB$C_DAT;
xabdat.xab$b_bln = (unsigned char) sizeof xabdat;
xabdat.xab$l_nxt = (char *) &xabfhc;
memset ((char *) &xabfhc, 0, sizeof xabfhc);
xabfhc.xab$b_cod = XAB$C_FHC;
xabfhc.xab$b_bln = (unsigned char) sizeof xabfhc;
xabfhc.xab$l_nxt = 0;
Status = sys$open (&fab);
if (!(Status & 1))
{
as_tsktsk (_("Couldn't find source file \"%s\", status=%%X%x"),
Filename, Status);
return 0;
}
sys$close (&fab);
memcpy (cdt, (char *) &xabdat.xab$q_cdt, 8);
ebk = xabfhc.xab$l_ebk;
ffb = xabfhc.xab$w_ffb;
rfo = xabfhc.xab$b_rfo;
len = nam.nam$b_rsl;
resultant_string_buffer[len] = '\0';
Filename = resultant_string_buffer;
#else
memset (cdt, 0, 8);
ebk = ffb = rfo = 0;
len = strlen (Filename);
if (len > 255)
{
Filename += (len - 255);
len = 255;
}
#endif
cp = &Local[1];
*cp++ = DST_S_C_SOURCE;
*cp++ = DST_S_C_SRC_FORMFEED;
*cp++ = DST_S_C_SRC_DECLFILE;
know (cp == &Local[4]);
*cp++ = 0;
*cp++ = 0;
COPY_SHORT (cp, ID_Number), cp += 2;
memcpy (cp, cdt, 8), cp += 8;
COPY_LONG (cp, ebk), cp += 4;
COPY_SHORT (cp, ffb), cp += 2;
*cp++ = (char) rfo;
*cp++ = (char) len;
while (--len >= 0)
*cp++ = *Filename++;
*cp++ = 0;
Local[4] = cp - &Local[5];
Local[0] = cp - &Local[1];
VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT);
return 1;
}
static void
VMS_TBT_Source_Lines (int ID_Number, int Starting_Line_Number,
int Number_Of_Lines)
{
char *cp;
int chunk_limit;
char Local[128];
cp = &Local[1];
*cp++ = DST_S_C_SOURCE;
*cp++ = DST_S_C_SRC_SETFILE;
COPY_SHORT (cp, ID_Number), cp += 2;
chunk_limit = (sizeof Local - 5) / 6;
if (Number_Of_Lines > 65535 * chunk_limit)
Number_Of_Lines = 65535 * chunk_limit;
while (Number_Of_Lines > 65535)
{
*cp++ = DST_S_C_SRC_SETREC_L;
COPY_LONG (cp, Starting_Line_Number), cp += 4;
*cp++ = DST_S_C_SRC_DEFLINES_W;
COPY_SHORT (cp, 65535), cp += 2;
Starting_Line_Number += 65535;
Number_Of_Lines -= 65535;
}
if (Starting_Line_Number <= 65535)
{
*cp++ = DST_S_C_SRC_SETREC_W;
COPY_SHORT (cp, Starting_Line_Number), cp += 2;
}
else
{
*cp++ = DST_S_C_SRC_SETREC_L;
COPY_LONG (cp, Starting_Line_Number), cp += 4;
}
*cp++ = DST_S_C_SRC_DEFLINES_W;
COPY_SHORT (cp, Number_Of_Lines), cp += 2;
Local[0] = cp - &Local[1];
VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT);
}
static struct input_file *
find_file (symbolS *sp)
{
struct input_file *same_file = 0;
struct input_file *fpnt, *last = 0;
char *sp_name;
for (fpnt = file_root; fpnt; fpnt = fpnt->next)
{
if (fpnt->spnt == sp)
return fpnt;
last = fpnt;
}
sp_name = S_GET_NAME (sp);
for (fpnt = file_root; fpnt; fpnt = fpnt->next)
{
if (strcmp (sp_name, fpnt->name) == 0)
{
if (fpnt->flag == 1)
return fpnt;
same_file = fpnt;
break;
}
}
fpnt = xmalloc (sizeof (struct input_file));
if (!file_root)
file_root = fpnt;
else
last->next = fpnt;
fpnt->next = 0;
fpnt->name = sp_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;
}
static char *
cvt_integer (char *str, int *rtn)
{
int ival = 0, sgn = 1;
if (*str == '-')
sgn = -1, ++str;
while (*str >= '0' && *str <= '9')
ival = 10 * ival + *str++ - '0';
*rtn = sgn * ival;
return str;
}
static char *
fix_name (char *pnt)
{
char *pnt1;
if (*pnt == '_')
pnt++;
if (HAS_PSECT_ATTRIBUTES (pnt))
{
pnt += PSECT_ATTRIBUTES_STRING_LENGTH;
while (*pnt)
{
if ((pnt[0] == '$') && (pnt[1] == '$'))
{
pnt += 2;
break;
}
pnt++;
}
}
for (pnt1 = pnt; *pnt1 != 0; pnt1++)
if (*pnt1 == '.')
*pnt1 = '$';
return pnt;
}
static char *
get_struct_name (char *str)
{
char *pnt;
pnt = str;
while ((*pnt != ':') && (*pnt != '\0'))
pnt--;
if (*pnt == '\0')
return (char *) 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;
}
static struct VMS_DBG_Symbol *
find_symbol (int dbx_type)
{
struct VMS_DBG_Symbol *spnt;
spnt = VMS_Symbol_type_list[SYMTYP_HASH (dbx_type)];
while (spnt)
{
if (spnt->dbx_type == dbx_type)
break;
spnt = spnt->next;
}
if (!spnt || spnt->advanced != ALIAS)
return spnt;
return find_symbol (spnt->type2);
}
#if 0
static void
push (int value, int size1)
{
if (size1 < 0)
{
size1 = -size1;
if (Lpnt < size1)
{
overflow = 1;
Lpnt = 1;
return;
}
Lpnt -= size1;
md_number_to_chars (&Local[Lpnt + 1], value, size1);
}
else
{
if (Apoint + size1 >= MAX_DEBUG_RECORD)
{
overflow = 1;
Apoint = MAX_DEBUG_RECORD - 1;
return;
}
md_number_to_chars (&Asuffix[Apoint], value, size1);
Apoint += size1;
}
}
#endif
static void
fpush (int value, int size)
{
if (Apoint + size >= MAX_DEBUG_RECORD)
{
overflow = 1;
Apoint = MAX_DEBUG_RECORD - 1;
return;
}
if (size == 1)
Asuffix[Apoint++] = (char) value;
else
{
md_number_to_chars (&Asuffix[Apoint], value, size);
Apoint += size;
}
}
static void
rpush (int value, int size)
{
if (Lpnt < size)
{
overflow = 1;
Lpnt = 1;
return;
}
if (size == 1)
Local[Lpnt--] = (char) value;
else
{
Lpnt -= size;
md_number_to_chars (&Local[Lpnt + 1], value, size);
}
}
static void
array_suffix (struct VMS_DBG_Symbol *spnt2)
{
struct VMS_DBG_Symbol *spnt;
struct VMS_DBG_Symbol *spnt1;
int rank;
int total_size;
rank = 0;
spnt = spnt2;
while (spnt->advanced != ARRAY)
{
spnt = find_symbol (spnt->type2);
if (!spnt)
return;
}
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;
fpush (spnt1->data_size, 2);
if (spnt1->VMS_type == DBG_S_C_ADVANCED_TYPE)
fpush (0, 1);
else
fpush (spnt1->VMS_type, 1);
fpush (DSC_K_CLASS_A, 1);
fpush (0, 4);
fpush (0, 1);
fpush (0, 1);
fpush (0xc0, 1);
fpush (rank, 1);
fpush (total_size, 4);
fpush (0, 4);
spnt1 = spnt;
while (spnt1->advanced == ARRAY)
{
fpush (spnt1->index_max - spnt1->index_min + 1, 4);
spnt1 = find_symbol (spnt1->type2);
}
spnt1 = spnt;
while (spnt1->advanced == ARRAY)
{
fpush (spnt1->index_min, 4);
fpush (spnt1->index_max, 4);
spnt1 = find_symbol (spnt1->type2);
}
}
static void
new_forward_ref (int dbx_type)
{
struct forward_ref *fpnt;
fpnt = xmalloc (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';
rpush (DST_K_TS_IND, 1);
total_len = 5;
rpush (total_len, 2);
struct_number = -fpnt->struc_numb;
}
static int
gen1 (struct VMS_DBG_Symbol *spnt, int array_suffix_len)
{
struct VMS_DBG_Symbol *spnt1;
int i;
switch (spnt->advanced)
{
case VOID:
rpush (DBG_S_C_VOID, 1);
total_len += 1;
rpush (total_len, 2);
return 0;
case BASIC:
case FUNCTION:
if (array_suffix_len == 0)
{
rpush (spnt->VMS_type, 1);
rpush (DBG_S_C_BASIC, 1);
total_len = 2;
rpush (total_len, 2);
return 1;
}
rpush (0, 4);
rpush (DST_K_VFLAGS_DSC, 1);
rpush (DST_K_TS_DSC, 1);
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;
}
rpush (DBG_S_C_STRUCT, 1);
total_len = 5;
rpush (total_len, 2);
return 1;
case POINTER:
spnt1 = find_symbol (spnt->type2);
i = 1;
if (!spnt1)
new_forward_ref (spnt->type2);
else
i = gen1 (spnt1, 0);
if (i)
{
rpush (DBG_S_C_POINTER, 1);
total_len += 3;
rpush (total_len, 2);
}
return 1;
case ARRAY:
spnt1 = spnt;
while (spnt1->advanced == ARRAY)
{
spnt1 = find_symbol (spnt1->type2);
if (!spnt1)
{
as_tsktsk (_("debugger forward reference error, dbx type %d"),
spnt->type2);
return 0;
}
}
(void) gen1 (spnt1, 1);
i = Apoint;
array_suffix (spnt);
array_suffix_len = Apoint - i;
switch (spnt1->advanced)
{
case BASIC:
case FUNCTION:
break;
default:
rpush (0, 2);
total_len += 2;
rpush (total_len, 2);
rpush (DST_K_VFLAGS_DSC, 1);
rpush (1, 1);
rpush (1, 1);
rpush (DBG_S_C_COMPLEX_ARRAY, 1);
}
total_len += array_suffix_len + 8;
rpush (total_len, 2);
break;
default:
break;
}
return 0;
}
static void
generate_suffix (struct VMS_DBG_Symbol *spnt, int dbx_type)
{
static const char pvoid[6] =
{
5,
DST_K_TYPSPEC,
0,
1, 0,
DBG_S_C_VOID
};
int i;
Apoint = 0;
Lpnt = MAX_DEBUG_RECORD - 1;
total_len = 0;
struct_number = 0;
overflow = 0;
if (!spnt)
new_forward_ref (dbx_type);
else
{
if (spnt->VMS_type != DBG_S_C_ADVANCED_TYPE)
return;
gen1 (spnt, 0);
}
rpush (0, 1);
rpush (DST_K_TYPSPEC, 1);
total_len += 4;
rpush (total_len, 1);
if ((total_len >= MAX_DEBUG_RECORD) || overflow)
{
as_warn (_("Variable descriptor %d too complicated. Defined as `void *'."),
spnt->dbx_type);
VMS_Store_Immediate_Data (pvoid, 6, OBJ_S_C_DBG);
return;
}
i = 0;
while (Lpnt < MAX_DEBUG_RECORD - 1)
Local[i++] = Local[++Lpnt];
Lpnt = i;
if (struct_number > 0)
{
VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
Lpnt = 0;
VMS_Store_Struct (struct_number);
}
if (struct_number < 0)
{
struct_number = -struct_number;
VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
Lpnt = 0;
VMS_Def_Struct (struct_number);
COPY_LONG (&Local[Lpnt], 0L);
Lpnt += 4;
VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
Lpnt = 0;
}
i = 0;
while (i < Apoint)
Local[Lpnt++] = Asuffix[i++];
if (Lpnt != 0)
VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
Lpnt = 0;
}
#define USE_BITSTRING_DESCRIPTOR(t) ((t)->advanced == BASIC)
#undef SETUP_BASIC_TYPES
static void
bitfield_suffix (struct VMS_DBG_Symbol *spnt, int width)
{
Local[Lpnt++] = 13;
Local[Lpnt++] = DST_K_TYPSPEC;
Local[Lpnt++] = 0;
COPY_SHORT (&Local[Lpnt], 9);
Lpnt += 2;
Local[Lpnt++] = DST_K_TS_NOV_LENG;
COPY_LONG (&Local[Lpnt], width);
Lpnt += 4;
VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
Lpnt = 0;
VMS_Store_Struct (spnt->struc_numb);
}
static void
setup_basic_type (struct VMS_DBG_Symbol *spnt ATTRIBUTE_UNUSED)
{
#ifdef SETUP_BASIC_TYPES
char *p;
#ifndef SETUP_SYNONYM_TYPES
struct VMS_DBG_Symbol *spnt2;
for (spnt2 = VMS_Symbol_type_list[SYMTYP_HASH (spnt->VMS_type)];
spnt2;
spnt2 = spnt2->next)
if (spnt2 != spnt && spnt2->VMS_type == spnt->VMS_type)
{
spnt->struc_numb = spnt2->struc_numb;
return;
}
#endif
spnt->struc_numb = ++structure_count;
VMS_Def_Struct (spnt->struc_numb);
Local[Lpnt++] = 6 + strlen (symbol_name) + 2;
Local[Lpnt++] = DST_K_TYPSPEC;
Local[Lpnt++] = strlen (symbol_name) + 2;
Local[Lpnt++] = '_';
Local[Lpnt++] = '_';
for (p = symbol_name; *p; p++)
Local[Lpnt++] = *p == ' ' ? '_' : *p;
COPY_SHORT (&Local[Lpnt], 2);
Lpnt += 2;
Local[Lpnt++] = DST_K_TS_ATOM;
Local[Lpnt++] = spnt->VMS_type;
VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
Lpnt = 0;
#endif
}
static void
VMS_DBG_record (struct VMS_DBG_Symbol *spnt, int Psect,
int Offset, char *Name)
{
char *Name_pnt;
int len;
int i = 0;
Name_pnt = fix_name (Name);
len = strlen (Name_pnt);
if (Psect < 0)
{
Local[i++] = 7 + len;
Local[i++] = spnt->VMS_type;
Local[i++] = (Offset > 0) ? DBG_C_FUNCTION_PARAM : DBG_C_LOCAL_SYM;
COPY_LONG (&Local[i], Offset);
i += 4;
}
else
{
Local[i++] = 7 + len;
Local[i++] = spnt->VMS_type;
Local[i++] = DST_K_VALKIND_ADDR;
VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
i = 0;
VMS_Set_Data (Psect, Offset, OBJ_S_C_DBG, 0);
}
Local[i++] = len;
while (*Name_pnt != '\0')
Local[i++] = *Name_pnt++;
VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
if (spnt->VMS_type == DBG_S_C_ADVANCED_TYPE)
generate_suffix (spnt, 0);
}
static void
VMS_local_stab_Parse (symbolS *sp)
{
struct VMS_DBG_Symbol *spnt;
char *pnt;
char *pnt1;
char *str;
int dbx_type;
dbx_type = 0;
str = S_GET_NAME (sp);
pnt = (char *) strchr (str, ':');
if (!pnt)
return;
pnt1 = pnt++;
if (*pnt == 'c')
return;
{
symbolS *sp1;
char *str1;
char *pnt2;
if (*pnt == 'p')
{
for (sp1 = symbol_next (sp); sp1; sp1 = symbol_next (sp1))
{
if (!S_IS_DEBUG (sp1))
continue;
if (S_GET_RAW_TYPE (sp1) == N_FUN)
{
pnt2 = (char *) strchr (S_GET_NAME (sp1), ':') + 1;
if (*pnt2 == 'F' || *pnt2 == 'f')
break;
}
if (S_GET_RAW_TYPE (sp1) != N_RSYM)
continue;
str1 = S_GET_NAME (sp1);
pnt2 = str;
while (*pnt2 != ':')
{
if (*pnt2 != *str1)
break;
pnt2++;
str1++;
}
if (*str1 == ':' && *pnt2 == ':')
return;
}
pnt++;
}
}
pnt = cvt_integer (pnt, &dbx_type);
spnt = find_symbol (dbx_type);
if (!spnt)
return;
*pnt1 = '\0';
VMS_DBG_record (spnt, -1, S_GET_VALUE (sp), str);
*pnt1 = ':';
}
static void
VMS_stab_parse (symbolS *sp, int 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;
dbx_type = 0;
str = S_GET_NAME (sp);
pnt = (char *) strchr (str, ':');
if (!pnt)
return;
pnt1 = pnt;
pnt++;
if (*pnt == expected_type)
{
pnt = cvt_integer (pnt + 1, &dbx_type);
spnt = find_symbol (dbx_type);
if (!spnt)
return;
*pnt1 = '\0';
vsp = VMS_Symbols;
while (vsp)
{
pnt = S_GET_NAME (vsp->Symbol);
if (pnt && *pnt++ == '_'
&& strcmp (pnt, str) == 0
&& (S_GET_RAW_TYPE (vsp->Symbol) == type1
|| S_GET_RAW_TYPE (vsp->Symbol) == type2))
break;
vsp = vsp->Next;
}
if (vsp)
{
VMS_DBG_record (spnt, vsp->Psect_Index, vsp->Psect_Offset, str);
*pnt1 = ':';
return;
}
for (sp1 = symbol_rootP; sp1; sp1 = symbol_next (sp1))
{
if (S_IS_DEBUG (sp1) || (S_GET_TYPE (sp1) != N_TEXT))
continue;
pnt = S_GET_NAME (sp1);
if (*pnt == '_')
pnt++;
if (strcmp (pnt, str) == 0)
{
if (!gave_compiler_message && expected_type == 'G')
{
char *long_const_msg = _("\
***Warning - the assembly code generated by the compiler has placed \n\
global constant(s) in the text psect. These will not be available to \n\
other modules, since this is not the correct way to handle this. You \n\
have two options: 1) get a patched compiler that does not put global \n\
constants in the text psect, or 2) remove the 'const' keyword from \n\
definitions of global variables in your source module(s). Don't say \n\
I didn't warn you! \n");
as_tsktsk (long_const_msg);
gave_compiler_message = 1;
}
VMS_DBG_record (spnt,
Text_Psect,
S_GET_VALUE (sp1),
str);
*pnt1 = ':';
pnt1 = S_GET_NAME (sp1);
*pnt1 = 'L';
S_SET_NAME (sp1, pnt1);
return;
}
}
}
*pnt1 = ':';
}
static void
VMS_GSYM_Parse (symbolS *sp, int Text_Psect)
{
VMS_stab_parse (sp, 'G', (N_UNDF | N_EXT), (N_DATA | N_EXT), Text_Psect);
}
static void
VMS_LCSYM_Parse (symbolS *sp, int Text_Psect)
{
VMS_stab_parse (sp, 'S', N_BSS, -1, Text_Psect);
}
static void
VMS_STSYM_Parse (symbolS *sp, int Text_Psect)
{
VMS_stab_parse (sp, 'S', N_DATA, -1, Text_Psect);
}
static void
VMS_RSYM_Parse (symbolS *sp, symbolS *Current_Routine ATTRIBUTE_UNUSED,
int Text_Psect)
{
symbolS *symbolP;
struct VMS_DBG_Symbol *spnt;
char *pnt;
char *pnt1;
char *str;
int dbx_type;
int len;
int i = 0;
int bcnt = 0;
int Min_Offset = -1;
int Max_Offset = 0;
for (symbolP = sp; symbolP; symbolP = symbol_next (symbolP))
{
switch (S_GET_RAW_TYPE (symbolP))
{
case N_LBRAC:
if (bcnt++ == 0)
Min_Offset = S_GET_VALUE (symbolP);
break;
case N_RBRAC:
if (--bcnt == 0)
Max_Offset = S_GET_VALUE (symbolP) - 1;
break;
}
if ((Min_Offset != -1) && (bcnt == 0))
break;
if (S_GET_RAW_TYPE (symbolP) == N_FUN)
{
pnt = (char *) strchr (S_GET_NAME (symbolP), ':') + 1;
if (*pnt == 'F' || *pnt == 'f') break;
}
}
if (Min_Offset == -1)
{
int Max_Source_Offset;
int This_Offset;
Min_Offset = S_GET_VALUE (sp);
Max_Source_Offset = Min_Offset;
for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
switch (S_GET_RAW_TYPE (symbolP))
{
case N_TEXT | N_EXT:
This_Offset = S_GET_VALUE (symbolP);
if (This_Offset > Min_Offset && This_Offset < Max_Offset)
Max_Offset = This_Offset;
break;
case N_SLINE:
This_Offset = S_GET_VALUE (symbolP);
if (This_Offset > Max_Source_Offset)
Max_Source_Offset = This_Offset;
break;
}
if (Max_Offset == 0x7fffffff)
Max_Offset = Max_Source_Offset;
}
dbx_type = 0;
str = S_GET_NAME (sp);
if ((pnt = (char *) strchr (str, ':')) == 0)
return;
pnt1 = pnt;
pnt++;
if (*pnt != 'r')
return;
pnt = cvt_integer (pnt + 1, &dbx_type);
spnt = find_symbol (dbx_type);
if (!spnt)
return;
*pnt1 = '\0';
pnt = fix_name (S_GET_NAME (sp));
len = strlen (pnt);
Local[i++] = 25 + len;
Local[i++] = spnt->VMS_type;
Local[i++] = DST_K_VFLAGS_TVS;
COPY_LONG (&Local[i], 1 + len);
i += 4;
Local[i++] = len;
while (*pnt != '\0')
Local[i++] = *pnt++;
Local[i++] = DST_K_VS_FOLLOWS;
COPY_SHORT (&Local[i], 15);
i += 2;
Local[i++] = DST_K_VS_ALLOC_SPLIT;
Local[i++] = 1;
VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
i = 0;
VMS_Set_Data (Text_Psect, Min_Offset, OBJ_S_C_DBG, 1);
VMS_Set_Data (Text_Psect, Max_Offset, OBJ_S_C_DBG, 1);
Local[i++] = DST_K_VALKIND_REG;
COPY_LONG (&Local[i], S_GET_VALUE (sp));
i += 4;
VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
*pnt1 = ':';
if (spnt->VMS_type == DBG_S_C_ADVANCED_TYPE)
generate_suffix (spnt, 0);
}
static int
forward_reference (char *pnt)
{
struct VMS_DBG_Symbol *spnt, *spnt1;
int i;
pnt = cvt_integer (pnt + 1, &i);
if (*pnt == ';')
return 0;
do
{
pnt = (char *) strchr (pnt, ':');
pnt = cvt_integer (pnt + 1, &i);
spnt = find_symbol (i);
while (spnt && (spnt->advanced == POINTER || spnt->advanced == ARRAY))
{
spnt1 = find_symbol (spnt->type2);
if (spnt->advanced == ARRAY && !spnt1)
return 1;
spnt = spnt1;
}
pnt = cvt_integer (pnt + 1, &i);
pnt = cvt_integer (pnt + 1, &i);
} while (*++pnt != ';');
return 0;
}
static int
final_forward_reference (struct VMS_DBG_Symbol *spnt)
{
struct VMS_DBG_Symbol *spnt1;
while (spnt && (spnt->advanced == POINTER || spnt->advanced == ARRAY))
{
spnt1 = find_symbol (spnt->type2);
if (spnt->advanced == ARRAY && !spnt1)
return 1;
spnt = spnt1;
}
return 0;
}
static int
VMS_typedef_parse (char *str)
{
char *pnt;
char *pnt1;
const char *pnt2;
int i;
int dtype;
struct forward_ref *fpnt;
int i1, i2, i3, len;
struct VMS_DBG_Symbol *spnt;
struct VMS_DBG_Symbol *spnt1;
pnt = (char *) strchr (str + 1, '=');
if (pnt && str[1] != '*' && (str[1] != 'a' || str[2] != 'r')
&& VMS_typedef_parse (pnt) == 1)
return 1;
pnt = str - 1;
if (*pnt == 'c')
{
*str = '\0';
return 0;
}
while ((*pnt <= '9') && (*pnt >= '0'))
pnt--;
pnt++;
cvt_integer (pnt, &i1);
spnt = find_symbol (i1);
if (!spnt)
{
i2 = SYMTYP_HASH (i1);
spnt = xmalloc (sizeof (struct VMS_DBG_Symbol));
spnt->next = VMS_Symbol_type_list[i2];
VMS_Symbol_type_list[i2] = spnt;
spnt->dbx_type = i1;
spnt->type2 = spnt->VMS_type = spnt->data_size = 0;
spnt->index_min = spnt->index_max = spnt->struc_numb = 0;
}
pnt = str + 1;
if (*pnt >= '0' && *pnt <= '9')
{
if (type_check ("void"))
{
*str = '\0';
spnt->advanced = VOID;
return 0;
}
if (type_check ("unknown type"))
{
*str = '\0';
spnt->advanced = UNKNOWN;
return 0;
}
pnt1 = cvt_integer (pnt, &i1);
if (i1 != spnt->dbx_type)
{
spnt->advanced = ALIAS;
spnt->type2 = i1;
strcpy (str, pnt1);
return 0;
}
as_tsktsk (_("debugginer output: %d is an unknown untyped variable."),
spnt->dbx_type);
return 1;
}
pnt = str + 1;
switch (*pnt)
{
case 'r':
spnt->advanced = BASIC;
if (type_check ("int"))
{
spnt->VMS_type = DBG_S_C_SLINT;
spnt->data_size = 4;
}
else if (type_check ("long int"))
{
spnt->VMS_type = DBG_S_C_SLINT;
spnt->data_size = 4;
}
else if (type_check ("unsigned int"))
{
spnt->VMS_type = DBG_S_C_ULINT;
spnt->data_size = 4;
}
else if (type_check ("long unsigned int"))
{
spnt->VMS_type = DBG_S_C_ULINT;
spnt->data_size = 4;
}
else if (type_check ("short int"))
{
spnt->VMS_type = DBG_S_C_SSINT;
spnt->data_size = 2;
}
else if (type_check ("short unsigned int"))
{
spnt->VMS_type = DBG_S_C_USINT;
spnt->data_size = 2;
}
else if (type_check ("char"))
{
spnt->VMS_type = DBG_S_C_SCHAR;
spnt->data_size = 1;
}
else if (type_check ("signed char"))
{
spnt->VMS_type = DBG_S_C_SCHAR;
spnt->data_size = 1;
}
else if (type_check ("unsigned char"))
{
spnt->VMS_type = DBG_S_C_UCHAR;
spnt->data_size = 1;
}
else if (type_check ("float"))
{
spnt->VMS_type = DBG_S_C_REAL4;
spnt->data_size = 4;
}
else if (type_check ("double"))
{
spnt->VMS_type = vax_g_doubles ? DBG_S_C_REAL8_G : DBG_S_C_REAL8;
spnt->data_size = 8;
}
else if (type_check ("long double"))
{
spnt->VMS_type = vax_g_doubles ? DBG_S_C_REAL8_G : DBG_S_C_REAL8;
spnt->data_size = 8;
}
else if (type_check ("long long int"))
{
spnt->VMS_type = DBG_S_C_SQUAD;
spnt->data_size = 8;
}
else if (type_check ("long long unsigned int"))
{
spnt->VMS_type = DBG_S_C_UQUAD;
spnt->data_size = 8;
}
else if (type_check ("complex float"))
{
spnt->VMS_type = DBG_S_C_COMPLX4;
spnt->data_size = 2 * 4;
}
else if (type_check ("complex double"))
{
spnt->VMS_type = vax_g_doubles ? DBG_S_C_COMPLX8_G : DBG_S_C_COMPLX8;
spnt->data_size = 2 * 8;
}
else if (type_check ("complex long double"))
{
spnt->VMS_type = vax_g_doubles ? DBG_S_C_COMPLX8_G : DBG_S_C_COMPLX8;
spnt->data_size = 2 * 8;
}
else
{
spnt->VMS_type = 0;
spnt->data_size = 0;
}
if (spnt->VMS_type != 0)
setup_basic_type (spnt);
pnt1 = (char *) strchr (str, ';') + 1;
break;
case 's':
case 'u':
spnt->advanced = (*pnt == 's') ? STRUCT : UNION;
spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
pnt1 = cvt_integer (pnt + 1, &spnt->data_size);
if (!final_pass && 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);
i = 0;
for (fpnt = f_ref_root; fpnt; fpnt = fpnt->next)
if (fpnt->dbx_type == spnt->dbx_type)
{
fpnt->resolved = 'Y';
VMS_Set_Struct (fpnt->struc_numb);
VMS_Store_Struct (spnt->struc_numb);
i++;
}
if (i > 0)
VMS_Set_Struct (spnt->struc_numb);
i = 0;
Local[i++] = 11 + strlen (pnt);
Local[i++] = DBG_S_C_STRUCT_START;
Local[i++] = DST_K_VFLAGS_NOVAL;
COPY_LONG (&Local[i], 0L);
i += 4;
Local[i++] = strlen (pnt);
pnt2 = pnt;
while (*pnt2 != '\0')
Local[i++] = *pnt2++;
i2 = spnt->data_size * 8;
COPY_LONG (&Local[i], i2);
i += 4;
VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
i = 0;
if (pnt != symbol_name)
{
pnt += strlen (pnt);
*pnt = ':';
}
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);
spnt1 = find_symbol (dtype);
len = strlen (pnt2);
if (spnt1 && (spnt1->advanced == BASIC || spnt1->advanced == ENUM)
&& ((i3 != spnt1->data_size * 8) || (i2 % 8 != 0)))
{
if (USE_BITSTRING_DESCRIPTOR (spnt1))
{
int unsigned_type = (spnt1->VMS_type == DBG_S_C_ULINT
|| spnt1->VMS_type == DBG_S_C_USINT
|| spnt1->VMS_type == DBG_S_C_UCHAR
|| spnt1->VMS_type == DBG_S_C_UQUAD
|| spnt1->advanced == ENUM);
Apoint = 0;
fpush (19 + len, 1);
fpush (unsigned_type ? DBG_S_C_UBITU : DBG_S_C_SBITU, 1);
fpush (DST_K_VFLAGS_DSC, 1);
fpush (1 + len, 4);
fpush (len, 1);
while (*pnt2 != '\0')
fpush (*pnt2++, 1);
fpush (i3, 2);
fpush (unsigned_type ? DBG_S_C_UBITU : DBG_S_C_SBITU, 1);
fpush (DSC_K_CLASS_UBS, 1);
fpush (0x00, 4);
fpush (i2, 4);
VMS_Store_Immediate_Data (Asuffix, Apoint, OBJ_S_C_DBG);
Apoint = 0;
}
else
{
Local[i++] = 7 + len;
Local[i++] = DBG_S_C_ADVANCED_TYPE;
Local[i++] = DBG_S_C_STRUCT_ITEM;
COPY_LONG (&Local[i], i2);
i += 4;
Local[i++] = strlen (pnt2);
while (*pnt2 != '\0')
Local[i++] = *pnt2++;
VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
i = 0;
bitfield_suffix (spnt1, i3);
}
}
else
{
if (final_pass && final_forward_reference (spnt1))
{
as_tsktsk (_("debugger output: structure element `%s' has undefined type"),
pnt2);
continue;
}
Local[i++] = 7 + len;
Local[i++] = spnt1 ? spnt1->VMS_type : DBG_S_C_ADVANCED_TYPE;
Local[i++] = DBG_S_C_STRUCT_ITEM;
COPY_LONG (&Local[i], i2);
i += 4;
Local[i++] = strlen (pnt2);
while (*pnt2 != '\0')
Local[i++] = *pnt2++;
VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
i = 0;
if (!spnt1)
generate_suffix (spnt1, dtype);
else if (spnt1->VMS_type == DBG_S_C_ADVANCED_TYPE)
generate_suffix (spnt1, 0);
}
}
pnt1++;
Local[i++] = 0x01;
Local[i++] = DBG_S_C_STRUCT_END;
VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
i = 0;
break;
case 'e':
spnt->advanced = ENUM;
spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
spnt->struc_numb = ++structure_count;
spnt->data_size = 4;
VMS_Def_Struct (spnt->struc_numb);
i = 0;
for (fpnt = f_ref_root; fpnt; fpnt = fpnt->next)
if (fpnt->dbx_type == spnt->dbx_type)
{
fpnt->resolved = 'Y';
VMS_Set_Struct (fpnt->struc_numb);
VMS_Store_Struct (spnt->struc_numb);
i++;
}
if (i > 0)
VMS_Set_Struct (spnt->struc_numb);
i = 0;
len = strlen (symbol_name);
Local[i++] = 3 + len;
Local[i++] = DBG_S_C_ENUM_START;
Local[i++] = 4 * 8;
Local[i++] = len;
pnt2 = symbol_name;
while (*pnt2 != '\0')
Local[i++] = *pnt2++;
VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
i = 0;
while (*++pnt != ';')
{
pnt1 = (char *) strchr (pnt, ':');
*pnt1++ = '\0';
pnt1 = cvt_integer (pnt1, &i1);
len = strlen (pnt);
Local[i++] = 7 + len;
Local[i++] = DBG_S_C_ENUM_ITEM;
Local[i++] = DST_K_VALKIND_LITERAL;
COPY_LONG (&Local[i], i1);
i += 4;
Local[i++] = len;
pnt2 = pnt;
while (*pnt != '\0')
Local[i++] = *pnt++;
VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
i = 0;
pnt = pnt1;
}
Local[i++] = 0x01;
Local[i++] = DBG_S_C_ENUM_END;
VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
i = 0;
pnt1 = pnt + 1;
break;
case 'a':
spnt->advanced = ARRAY;
spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
pnt = (char *) strchr (pnt, ';');
if (!pnt)
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);
pnt = (char *) strchr (str + 1, '=');
if (pnt && VMS_typedef_parse (pnt) == 1)
return 1;
break;
case 'f':
spnt->advanced = FUNCTION;
spnt->VMS_type = DBG_S_C_FUNCTION_ADDR;
spnt->data_size = 4;
pnt1 = cvt_integer (pnt + 1, &spnt->type2);
break;
case '*':
spnt->advanced = POINTER;
spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
spnt->data_size = 4;
pnt1 = cvt_integer (pnt + 1, &spnt->type2);
pnt = (char *) strchr (str + 1, '=');
if (pnt && VMS_typedef_parse (pnt) == 1)
return 1;
break;
default:
spnt->advanced = UNKNOWN;
spnt->VMS_type = 0;
as_tsktsk (_("debugger output: %d is an unknown type of variable."),
spnt->dbx_type);
return 1;
}
pnt = str;
while (*pnt1 != '\0')
*pnt++ = *pnt1++;
*pnt = '\0';
return 0;
}
static void
VMS_LSYM_Parse (void)
{
char *pnt;
char *pnt1;
char *pnt2;
char *str;
char *parse_buffer = 0;
char fixit[10];
int incomplete, pass, incom1;
struct forward_ref *fpnt;
symbolS *sp;
pass = 0;
final_pass = 0;
incomplete = 0;
do
{
incom1 = incomplete;
incomplete = 0;
for (sp = symbol_rootP; sp; sp = symbol_next (sp))
{
if (S_IS_DEBUG (sp))
{
switch (S_GET_RAW_TYPE (sp))
{
case N_GSYM:
case N_LCSYM:
case N_STSYM:
case N_PSYM:
case N_RSYM:
case N_LSYM:
case N_FUN:
str = S_GET_NAME (sp);
symbol_name = str;
pnt = str + strlen (str) - 1;
if (*pnt == '?')
{
symbolS *spnext;
int tlen = 0;
spnext = sp;
do
{
tlen += strlen (str) - 1;
spnext = symbol_next (spnext);
str = S_GET_NAME (spnext);
pnt = str + strlen (str) - 1;
}
while (*pnt == '?');
tlen += strlen (str);
parse_buffer = xmalloc (tlen + 1);
strcpy (parse_buffer, S_GET_NAME (sp));
pnt2 = parse_buffer + strlen (parse_buffer) - 1;
*pnt2 = '\0';
spnext = sp;
do
{
spnext = symbol_next (spnext);
str = S_GET_NAME (spnext);
strcat (pnt2, str);
pnt2 += strlen (str) - 1;
*str = '\0';
if (*pnt2 != '?') break;
*pnt2 = '\0';
}
while (1);
str = parse_buffer;
symbol_name = str;
}
if ((pnt = (char *) strchr (str, ':')) != 0)
{
*pnt = '\0';
pnt1 = pnt + 1;
if ((pnt2 = (char *) strchr (pnt1, '=')) != 0)
incomplete += VMS_typedef_parse (pnt2);
if (parse_buffer)
{
pnt2 = S_GET_NAME (sp);
strcpy (pnt2, parse_buffer);
free (parse_buffer), parse_buffer = 0;
}
*pnt = ':';
}
break;
}
}
}
pass++;
if (final_pass == 0 && incomplete == incom1)
{
final_pass = 1;
incom1++;
}
}
while (incomplete != 0 && incomplete != incom1);
if (incomplete != 0)
as_tsktsk (_("debugger output: Unable to resolve %d circular references."),
incomplete);
fpnt = f_ref_root;
symbol_name = "\0";
while (fpnt)
{
if (fpnt->resolved != 'Y')
{
if (find_symbol (fpnt->dbx_type))
{
as_tsktsk (_("debugger forward reference error, dbx type %d"),
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 void
Define_Local_Symbols (symbolS *s0P, symbolS *s2P, symbolS *Current_Routine,
int Text_Psect)
{
symbolS *s1P;
for (s1P = symbol_next (s0P); s1P != s2P; s1P = symbol_next (s1P))
{
if (!s1P)
break;
if (S_GET_RAW_TYPE (s1P) == N_FUN)
{
char *pnt = (char *) strchr (S_GET_NAME (s1P), ':') + 1;
if (*pnt == 'F' || *pnt == 'f') break;
}
if (!S_IS_DEBUG (s1P))
continue;
switch (S_GET_RAW_TYPE (s1P))
{
default:
continue;
case N_LSYM:
case N_PSYM:
VMS_local_stab_Parse (s1P);
break;
case N_RSYM:
VMS_RSYM_Parse (s1P, Current_Routine, Text_Psect);
break;
}
}
}
static symbolS *
Define_Routine (symbolS *s0P, int Level, symbolS *Current_Routine,
int Text_Psect)
{
symbolS *s1P;
valueT Offset;
int rcount = 0;
for (s1P = symbol_next (s0P); s1P != 0; s1P = symbol_next (s1P))
{
if (S_GET_RAW_TYPE (s1P) == N_FUN)
{
char *pnt = (char *) strchr (S_GET_NAME (s1P), ':') + 1;
if (*pnt == 'F' || *pnt == 'f') break;
}
if (!S_IS_DEBUG (s1P))
continue;
switch (S_GET_RAW_TYPE (s1P))
{
default:
continue;
case N_LBRAC:
if (Level != 0)
{
char str[10];
sprintf (str, "$%d", rcount++);
VMS_TBT_Block_Begin (s1P, Text_Psect, str);
}
Offset = S_GET_VALUE (s1P);
Define_Local_Symbols (s0P, s1P, Current_Routine, Text_Psect);
s1P = Define_Routine (s1P, Level + 1, Current_Routine, Text_Psect);
if (Level != 0)
VMS_TBT_Block_End (S_GET_VALUE (s1P) - Offset);
s0P = s1P;
break;
case N_RBRAC:
return s1P;
}
}
Define_Local_Symbols (s0P, (symbolS *)0, Current_Routine, Text_Psect);
return s1P;
}
#ifndef VMS
#include <sys/types.h>
#include <time.h>
static void get_VMS_time_on_unix (char *);
static void
get_VMS_time_on_unix (char *Now)
{
char *pnt;
time_t timeb;
time (&timeb);
pnt = ctime (&timeb);
pnt[3] = 0;
pnt[7] = 0;
pnt[10] = 0;
pnt[16] = 0;
pnt[24] = 0;
sprintf (Now, "%2s-%3s-%s %s", pnt + 8, pnt + 4, pnt + 20, pnt + 11);
}
#endif
static void
Write_VMS_MHD_Records (void)
{
const char *cp;
char *cp1;
int i;
#ifdef VMS
struct { unsigned short len, mbz; char *ptr; } Descriptor;
#endif
char Now[17+1];
Set_VMS_Object_File_Record (OBJ_S_C_HDR);
PUT_CHAR (OBJ_S_C_HDR);
PUT_CHAR (MHD_S_C_MHD);
PUT_CHAR (OBJ_S_C_STRLVL);
PUT_SHORT (sizeof (Object_Record_Buffer));
cp = out_file_name;
cp1 = Module_Name;
while (*cp)
{
if (*cp == ']' || *cp == '>' || *cp == ':' || *cp == '/')
{
cp1 = Module_Name;
cp++;
continue;
}
*cp1++ = TOUPPER (*cp++);
}
*cp1 = '\0';
while (--cp1 >= Module_Name)
if (*cp1 == '.')
*cp1 = '\0';
if (strlen (Module_Name) > 31)
{
if (flag_hash_long_names)
as_tsktsk (_("Module name truncated: %s\n"), Module_Name);
Module_Name[31] = '\0';
}
PUT_COUNTED_STRING (Module_Name);
PUT_COUNTED_STRING ("V1.0");
#ifndef VMS
get_VMS_time_on_unix (Now);
#else
Descriptor.len = sizeof Now - 1;
Descriptor.mbz = 0;
Descriptor.ptr = Now;
(void) sys$asctim ((unsigned short *)0, &Descriptor, (long *)0, 0);
#endif
for (i = 0; i < 17; i++)
PUT_CHAR (Now[i]);
for (i = 0; i < 17; i++)
PUT_CHAR (0);
Flush_VMS_Object_Record_Buffer ();
PUT_CHAR (OBJ_S_C_HDR);
PUT_CHAR (MHD_S_C_LNM);
cp = compiler_version_string;
if (cp == 0)
{
cp = "GNU AS V";
while (*cp)
PUT_CHAR (*cp++);
cp = VERSION;
}
while (*cp >= ' ')
PUT_CHAR (*cp++);
Flush_VMS_Object_Record_Buffer ();
}
static void
Write_VMS_EOM_Record (int Psect, valueT Offset)
{
Set_VMS_Object_File_Record (OBJ_S_C_EOM);
PUT_CHAR (OBJ_S_C_EOM);
PUT_CHAR (0);
if (Psect >= 0)
{
PUT_CHAR (Psect);
PUT_LONG (Offset);
}
Flush_VMS_Object_Record_Buffer ();
}
static int
hash_string (const char *ptr)
{
const unsigned char *p = (unsigned char *) ptr;
const unsigned char *end = p + strlen (ptr);
unsigned char c;
int hash = 0;
while (p != end)
{
c = *p++;
hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
}
return hash;
}
static void
VMS_Case_Hack_Symbol (const char *In, char *Out)
{
long int init;
long int result;
char *pnt = 0;
char *new_name;
const char *old_name;
int i;
int destructor = 0;
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'};
if ((In[0] == '_') && ((In[1] > '9') || (In[1] < '0')))
In++;
new_name = Out;
#if 0
if ((In[0] == '_') && (In[1] == '$') && (In[2] == '_'))
destructor = 1;
#endif
result = (strlen (In) > 23) ? hash_string (In) : 0;
if (HAS_PSECT_ATTRIBUTES (In))
{
In += PSECT_ATTRIBUTES_STRING_LENGTH;
while (*In)
{
if ((In[0] == '$') && (In[1] == '$'))
{
In += 2;
break;
}
In++;
}
}
old_name = In;
#if 0
if (strlen (In) > 31 && flag_hash_long_names)
as_tsktsk ("Symbol name truncated: %s\n", In);
#endif
i = 23;
while (*In && (--i >= 0))
{
Case_Hack_Bits <<= 1;
if (*In == '$')
Saw_Dollar = 1;
if ((destructor == 1) && (i == 21))
Saw_Dollar = 0;
switch (vms_name_mapping)
{
case 0:
if (ISUPPER (*In))
{
*Out++ = *In++;
Case_Hack_Bits |= 1;
}
else
*Out++ = TOUPPER (*In++);
break;
case 3:
*Out++ = *In++;
break;
case 2:
if (ISLOWER (*In))
*Out++ = *In++;
else
*Out++ = TOLOWER (*In++);
break;
}
}
if (flag_no_hash_mixed_case || Saw_Dollar)
Case_Hack_Bits = 0;
if (*In)
{
pnt = Out;
truncate = 1;
if (Case_Hack_Bits == 0)
{
for (i = 0; (In[i] != 0) && (i < 8); i++)
if (ISUPPER (In[i]) && !Saw_Dollar && !flag_no_hash_mixed_case)
break;
if (In[i] == 0)
truncate = 0;
if ((i == 8) || (In[i] == 0))
{
i = 8;
while ((--i >= 0) && (*In))
switch (vms_name_mapping){
case 0: *Out++ = TOUPPER (*In++);
break;
case 3: *Out++ = *In++;
break;
case 2: *Out++ = TOLOWER (*In++);
break;
}
}
}
}
if (!flag_hash_long_names)
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;
*Out++ = '_';
for (i = 0; i < 7; i++)
{
init = result & 0x01f;
*Out++ = (init < 10) ? ('0' + init) : ('A' + init - 10);
result = result >> 5;
}
}
}
*Out = 0;
if (truncate == 1 && flag_hash_long_names && flag_show_after_trunc)
as_tsktsk (_("Symbol %s replaced by %s\n"), old_name, new_name);
}
#define GLOBALSYMBOL_BIT 0x10000
#define GLOBALVALUE_BIT 0x20000
static void
VMS_Modify_Psect_Attributes (const char *Name, int *Attribute_Pointer)
{
int i;
const char *cp;
int Negate;
static const struct
{
const char *Name;
int Value;
} Attributes[] =
{
{"PIC", GPS_S_M_PIC},
{"LIB", GPS_S_M_LIB},
{"OVR", GPS_S_M_OVR},
{"REL", GPS_S_M_REL},
{"GBL", GPS_S_M_GBL},
{"SHR", GPS_S_M_SHR},
{"EXE", GPS_S_M_EXE},
{"RD", GPS_S_M_RD},
{"WRT", GPS_S_M_WRT},
{"VEC", GPS_S_M_VEC},
{"GLOBALSYMBOL", GLOBALSYMBOL_BIT},
{"GLOBALVALUE", GLOBALVALUE_BIT},
{0, 0}
};
if (*Name == '_')
Name++;
if (!HAS_PSECT_ATTRIBUTES (Name))
return;
Name += PSECT_ATTRIBUTES_STRING_LENGTH;
while (*Name != '$')
{
Negate = 0;
if ((Name[0] == 'N') && (Name[1] == 'O'))
{
Negate = 1;
Name += 2;
}
cp = Name;
while (*cp && (*cp != '_') && (*cp != '$'))
cp++;
for (i = 0; Attributes[i].Name; i++)
{
if (strncmp (Name, Attributes[i].Name, cp - Name) == 0)
{
if (Negate)
*Attribute_Pointer &=
~Attributes[i].Value;
else
*Attribute_Pointer |=
Attributes[i].Value;
break;
}
}
Name = cp;
if (*Name == '_')
Name++;
}
}
#define GBLSYM_REF 0
#define GBLSYM_DEF 1
#define GBLSYM_VAL 2
#define GBLSYM_LCL 4
#define GBLSYM_WEAK 8
static void
VMS_Global_Symbol_Spec (const char *Name, int Psect_Number, int Psect_Offset, int Flags)
{
char Local[32];
Set_VMS_Object_File_Record (OBJ_S_C_GSD);
if (Object_Record_Offset == 0)
PUT_CHAR (OBJ_S_C_GSD);
PUT_CHAR ((Flags & GBLSYM_LCL) != 0 ? GSD_S_C_LSY :
((unsigned) Psect_Number <= 255) ? GSD_S_C_SYM : GSD_S_C_SYMW);
PUT_CHAR (0);
if ((Flags & GBLSYM_DEF) == 0)
{
PUT_SHORT (((Flags & GBLSYM_VAL) == 0) ? GSY_S_M_REL : 0);
if ((Flags & GBLSYM_LCL) != 0)
PUT_SHORT (Current_Environment);
}
else
{
int sym_flags;
sym_flags = GSY_S_M_DEF;
if (Flags & GBLSYM_WEAK)
sym_flags |= GSY_S_M_WEAK;
if ((Flags & GBLSYM_VAL) == 0)
sym_flags |= GSY_S_M_REL;
PUT_SHORT (sym_flags);
if ((Flags & GBLSYM_LCL) != 0)
PUT_SHORT (Current_Environment);
if ((Flags & GBLSYM_LCL) == 0 && (unsigned) Psect_Number <= 255)
PUT_CHAR (Psect_Number);
else
PUT_SHORT (Psect_Number);
PUT_LONG (Psect_Offset);
}
VMS_Case_Hack_Symbol (Name, Local);
PUT_COUNTED_STRING (Local);
if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
Flush_VMS_Object_Record_Buffer ();
}
static void
VMS_Local_Environment_Setup (const char *Env_Name)
{
Set_VMS_Object_File_Record (OBJ_S_C_GSD);
if (Object_Record_Offset == 0)
PUT_CHAR (OBJ_S_C_GSD);
PUT_CHAR (GSD_S_C_ENV);
++Current_Environment;
PUT_SHORT (ENV_S_M_DEF);
PUT_SHORT (0);
if (!Env_Name) Env_Name = "";
PUT_COUNTED_STRING ((char *)Env_Name);
if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
Flush_VMS_Object_Record_Buffer ();
}
static int
VMS_Psect_Spec (const char *Name, int Size, enum ps_type Type, struct VMS_Symbol *vsp)
{
char Local[32];
int Psect_Attributes;
switch (Type)
{
case ps_TEXT:
Psect_Attributes = (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_SHR|GPS_S_M_EXE
|GPS_S_M_RD);
break;
case ps_DATA:
Psect_Attributes = (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_RD|GPS_S_M_WRT);
break;
case ps_COMMON:
Psect_Attributes = (GPS_S_M_PIC|GPS_S_M_OVR|GPS_S_M_REL|GPS_S_M_GBL
|GPS_S_M_RD|GPS_S_M_WRT);
break;
case ps_CONST:
Psect_Attributes = (GPS_S_M_PIC|GPS_S_M_OVR|GPS_S_M_REL|GPS_S_M_GBL
|GPS_S_M_RD);
break;
case ps_CTORS:
Psect_Attributes = (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_GBL|GPS_S_M_RD);
break;
case ps_DTORS:
Psect_Attributes = (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_GBL|GPS_S_M_RD);
break;
default:
error (_("Unknown VMS psect type (%ld)"), (long) Type);
break;
}
if (vsp && S_GET_TYPE (vsp->Symbol) == N_ABS)
Psect_Attributes |= GLOBALVALUE_BIT;
else if (HAS_PSECT_ATTRIBUTES (Name))
VMS_Modify_Psect_Attributes (Name, &Psect_Attributes);
if ((Psect_Attributes & GLOBALVALUE_BIT) != 0)
{
vsp->Psect_Index = -1;
S_SET_TYPE (vsp->Symbol, N_UNDF);
return 1;
}
if ((Psect_Attributes & GLOBALSYMBOL_BIT) != 0)
{
switch (S_GET_RAW_TYPE (vsp->Symbol))
{
case N_UNDF | N_EXT:
VMS_Global_Symbol_Spec (Name, vsp->Psect_Index,
vsp->Psect_Offset, GBLSYM_REF);
vsp->Psect_Index = -1;
S_SET_TYPE (vsp->Symbol, N_UNDF);
return 1;
case N_DATA | N_EXT:
VMS_Global_Symbol_Spec (Name, vsp->Psect_Index,
vsp->Psect_Offset, GBLSYM_DEF);
break;
default:
as_fatal (_("Globalsymbol attribute for symbol %s was unexpected."),
Name);
break;
}
}
Psect_Attributes &= 0xffff;
Set_VMS_Object_File_Record (OBJ_S_C_GSD);
if (Object_Record_Offset == 0)
PUT_CHAR (OBJ_S_C_GSD);
PUT_CHAR (GSD_S_C_PSC);
PUT_CHAR (2);
PUT_SHORT (Psect_Attributes);
PUT_LONG (Size);
VMS_Case_Hack_Symbol (Name, Local);
PUT_COUNTED_STRING (Local);
if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
Flush_VMS_Object_Record_Buffer ();
return 0;
}
static offsetT
VMS_Initialized_Data_Size (symbolS *s0P, unsigned End_Of_Data)
{
symbolS *s1P;
valueT s0P_val = S_GET_VALUE (s0P), s1P_val,
nearest_val = (valueT) End_Of_Data;
for (s1P = symbol_rootP; s1P; s1P = symbol_next (s1P))
{
if (S_GET_TYPE (s1P) != N_DATA)
continue;
s1P_val = S_GET_VALUE (s1P);
if (s1P_val > s0P_val && s1P_val < nearest_val)
nearest_val = s1P_val;
}
return (offsetT) (nearest_val - s0P_val);
}
static void
VMS_Emit_Globalvalues (unsigned text_siz, unsigned data_siz,
char *Data_Segment)
{
symbolS *sp;
char *stripped_name, *Name;
int Size;
int Psect_Attributes;
int globalvalue;
int typ, abstyp;
for (sp = symbol_rootP; sp; sp = sp->sy_next)
{
typ = S_GET_RAW_TYPE (sp);
abstyp = ((typ & ~N_EXT) == N_ABS);
if (!abstyp &&
typ != (N_DATA | N_EXT) &&
typ != (N_UNDF | N_EXT))
continue;
Name = S_GET_NAME (sp);
if (abstyp)
{
stripped_name = 0;
Psect_Attributes = GLOBALVALUE_BIT;
}
else if (HAS_PSECT_ATTRIBUTES (Name))
{
stripped_name = xmalloc (strlen (Name) + 1);
strcpy (stripped_name, Name);
Psect_Attributes = 0;
VMS_Modify_Psect_Attributes (stripped_name, &Psect_Attributes);
}
else
continue;
if ((Psect_Attributes & GLOBALVALUE_BIT) != 0)
{
switch (typ)
{
case N_ABS:
if (Current_Environment < 0)
VMS_Local_Environment_Setup (".N_ABS");
VMS_Global_Symbol_Spec (Name, 0,
S_GET_VALUE (sp),
GBLSYM_DEF|GBLSYM_VAL|GBLSYM_LCL);
break;
case N_ABS | N_EXT:
VMS_Global_Symbol_Spec (Name, 0,
S_GET_VALUE (sp),
GBLSYM_DEF|GBLSYM_VAL);
break;
case N_UNDF | N_EXT:
VMS_Global_Symbol_Spec (stripped_name, 0, 0, GBLSYM_VAL);
break;
case N_DATA | N_EXT:
Size = VMS_Initialized_Data_Size (sp, text_siz + data_siz);
if (Size > 4)
error (_("Invalid data type for globalvalue"));
globalvalue = md_chars_to_number (Data_Segment +
S_GET_VALUE (sp) - text_siz , Size);
VMS_Global_Symbol_Spec (stripped_name, 0, 0, GBLSYM_VAL);
VMS_Global_Symbol_Spec (stripped_name, 0, globalvalue,
GBLSYM_DEF|GBLSYM_VAL);
VMS_Global_Symbol_Spec (stripped_name, 0, globalvalue,
GBLSYM_DEF|GBLSYM_VAL);
break;
default:
as_warn (_("Invalid globalvalue of %s"), stripped_name);
break;
}
}
if (stripped_name)
free (stripped_name);
}
}
static void
VMS_Procedure_Entry_Pt (char *Name, int Psect_Number, int Psect_Offset,
int Entry_Mask)
{
char Local[32];
Set_VMS_Object_File_Record (OBJ_S_C_GSD);
if (Object_Record_Offset == 0)
PUT_CHAR (OBJ_S_C_GSD);
PUT_CHAR (((unsigned) Psect_Number <= 255) ? GSD_S_C_EPM : GSD_S_C_EPMW);
PUT_CHAR (0);
PUT_SHORT (GSY_S_M_DEF | GSY_S_M_REL);
if ((unsigned) Psect_Number <= 255)
PUT_CHAR (Psect_Number);
else
PUT_SHORT (Psect_Number);
PUT_LONG (Psect_Offset);
PUT_SHORT (Entry_Mask);
VMS_Case_Hack_Symbol (Name, Local);
PUT_COUNTED_STRING (Local);
if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
Flush_VMS_Object_Record_Buffer ();
}
static void
VMS_Set_Psect (int Psect_Index, int Offset, int Record_Type)
{
Set_VMS_Object_File_Record (Record_Type);
if (Object_Record_Offset == 0)
PUT_CHAR (Record_Type);
vms_tir_stack_psect (Psect_Index, Offset, 0);
PUT_CHAR (TIR_S_C_CTL_SETRB);
if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
Flush_VMS_Object_Record_Buffer ();
}
static void
VMS_Store_Repeated_Data (int Repeat_Count, char *Pointer, int Size,
int Record_Type)
{
switch (Size)
{
case 4:
if (Pointer[3] != 0 || Pointer[2] != 0) break;
case 2:
if (Pointer[1] != 0) break;
case 1:
if (Pointer[0] != 0) break;
return;
default:
break;
}
if (Size > 255)
{
while (--Repeat_Count >= 0)
VMS_Store_Immediate_Data (Pointer, Size, Record_Type);
return;
}
Set_VMS_Object_File_Record (Record_Type);
if (Object_Record_Offset == 0)
PUT_CHAR (Record_Type);
PUT_CHAR (TIR_S_C_STA_LW);
PUT_LONG (Repeat_Count);
PUT_CHAR (TIR_S_C_STO_RIVB);
PUT_CHAR (Size);
while (--Size >= 0)
PUT_CHAR (*Pointer++);
if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
Flush_VMS_Object_Record_Buffer ();
}
static void
VMS_Store_PIC_Symbol_Reference (symbolS *Symbol, int Offset, int PC_Relative,
int Psect, int Psect_Offset, int Record_Type)
{
struct VMS_Symbol *vsp = Symbol->sy_obj;
char Local[32];
int local_sym = 0;
Set_VMS_Object_File_Record (Record_Type);
if (Object_Record_Offset == 0)
PUT_CHAR (Record_Type);
VMS_Set_Psect (Psect,
PC_Relative ? Psect_Offset - 1 : Psect_Offset,
Record_Type);
if (Object_Record_Offset == 0)
PUT_CHAR (Record_Type);
switch (S_GET_RAW_TYPE (Symbol))
{
case N_ABS:
local_sym = 1;
case N_ABS | N_EXT:
#ifdef NOT_VAX_11_C_COMPATIBLE
case N_UNDF | N_EXT:
case N_DATA | N_EXT:
#endif
case N_UNDF:
case N_TEXT | N_EXT:
VMS_Case_Hack_Symbol (S_GET_NAME (Symbol), Local);
if (!local_sym)
{
PUT_CHAR (TIR_S_C_STA_GBL);
}
else
{
PUT_CHAR (TIR_S_C_STA_LSY);
PUT_SHORT (Current_Environment);
}
PUT_COUNTED_STRING (Local);
if (Offset)
{
PUT_CHAR (TIR_S_C_STA_LW);
PUT_LONG (Offset);
PUT_CHAR (TIR_S_C_OPR_ADD);
}
break;
case N_BSS:
vms_tir_stack_psect (vsp->Psect_Index,
vsp->Psect_Offset + Offset,
0);
break;
case N_TEXT:
vms_tir_stack_psect (vsp->Psect_Index,
S_GET_VALUE (Symbol) + Offset,
0);
break;
case N_DATA:
#ifndef NOT_VAX_11_C_COMPATIBLE
case N_UNDF | N_EXT:
case N_DATA | N_EXT:
#endif
vms_tir_stack_psect (vsp->Psect_Index,
vsp->Psect_Offset + Offset,
0);
break;
}
PUT_CHAR (PC_Relative ? TIR_S_C_STO_PICR : TIR_S_C_STO_PIDR);
if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
Flush_VMS_Object_Record_Buffer ();
}
static void
VMS_Fix_Indirect_Reference (int Text_Psect, addressT Offset,
fragS *fragP, fragS *text_frag_root)
{
Offset--;
if ((Offset < fragP->fr_address) ||
(Offset >= (fragP->fr_address + fragP->fr_fix)))
{
for (fragP = text_frag_root; fragP; fragP = fragP->fr_next)
{
if ((Offset >= fragP->fr_address) &&
(Offset < (fragP->fr_address + fragP->fr_fix)))
break;
}
if (fragP == 0)
error (_("Couldn't find fixup fragment when checking for indirect reference"));
}
if (fragP->fr_literal[Offset - fragP->fr_address] == (char) 0xff)
{
static char Address_Mode = (char) 0xff;
VMS_Set_Psect (Text_Psect, Offset, OBJ_S_C_TIR);
VMS_Store_Immediate_Data (&Address_Mode, 1, OBJ_S_C_TIR);
}
}
void
vms_check_for_main (void)
{
symbolS *symbolP;
#ifdef HACK_DEC_C_STARTUP
struct frchain *frchainP;
fragS *fragP;
fragS **prev_fragPP;
struct fix *fixP;
fragS *New_Frag;
int i;
#endif
symbolP = (symbolS *) symbol_find ("_main");
if (symbolP && !S_IS_DEBUG (symbolP) &&
S_IS_EXTERNAL (symbolP) && (S_GET_TYPE (symbolP) == N_TEXT))
{
#ifdef HACK_DEC_C_STARTUP
if (!flag_hash_long_names)
{
#endif
Entry_Point_Symbol = symbolP;
#ifdef HACK_DEC_C_STARTUP
}
else
{
frchainP = frchain_root;
while (frchainP)
{
prev_fragPP = &frchainP->frch_root;
fragP = frchainP->frch_root;
while (fragP && (fragP != frchainP->frch_last))
{
if (fragP == symbolP->sy_frag)
{
New_Frag =
xmalloc (sizeof (*New_Frag) +
fragP->fr_fix +
fragP->fr_var +
5);
*New_Frag = *fragP;
New_Frag->fr_fix += 6;
New_Frag->fr_literal[0] = fragP->fr_literal[0];
New_Frag->fr_literal[1] = fragP->fr_literal[1];
New_Frag->fr_literal[2] = 0x16;
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];
*prev_fragPP = New_Frag;
Entry_Point_Symbol = symbolP;
for (fixP = text_fix_root; fixP; fixP = fixP->fx_next)
{
if (fixP->fx_frag == fragP)
{
fixP->fx_frag = New_Frag;
if (fixP->fx_where >= 2)
fixP->fx_where += 6;
}
}
for (symbolP = symbol_rootP;
symbolP;
symbolP = symbol_next (symbolP))
{
if (symbolP->sy_frag == fragP)
{
symbolP->sy_frag = New_Frag;
if (S_GET_VALUE (symbolP) >= 2)
S_SET_VALUE (symbolP,
S_GET_VALUE (symbolP) + 6);
}
}
symbolP = xmalloc (sizeof (*symbolP));
S_SET_NAME (symbolP, "_C$MAIN_ARGS");
S_SET_TYPE (symbolP, N_UNDF);
S_SET_OTHER (symbolP, 0);
S_SET_DESC (symbolP, 0);
S_SET_VALUE (symbolP, 0);
symbolP->sy_name_offset = 0;
symbolP->sy_number = 0;
symbolP->sy_obj = 0;
symbolP->sy_frag = New_Frag;
symbolP->sy_resolved = 0;
symbolP->sy_resolving = 0;
symbol_append (symbol_rootP, symbolP,
&symbol_rootP, &symbol_lastP);
symbol_rootP = symbolP;
fixP = 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 = 4;
fixP->fx_pcrel = 1;
fixP->fx_next = text_fix_root;
text_fix_root = fixP;
frchainP = 0;
break;
}
prev_fragPP = &fragP->fr_next;
fragP = fragP->fr_next;
}
if (frchainP)
frchainP = frchainP->frch_next;
}
}
#endif
}
}
static
struct vms_obj_state
{
int psect_number;
int text_psect;
int data_psect;
int bss_psect;
int ctors_psect;
int dtors_psect;
int local_initd_data_size;
char *data_segment;
} vms_obj_state;
#define Psect_Number vms_obj_state.psect_number
#define Text_Psect vms_obj_state.text_psect
#define Data_Psect vms_obj_state.data_psect
#define Bss_Psect vms_obj_state.bss_psect
#define Ctors_Psect vms_obj_state.ctors_psect
#define Dtors_Psect vms_obj_state.dtors_psect
#define Local_Initd_Data_Size vms_obj_state.local_initd_data_size
#define Data_Segment vms_obj_state.data_segment
#define IS_GXX_VTABLE(symP) (strncmp (S_GET_NAME (symP), "__vt.", 5) == 0)
#define IS_GXX_XTOR(symP) (strncmp (S_GET_NAME (symP), "__GLOBAL_.", 10) == 0)
#define XTOR_SIZE 4
static void
vms_fixup_text_section (unsigned text_siz ATTRIBUTE_UNUSED,
struct frag *text_frag_root,
struct frag *data_frag_root)
{
fragS *fragP;
struct fix *fixP;
offsetT dif;
for (fragP = text_frag_root; fragP; fragP = fragP->fr_next)
{
if (fragP == data_frag_root)
break;
if ((fragP->fr_fix == 0) && (fragP->fr_var == 0))
continue;
VMS_Set_Psect (Text_Psect, fragP->fr_address, OBJ_S_C_TIR);
if (fragP->fr_fix)
VMS_Store_Immediate_Data (fragP->fr_literal,
fragP->fr_fix,
OBJ_S_C_TIR);
if (fragP->fr_var && fragP->fr_offset)
VMS_Store_Repeated_Data (fragP->fr_offset,
fragP->fr_literal + fragP->fr_fix,
fragP->fr_var,
OBJ_S_C_TIR);
}
for (fixP = text_fix_root; fixP; fixP = fixP->fx_next)
{
if (fixP->fx_subsy && fixP->fx_addsy)
{
if (S_GET_RAW_TYPE (fixP->fx_subsy) !=
S_GET_RAW_TYPE (fixP->fx_addsy))
error (_("Fixup data addsy and subsy don't have the same type"));
if ((S_GET_TYPE (fixP->fx_addsy) != N_DATA) &&
(S_GET_TYPE (fixP->fx_addsy) != N_TEXT))
error (_("Fixup data addsy and subsy don't have an appropriate type"));
if (fixP->fx_pcrel)
error (_("Fixup data is erroneously \"pcrel\""));
dif = S_GET_VALUE (fixP->fx_addsy) - S_GET_VALUE (fixP->fx_subsy);
md_number_to_chars (Local, (valueT)dif, fixP->fx_size);
VMS_Set_Psect (Text_Psect,
fixP->fx_where + fixP->fx_frag->fr_address,
OBJ_S_C_TIR);
VMS_Store_Immediate_Data (Local,
fixP->fx_size,
OBJ_S_C_TIR);
continue;
}
if (fixP->fx_size != 4)
error (_("Fixup datum is not a longword"));
if (fixP->fx_addsy == 0)
error (_("Fixup datum is not \"fixP->fx_addsy\""));
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_S_C_TIR);
if (fixP->fx_pcrel)
VMS_Fix_Indirect_Reference (Text_Psect,
fixP->fx_where + fixP->fx_frag->fr_address,
fixP->fx_frag,
text_frag_root);
}
}
static void
synthesize_data_segment (unsigned data_siz, unsigned text_siz,
struct frag *data_frag_root)
{
fragS *fragP;
char *fill_literal;
long fill_size, count, i;
Data_Segment = xmalloc (data_siz);
for (fragP = data_frag_root; fragP; fragP = fragP->fr_next)
{
i = fragP->fr_address - text_siz;
if (fragP->fr_fix)
memcpy (Data_Segment + i, fragP->fr_literal, fragP->fr_fix);
i += fragP->fr_fix;
if ((fill_size = fragP->fr_var) != 0)
{
fill_literal = fragP->fr_literal + fragP->fr_fix;
for (count = fragP->fr_offset; count; count--)
{
memcpy (Data_Segment + i, fill_literal, fill_size);
i += fill_size;
}
}
}
}
static void
vms_fixup_data_section (unsigned int data_siz ATTRIBUTE_UNUSED,
unsigned int text_siz)
{
struct VMS_Symbol *vsp;
struct fix *fixP;
symbolS *sp;
addressT fr_address;
offsetT dif;
valueT val;
for (vsp = VMS_Symbols; vsp; vsp = vsp->Next)
{
if (S_GET_TYPE (vsp->Symbol) != N_DATA)
continue;
VMS_Set_Psect (vsp->Psect_Index,
vsp->Psect_Offset,
OBJ_S_C_TIR);
val = S_GET_VALUE (vsp->Symbol);
VMS_Store_Immediate_Data (Data_Segment + val - text_siz,
vsp->Size,
OBJ_S_C_TIR);
}
for (fixP = data_fix_root; fixP; fixP = fixP->fx_next)
{
for (vsp = VMS_Symbols; vsp; vsp = vsp->Next)
{
sp = vsp->Symbol;
if (S_GET_TYPE (sp) != N_DATA)
continue;
val = S_GET_VALUE (sp);
fr_address = fixP->fx_frag->fr_address;
if (val > fixP->fx_where + fr_address)
continue;
if (val + vsp->Size <= fixP->fx_where + fr_address)
continue;
if (fixP->fx_subsy && fixP->fx_addsy)
{
if (S_GET_RAW_TYPE (fixP->fx_subsy) !=
S_GET_RAW_TYPE (fixP->fx_addsy))
error (_("Fixup data addsy and subsy don't have the same type"));
if ((S_GET_TYPE (fixP->fx_addsy) != N_DATA) &&
(S_GET_TYPE (fixP->fx_addsy) != N_TEXT))
error (_("Fixup data addsy and subsy don't have an appropriate type"));
if (fixP->fx_pcrel)
error (_("Fixup data is erroneously \"pcrel\""));
dif = S_GET_VALUE (fixP->fx_addsy) - S_GET_VALUE (fixP->fx_subsy);
md_number_to_chars (Local, (valueT)dif, fixP->fx_size);
VMS_Set_Psect (vsp->Psect_Index,
fr_address + fixP->fx_where
- val + vsp->Psect_Offset,
OBJ_S_C_TIR);
VMS_Store_Immediate_Data (Local,
fixP->fx_size,
OBJ_S_C_TIR);
break;
}
if (fixP->fx_size != 4)
error (_("Fixup datum is not a longword"));
if (fixP->fx_addsy == 0)
error (_("Fixup datum is not \"fixP->fx_addsy\""));
VMS_Store_PIC_Symbol_Reference (fixP->fx_addsy,
fixP->fx_offset,
fixP->fx_pcrel,
vsp->Psect_Index,
fr_address + fixP->fx_where
- val + vsp->Psect_Offset,
OBJ_S_C_TIR);
break;
}
}
}
static void
vms_fixup_xtors_section (struct VMS_Symbol *symbols,
int sect_no ATTRIBUTE_UNUSED)
{
struct VMS_Symbol *vsp;
for (vsp = symbols; vsp; vsp = vsp->Next)
{
symbolS *sp;
VMS_Set_Psect (vsp->Psect_Index, vsp->Psect_Offset, OBJ_S_C_TIR);
sp = vsp->Symbol;
VMS_Set_Data (Text_Psect, S_GET_VALUE (sp), OBJ_S_C_TIR, 0);
}
if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
Flush_VMS_Object_Record_Buffer ();
}
static void
global_symbol_directory (unsigned text_siz, unsigned data_siz)
{
fragS *fragP;
symbolS *sp;
struct VMS_Symbol *vsp;
int Globalref, define_as_global_symbol;
#if 0
for (sp = symbol_rootP; sp; sp = symbol_next (sp))
if (S_GET_RAW_TYPE (sp) == N_UNDF && IS_GXX_VTABLE (sp))
{
S_SET_TYPE (sp, N_UNDF | N_EXT);
S_SET_OTHER (sp, 1);
as_warn (_("g++ wrote an extern reference to `%s' as a routine.\nI will fix it, but I hope that it was note really a routine."),
S_GET_NAME (sp));
}
#endif
for (sp = symbol_rootP; sp; sp = symbol_next (sp))
{
define_as_global_symbol = 0;
vsp = 0;
switch (S_GET_RAW_TYPE (sp))
{
case N_UNDF | N_EXT:
vsp = xmalloc (sizeof *vsp);
vsp->Symbol = sp;
vsp->Size = S_GET_VALUE (sp);
vsp->Psect_Index = Psect_Number++;
vsp->Psect_Offset = 0;
vsp->Next = VMS_Symbols;
VMS_Symbols = vsp;
sp->sy_obj = vsp;
Globalref = VMS_Psect_Spec (S_GET_NAME (sp),
vsp->Size,
S_GET_OTHER (sp) ? ps_CONST : ps_COMMON,
vsp);
if (Globalref)
Psect_Number--;
#ifdef NOT_VAX_11_C_COMPATIBLE
define_as_global_symbol = 1;
#else
define_as_global_symbol = IS_GXX_VTABLE (sp);
#endif
break;
case N_BSS:
vsp = xmalloc (sizeof *vsp);
vsp->Symbol = sp;
vsp->Size = 0;
vsp->Psect_Index = Bss_Psect;
vsp->Psect_Offset = S_GET_VALUE (sp) - bss_address_frag.fr_address;
vsp->Next = VMS_Symbols;
VMS_Symbols = vsp;
sp->sy_obj = vsp;
break;
case N_DATA | N_EXT:
vsp = 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_obj = vsp;
Globalref = VMS_Psect_Spec (S_GET_NAME (sp),
vsp->Size,
S_GET_OTHER (sp) ? ps_CONST : ps_COMMON,
vsp);
if (Globalref)
Psect_Number--;
#ifdef NOT_VAX_11_C_COMPATIBLE
define_as_global_symbol = 1;
#else
define_as_global_symbol = IS_GXX_VTABLE (sp);
#endif
break;
case N_DATA:
{
char *sym_name = S_GET_NAME (sp);
if (sym_name && strcmp (sym_name, FAKE_LABEL_NAME) == 0)
break;
vsp = 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_Initd_Data_Size;
Local_Initd_Data_Size += vsp->Size;
vsp->Next = VMS_Symbols;
VMS_Symbols = vsp;
sp->sy_obj = vsp;
}
break;
case N_TEXT | N_EXT:
{
if (IS_GXX_XTOR (sp))
{
vsp = xmalloc (sizeof *vsp);
vsp->Symbol = sp;
vsp->Size = XTOR_SIZE;
sp->sy_obj = vsp;
switch ((S_GET_NAME (sp))[10])
{
case 'I':
vsp->Psect_Index = Ctors_Psect;
vsp->Psect_Offset = (Ctors_Symbols==0)?0:(Ctors_Symbols->Psect_Offset+XTOR_SIZE);
vsp->Next = Ctors_Symbols;
Ctors_Symbols = vsp;
break;
case 'D':
vsp->Psect_Index = Dtors_Psect;
vsp->Psect_Offset = (Dtors_Symbols==0)?0:(Dtors_Symbols->Psect_Offset+XTOR_SIZE);
vsp->Next = Dtors_Symbols;
Dtors_Symbols = vsp;
break;
case 'G':
as_warn (_("Can't handle global xtors symbols yet."));
break;
default:
as_warn (_("Unknown %s"), S_GET_NAME (sp));
break;
}
}
else
{
unsigned short Entry_Mask;
fragP = sp->sy_frag;
while (fragP && fragP->fr_type == rs_fill && fragP->fr_fix == 0)
fragP = fragP->fr_next;
if (fragP->fr_fix < 2)
abort ();
Entry_Mask = (fragP->fr_literal[0] & 0x00ff) |
((fragP->fr_literal[1] & 0x00ff) << 8);
VMS_Procedure_Entry_Pt (S_GET_NAME (sp),
Text_Psect,
S_GET_VALUE (sp),
Entry_Mask);
}
break;
}
case N_TEXT:
if (Text_Psect != -1)
{
vsp = xmalloc (sizeof *vsp);
vsp->Symbol = sp;
vsp->Size = 0;
vsp->Psect_Index = Text_Psect;
vsp->Psect_Offset = S_GET_VALUE (sp);
vsp->Next = VMS_Symbols;
VMS_Symbols = vsp;
sp->sy_obj = vsp;
}
break;
case N_UNDF:
VMS_Global_Symbol_Spec (S_GET_NAME (sp),
0,
0,
GBLSYM_REF);
break;
case N_ABS:
case N_ABS | N_EXT:
vsp = xmalloc (sizeof *vsp);
vsp->Symbol = sp;
vsp->Size = 4;
vsp->Psect_Index = 0;
vsp->Psect_Offset = S_GET_VALUE (sp);
vsp->Next = VMS_Symbols;
VMS_Symbols = vsp;
sp->sy_obj = vsp;
break;
default:
if (S_IS_DEBUG (sp) || (S_GET_TYPE (sp) == 22))
break;
as_tsktsk (_("unhandled stab type %d"), S_GET_TYPE (sp));
break;
}
if (define_as_global_symbol)
VMS_Global_Symbol_Spec (S_GET_NAME (sp),
vsp->Psect_Index,
0,
GBLSYM_DEF);
}
}
static void
local_symbols_DST (symbolS *s0P, symbolS *Current_Routine)
{
symbolS *s1P;
char *s0P_name, *pnt0, *pnt1;
s0P_name = S_GET_NAME (s0P);
if (*s0P_name++ != '_')
return;
for (s1P = Current_Routine; s1P; s1P = symbol_next (s1P))
{
#if 0
if (!S_IS_DEBUG (s1P))
continue;
#endif
if (S_GET_RAW_TYPE (s1P) != N_FUN)
continue;
pnt0 = s0P_name;
pnt1 = S_GET_NAME (s1P);
while (*pnt0++ == *pnt1++)
{
}
if ((*pnt1 == 'F' || *pnt1 == 'f') && *--pnt1 == ':' && *--pnt0 == '\0')
{
Define_Routine (s1P, 0, Current_Routine, Text_Psect);
return;
}
}
}
static void
vms_build_DST (unsigned text_siz)
{
symbolS *symbolP;
symbolS *Current_Routine = 0;
struct input_file *Cur_File = 0;
offsetT Cur_Offset = -1;
int Cur_Line_Number = 0;
int File_Number = 0;
int Debugger_Offset = 0;
int file_available;
int dsc;
offsetT val;
VMS_TBT_Module_Begin ();
VMS_LSYM_Parse ();
for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
{
if (!S_IS_DEBUG (symbolP))
continue;
switch (S_GET_RAW_TYPE (symbolP))
{
case N_SLINE:
dsc = S_GET_DESC (symbolP);
if (dsc > Cur_File->max_line)
Cur_File->max_line = dsc;
if (dsc < Cur_File->min_line)
Cur_File->min_line = dsc;
break;
case N_SO:
Cur_File = find_file (symbolP);
Cur_File->flag = 1;
Cur_File->min_line = 1;
break;
case N_SOL:
Cur_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:
case N_STSYM:
VMS_STSYM_Parse (symbolP, Text_Psect);
break;
default:
break;
}
}
for (Cur_File = file_root; Cur_File; Cur_File = Cur_File->next)
{
if (Cur_File->max_line == 0)
continue;
if ((strncmp (Cur_File->name, "GNU_GXX_INCLUDE:", 16) == 0) &&
!flag_debug)
continue;
if ((strncmp (Cur_File->name, "GNU_CC_INCLUDE:", 15) == 0) &&
!flag_debug)
continue;
if (Cur_File->min_line > 2)
Cur_File->min_line -= 2;
Cur_File->offset = Debugger_Offset - Cur_File->min_line + 1;
Debugger_Offset += Cur_File->max_line - Cur_File->min_line + 1;
if (Cur_File->same_file_fpnt)
{
Cur_File->file_number = Cur_File->same_file_fpnt->file_number;
}
else
{
Cur_File->file_number = ++File_Number;
file_available = VMS_TBT_Source_File (Cur_File->name,
Cur_File->file_number);
if (!file_available)
{
Cur_File->file_number = 0;
File_Number--;
continue;
}
}
VMS_TBT_Source_Lines (Cur_File->file_number,
Cur_File->min_line,
Cur_File->max_line - Cur_File->min_line + 1);
}
Cur_File = (struct input_file *) NULL;
for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
{
if (!S_IS_DEBUG (symbolP) && S_GET_TYPE (symbolP) == N_TEXT)
{
if (*S_GET_NAME (symbolP) == 'L')
continue;
if (Current_Routine)
VMS_TBT_Routine_End (text_siz, Current_Routine);
if ((S_GET_OTHER (symbolP) & IN_DEFAULT_SECTION) != 0 &&
S_GET_VALUE (symbolP) == 0)
continue;
VMS_TBT_Routine_Begin (symbolP, Text_Psect);
Current_Routine = symbolP;
local_symbols_DST (symbolP, Current_Routine);
continue;
}
else if (S_IS_DEBUG (symbolP))
{
switch (S_GET_RAW_TYPE (symbolP))
{
case N_SLINE:
if (Cur_File->file_number == 0)
break;
val = S_GET_VALUE (symbolP);
if (val == Cur_Offset && Cur_File->file_number != 1)
break;
dsc = S_GET_DESC (symbolP) + Cur_File->offset;
S_SET_DESC (symbolP, dsc);
if (Cur_Offset == -1)
{
VMS_TBT_Line_PC_Correlation (dsc,
val,
Text_Psect,
0);
}
else if ((dsc - Cur_Line_Number) <= 0)
{
VMS_TBT_Line_PC_Correlation (0,
val - Cur_Offset,
0,
-1);
VMS_TBT_Line_PC_Correlation (dsc,
val,
Text_Psect,
0);
}
else
{
VMS_TBT_Line_PC_Correlation (dsc - Cur_Line_Number,
val - Cur_Offset,
0,
1);
}
Cur_Line_Number = dsc;
Cur_Offset = val;
break;
case N_SO:
Cur_File = find_file (symbolP);
break;
case N_SOL:
Cur_File = find_file (symbolP);
break;
default:
break;
}
}
}
if (Current_Routine)
{
VMS_TBT_Line_PC_Correlation (0,
text_siz - S_GET_VALUE (Current_Routine),
0,
-1);
VMS_TBT_Routine_End (text_siz, Current_Routine);
}
VMS_TBT_Module_End ();
}
void
vms_write_object_file (unsigned text_siz, unsigned data_siz, unsigned bss_siz,
fragS *text_frag_root, fragS *data_frag_root)
{
struct VMS_Symbol *vsp;
Psect_Number = 0;
Text_Psect = -1;
Data_Psect = -2;
Bss_Psect = -3;
Ctors_Psect = -4;
Dtors_Psect = -5;
Data_Segment = 0;
Local_Initd_Data_Size = 0;
Create_VMS_Object_File ();
Write_VMS_MHD_Records ();
if (data_siz > 0)
synthesize_data_segment (data_siz, text_siz, data_frag_root);
VMS_Emit_Globalvalues (text_siz, data_siz, Data_Segment);
Text_Psect = Psect_Number++;
VMS_Psect_Spec ("$code", text_siz, ps_TEXT, 0);
if (bss_siz > 0)
{
Bss_Psect = Psect_Number++;
VMS_Psect_Spec ("$uninitialized_data", bss_siz, ps_DATA, 0);
}
global_symbol_directory (text_siz, data_siz);
if (data_siz > 0 && Local_Initd_Data_Size > 0)
{
Data_Psect = Psect_Number++;
VMS_Psect_Spec ("$data", Local_Initd_Data_Size, ps_DATA, 0);
for (vsp = VMS_Symbols; vsp; vsp = vsp->Next)
if (vsp->Psect_Index < 0 && S_GET_RAW_TYPE (vsp->Symbol) == N_DATA)
vsp->Psect_Index = Data_Psect;
}
if (Ctors_Symbols != 0)
{
char *ps_name = "$ctors";
Ctors_Psect = Psect_Number++;
VMS_Psect_Spec (ps_name, Ctors_Symbols->Psect_Offset + XTOR_SIZE,
ps_CTORS, 0);
VMS_Global_Symbol_Spec (ps_name, Ctors_Psect,
0, GBLSYM_DEF|GBLSYM_WEAK);
for (vsp = Ctors_Symbols; vsp; vsp = vsp->Next)
vsp->Psect_Index = Ctors_Psect;
}
if (Dtors_Symbols != 0)
{
char *ps_name = "$dtors";
Dtors_Psect = Psect_Number++;
VMS_Psect_Spec (ps_name, Dtors_Symbols->Psect_Offset + XTOR_SIZE,
ps_DTORS, 0);
VMS_Global_Symbol_Spec (ps_name, Dtors_Psect,
0, GBLSYM_DEF|GBLSYM_WEAK);
for (vsp = Dtors_Symbols; vsp; vsp = vsp->Next)
vsp->Psect_Index = Dtors_Psect;
}
if (text_siz > 0)
vms_fixup_text_section (text_siz, text_frag_root, data_frag_root);
if (data_siz > 0)
{
vms_fixup_data_section (data_siz, text_siz);
free (Data_Segment), Data_Segment = 0;
}
if (Ctors_Symbols != 0)
vms_fixup_xtors_section (Ctors_Symbols, Ctors_Psect);
if (Dtors_Symbols != 0)
vms_fixup_xtors_section (Dtors_Symbols, Dtors_Psect);
vms_build_DST (text_siz);
if (Entry_Point_Symbol)
Write_VMS_EOM_Record (Text_Psect, S_GET_VALUE (Entry_Point_Symbol));
else
Write_VMS_EOM_Record (-1, (valueT) 0);
Close_VMS_Object_File ();
}