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