Commit | Line | Data |
---|---|---|
1364805a KB |
1 | /* |
2 | * Copyright (c) 1980 Regents of the University of California. | |
3 | * All rights reserved. The Berkeley software License Agreement | |
4 | * specifies the terms and conditions for redistribution. | |
5 | */ | |
6 | ||
7 | #ifndef lint | |
8 | static char sccsid[] = "@(#)stab.c 5.1 (Berkeley) 6/7/85"; | |
9 | #endif not lint | |
10 | ||
11 | /* | |
12 | * stab.c | |
13 | * | |
14 | * Symbolic debugging info interface for the f77 compiler. | |
15 | * | |
16 | * Here we generate pseudo-ops that cause the assembler to put | |
17 | * symbolic debugging information into the object file. | |
18 | * | |
19 | * University of Utah CS Dept modification history: | |
20 | * | |
21 | * $Log: stab.c,v $ | |
22 | * Revision 1.2 85/02/02 01:30:09 donn | |
23 | * Don't put the 'program' name into the file; it only confuses dbx, sigh. | |
24 | * | |
25 | */ | |
26 | ||
27 | #include "defs.h" | |
28 | ||
29 | #include <sys/types.h> | |
30 | #include <a.out.h> | |
31 | #include <stab.h> | |
32 | ||
33 | #define public | |
34 | #define private static | |
35 | #define and && | |
36 | #define or || | |
37 | #define not ! | |
38 | #define div / | |
39 | #define mod % | |
40 | #define nil 0 | |
41 | ||
42 | typedef enum { false, true } Boolean; | |
43 | ||
44 | static char asmline[128]; | |
45 | int len; | |
46 | extern char *malloc(); | |
47 | ||
48 | prstab(s, code, type, loc) | |
49 | char *s, *loc; | |
50 | int code, type; | |
51 | { | |
52 | char *locout; | |
53 | ||
54 | if (sdbflag) { | |
55 | locout = (loc == nil) ? "0" : loc; | |
56 | if (s == nil) { | |
57 | sprintf(asmline, "\t.stabn\t0x%x,0,0x%x,%s\n", code, type, locout); | |
58 | } else { | |
59 | sprintf(asmline, "\t.stabs\t\"%s\",0x%x,0,0x%x,%s\n", s, code, type, | |
60 | locout); | |
61 | } | |
62 | p2pass( asmline ); | |
63 | } | |
64 | } | |
65 | ||
66 | filenamestab(s) | |
67 | char *s; | |
68 | { | |
69 | sprintf(asmline,"\t.stabs\t\"%s\",0x%x,0,0,0\n", s, N_SO); | |
70 | p2pass( asmline ); | |
71 | } | |
72 | ||
73 | linenostab(lineno) | |
74 | int lineno; | |
75 | { | |
76 | sprintf(asmline,"\t.stabd\t0x%x,0,%d\n", N_SLINE, lineno); | |
77 | p2pass( asmline ); | |
78 | } | |
79 | ||
80 | /* | |
81 | * Generate information for an entry point | |
82 | */ | |
83 | ||
84 | public entrystab(p,class) | |
85 | register struct Entrypoint *p; | |
86 | int class; | |
87 | { | |
88 | int et; | |
89 | Namep q; | |
90 | ||
91 | switch(class) { | |
92 | case CLMAIN: | |
93 | et=writestabtype(TYSUBR); | |
94 | sprintf(asmline, "\t.stabs\t\"MAIN:F%2d\",0x%x,0,0,L%d\n", | |
95 | et,N_FUN,p->entrylabel); | |
96 | p2pass(asmline); | |
97 | break; | |
98 | ||
99 | case CLBLOCK: /* May need to something with block data LATER */ | |
100 | break; | |
101 | ||
102 | default : | |
103 | if( (q=p->enamep) == nil) fatal("entrystab has no nameblock"); | |
104 | sprintf(asmline, "\t.stabs\t\"%s:F", varstr(VL,q->varname)); | |
105 | len = strlen(asmline); | |
106 | /* when insufficient information is around assume TYSUBR; enddcl | |
107 | will fill this in*/ | |
108 | if(q->vtype == TYUNKNOWN || (q->vtype == TYCHAR && q->vleng == nil) ){ | |
109 | sprintf(asmline+len, "%2d", writestabtype(TYSUBR)); | |
110 | } | |
111 | else addtypeinfo(q); | |
112 | len += strlen(asmline+len); | |
113 | sprintf(asmline+len, "\",0x%x,0,0,L%d\n",N_FUN,p->entrylabel); | |
114 | p2pass(asmline); | |
115 | break; | |
116 | } | |
117 | } | |
118 | ||
119 | /* | |
120 | * Generate information for a symbol table (name block ) entry. | |
121 | */ | |
122 | ||
123 | public namestab(sym) | |
124 | Namep sym; | |
125 | { | |
126 | register Namep p; | |
127 | char *varname, *classname; | |
128 | Boolean ignore; | |
129 | int vartype; | |
130 | ||
131 | ignore = false; | |
132 | p = sym; | |
133 | if(!p->vdcldone) return; | |
134 | vartype = p->vtype; | |
135 | varname = varstr(VL, p->varname); | |
136 | switch (p->vclass) { | |
137 | case CLPARAM: /* parameter (constant) */ | |
138 | classname = "c"; | |
139 | break; | |
140 | ||
141 | case CLVAR: /* variable */ | |
142 | case CLUNKNOWN: | |
143 | if(p->vstg == STGARG) classname = "v"; | |
144 | else classname = "V"; | |
145 | break; | |
146 | ||
147 | case CLMAIN: /* main program */ | |
148 | case CLENTRY: /* secondary entry point */ | |
149 | case CLBLOCK: /* block data name*/ | |
150 | case CLPROC: /* external or function or subroutine */ | |
151 | ignore = true; /* these are put out by entrystab */ | |
152 | break; | |
153 | ||
154 | ||
155 | } | |
156 | if (not ignore) { | |
157 | sprintf(asmline, "\t.stabs\t\"%s:%s", varname, classname); | |
158 | len = strlen(asmline); | |
159 | addtypeinfo(p); | |
160 | len += strlen(asmline+len); | |
161 | switch(p->vstg) { | |
162 | ||
163 | case STGUNKNOWN : | |
164 | case STGCONST : | |
165 | case STGEXT : | |
166 | case STGINTR : | |
167 | case STGSTFUNCT : | |
168 | case STGLENG : | |
169 | case STGNULL : | |
170 | case STGREG : | |
171 | case STGINIT : | |
172 | sprintf(asmline+len, | |
173 | "\",0x%x,0,0,0 /* don't know how to calc loc for stg %d*/ \n", | |
174 | N_LSYM,p->vstg); | |
175 | break; | |
176 | ||
177 | case STGARG : | |
178 | sprintf(asmline+len,"\",0x%x,0,0,%d \n", | |
179 | N_PSYM,p->vardesc.varno + ARGOFFSET ); | |
180 | break; | |
181 | ||
182 | case STGCOMMON : | |
183 | sprintf(asmline+len, "\",0x%x,0,0,%d\n", | |
184 | N_GSYM, p->voffset); | |
185 | break; | |
186 | ||
187 | case STGBSS : | |
188 | sprintf(asmline+len, "\",0x%x,0,0,v.%d\n", | |
189 | (p->inlcomm ? N_LCSYM : N_STSYM), | |
190 | p->vardesc.varno); | |
191 | break; | |
192 | ||
193 | case STGEQUIV : | |
194 | sprintf(asmline+len, "\",0x%x,0,0,%s + %d \n", | |
195 | (p->inlcomm ? N_LCSYM : N_STSYM) , | |
196 | memname(STGEQUIV,p->vardesc.varno),(p->voffset)) ; | |
197 | break; | |
198 | ||
199 | case STGAUTO : | |
200 | sprintf(asmline+len, "\",0x%x,0,0,-%d \n", | |
201 | N_LSYM, p->voffset); | |
202 | ||
203 | } | |
204 | p2pass(asmline); | |
205 | } | |
206 | } | |
207 | ||
208 | static typenum[NTYPES]; /* has the given type already been defined ?*/ | |
209 | ||
210 | private writestabtype(type) | |
211 | int type; | |
212 | { | |
213 | char asmline[130]; | |
214 | static char *typename[NTYPES] = | |
215 | { "unknown", "addr","integer*2", "integer", "real", "double precision", | |
216 | "complex", "double complex", "logical", "char", "void", "error" }; | |
217 | ||
218 | static int typerange[NTYPES] = { 0, 3, 2, 3, 4, 5, 6, 7, 3, 9, 10, 11 }; | |
219 | ||
220 | /* compare with typesize[] in init.c */ | |
221 | static int typebounds[2] [NTYPES] ={ | |
222 | /* "unknown", "addr","integer*2", "integer", "real", "double precision", */ | |
223 | { 0 , 0 , -32768, -2147483648, 4, 8, | |
224 | /* "complex", "double complex", "logical", "char", "void", "error" }; */ | |
225 | 8, 16, 0, 0, 0, 0 }, | |
226 | /* "unknown", "addr","integer*2", "integer", "real", "double precision", */ | |
227 | { 0 , -1, 32767, 2147483647, 0, 0, | |
228 | /* "complex", "double complex", "logical", "char", "void", "error" }; */ | |
229 | 0, 0, 1, 127, 0, 0 } | |
230 | }; | |
231 | ||
232 | ||
233 | if( type < 0 || type > NTYPES) badtype("writestabtype",type); | |
234 | ||
235 | if (typenum[type]) return(typenum[type]); | |
236 | typenum[type] = type; | |
237 | sprintf(asmline, "\t.stabs\t\"%s:t%d=r%d;%ld;%ld;\",0x%x,0,0,0 \n", | |
238 | typename[type], type, typerange[type], typebounds[0][type], | |
239 | typebounds[1][type], N_GSYM) ; | |
240 | p2pass(asmline); | |
241 | return(typenum[type]); | |
242 | } | |
243 | ||
244 | ||
245 | private getbasenum(p) | |
246 | Namep p; | |
247 | { | |
248 | ||
249 | int t; | |
250 | t = p->vtype; | |
251 | if( t < TYSHORT || t > TYSUBR) | |
252 | dclerr("can't get dbx basetype information",p); | |
253 | ||
254 | if (p->vtype == TYCHAR || p->vdim != nil ) writestabtype(TYINT); | |
255 | return(writestabtype(t)); | |
256 | } | |
257 | ||
258 | /* | |
259 | * Generate debugging information for the given type of the given symbol. | |
260 | */ | |
261 | ||
262 | private addtypeinfo(sym) | |
263 | Namep sym; | |
264 | { | |
265 | Namep p; | |
266 | int i,tnum; | |
267 | char lb[20],ub[20]; | |
268 | ||
269 | p = sym; | |
270 | if (p->tag != TNAME) badtag("addtypeinfo",p->tag); | |
271 | ||
272 | tnum = getbasenum(p); | |
273 | if(p->vdim != (struct Dimblock *) ENULL) { | |
274 | ||
275 | for (i = p->vdim->ndim-1; i >=0 ; --i) { | |
276 | if(p->vdim->dims[i].lbaddr == ENULL) { | |
277 | sprintf(lb,"%d", p->vdim->dims[i].lb->constblock.const.ci); | |
278 | } | |
279 | else { | |
280 | sprintf(lb,"T%d", p->vdim->dims[i].lbaddr->addrblock.memoffset->constblock.const.ci); | |
281 | } | |
282 | if(p->vdim->dims[i].ubaddr == ENULL) { | |
283 | sprintf(ub,"%d",p->vdim->dims[i].ub->constblock.const.ci); | |
284 | } | |
285 | else { | |
286 | sprintf(ub,"T%d",p->vdim->dims[i].ubaddr->addrblock.memoffset->constblock.const.ci); | |
287 | } | |
288 | sprintf(asmline+len, "ar%d;%s;%s;", TYINT, lb, ub); | |
289 | len += strlen(asmline+len); | |
290 | } | |
291 | } | |
292 | if (p->vtype == TYCHAR) { | |
293 | /* character type always an array(1:?) */ | |
294 | if( ! (p->vleng ) ) | |
295 | fatalstr("missing length in addtypeinfo for character variable %s", varstr(p->varname)); | |
296 | ||
297 | if (ISCONST(p->vleng)) sprintf(ub,"%d",p->vleng->constblock.const.ci); | |
298 | else sprintf(ub,"A%d",p->vleng->addrblock.memno + ARGOFFSET); | |
299 | ||
300 | sprintf(asmline+len,"ar%d;1;%s;", TYINT, ub); | |
301 | len += strlen(asmline+len); | |
302 | } | |
303 | sprintf(asmline+len, "%d",tnum); | |
304 | } |