xref: /openbsd/gnu/usr.bin/binutils/gas/README-vms (revision cf2f2c56)
12159047fSniklas	This document explains a couple of things that are specific to VMS.
22159047fSniklasThere are currently two "chapters", the first deals with cross-assembly
32159047fSniklasissues, and the second deals with the VMS debugger and GNU-CC.
42159047fSniklas
52159047fSniklas
62159047fSniklas***********************************************************************
72159047fSniklas****************** Notes for Cross Assembly with VMS ******************
82159047fSniklas***********************************************************************
92159047fSniklas
102159047fSniklas	If you wish to build gas on a non-VMS system to cross-assemble,
112159047fSniklasyou should use:
122159047fSniklas
132159047fSniklasconfigure ${hosttype} -target=vms
142159047fSniklas
152159047fSniklasand then follow the usual procedure.  The object files generated on
162159047fSniklasUnix will be correct from a binary point of view, but the real trick is
172159047fSniklasgetting them to the VMS machine.  The format of the object file is
182159047fSniklasa variable-length record, but each record contains binary data.  gas
192159047fSniklaswrites the records in the same format that VMS would expect,
202159047fSniklasnamely a two-byte count followed by that number of bytes.
212159047fSniklas
222159047fSniklas	If you try to copy the file to a VMS system using ftp, the ftp
232159047fSniklasprotocol will screw up the file by looking for nulls (record terminator for
242159047fSniklasunix) and it will insert it's own record terminators at that point.  This
252159047fSniklaswill obviously corrupt the file.
262159047fSniklas
272159047fSniklas	If you try to transfer the file with ftp in binary mode, the
282159047fSniklasfile itself will not be corrupt, but VMS will think that the file contains
292159047fSniklasfixed-length records of 512 bytes.  You can use the public-domain FILE
302159047fSniklasutility to change this with a command like:
312159047fSniklas
322159047fSniklas$FILE foo.o/type=variable
332159047fSniklas
342159047fSniklasIf you do not have this utility available, the following program can be
352159047fSniklasused to perform this task:
362159047fSniklas
372159047fSniklas	#include <fab.h>
382159047fSniklas
392159047fSniklas	#define RME$C_SETRFM 1
402159047fSniklas
412159047fSniklas	struct FAB * fab;
422159047fSniklas
432159047fSniklas	main(int argc, char * argv[]){
442159047fSniklas		int i, status;
452159047fSniklas		fab = (struct FAB*) malloc(sizeof(struct FAB));
462159047fSniklas		*fab = cc$rms_fab;	/* initialize FAB*/
472159047fSniklas		fab->fab$b_fac = FAB$M_PUT;
482159047fSniklas		fab->fab$l_fop |= FAB$M_ESC;
492159047fSniklas		fab->fab$l_ctx = RME$C_SETRFM;
502159047fSniklas		fab->fab$w_ifi = 0;
512159047fSniklas		for(i=1;i<argc;i++){
522159047fSniklas		  printf("Setting %s to variable length records.\n",argv[i]);
532159047fSniklas		  fab->fab$l_fna = argv[i];
542159047fSniklas	       	  fab->fab$b_fns = strlen(argv[i]);
552159047fSniklas		  status = sys$open(fab,0,0);
562159047fSniklas		  if((status & 7) != 1) lib$signal(status);
572159047fSniklas		  fab->fab$b_rfm = FAB$C_VAR;
582159047fSniklas		  status = sys$modify(fab,0,0);
592159047fSniklas		  if((status & 7) != 1) lib$signal(status);
602159047fSniklas		  status = sys$close(fab,0,0);
612159047fSniklas		  if((status & 7) != 1) lib$signal(status);
622159047fSniklas		};
632159047fSniklas	}
642159047fSniklas
652159047fSniklas	If you have NFS running on the VMS system, what you need to do
662159047fSniklasdepends upon which NFS software you are running on the VMS system.  There
672159047fSniklasare a number of different TCP/IP packages for VMS available, and only very
682159047fSniklaslimited testing has been performed.   In the tests that has been done so
692159047fSniklasfar, the contents of the file will always be correct when transferring the
702159047fSniklasfile via NFS, but the record attributes may or may not be correct.
712159047fSniklas
722159047fSniklas	One proprietary TCP/IP/NFS package for VMS is known to
732159047fSniklasautomatically fix the record attributes of the object file if you NFS mount
742159047fSniklasa unix disk from the VMS system, and if the file has a ".obj" extension on
752159047fSniklasthe unix system.  Other TCP/IP packages might do this for you as well, but
762159047fSniklasthey have not been checked.
772159047fSniklas
782159047fSniklasNo matter what method you use to get the file to the VMS system, it is
792159047fSniklasalways a good idea to check to make sure that it is the correct type by
802159047fSniklasdoing a "$dir/full" on the object file. The desired record attributes will
812159047fSniklasbe "None".  Undesirable record attributes will be "Stream-LF" or anything
822159047fSniklaselse.
832159047fSniklas
842159047fSniklasOnce you get the files on the VMS system, you can check their integrity
852159047fSniklaswith the "$anal/obj" command.  (Naturally at some point you should rename
862159047fSniklasthe .o files to .obj).  As far as the debugger is concerned, the records
872159047fSniklaswill be correct, but the debugger will not be able to find the source files,
882159047fSniklassince it only has the file name, and not the full directory specification.
892159047fSniklasYou must give the debugger some help by telling it which directories to
902159047fSniklassearch for the individual files - once you have done this you should be
912159047fSniklasable to proceed normally.
922159047fSniklas
932159047fSniklas	It is a good idea to use names for your files which will be valid
942159047fSniklasunder VMS, since otherwise you will have no way of getting the debugger to
952159047fSniklasfind the source file when deugging.
962159047fSniklas
972159047fSniklasThe reason for this is that the object file normally contins specific
982159047fSniklasinformation that the debugger can use to positively identify a file, and if
992159047fSniklasyou are assembling on a unix system this information simply does not exist
1002159047fSniklasin a meaningful way.  You must help the debugger by using the "SET FILE="
1012159047fSniklascommand to tell the debugger where to look for source files. The debugger
1022159047fSniklasrecords will be correct, except that the debugger will not be initially
1032159047fSniklasable to find the source files.  You can use the "SET FILE" command to tell
1042159047fSniklasthe debugger where to look for the source files.
1052159047fSniklas
1062159047fSniklasI have only tested this with a SVr4 i486 machine, and everything seems to
1072159047fSniklaswork OK, with the limited testing that I have done.  Other machines may
1082159047fSniklasor may not work.  You should read the chapters on cross-compilers in the gcc
1092159047fSniklasmanual before fooling with this.  Since gas does not need to do any floating
1102159047fSniklaspoint arithmetic, the floating point constants that are generated here should
1112159047fSniklasbe correct - the only concern is with constant folding in the main compiler.
1122159047fSniklasThe range and precision of floats and doubles are similar on the 486 (with
1132159047fSniklasa builtin 80387) and the VAX, although there is a factor of 2 to 4
1142159047fSniklasdifference in the range.  The double, as implemented on the 486, is quite
1152159047fSniklassimilar to the G_FLOAT on the VAX.
1162159047fSniklas
1172159047fSniklas***********************************************************************
1182159047fSniklas****************** Notes for using GNU CC with the VMS debugger********
1192159047fSniklas***********************************************************************
1202159047fSniklas
1212159047fSniklas
1222159047fSniklas	1) You should be aware that GNU-C, as with any other decent compiler,
1232159047fSniklaswill do things when optimization is turned on that you may not expect.
1242159047fSniklasSometimes intermediate results are not written to variables, if they are only
1252159047fSniklasused in one place, and sometimes variables that are not used at all will not be
1262159047fSniklaswritten to the symbol table.  Also, parameters to inline functions are often
1272159047fSniklasinaccessible. You can see the assembly code equivalent by using KP7 in the
1282159047fSniklasdebugger, and from this you can tell if in fact a variable should have the
1292159047fSniklasvalue that you expect.  You can find out if a variable lives withing a register
1302159047fSniklasby doing a 'show symbol/addr'.
1312159047fSniklas
1322159047fSniklas	2) Overly complex data types, such as:
1332159047fSniklas
1342159047fSniklasint (*(*(*(*(*(* sarr6)[1])[1])[2])[3])[4])[5];
1352159047fSniklas
1362159047fSniklaswill not be debugged properly, since the debugging record overflows an internal
1372159047fSniklasdebugger buffer.  gcc-as will convert these to *void as far as the debugger
1382159047fSniklassymbol table is concerned, which will avoid any problems, and the assembler
1392159047fSniklaswill give you a message informing you that this has happened.
1402159047fSniklas
1412159047fSniklas	3) You must, of course, compile and link with /debug.  If you link
1422159047fSniklaswithout debug, you still get traceback table in the executable, but there is no
1432159047fSniklassymbol table for variables.
1442159047fSniklas
1452159047fSniklas	4) Included in the patches to VMS.C are fixes to two bugs that are
1462159047fSniklasunrelated to the changes that I have made.  One of these made it impossible to
1472159047fSniklasdebug small programs sometimes, and the other caused the debugger to become
1482159047fSniklasconfused about which routine it was in, and give this incorrect info in
1492159047fSniklastracebacks.
1502159047fSniklas
1512159047fSniklas	5) If you are using the GNU-C++ compiler, you should modify the
1522159047fSniklascompiler driver file GNU_CC:[000000]GCC.COM (or GXX.COM).  If you have a
153*cf2f2c56Smiodseparate GXX.COM, then you need to change one line in GXX.COM to:
1542159047fSniklas$ if f$locate("D",p2) .ne. P2_Length then Debug = " ""-G0"""
1552159047fSniklas                                       Notice zero--->  ^
1562159047fSniklasIf you are using a GCC.COM that does both C and C++, add the following lines to
1572159047fSniklasGCC.COM:
1582159047fSniklas
1592159047fSniklas$!
1602159047fSniklas$! Use old style debugging records for VMS
1612159047fSniklas$!
1622159047fSniklas$ if (Debug.nes."" ).and. Plus then Debug = " ""-G0"""
1632159047fSniklas
1642159047fSniklasafter the variables Plus and Debug are set.  The reason for this, is that C++
1652159047fSniklascompiler by default generates debugging records that are more complex,
1662159047fSniklaswith many new syntactical elements that allow for the new features of the
1672159047fSniklaslanguage.  The -G0 switch tells the C++ compiler to use the old style debugging
1682159047fSniklasrecords.  Until the debugger understands C++ there is not any point to try and
1692159047fSniklasuse the expanded syntax.
1702159047fSniklas
1712159047fSniklas	6) When you have nested scopes, i.e.:
1722159047fSniklasmain(){
1732159047fSniklas	int i;
1742159047fSniklas	{int i;
1752159047fSniklas		{int i;
1762159047fSniklas};};}
1772159047fSniklasand you say "EXAM i" the debugger needs to figure out which variable you
1782159047fSniklasactually want to reference.  I have arranged things to define a block to the
1792159047fSniklasdebugger when you use brackets to enter a new scope, so in the example above,
1802159047fSniklasthe variables would be described as:
1812159047fSniklasTEST\main\i
1822159047fSniklasTEST\main\$0\i
1832159047fSniklasTEST\main\$0\$0\i
1842159047fSniklasAt each level, the block name is a number with a dollar sign prefix, the
1852159047fSniklasnumbers start with 0 and count upward.  When you say EXAM i, the debugger looks
1862159047fSniklasat the current PC, and decides which block it is currently in.  It works from
1872159047fSniklasthe innermost level outward until it finds a block that has the variable "i"
1882159047fSniklasdefined.  You can always specify the scope explicitly.
1892159047fSniklas
1902159047fSniklas	7)  With C++, there can be a lot of inline functions, and it would be
1912159047fSniklasrather restrictive to force the user to debug the program by converting all of
1922159047fSniklasthe inline functions to normal functions.  What I have done is to essentially
1932159047fSniklas"add" (with the debugger) source lines from the include files that contain the
1942159047fSniklasinline functions.  Thus when you step into an inline function it appears as if
1952159047fSniklasyou have called the function, and you can examine variables and so forth.
1962159047fSniklasThere are several *very* important differences, however.  First of all, since
1972159047fSniklasthere is no function call involved, you cannot step over the inline function
1982159047fSniklascall - you always step into it. Secondly, since the same source lines are used
199*cf2f2c56Smiodin many locations, there is a separate copy of the source for *each* usage.
2002159047fSniklasWithout this, breakpoints do not work, since we must have a 1-to-1 mapping
2012159047fSniklasbetween source lines and PC.
2022159047fSniklas	Since you cannot step over inline function calls, it can be a real pain
2032159047fSniklasif you are not really interested in what is going on for that function call.
2042159047fSniklasWhat I have done is to use the "-D" switch for the assembler to toggle the
2052159047fSniklasfollowing behavior.  With the "-D" switch, all inline functions are included in
2062159047fSniklasthe object file, and you can debug everything.  Without the "-D" switch
2072159047fSniklas(default case with VMS implementation), inline functions are included *only* if
2082159047fSniklasthey did not come from system header files (i.e. from GNU_CC_INCLUDE: or
2092159047fSniklasGNU_GXX_INCLUDE:).  Thus, without the switch the user only debugs his/her own
2102159047fSniklasinline functions, and not the system ones. (This is especially useful if you do
2112159047fSniklasa lot of stream I/O in C++).  This probably will not provide enough granularity
2122159047fSniklasfor many users, but for now this is still somewhat experimental, and I would
2132159047fSniklaslike to reflect upon it and get some feedback before I go any further.
2142159047fSniklasPossible solutions include an interactive prompting, a logical name, or a new
2152159047fSniklascommand line option in gcc.c (which is then passed through somehow to the guts
2162159047fSniklasof the assembler).
2172159047fSniklas	The inline functions from header files appear after the source code
2182159047fSniklasfor the source file.  This has the advantage that the source file itself is
2192159047fSniklasnumbered with the same line numbers that you get with an editor.  In addition,
2202159047fSniklasthe entire header file is not included, since the assembler makes a list of
2212159047fSniklasthe min and max source lines that are used, and only includes those lines from
2222159047fSniklasthe first to the last actually used. (It is easy to change it to include the
2232159047fSniklaswhole file).
2242159047fSniklas
2252159047fSniklas	8) When you are debugging C++ objects, the object "this" is refered to
2262159047fSniklasas "$this".  Actually, the compiler writes it as ".this", but the period is
2272159047fSniklasnot good for the debugger, so I have a routine to convert it to a $.  (It
2282159047fSniklasactually converts all periods to $, but only for variables, since this was
2292159047fSniklasintended to allow us to access "this".
2302159047fSniklas
2312159047fSniklas	9) If you use the asm("...") keyword for global symbols, you will not
2322159047fSniklasbe able to see that symbol with the debugger.  The reason is that there are two
2332159047fSniklasrecords for the symbol stored in the data structures of the assembler.  One
2342159047fSniklascontains the info such as psect number and offset, and the other one contains
2352159047fSniklasthe information having to do with the data type of the variable.  In order to
2362159047fSniklasdebug as symbol, you need to be able to coorelate these records, and the only
2372159047fSniklasway to do this is by name.  The record with the storage attributes will take
2382159047fSniklasthe name used in the asm directive, and the record that specifies the data type
2392159047fSniklashas the actual variable name, and thus when you use the asm directive to change
2402159047fSniklasa variable name, the symbol becomes invisible.
2412159047fSniklas
2422159047fSniklas	10) Older versions of the compiler ( GNU-C 1.37.92 and earlier) place
2432159047fSniklasglobal constants in the text psect.  This is unfortunate, since to the linker
2442159047fSniklasthis appears to be an entry point.  I sent a patch to the compiler to RMS,
2452159047fSniklaswhich will generate a .const section for these variables, and patched the
2462159047fSniklasassembler to put these variables into a psect just like that for normal
2472159047fSniklasvariables, except that they are marked NOWRT.  static constants are still
2482159047fSniklasplaced in the text psect, since there is no need for any external access.
249