1 This document explains a couple of things that are specific to VMS. 2There are currently two "chapters", the first deals with cross-assembly 3issues, and the second deals with the VMS debugger and GNU-CC. 4 5 6*********************************************************************** 7****************** Notes for Cross Assembly with VMS ****************** 8*********************************************************************** 9 10 If you wish to build gas on a non-VMS system to cross-assemble, 11you should use: 12 13configure ${hosttype} -target=vms 14 15and then follow the usual procedure. The object files generated on 16Unix will be correct from a binary point of view, but the real trick is 17getting them to the VMS machine. The format of the object file is 18a variable-length record, but each record contains binary data. gas 19writes the records in the same format that VMS would expect, 20namely a two-byte count followed by that number of bytes. 21 22 If you try to copy the file to a VMS system using ftp, the ftp 23protocol will screw up the file by looking for nulls (record terminator for 24unix) and it will insert it's own record terminators at that point. This 25will obviously corrupt the file. 26 27 If you try to transfer the file with ftp in binary mode, the 28file itself will not be corrupt, but VMS will think that the file contains 29fixed-length records of 512 bytes. You can use the public-domain FILE 30utility to change this with a command like: 31 32$FILE foo.o/type=variable 33 34If you do not have this utility available, the following program can be 35used to perform this task: 36 37 #include <fab.h> 38 39 #define RME$C_SETRFM 1 40 41 struct FAB * fab; 42 43 main(int argc, char * argv[]){ 44 int i, status; 45 fab = (struct FAB*) malloc(sizeof(struct FAB)); 46 *fab = cc$rms_fab; /* initialize FAB*/ 47 fab->fab$b_fac = FAB$M_PUT; 48 fab->fab$l_fop |= FAB$M_ESC; 49 fab->fab$l_ctx = RME$C_SETRFM; 50 fab->fab$w_ifi = 0; 51 for(i=1;i<argc;i++){ 52 printf("Setting %s to variable length records.\n",argv[i]); 53 fab->fab$l_fna = argv[i]; 54 fab->fab$b_fns = strlen(argv[i]); 55 status = sys$open(fab,0,0); 56 if((status & 7) != 1) lib$signal(status); 57 fab->fab$b_rfm = FAB$C_VAR; 58 status = sys$modify(fab,0,0); 59 if((status & 7) != 1) lib$signal(status); 60 status = sys$close(fab,0,0); 61 if((status & 7) != 1) lib$signal(status); 62 }; 63 } 64 65 If you have NFS running on the VMS system, what you need to do 66depends upon which NFS software you are running on the VMS system. There 67are a number of different TCP/IP packages for VMS available, and only very 68limited testing has been performed. In the tests that has been done so 69far, the contents of the file will always be correct when transferring the 70file via NFS, but the record attributes may or may not be correct. 71 72 One proprietary TCP/IP/NFS package for VMS is known to 73automatically fix the record attributes of the object file if you NFS mount 74a unix disk from the VMS system, and if the file has a ".obj" extension on 75the unix system. Other TCP/IP packages might do this for you as well, but 76they have not been checked. 77 78No matter what method you use to get the file to the VMS system, it is 79always a good idea to check to make sure that it is the correct type by 80doing a "$dir/full" on the object file. The desired record attributes will 81be "None". Undesirable record attributes will be "Stream-LF" or anything 82else. 83 84Once you get the files on the VMS system, you can check their integrity 85with the "$anal/obj" command. (Naturally at some point you should rename 86the .o files to .obj). As far as the debugger is concerned, the records 87will be correct, but the debugger will not be able to find the source files, 88since it only has the file name, and not the full directory specification. 89You must give the debugger some help by telling it which directories to 90search for the individual files - once you have done this you should be 91able to proceed normally. 92 93 It is a good idea to use names for your files which will be valid 94under VMS, since otherwise you will have no way of getting the debugger to 95find the source file when deugging. 96 97The reason for this is that the object file normally contins specific 98information that the debugger can use to positively identify a file, and if 99you are assembling on a unix system this information simply does not exist 100in a meaningful way. You must help the debugger by using the "SET FILE=" 101command to tell the debugger where to look for source files. The debugger 102records will be correct, except that the debugger will not be initially 103able to find the source files. You can use the "SET FILE" command to tell 104the debugger where to look for the source files. 105 106I have only tested this with a SVr4 i486 machine, and everything seems to 107work OK, with the limited testing that I have done. Other machines may 108or may not work. You should read the chapters on cross-compilers in the gcc 109manual before fooling with this. Since gas does not need to do any floating 110point arithmetic, the floating point constants that are generated here should 111be correct - the only concern is with constant folding in the main compiler. 112The range and precision of floats and doubles are similar on the 486 (with 113a builtin 80387) and the VAX, although there is a factor of 2 to 4 114difference in the range. The double, as implemented on the 486, is quite 115similar to the G_FLOAT on the VAX. 116 117*********************************************************************** 118****************** Notes for using GNU CC with the VMS debugger******** 119*********************************************************************** 120 121 122 1) You should be aware that GNU-C, as with any other decent compiler, 123will do things when optimization is turned on that you may not expect. 124Sometimes intermediate results are not written to variables, if they are only 125used in one place, and sometimes variables that are not used at all will not be 126written to the symbol table. Also, parameters to inline functions are often 127inaccessible. You can see the assembly code equivalent by using KP7 in the 128debugger, and from this you can tell if in fact a variable should have the 129value that you expect. You can find out if a variable lives withing a register 130by doing a 'show symbol/addr'. 131 132 2) Overly complex data types, such as: 133 134int (*(*(*(*(*(* sarr6)[1])[1])[2])[3])[4])[5]; 135 136will not be debugged properly, since the debugging record overflows an internal 137debugger buffer. gcc-as will convert these to *void as far as the debugger 138symbol table is concerned, which will avoid any problems, and the assembler 139will give you a message informing you that this has happened. 140 141 3) You must, of course, compile and link with /debug. If you link 142without debug, you still get traceback table in the executable, but there is no 143symbol table for variables. 144 145 4) Included in the patches to VMS.C are fixes to two bugs that are 146unrelated to the changes that I have made. One of these made it impossible to 147debug small programs sometimes, and the other caused the debugger to become 148confused about which routine it was in, and give this incorrect info in 149tracebacks. 150 151 5) If you are using the GNU-C++ compiler, you should modify the 152compiler driver file GNU_CC:[000000]GCC.COM (or GXX.COM). If you have a 153separate GXX.COM, then you need to change one line in GXX.COM to: 154$ if f$locate("D",p2) .ne. P2_Length then Debug = " ""-G0""" 155 Notice zero---> ^ 156If you are using a GCC.COM that does both C and C++, add the following lines to 157GCC.COM: 158 159$! 160$! Use old style debugging records for VMS 161$! 162$ if (Debug.nes."" ).and. Plus then Debug = " ""-G0""" 163 164after the variables Plus and Debug are set. The reason for this, is that C++ 165compiler by default generates debugging records that are more complex, 166with many new syntactical elements that allow for the new features of the 167language. The -G0 switch tells the C++ compiler to use the old style debugging 168records. Until the debugger understands C++ there is not any point to try and 169use the expanded syntax. 170 171 6) When you have nested scopes, i.e.: 172main(){ 173 int i; 174 {int i; 175 {int i; 176};};} 177and you say "EXAM i" the debugger needs to figure out which variable you 178actually want to reference. I have arranged things to define a block to the 179debugger when you use brackets to enter a new scope, so in the example above, 180the variables would be described as: 181TEST\main\i 182TEST\main\$0\i 183TEST\main\$0\$0\i 184At each level, the block name is a number with a dollar sign prefix, the 185numbers start with 0 and count upward. When you say EXAM i, the debugger looks 186at the current PC, and decides which block it is currently in. It works from 187the innermost level outward until it finds a block that has the variable "i" 188defined. You can always specify the scope explicitly. 189 190 7) With C++, there can be a lot of inline functions, and it would be 191rather restrictive to force the user to debug the program by converting all of 192the inline functions to normal functions. What I have done is to essentially 193"add" (with the debugger) source lines from the include files that contain the 194inline functions. Thus when you step into an inline function it appears as if 195you have called the function, and you can examine variables and so forth. 196There are several *very* important differences, however. First of all, since 197there is no function call involved, you cannot step over the inline function 198call - you always step into it. Secondly, since the same source lines are used 199in many locations, there is a separate copy of the source for *each* usage. 200Without this, breakpoints do not work, since we must have a 1-to-1 mapping 201between source lines and PC. 202 Since you cannot step over inline function calls, it can be a real pain 203if you are not really interested in what is going on for that function call. 204What I have done is to use the "-D" switch for the assembler to toggle the 205following behavior. With the "-D" switch, all inline functions are included in 206the object file, and you can debug everything. Without the "-D" switch 207(default case with VMS implementation), inline functions are included *only* if 208they did not come from system header files (i.e. from GNU_CC_INCLUDE: or 209GNU_GXX_INCLUDE:). Thus, without the switch the user only debugs his/her own 210inline functions, and not the system ones. (This is especially useful if you do 211a lot of stream I/O in C++). This probably will not provide enough granularity 212for many users, but for now this is still somewhat experimental, and I would 213like to reflect upon it and get some feedback before I go any further. 214Possible solutions include an interactive prompting, a logical name, or a new 215command line option in gcc.c (which is then passed through somehow to the guts 216of the assembler). 217 The inline functions from header files appear after the source code 218for the source file. This has the advantage that the source file itself is 219numbered with the same line numbers that you get with an editor. In addition, 220the entire header file is not included, since the assembler makes a list of 221the min and max source lines that are used, and only includes those lines from 222the first to the last actually used. (It is easy to change it to include the 223whole file). 224 225 8) When you are debugging C++ objects, the object "this" is refered to 226as "$this". Actually, the compiler writes it as ".this", but the period is 227not good for the debugger, so I have a routine to convert it to a $. (It 228actually converts all periods to $, but only for variables, since this was 229intended to allow us to access "this". 230 231 9) If you use the asm("...") keyword for global symbols, you will not 232be able to see that symbol with the debugger. The reason is that there are two 233records for the symbol stored in the data structures of the assembler. One 234contains the info such as psect number and offset, and the other one contains 235the information having to do with the data type of the variable. In order to 236debug as symbol, you need to be able to coorelate these records, and the only 237way to do this is by name. The record with the storage attributes will take 238the name used in the asm directive, and the record that specifies the data type 239has the actual variable name, and thus when you use the asm directive to change 240a variable name, the symbol becomes invisible. 241 242 10) Older versions of the compiler ( GNU-C 1.37.92 and earlier) place 243global constants in the text psect. This is unfortunate, since to the linker 244this appears to be an entry point. I sent a patch to the compiler to RMS, 245which will generate a .const section for these variables, and patched the 246assembler to put these variables into a psect just like that for normal 247variables, except that they are marked NOWRT. static constants are still 248placed in the text psect, since there is no need for any external access. 249