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.
|
---|