]> Git Repo - binutils.git/blob - gdb/symm-tdep.c
Fix demangling of destructors, and fix a minor indentation problem.
[binutils.git] / gdb / symm-tdep.c
1 /* Sequent Symmetry target interface, for GDB when running under Unix.
2    Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 /* many 387-specific items of use taken from i386-dep.c */
21
22 #include <stdio.h>
23 #include "defs.h"
24 #include "frame.h"
25 #include "inferior.h"
26 #include "symtab.h"
27
28 #include <signal.h>
29 #include <sys/param.h>
30 #include <sys/user.h>
31 #include <sys/dir.h>
32 #include <sys/ioctl.h>
33 #include <sys/stat.h>
34 #include "gdbcore.h"
35 #include <fcntl.h>
36
37 static long i386_get_frame_setup ();
38 static i386_follow_jump ();
39
40 #include <sgtty.h>
41 #define TERMINAL struct sgttyb
42
43 exec_file_command (filename, from_tty)
44      char *filename;
45      int from_tty;
46 {
47   int val;
48
49   /* Eliminate all traces of old exec file.
50      Mark text segment as empty.  */
51
52   if (execfile)
53     free (execfile);
54   execfile = 0;
55   data_start = 0;
56   data_end -= exec_data_start;
57   text_start = 0;
58   text_end = 0;
59   exec_data_start = 0;
60   exec_data_end = 0;
61   if (execchan >= 0)
62     close (execchan);
63   execchan = -1;
64
65   /* Now open and digest the file the user requested, if any.  */
66
67   if (filename)
68     {
69       filename = tilde_expand (filename);
70       make_cleanup (free, filename);
71       
72       execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
73                         &execfile);
74       if (execchan < 0)
75         perror_with_name (filename);
76
77 #ifdef COFF_FORMAT
78       {
79         int aout_hdrsize;
80         int num_sections;
81
82         if (read_file_hdr (execchan, &file_hdr) < 0)
83           error ("\"%s\": not in executable format.", execfile);
84
85         aout_hdrsize = file_hdr.f_opthdr;
86         num_sections = file_hdr.f_nscns;
87
88         if (read_aout_hdr (execchan, &exec_aouthdr, aout_hdrsize) < 0)
89           error ("\"%s\": can't read optional aouthdr", execfile);
90
91         if (read_section_hdr (execchan, _TEXT, &text_hdr, num_sections,
92                               aout_hdrsize) < 0)
93           error ("\"%s\": can't read text section header", execfile);
94
95         if (read_section_hdr (execchan, _DATA, &data_hdr, num_sections,
96                               aout_hdrsize) < 0)
97           error ("\"%s\": can't read data section header", execfile);
98
99         text_start = exec_aouthdr.text_start;
100         text_end = text_start + exec_aouthdr.tsize;
101         text_offset = text_hdr.s_scnptr;
102         exec_data_start = exec_aouthdr.data_start;
103         exec_data_end = exec_data_start + exec_aouthdr.dsize;
104         exec_data_offset = data_hdr.s_scnptr;
105         data_start = exec_data_start;
106         data_end += exec_data_start;
107         exec_mtime = file_hdr.f_timdat;
108       }
109 #else /* not COFF_FORMAT */
110       {
111         struct stat st_exec;
112
113         val = myread (execchan, &exec_aouthdr, sizeof (AOUTHDR));
114
115         if (val < 0)
116           perror_with_name (filename);
117
118         text_start = N_ADDRADJ(exec_aouthdr);
119         exec_data_start = round(exec_aouthdr.a_text, NBPG*CLSIZE);
120         text_offset = N_TXTOFF (exec_aouthdr);
121         exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
122         text_end = exec_aouthdr.a_text;
123         exec_data_end = exec_data_start + exec_aouthdr.a_data;
124         data_start = exec_data_start;
125         data_end = data_start + exec_aouthdr.a_data;
126         exec_data_offset = N_TXTOFF(exec_aouthdr);
127         fstat (execchan, &st_exec);
128         exec_mtime = st_exec.st_mtime;
129       }
130 #endif /* not COFF_FORMAT */
131
132       validate_files ();
133     }
134   else if (from_tty)
135     printf ("No exec file now.\n");
136
137   /* Tell display code (if any) about the changed file name.  */
138   if (exec_file_display_hook)
139     (*exec_file_display_hook) (filename);
140 }
141
142 /* rounds 'one' up to divide evenly by 'two' */
143
144 int
145 round(one,two)
146 register int one, two;
147
148 {
149     register int temp;
150     temp = (one/two)*two;
151     if (one != temp) {
152         temp += two;
153     }
154     return temp;
155 }
156
157
158 static CORE_ADDR codestream_next_addr;
159 static CORE_ADDR codestream_addr;
160 static unsigned char codestream_buf[sizeof (int)];
161 static int codestream_off;
162 static int codestream_cnt;
163
164 #define codestream_tell() (codestream_addr + codestream_off)
165 #define codestream_peek() (codestream_cnt == 0 ? \
166                            codestream_fill(1): codestream_buf[codestream_off])
167 #define codestream_get() (codestream_cnt-- == 0 ? \
168                          codestream_fill(0) : codestream_buf[codestream_off++])
169
170
171 static unsigned char 
172 codestream_fill (peek_flag)
173 {
174   codestream_addr = codestream_next_addr;
175   codestream_next_addr += sizeof (int);
176   codestream_off = 0;
177   codestream_cnt = sizeof (int);
178   read_memory (codestream_addr,
179                (unsigned char *)codestream_buf,
180                sizeof (int));
181   
182   if (peek_flag)
183     return (codestream_peek());
184   else
185     return (codestream_get());
186 }
187
188 static void
189 codestream_seek (place)
190 {
191   codestream_next_addr = place & -sizeof (int);
192   codestream_cnt = 0;
193   codestream_fill (1);
194   while (codestream_tell() != place)
195     codestream_get ();
196 }
197
198 static void
199 codestream_read (buf, count)
200      unsigned char *buf;
201 {
202   unsigned char *p;
203   int i;
204   p = buf;
205   for (i = 0; i < count; i++)
206     *p++ = codestream_get ();
207 }
208
209 /*
210  * Following macro translates i386 opcode register numbers to Symmetry
211  * register numbers.  This is used by FRAME_FIND_SAVED_REGS.
212  *
213  *           %eax  %ecx  %edx  %ebx  %esp  %ebp  %esi  %edi
214  * i386        0     1     2     3     4     5     6     7
215  * Symmetry    0     2     1     5    14    15     6     7
216  *
217  */
218 #define I386_REGNO_TO_SYMMETRY(n) \
219 ((n)==0?0 :(n)==1?2 :(n)==2?1 :(n)==3?5 :(n)==4?14 :(n)==5?15 :(n))
220
221 /* from i386-dep.c */
222 i386_frame_find_saved_regs (fip, fsrp)
223      struct frame_info *fip;
224      struct frame_saved_regs *fsrp;
225 {
226   unsigned long locals;
227   unsigned char *p;
228   unsigned char op;
229   CORE_ADDR dummy_bottom;
230   CORE_ADDR adr;
231   int i;
232   
233   bzero (fsrp, sizeof *fsrp);
234   
235   /* if frame is the end of a dummy, compute where the
236    * beginning would be
237    */
238   dummy_bottom = fip->frame - 4 - NUM_REGS*4 - CALL_DUMMY_LENGTH;
239   
240   /* check if the PC is in the stack, in a dummy frame */
241   if (dummy_bottom <= fip->pc && fip->pc <= fip->frame) 
242     {
243       /* all regs were saved by push_call_dummy () */
244       adr = fip->frame - 4;
245       for (i = 0; i < NUM_REGS; i++) 
246         {
247           fsrp->regs[i] = adr;
248           adr -= 4;
249         }
250       return;
251     }
252   
253   locals = i386_get_frame_setup (get_pc_function_start (fip->pc));
254   
255   if (locals >= 0) 
256     {
257       adr = fip->frame - 4 - locals;
258       for (i = 0; i < 8; i++) 
259         {
260           op = codestream_get ();
261           if (op < 0x50 || op > 0x57)
262             break;
263           fsrp->regs[I386_REGNO_TO_SYMMETRY(op - 0x50)] = adr;
264           adr -= 4;
265         }
266     }
267   
268   fsrp->regs[PC_REGNUM] = fip->frame + 4;
269   fsrp->regs[FP_REGNUM] = fip->frame;
270 }
271
272 static long
273 i386_get_frame_setup (pc)
274 {
275   unsigned char op;
276   
277   codestream_seek (pc);
278   
279   i386_follow_jump ();
280   
281   op = codestream_get ();
282   
283   if (op == 0x58) /* popl %eax */
284     {
285       /*
286        * this function must start with
287        * 
288        *    popl %eax             0x58
289        *    xchgl %eax, (%esp)  0x87 0x04 0x24
290        * or xchgl %eax, 0(%esp) 0x87 0x44 0x24 0x00
291        *
292        * (the system 5 compiler puts out the second xchg
293        * inst, and the assembler doesn't try to optimize it,
294        * so the 'sib' form gets generated)
295        * 
296        * this sequence is used to get the address of the return
297        * buffer for a function that returns a structure
298        */
299       int pos;
300       unsigned char buf[4];
301       static unsigned char proto1[3] = { 0x87,0x04,0x24 };
302       static unsigned char proto2[4] = { 0x87,0x44,0x24,0x00 };
303       pos = codestream_tell ();
304       codestream_read (buf, 4);
305       if (bcmp (buf, proto1, 3) == 0)
306         pos += 3;
307       else if (bcmp (buf, proto2, 4) == 0)
308         pos += 4;
309       
310       codestream_seek (pos);
311       op = codestream_get (); /* update next opcode */
312     }
313   
314   if (op == 0x55)                       /* pushl %esp */
315     {
316       if (codestream_get () != 0x8b)    /* movl %esp, %ebp (2bytes) */
317         return (-1);
318       if (codestream_get () != 0xec)
319         return (-1);
320       /*
321        * check for stack adjustment 
322        *
323        *  subl $XXX, %esp
324        *
325        * note: you can't subtract a 16 bit immediate
326        * from a 32 bit reg, so we don't have to worry
327        * about a data16 prefix 
328        */
329       op = codestream_peek ();
330       if (op == 0x83)  /* subl with 8 bit immed */
331         {
332           codestream_get ();
333           if (codestream_get () != 0xec)
334             return (-1);
335           /* subl with signed byte immediate 
336            * (though it wouldn't make sense to be negative)
337            */
338           return (codestream_get());
339         }
340       else if (op == 0x81)  /* subl with 32 bit immed */
341         {
342           int locals;
343           if (codestream_get () != 0xec)
344             return (-1);
345           /* subl with 32 bit immediate */
346           codestream_read ((unsigned char *)&locals, 4);
347           return (locals);
348         } 
349       else 
350         {
351           return (0);
352         }
353     } 
354   else if (op == 0xc8) 
355     {
356       /* enter instruction: arg is 16 unsigned immed */
357       unsigned short slocals;
358       codestream_read ((unsigned char *)&slocals, 2);
359       codestream_get (); /* flush final byte of enter instruction */
360       return (slocals);
361     }
362   return (-1);
363 }
364
365 /* next instruction is a jump, move to target */
366 static
367 i386_follow_jump ()
368 {
369   int long_delta;
370   short short_delta;
371   char byte_delta;
372   int data16;
373   int pos;
374   
375   pos = codestream_tell ();
376   
377   data16 = 0;
378   if (codestream_peek () == 0x66)
379     {
380       codestream_get ();
381       data16 = 1;
382     }
383   
384   switch (codestream_get ())
385     {
386     case 0xe9:
387       /* relative jump: if data16 == 0, disp32, else disp16 */
388       if (data16)
389         {
390           codestream_read ((unsigned char *)&short_delta, 2);
391           pos += short_delta + 3; /* include size of jmp inst */
392         }
393       else
394         {
395           codestream_read ((unsigned char *)&long_delta, 4);
396           pos += long_delta + 5;
397         }
398       break;
399     case 0xeb:
400       /* relative jump, disp8 (ignore data16) */
401       codestream_read ((unsigned char *)&byte_delta, 1);
402       pos += byte_delta + 2;
403       break;
404     }
405   codestream_seek (pos + data16);
406 }
407
408 /* return pc of first real instruction */
409 /* from i386-dep.c */
410
411 i386_skip_prologue (pc)
412 {
413   unsigned char op;
414   int i;
415   
416   if (i386_get_frame_setup (pc) < 0)
417     return (pc);
418   
419   /* found valid frame setup - codestream now points to 
420    * start of push instructions for saving registers
421    */
422   
423   /* skip over register saves */
424   for (i = 0; i < 8; i++)
425     {
426       op = codestream_peek ();
427       /* break if not pushl inst */
428       if (op < 0x50 || op > 0x57) 
429         break;
430       codestream_get ();
431     }
432   
433   i386_follow_jump ();
434   
435   return (codestream_tell ());
436 }
437
438 symmetry_extract_return_value(type, regbuf, valbuf)
439      struct type *type;
440      char *regbuf;
441      char *valbuf;
442 {
443   union { 
444     double      d; 
445     int l[2]; 
446   } xd; 
447   int i;
448   float f;
449
450   if (TYPE_CODE_FLT == TYPE_CODE(type)) { 
451     for (i = 0; i < misc_function_count; i++) {
452       if (!strcmp(misc_function_vector[i].name, "1167_flt"))
453         break;
454     }
455     if (i < misc_function_count) {
456       /* found "1167_flt" means 1167, %fp2-%fp3 */ 
457       /* float & double; 19= %fp2, 20= %fp3 */
458       /* no single precision on 1167 */
459       xd.l[1] = *((int *)&regbuf[REGISTER_BYTE(19)]);
460       xd.l[0] = *((int *)&regbuf[REGISTER_BYTE(20)]);
461       switch (TYPE_LENGTH(type)) {
462       case 4:
463         f = (float) xd.d;
464         bcopy(&f, valbuf, TYPE_LENGTH(type));
465         break;
466       case 8:
467         bcopy(&xd.d, valbuf, TYPE_LENGTH(type)); 
468         break;
469       default:
470         error("Unknown floating point size");
471         break;
472       }
473     } else { 
474       /* 387 %st(0), gcc uses this */ 
475       i387_to_double(((int *)&regbuf[REGISTER_BYTE(3)]),
476                      &xd.d); 
477       switch (TYPE_LENGTH(type)) {
478       case 4:                   /* float */
479         f = (float) xd.d;
480         bcopy(&f, valbuf, 4); 
481         break;
482       case 8:                   /* double */
483         bcopy(&xd.d, valbuf, 8);
484         break;
485       default:
486         error("Unknown floating point size");
487         break;
488       }
489     }
490   } else { 
491     bcopy (regbuf, valbuf, TYPE_LENGTH (type)); 
492   }
493 }
This page took 0.059216 seconds and 4 git commands to generate.