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