e91b87a3 |
1 | /* Low level interface to ptrace, for GDB when running on the Intel 386. |
4187119d |
2 | Copyright (C) 1988, 1989 Free Software Foundation, Inc. |
e91b87a3 |
3 | |
4187119d |
4 | This file is part of GDB. |
e91b87a3 |
5 | |
4187119d |
6 | GDB 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 1, or (at your option) |
9 | any later version. |
e91b87a3 |
10 | |
4187119d |
11 | GDB 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 GDB; see the file COPYING. If not, write to |
18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ |
e91b87a3 |
19 | |
7a67dd45 |
20 | #include <stdio.h> |
e91b87a3 |
21 | #include "defs.h" |
22 | #include "param.h" |
23 | #include "frame.h" |
24 | #include "inferior.h" |
25 | |
26 | #ifdef USG |
27 | #include <sys/types.h> |
28 | #endif |
29 | |
e91b87a3 |
30 | #include <sys/param.h> |
31 | #include <sys/dir.h> |
32 | #include <signal.h> |
33 | #include <sys/user.h> |
34 | #include <sys/ioctl.h> |
35 | #include <fcntl.h> |
36 | |
37 | #ifdef COFF_ENCAPSULATE |
38 | #include "a.out.encap.h" |
39 | #else |
40 | #include <a.out.h> |
41 | #endif |
42 | |
43 | #ifndef N_SET_MAGIC |
44 | #ifdef COFF_FORMAT |
45 | #define N_SET_MAGIC(exec, val) ((exec).magic = (val)) |
46 | #else |
47 | #define N_SET_MAGIC(exec, val) ((exec).a_magic = (val)) |
48 | #endif |
49 | #endif |
50 | |
51 | #include <sys/file.h> |
52 | #include <sys/stat.h> |
53 | |
54 | #include <sys/reg.h> |
55 | |
56 | extern int errno; |
57 | \f |
58 | /* This function simply calls ptrace with the given arguments. |
59 | It exists so that all calls to ptrace are isolated in this |
60 | machine-dependent file. */ |
61 | int |
62 | call_ptrace (request, pid, arg3, arg4) |
63 | int request, pid, arg3, arg4; |
64 | { |
65 | return ptrace (request, pid, arg3, arg4); |
66 | } |
67 | |
68 | kill_inferior () |
69 | { |
70 | if (remote_debugging) |
71 | return; |
72 | if (inferior_pid == 0) |
73 | return; |
74 | ptrace (8, inferior_pid, 0, 0); |
75 | wait (0); |
76 | inferior_died (); |
77 | } |
78 | |
79 | /* This is used when GDB is exiting. It gives less chance of error.*/ |
80 | |
81 | kill_inferior_fast () |
82 | { |
83 | if (remote_debugging) |
84 | return; |
85 | if (inferior_pid == 0) |
86 | return; |
87 | ptrace (8, inferior_pid, 0, 0); |
88 | wait (0); |
89 | } |
90 | |
91 | /* Resume execution of the inferior process. |
92 | If STEP is nonzero, single-step it. |
93 | If SIGNAL is nonzero, give it that signal. */ |
94 | |
95 | void |
96 | resume (step, signal) |
97 | int step; |
98 | int signal; |
99 | { |
100 | errno = 0; |
101 | if (remote_debugging) |
102 | remote_resume (step, signal); |
103 | else |
104 | { |
105 | ptrace (step ? 9 : 7, inferior_pid, 1, signal); |
106 | if (errno) |
107 | perror_with_name ("ptrace"); |
108 | } |
109 | } |
110 | \f |
111 | void |
112 | fetch_inferior_registers () |
113 | { |
114 | register int regno; |
115 | register unsigned int regaddr; |
116 | char buf[MAX_REGISTER_RAW_SIZE]; |
117 | register int i; |
118 | |
119 | struct user u; |
120 | unsigned int offset = (char *) &u.u_ar0 - (char *) &u; |
121 | offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR; |
122 | |
123 | for (regno = 0; regno < NUM_REGS; regno++) |
124 | { |
125 | regaddr = register_addr (regno, offset); |
126 | for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int)) |
127 | { |
128 | *(int *) &buf[i] = ptrace (3, inferior_pid, regaddr, 0); |
129 | regaddr += sizeof (int); |
130 | } |
131 | supply_register (regno, buf); |
132 | } |
133 | } |
134 | |
135 | /* Store our register values back into the inferior. |
136 | If REGNO is -1, do this for all registers. |
137 | Otherwise, REGNO specifies which register (so we can save time). */ |
138 | |
139 | store_inferior_registers (regno) |
140 | int regno; |
141 | { |
142 | register unsigned int regaddr; |
143 | char buf[80]; |
144 | |
145 | struct user u; |
146 | unsigned int offset = (char *) &u.u_ar0 - (char *) &u; |
147 | offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR; |
148 | |
149 | if (regno >= 0) |
150 | { |
151 | regaddr = register_addr (regno, offset); |
152 | errno = 0; |
153 | ptrace (6, inferior_pid, regaddr, read_register (regno)); |
154 | if (errno != 0) |
155 | { |
156 | sprintf (buf, "writing register number %d", regno); |
157 | perror_with_name (buf); |
158 | } |
159 | } |
160 | else for (regno = 0; regno < NUM_REGS; regno++) |
161 | { |
162 | regaddr = register_addr (regno, offset); |
163 | errno = 0; |
164 | ptrace (6, inferior_pid, regaddr, read_register (regno)); |
165 | if (errno != 0) |
166 | { |
167 | sprintf (buf, "writing register number %d", regno); |
168 | perror_with_name (buf); |
169 | } |
170 | } |
171 | } |
172 | \f |
173 | /* Copy LEN bytes from inferior's memory starting at MEMADDR |
174 | to debugger memory starting at MYADDR. |
175 | On failure (cannot read from inferior, usually because address is out |
176 | of bounds) returns the value of errno. */ |
177 | |
178 | int |
179 | read_inferior_memory (memaddr, myaddr, len) |
180 | CORE_ADDR memaddr; |
181 | char *myaddr; |
182 | int len; |
183 | { |
184 | register int i; |
185 | /* Round starting address down to longword boundary. */ |
186 | register CORE_ADDR addr = memaddr & - sizeof (int); |
187 | /* Round ending address up; get number of longwords that makes. */ |
188 | register int count |
189 | = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int); |
190 | /* Allocate buffer of that many longwords. */ |
191 | register int *buffer = (int *) alloca (count * sizeof (int)); |
192 | extern int errno; |
193 | |
194 | /* Read all the longwords */ |
195 | for (i = 0; i < count; i++, addr += sizeof (int)) |
196 | { |
197 | errno = 0; |
198 | if (remote_debugging) |
199 | buffer[i] = remote_fetch_word (addr); |
200 | else |
201 | buffer[i] = ptrace (1, inferior_pid, addr, 0); |
202 | if (errno) |
203 | return errno; |
204 | } |
205 | |
206 | /* Copy appropriate bytes out of the buffer. */ |
207 | bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len); |
208 | return 0; |
209 | } |
210 | |
211 | /* Copy LEN bytes of data from debugger memory at MYADDR |
212 | to inferior's memory at MEMADDR. |
213 | On failure (cannot write the inferior) |
214 | returns the value of errno. */ |
215 | |
216 | int |
217 | write_inferior_memory (memaddr, myaddr, len) |
218 | CORE_ADDR memaddr; |
219 | char *myaddr; |
220 | int len; |
221 | { |
222 | register int i; |
223 | /* Round starting address down to longword boundary. */ |
224 | register CORE_ADDR addr = memaddr & - sizeof (int); |
225 | /* Round ending address up; get number of longwords that makes. */ |
226 | register int count |
227 | = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int); |
228 | /* Allocate buffer of that many longwords. */ |
229 | register int *buffer = (int *) alloca (count * sizeof (int)); |
230 | extern int errno; |
231 | |
232 | /* Fill start and end extra bytes of buffer with existing memory data. */ |
233 | |
234 | if (remote_debugging) |
235 | buffer[0] = remote_fetch_word (addr); |
236 | else |
237 | buffer[0] = ptrace (1, inferior_pid, addr, 0); |
238 | |
239 | if (count > 1) |
240 | { |
241 | if (remote_debugging) |
242 | buffer[count - 1] |
243 | = remote_fetch_word (addr + (count - 1) * sizeof (int)); |
244 | else |
245 | buffer[count - 1] |
246 | = ptrace (1, inferior_pid, |
247 | addr + (count - 1) * sizeof (int), 0); |
248 | } |
249 | |
250 | /* Copy data to be written over corresponding part of buffer */ |
251 | |
252 | bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len); |
253 | |
254 | /* Write the entire buffer. */ |
255 | |
256 | for (i = 0; i < count; i++, addr += sizeof (int)) |
257 | { |
258 | errno = 0; |
259 | if (remote_debugging) |
260 | remote_store_word (addr, buffer[i]); |
261 | else |
262 | ptrace (4, inferior_pid, addr, buffer[i]); |
263 | if (errno) |
264 | return errno; |
265 | } |
266 | |
267 | return 0; |
268 | } |
269 | \f |
270 | /* Work with core dump and executable files, for GDB. |
271 | This code would be in core.c if it weren't machine-dependent. */ |
272 | |
273 | #ifndef N_TXTADDR |
274 | #define N_TXTADDR(hdr) 0 |
275 | #endif /* no N_TXTADDR */ |
276 | |
277 | #ifndef N_DATADDR |
278 | #define N_DATADDR(hdr) hdr.a_text |
279 | #endif /* no N_DATADDR */ |
280 | |
281 | /* Make COFF and non-COFF names for things a little more compatible |
282 | to reduce conditionals later. */ |
283 | |
284 | #ifndef COFF_FORMAT |
4187119d |
285 | #ifndef AOUTHDR |
e91b87a3 |
286 | #define AOUTHDR struct exec |
287 | #endif |
4187119d |
288 | #endif |
e91b87a3 |
289 | |
290 | extern char *sys_siglist[]; |
291 | |
292 | |
293 | /* Hook for `exec_file_command' command to call. */ |
294 | |
295 | extern void (*exec_file_display_hook) (); |
296 | |
297 | /* File names of core file and executable file. */ |
298 | |
299 | extern char *corefile; |
300 | extern char *execfile; |
301 | |
302 | /* Descriptors on which core file and executable file are open. |
303 | Note that the execchan is closed when an inferior is created |
304 | and reopened if the inferior dies or is killed. */ |
305 | |
306 | extern int corechan; |
307 | extern int execchan; |
308 | |
309 | /* Last modification time of executable file. |
310 | Also used in source.c to compare against mtime of a source file. */ |
311 | |
312 | extern int exec_mtime; |
313 | |
314 | /* Virtual addresses of bounds of the two areas of memory in the core file. */ |
315 | |
316 | extern CORE_ADDR data_start; |
317 | extern CORE_ADDR data_end; |
318 | extern CORE_ADDR stack_start; |
319 | extern CORE_ADDR stack_end; |
320 | |
321 | /* Virtual addresses of bounds of two areas of memory in the exec file. |
322 | Note that the data area in the exec file is used only when there is no core file. */ |
323 | |
324 | extern CORE_ADDR text_start; |
325 | extern CORE_ADDR text_end; |
326 | |
327 | extern CORE_ADDR exec_data_start; |
328 | extern CORE_ADDR exec_data_end; |
329 | |
330 | /* Address in executable file of start of text area data. */ |
331 | |
332 | extern int text_offset; |
333 | |
334 | /* Address in executable file of start of data area data. */ |
335 | |
336 | extern int exec_data_offset; |
337 | |
338 | /* Address in core file of start of data area data. */ |
339 | |
340 | extern int data_offset; |
341 | |
342 | /* Address in core file of start of stack area data. */ |
343 | |
344 | extern int stack_offset; |
345 | |
346 | #ifdef COFF_FORMAT |
347 | /* various coff data structures */ |
348 | |
349 | extern FILHDR file_hdr; |
350 | extern SCNHDR text_hdr; |
351 | extern SCNHDR data_hdr; |
352 | |
353 | #endif /* not COFF_FORMAT */ |
354 | |
355 | /* a.out header saved in core file. */ |
356 | |
357 | extern AOUTHDR core_aouthdr; |
358 | |
359 | /* a.out header of exec file. */ |
360 | |
361 | extern AOUTHDR exec_aouthdr; |
362 | |
363 | extern void validate_files (); |
364 | \f |
365 | core_file_command (filename, from_tty) |
366 | char *filename; |
367 | int from_tty; |
368 | { |
369 | int val; |
370 | extern char registers[]; |
371 | |
372 | /* Discard all vestiges of any previous core file |
373 | and mark data and stack spaces as empty. */ |
374 | |
375 | if (corefile) |
376 | free (corefile); |
377 | corefile = 0; |
378 | |
379 | if (corechan >= 0) |
380 | close (corechan); |
381 | corechan = -1; |
382 | |
383 | data_start = 0; |
384 | data_end = 0; |
385 | stack_start = STACK_END_ADDR; |
386 | stack_end = STACK_END_ADDR; |
387 | |
388 | /* Now, if a new core file was specified, open it and digest it. */ |
389 | |
390 | if (filename) |
391 | { |
4187119d |
392 | filename = tilde_expand (filename); |
393 | make_cleanup (free, filename); |
394 | |
e91b87a3 |
395 | if (have_inferior_p ()) |
396 | error ("To look at a core file, you must kill the inferior with \"kill\"."); |
397 | corechan = open (filename, O_RDONLY, 0); |
398 | if (corechan < 0) |
399 | perror_with_name (filename); |
400 | /* 4.2-style (and perhaps also sysV-style) core dump file. */ |
401 | { |
402 | struct user u; |
403 | |
404 | int reg_offset; |
405 | |
406 | val = myread (corechan, &u, sizeof u); |
407 | if (val < 0) |
408 | perror_with_name (filename); |
409 | data_start = exec_data_start; |
410 | |
411 | data_end = data_start + NBPG * u.u_dsize; |
412 | stack_start = stack_end - NBPG * u.u_ssize; |
413 | data_offset = NBPG * UPAGES; |
414 | stack_offset = NBPG * (UPAGES + u.u_dsize); |
415 | reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR; |
416 | |
417 | /* I don't know where to find this info. |
418 | So, for now, mark it as not available. */ |
419 | /* N_SET_MAGIC (core_aouthdr, 0); */ |
420 | bzero ((char *) &core_aouthdr, sizeof core_aouthdr); |
421 | |
422 | /* Read the register values out of the core file and store |
423 | them where `read_register' will find them. */ |
424 | |
425 | { |
426 | register int regno; |
427 | |
428 | for (regno = 0; regno < NUM_REGS; regno++) |
429 | { |
430 | char buf[MAX_REGISTER_RAW_SIZE]; |
431 | |
432 | val = lseek (corechan, register_addr (regno, reg_offset), 0); |
433 | if (val < 0) |
434 | perror_with_name (filename); |
435 | |
436 | val = myread (corechan, buf, sizeof buf); |
437 | if (val < 0) |
438 | perror_with_name (filename); |
439 | supply_register (regno, buf); |
440 | } |
441 | } |
442 | } |
443 | if (filename[0] == '/') |
444 | corefile = savestring (filename, strlen (filename)); |
445 | else |
446 | { |
447 | corefile = concat (current_directory, "/", filename); |
448 | } |
449 | |
450 | set_current_frame ( create_new_frame (read_register (FP_REGNUM), |
451 | read_pc ())); |
452 | select_frame (get_current_frame (), 0); |
453 | validate_files (); |
454 | } |
455 | else if (from_tty) |
456 | printf ("No core file now.\n"); |
457 | } |
458 | \f |
459 | exec_file_command (filename, from_tty) |
460 | char *filename; |
461 | int from_tty; |
462 | { |
463 | int val; |
464 | |
465 | /* Eliminate all traces of old exec file. |
466 | Mark text segment as empty. */ |
467 | |
468 | if (execfile) |
469 | free (execfile); |
470 | execfile = 0; |
471 | data_start = 0; |
472 | data_end -= exec_data_start; |
473 | text_start = 0; |
474 | text_end = 0; |
475 | exec_data_start = 0; |
476 | exec_data_end = 0; |
477 | if (execchan >= 0) |
478 | close (execchan); |
479 | execchan = -1; |
480 | |
481 | /* Now open and digest the file the user requested, if any. */ |
482 | |
483 | if (filename) |
484 | { |
4187119d |
485 | filename = tilde_expand (filename); |
486 | make_cleanup (free, filename); |
487 | |
e91b87a3 |
488 | execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0, |
489 | &execfile); |
490 | if (execchan < 0) |
491 | perror_with_name (filename); |
492 | |
493 | #ifdef COFF_FORMAT |
494 | { |
495 | int aout_hdrsize; |
496 | int num_sections; |
497 | |
498 | if (read_file_hdr (execchan, &file_hdr) < 0) |
499 | error ("\"%s\": not in executable format.", execfile); |
500 | |
501 | aout_hdrsize = file_hdr.f_opthdr; |
502 | num_sections = file_hdr.f_nscns; |
503 | |
504 | if (read_aout_hdr (execchan, &exec_aouthdr, aout_hdrsize) < 0) |
505 | error ("\"%s\": can't read optional aouthdr", execfile); |
506 | |
7a67dd45 |
507 | if (read_section_hdr (execchan, _TEXT, &text_hdr, num_sections, |
508 | aout_hdrsize) < 0) |
e91b87a3 |
509 | error ("\"%s\": can't read text section header", execfile); |
510 | |
7a67dd45 |
511 | if (read_section_hdr (execchan, _DATA, &data_hdr, num_sections, |
512 | aout_hdrsize) < 0) |
e91b87a3 |
513 | error ("\"%s\": can't read data section header", execfile); |
514 | |
515 | text_start = exec_aouthdr.text_start; |
516 | text_end = text_start + exec_aouthdr.tsize; |
517 | text_offset = text_hdr.s_scnptr; |
518 | exec_data_start = exec_aouthdr.data_start; |
519 | exec_data_end = exec_data_start + exec_aouthdr.dsize; |
520 | exec_data_offset = data_hdr.s_scnptr; |
521 | data_start = exec_data_start; |
522 | data_end += exec_data_start; |
523 | exec_mtime = file_hdr.f_timdat; |
524 | } |
525 | #else /* not COFF_FORMAT */ |
526 | { |
527 | struct stat st_exec; |
528 | |
529 | #ifdef HEADER_SEEK_FD |
530 | HEADER_SEEK_FD (execchan); |
531 | #endif |
532 | |
533 | val = myread (execchan, &exec_aouthdr, sizeof (AOUTHDR)); |
534 | |
535 | if (val < 0) |
536 | perror_with_name (filename); |
537 | |
538 | text_start = N_TXTADDR (exec_aouthdr); |
539 | exec_data_start = N_DATADDR (exec_aouthdr); |
540 | |
541 | text_offset = N_TXTOFF (exec_aouthdr); |
542 | exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text; |
543 | |
544 | text_end = text_start + exec_aouthdr.a_text; |
545 | exec_data_end = exec_data_start + exec_aouthdr.a_data; |
546 | data_start = exec_data_start; |
547 | data_end += exec_data_start; |
548 | |
549 | fstat (execchan, &st_exec); |
550 | exec_mtime = st_exec.st_mtime; |
551 | } |
552 | #endif /* not COFF_FORMAT */ |
553 | |
554 | validate_files (); |
555 | } |
556 | else if (from_tty) |
557 | printf ("No exec file now.\n"); |
558 | |
559 | /* Tell display code (if any) about the changed file name. */ |
560 | if (exec_file_display_hook) |
561 | (*exec_file_display_hook) (filename); |
562 | } |
563 | |
564 | /* helper functions for m-i386.h */ |
565 | |
566 | /* stdio style buffering to minimize calls to ptrace */ |
567 | static CORE_ADDR codestream_next_addr; |
568 | static CORE_ADDR codestream_addr; |
569 | static unsigned char codestream_buf[sizeof (int)]; |
570 | static int codestream_off; |
571 | static int codestream_cnt; |
572 | |
573 | #define codestream_tell() (codestream_addr + codestream_off) |
574 | #define codestream_peek() (codestream_cnt == 0 ? \ |
575 | codestream_fill(1): codestream_buf[codestream_off]) |
576 | #define codestream_get() (codestream_cnt-- == 0 ? \ |
577 | codestream_fill(0) : codestream_buf[codestream_off++]) |
578 | |
579 | static unsigned char |
580 | codestream_fill (peek_flag) |
581 | { |
582 | codestream_addr = codestream_next_addr; |
583 | codestream_next_addr += sizeof (int); |
584 | codestream_off = 0; |
585 | codestream_cnt = sizeof (int); |
586 | read_memory (codestream_addr, |
587 | (unsigned char *)codestream_buf, |
588 | sizeof (int)); |
589 | |
590 | if (peek_flag) |
591 | return (codestream_peek()); |
592 | else |
593 | return (codestream_get()); |
594 | } |
595 | |
596 | static void |
597 | codestream_seek (place) |
598 | { |
599 | codestream_next_addr = place & -sizeof (int); |
600 | codestream_cnt = 0; |
601 | codestream_fill (1); |
602 | while (codestream_tell() != place) |
603 | codestream_get (); |
604 | } |
605 | |
606 | static void |
607 | codestream_read (buf, count) |
608 | unsigned char *buf; |
609 | { |
610 | unsigned char *p; |
611 | int i; |
612 | p = buf; |
613 | for (i = 0; i < count; i++) |
614 | *p++ = codestream_get (); |
615 | } |
616 | |
617 | /* next instruction is a jump, move to target */ |
618 | static |
619 | i386_follow_jump () |
620 | { |
621 | int long_delta; |
622 | short short_delta; |
623 | char byte_delta; |
624 | int data16; |
625 | int pos; |
626 | |
627 | pos = codestream_tell (); |
628 | |
629 | data16 = 0; |
630 | if (codestream_peek () == 0x66) |
631 | { |
632 | codestream_get (); |
633 | data16 = 1; |
634 | } |
635 | |
636 | switch (codestream_get ()) |
637 | { |
638 | case 0xe9: |
639 | /* relative jump: if data16 == 0, disp32, else disp16 */ |
640 | if (data16) |
641 | { |
642 | codestream_read ((unsigned char *)&short_delta, 2); |
643 | pos += short_delta + 3; /* include size of jmp inst */ |
644 | } |
645 | else |
646 | { |
647 | codestream_read ((unsigned char *)&long_delta, 4); |
648 | pos += long_delta + 5; |
649 | } |
650 | break; |
651 | case 0xeb: |
652 | /* relative jump, disp8 (ignore data16) */ |
653 | codestream_read ((unsigned char *)&byte_delta, 1); |
654 | pos += byte_delta + 2; |
655 | break; |
656 | } |
657 | codestream_seek (pos + data16); |
658 | } |
659 | |
660 | /* |
661 | * find & return amound a local space allocated, and advance codestream to |
662 | * first register push (if any) |
663 | * |
664 | * if entry sequence doesn't make sense, return -1, and leave |
665 | * codestream pointer random |
666 | */ |
667 | static long |
668 | i386_get_frame_setup (pc) |
669 | { |
670 | unsigned char op; |
671 | |
672 | codestream_seek (pc); |
673 | |
674 | i386_follow_jump (); |
675 | |
676 | op = codestream_get (); |
677 | |
678 | if (op == 0x58) /* popl %eax */ |
679 | { |
680 | /* |
681 | * this function must start with |
682 | * |
683 | * popl %eax 0x58 |
684 | * xchgl %eax, (%esp) 0x87 0x04 0x24 |
685 | * or xchgl %eax, 0(%esp) 0x87 0x44 0x24 0x00 |
686 | * |
687 | * (the system 5 compiler puts out the second xchg |
688 | * inst, and the assembler doesn't try to optimize it, |
689 | * so the 'sib' form gets generated) |
690 | * |
691 | * this sequence is used to get the address of the return |
692 | * buffer for a function that returns a structure |
693 | */ |
694 | int pos; |
695 | unsigned char buf[4]; |
696 | static unsigned char proto1[3] = { 0x87,0x04,0x24 }; |
697 | static unsigned char proto2[4] = { 0x87,0x44,0x24,0x00 }; |
698 | pos = codestream_tell (); |
699 | codestream_read (buf, 4); |
700 | if (bcmp (buf, proto1, 3) == 0) |
701 | pos += 3; |
702 | else if (bcmp (buf, proto2, 4) == 0) |
703 | pos += 4; |
704 | |
705 | codestream_seek (pos); |
706 | op = codestream_get (); /* update next opcode */ |
707 | } |
708 | |
709 | if (op == 0x55) /* pushl %esp */ |
710 | { |
711 | /* check for movl %esp, %ebp - can be written two ways */ |
712 | switch (codestream_get ()) |
713 | { |
714 | case 0x8b: |
715 | if (codestream_get () != 0xec) |
716 | return (-1); |
717 | break; |
718 | case 0x89: |
719 | if (codestream_get () != 0xe5) |
720 | return (-1); |
721 | break; |
722 | default: |
723 | return (-1); |
724 | } |
725 | /* check for stack adjustment |
726 | * |
727 | * subl $XXX, %esp |
728 | * |
729 | * note: you can't subtract a 16 bit immediate |
730 | * from a 32 bit reg, so we don't have to worry |
731 | * about a data16 prefix |
732 | */ |
733 | op = codestream_peek (); |
734 | if (op == 0x83) |
735 | { |
736 | /* subl with 8 bit immed */ |
737 | codestream_get (); |
738 | if (codestream_get () != 0xec) |
739 | return (-1); |
740 | /* subl with signed byte immediate |
741 | * (though it wouldn't make sense to be negative) |
742 | */ |
743 | return (codestream_get()); |
744 | } |
745 | else if (op == 0x81) |
746 | { |
747 | /* subl with 32 bit immed */ |
748 | int locals; |
749 | codestream_get(); |
750 | if (codestream_get () != 0xec) |
751 | return (-1); |
752 | /* subl with 32 bit immediate */ |
753 | codestream_read ((unsigned char *)&locals, 4); |
754 | return (locals); |
755 | } |
756 | else |
757 | { |
758 | return (0); |
759 | } |
760 | } |
761 | else if (op == 0xc8) |
762 | { |
763 | /* enter instruction: arg is 16 bit unsigned immed */ |
764 | unsigned short slocals; |
765 | codestream_read ((unsigned char *)&slocals, 2); |
766 | codestream_get (); /* flush final byte of enter instruction */ |
767 | return (slocals); |
768 | } |
769 | return (-1); |
770 | } |
771 | |
1c997a4a |
772 | /* Return number of args passed to a frame. |
773 | Can return -1, meaning no way to tell. */ |
774 | |
775 | /* on the 386, the instruction following the call could be: |
776 | * popl %ecx - one arg |
777 | * addl $imm, %esp - imm/4 args; imm may be 8 or 32 bits |
778 | * anything else - zero args |
779 | */ |
780 | |
781 | int |
782 | i386_frame_num_args (fi) |
783 | struct frame_info fi; |
784 | { |
785 | int retpc; |
786 | unsigned char op; |
787 | struct frame_info *pfi; |
788 | |
789 | pfi = get_prev_frame_info ((fi)); |
790 | if (pfi == 0) |
791 | { |
792 | /* Note: this can happen if we are looking at the frame for |
793 | main, because FRAME_CHAIN_VALID won't let us go into |
794 | start. If we have debugging symbols, that's not really |
795 | a big deal; it just means it will only show as many arguments |
796 | to main as are declared. */ |
797 | return -1; |
798 | } |
799 | else |
800 | { |
801 | retpc = pfi->pc; |
802 | op = read_memory_integer (retpc, 1); |
803 | if (op == 0x59) |
804 | /* pop %ecx */ |
805 | return 1; |
806 | else if (op == 0x83) |
807 | { |
808 | op = read_memory_integer (retpc+1, 1); |
809 | if (op == 0xc4) |
810 | /* addl $<signed imm 8 bits>, %esp */ |
811 | return (read_memory_integer (retpc+2,1)&0xff)/4; |
812 | else |
813 | return 0; |
814 | } |
815 | else if (op == 0x81) |
816 | { /* add with 32 bit immediate */ |
817 | op = read_memory_integer (retpc+1, 1); |
818 | if (op == 0xc4) |
819 | /* addl $<imm 32>, %esp */ |
820 | return read_memory_integer (retpc+2, 4) / 4; |
821 | else |
822 | return 0; |
823 | } |
824 | else |
825 | { |
826 | return 0; |
827 | } |
828 | } |
829 | } |
830 | |
e91b87a3 |
831 | /* |
832 | * parse the first few instructions of the function to see |
833 | * what registers were stored. |
834 | * |
835 | * We handle these cases: |
836 | * |
837 | * The startup sequence can be at the start of the function, |
838 | * or the function can start with a branch to startup code at the end. |
839 | * |
840 | * %ebp can be set up with either the 'enter' instruction, or |
841 | * 'pushl %ebp, movl %esp, %ebp' (enter is too slow to be useful, |
842 | * but was once used in the sys5 compiler) |
843 | * |
844 | * Local space is allocated just below the saved %ebp by either the |
845 | * 'enter' instruction, or by 'subl $<size>, %esp'. 'enter' has |
846 | * a 16 bit unsigned argument for space to allocate, and the |
847 | * 'addl' instruction could have either a signed byte, or |
848 | * 32 bit immediate. |
849 | * |
850 | * Next, the registers used by this function are pushed. In |
851 | * the sys5 compiler they will always be in the order: %edi, %esi, %ebx |
852 | * (and sometimes a harmless bug causes it to also save but not restore %eax); |
853 | * however, the code below is willing to see the pushes in any order, |
854 | * and will handle up to 8 of them. |
855 | * |
856 | * If the setup sequence is at the end of the function, then the |
857 | * next instruction will be a branch back to the start. |
858 | */ |
859 | |
860 | i386_frame_find_saved_regs (fip, fsrp) |
861 | struct frame_info *fip; |
862 | struct frame_saved_regs *fsrp; |
863 | { |
864 | unsigned long locals; |
865 | unsigned char *p; |
866 | unsigned char op; |
867 | CORE_ADDR dummy_bottom; |
868 | CORE_ADDR adr; |
869 | int i; |
870 | |
871 | bzero (fsrp, sizeof *fsrp); |
872 | |
873 | /* if frame is the end of a dummy, compute where the |
874 | * beginning would be |
875 | */ |
876 | dummy_bottom = fip->frame - 4 - NUM_REGS*4 - CALL_DUMMY_LENGTH; |
877 | |
878 | /* check if the PC is in the stack, in a dummy frame */ |
879 | if (dummy_bottom <= fip->pc && fip->pc <= fip->frame) |
880 | { |
881 | /* all regs were saved by push_call_dummy () */ |
882 | adr = fip->frame - 4; |
883 | for (i = 0; i < NUM_REGS; i++) |
884 | { |
885 | fsrp->regs[i] = adr; |
886 | adr -= 4; |
887 | } |
888 | return; |
889 | } |
890 | |
891 | locals = i386_get_frame_setup (get_pc_function_start (fip->pc)); |
892 | |
893 | if (locals >= 0) |
894 | { |
895 | adr = fip->frame - 4 - locals; |
896 | for (i = 0; i < 8; i++) |
897 | { |
898 | op = codestream_get (); |
899 | if (op < 0x50 || op > 0x57) |
900 | break; |
901 | fsrp->regs[op - 0x50] = adr; |
902 | adr -= 4; |
903 | } |
904 | } |
905 | |
906 | fsrp->regs[PC_REGNUM] = fip->frame + 4; |
907 | fsrp->regs[FP_REGNUM] = fip->frame; |
908 | } |
909 | |
910 | /* return pc of first real instruction */ |
911 | i386_skip_prologue (pc) |
912 | { |
913 | unsigned char op; |
914 | int i; |
915 | |
916 | if (i386_get_frame_setup (pc) < 0) |
917 | return (pc); |
918 | |
919 | /* found valid frame setup - codestream now points to |
920 | * start of push instructions for saving registers |
921 | */ |
922 | |
923 | /* skip over register saves */ |
924 | for (i = 0; i < 8; i++) |
925 | { |
926 | op = codestream_peek (); |
927 | /* break if not pushl inst */ |
928 | if (op < 0x50 || op > 0x57) |
929 | break; |
930 | codestream_get (); |
931 | } |
932 | |
933 | i386_follow_jump (); |
934 | |
935 | return (codestream_tell ()); |
936 | } |
937 | |
938 | i386_push_dummy_frame () |
939 | { |
940 | CORE_ADDR sp = read_register (SP_REGNUM); |
941 | int regnum; |
942 | |
943 | sp = push_word (sp, read_register (PC_REGNUM)); |
944 | sp = push_word (sp, read_register (FP_REGNUM)); |
945 | write_register (FP_REGNUM, sp); |
946 | for (regnum = 0; regnum < NUM_REGS; regnum++) |
947 | sp = push_word (sp, read_register (regnum)); |
948 | write_register (SP_REGNUM, sp); |
949 | } |
950 | |
951 | i386_pop_frame () |
952 | { |
953 | FRAME frame = get_current_frame (); |
954 | CORE_ADDR fp; |
955 | int regnum; |
956 | struct frame_saved_regs fsr; |
957 | struct frame_info *fi; |
958 | |
959 | fi = get_frame_info (frame); |
960 | fp = fi->frame; |
961 | get_frame_saved_regs (fi, &fsr); |
962 | for (regnum = 0; regnum < NUM_REGS; regnum++) |
963 | { |
964 | CORE_ADDR adr; |
965 | adr = fsr.regs[regnum]; |
966 | if (adr) |
967 | write_register (regnum, read_memory_integer (adr, 4)); |
968 | } |
969 | write_register (FP_REGNUM, read_memory_integer (fp, 4)); |
970 | write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); |
971 | write_register (SP_REGNUM, fp + 8); |
972 | flush_cached_frames (); |
973 | set_current_frame ( create_new_frame (read_register (FP_REGNUM), |
974 | read_pc ())); |
975 | } |
976 | |
977 | /* this table must line up with REGISTER_NAMES in m-i386.h */ |
978 | /* symbols like 'EAX' come from <sys/reg.h> */ |
979 | static int regmap[] = |
980 | { |
981 | EAX, ECX, EDX, EBX, |
982 | UESP, EBP, ESI, EDI, |
983 | EIP, EFL, CS, SS, |
984 | DS, ES, FS, GS, |
985 | }; |
986 | |
987 | /* blockend is the value of u.u_ar0, and points to the |
988 | * place where GS is stored |
989 | */ |
990 | i386_register_u_addr (blockend, regnum) |
991 | { |
992 | #if 0 |
993 | /* this will be needed if fp registers are reinstated */ |
994 | /* for now, you can look at them with 'info float' |
995 | * sys5 wont let you change them with ptrace anyway |
996 | */ |
997 | if (regnum >= FP0_REGNUM && regnum <= FP7_REGNUM) |
998 | { |
999 | int ubase, fpstate; |
1000 | struct user u; |
1001 | ubase = blockend + 4 * (SS + 1) - KSTKSZ; |
1002 | fpstate = ubase + ((char *)&u.u_fpstate - (char *)&u); |
1003 | return (fpstate + 0x1c + 10 * (regnum - FP0_REGNUM)); |
1004 | } |
1005 | else |
1006 | #endif |
1007 | return (blockend + 4 * regmap[regnum]); |
1008 | |
1009 | } |
1010 | |
1011 | i387_to_double (from, to) |
1012 | char *from; |
1013 | char *to; |
1014 | { |
1015 | long *lp; |
1016 | /* push extended mode on 387 stack, then pop in double mode |
1017 | * |
1018 | * first, set exception masks so no error is generated - |
1019 | * number will be rounded to inf or 0, if necessary |
1020 | */ |
1021 | asm ("pushl %eax"); /* grab a stack slot */ |
1022 | asm ("fstcw (%esp)"); /* get 387 control word */ |
1023 | asm ("movl (%esp),%eax"); /* save old value */ |
1024 | asm ("orl $0x3f,%eax"); /* mask all exceptions */ |
1025 | asm ("pushl %eax"); |
1026 | asm ("fldcw (%esp)"); /* load new value into 387 */ |
1027 | |
1028 | asm ("movl 8(%ebp),%eax"); |
1029 | asm ("fldt (%eax)"); /* push extended number on 387 stack */ |
1030 | asm ("fwait"); |
1031 | asm ("movl 12(%ebp),%eax"); |
1032 | asm ("fstpl (%eax)"); /* pop double */ |
1033 | asm ("fwait"); |
1034 | |
1035 | asm ("popl %eax"); /* flush modified control word */ |
1036 | asm ("fnclex"); /* clear exceptions */ |
1037 | asm ("fldcw (%esp)"); /* restore original control word */ |
1038 | asm ("popl %eax"); /* flush saved copy */ |
1039 | } |
1040 | |
1041 | double_to_i387 (from, to) |
1042 | char *from; |
1043 | char *to; |
1044 | { |
1045 | /* push double mode on 387 stack, then pop in extended mode |
1046 | * no errors are possible because every 64-bit pattern |
1047 | * can be converted to an extended |
1048 | */ |
1049 | asm ("movl 8(%ebp),%eax"); |
1050 | asm ("fldl (%eax)"); |
1051 | asm ("fwait"); |
1052 | asm ("movl 12(%ebp),%eax"); |
1053 | asm ("fstpt (%eax)"); |
1054 | asm ("fwait"); |
1055 | } |
1056 | |
1057 | struct env387 |
1058 | { |
1059 | unsigned short control; |
1060 | unsigned short r0; |
1061 | unsigned short status; |
1062 | unsigned short r1; |
1063 | unsigned short tag; |
1064 | unsigned short r2; |
1065 | unsigned long eip; |
1066 | unsigned short code_seg; |
1067 | unsigned short opcode; |
1068 | unsigned long operand; |
1069 | unsigned short operand_seg; |
1070 | unsigned short r3; |
1071 | unsigned char regs[8][10]; |
1072 | }; |
1073 | |
1074 | static |
1075 | print_387_control_word (control) |
1076 | unsigned short control; |
1077 | { |
1078 | printf ("control 0x%04x: ", control); |
1079 | printf ("compute to "); |
1080 | switch ((control >> 8) & 3) |
1081 | { |
1082 | case 0: printf ("24 bits; "); break; |
1083 | case 1: printf ("(bad); "); break; |
1084 | case 2: printf ("53 bits; "); break; |
1085 | case 3: printf ("64 bits; "); break; |
1086 | } |
1087 | printf ("round "); |
1088 | switch ((control >> 10) & 3) |
1089 | { |
1090 | case 0: printf ("NEAREST; "); break; |
1091 | case 1: printf ("DOWN; "); break; |
1092 | case 2: printf ("UP; "); break; |
1093 | case 3: printf ("CHOP; "); break; |
1094 | } |
1095 | if (control & 0x3f) |
1096 | { |
1097 | printf ("mask:"); |
1098 | if (control & 0x0001) printf (" INVALID"); |
1099 | if (control & 0x0002) printf (" DENORM"); |
1100 | if (control & 0x0004) printf (" DIVZ"); |
1101 | if (control & 0x0008) printf (" OVERF"); |
1102 | if (control & 0x0010) printf (" UNDERF"); |
1103 | if (control & 0x0020) printf (" LOS"); |
1104 | printf (";"); |
1105 | } |
1106 | printf ("\n"); |
1107 | if (control & 0xe080) printf ("warning: reserved bits on 0x%x\n", |
1108 | control & 0xe080); |
1109 | } |
1110 | |
1111 | static |
1112 | print_387_status_word (status) |
1113 | unsigned short status; |
1114 | { |
1115 | printf ("status 0x%04x: ", status); |
1116 | if (status & 0xff) |
1117 | { |
1118 | printf ("exceptions:"); |
1119 | if (status & 0x0001) printf (" INVALID"); |
1120 | if (status & 0x0002) printf (" DENORM"); |
1121 | if (status & 0x0004) printf (" DIVZ"); |
1122 | if (status & 0x0008) printf (" OVERF"); |
1123 | if (status & 0x0010) printf (" UNDERF"); |
1124 | if (status & 0x0020) printf (" LOS"); |
1125 | if (status & 0x0040) printf (" FPSTACK"); |
1126 | printf ("; "); |
1127 | } |
1128 | printf ("flags: %d%d%d%d; ", |
1129 | (status & 0x4000) != 0, |
1130 | (status & 0x0400) != 0, |
1131 | (status & 0x0200) != 0, |
1132 | (status & 0x0100) != 0); |
1133 | |
1134 | printf ("top %d\n", (status >> 11) & 7); |
1135 | } |
1136 | |
1137 | static |
1138 | print_387_status (status, ep) |
1139 | unsigned short status; |
1140 | struct env387 *ep; |
1141 | { |
1142 | int i; |
1143 | int bothstatus; |
1144 | int top; |
1145 | int fpreg; |
1146 | unsigned char *p; |
1147 | |
1148 | bothstatus = ((status != 0) && (ep->status != 0)); |
1149 | if (status != 0) |
1150 | { |
1151 | if (bothstatus) |
1152 | printf ("u: "); |
1153 | print_387_status_word (status); |
1154 | } |
1155 | |
1156 | if (ep->status != 0) |
1157 | { |
1158 | if (bothstatus) |
1159 | printf ("e: "); |
1160 | print_387_status_word (ep->status); |
1161 | } |
1162 | |
1163 | print_387_control_word (ep->control); |
1164 | printf ("last exception: "); |
1165 | printf ("opcode 0x%x; ", ep->opcode); |
1166 | printf ("pc 0x%x:0x%x; ", ep->code_seg, ep->eip); |
1167 | printf ("operand 0x%x:0x%x\n", ep->operand_seg, ep->operand); |
1168 | |
1169 | top = (ep->status >> 11) & 7; |
1170 | |
1171 | printf ("regno tag msb lsb value\n"); |
1172 | for (fpreg = 7; fpreg >= 0; fpreg--) |
1173 | { |
1174 | double val; |
1175 | |
1176 | printf ("%s %d: ", fpreg == top ? "=>" : " ", fpreg); |
1177 | |
1178 | switch ((ep->tag >> (fpreg * 2)) & 3) |
1179 | { |
1180 | case 0: printf ("valid "); break; |
1181 | case 1: printf ("zero "); break; |
1182 | case 2: printf ("trap "); break; |
1183 | case 3: printf ("empty "); break; |
1184 | } |
1185 | for (i = 9; i >= 0; i--) |
1186 | printf ("%02x", ep->regs[fpreg][i]); |
1187 | |
1188 | i387_to_double (ep->regs[fpreg], (char *)&val); |
1189 | printf (" %g\n", val); |
1190 | } |
1191 | if (ep->r0) |
1192 | printf ("warning: reserved0 is 0x%x\n", ep->r0); |
1193 | if (ep->r1) |
1194 | printf ("warning: reserved1 is 0x%x\n", ep->r1); |
1195 | if (ep->r2) |
1196 | printf ("warning: reserved2 is 0x%x\n", ep->r2); |
1197 | if (ep->r3) |
1198 | printf ("warning: reserved3 is 0x%x\n", ep->r3); |
1199 | } |
4187119d |
1200 | |
1201 | #ifndef U_FPSTATE |
1202 | #define U_FPSTATE(u) u.u_fpstate |
1203 | #endif |
1204 | |
e91b87a3 |
1205 | i386_float_info () |
1206 | { |
1207 | struct user u; /* just for address computations */ |
1208 | int i; |
1209 | /* fpstate defined in <sys/user.h> */ |
1210 | struct fpstate *fpstatep; |
1211 | char buf[sizeof (struct fpstate) + 2 * sizeof (int)]; |
1212 | unsigned int uaddr; |
1213 | char fpvalid; |
1214 | unsigned int rounded_addr; |
1215 | unsigned int rounded_size; |
1216 | extern int corechan; |
1217 | int skip; |
1218 | |
1219 | uaddr = (char *)&u.u_fpvalid - (char *)&u; |
1220 | if (have_inferior_p()) |
1221 | { |
1222 | unsigned int data; |
1223 | unsigned int mask; |
1224 | |
1225 | rounded_addr = uaddr & -sizeof (int); |
1226 | data = ptrace (3, inferior_pid, rounded_addr, 0); |
1227 | mask = 0xff << ((uaddr - rounded_addr) * 8); |
1228 | |
1229 | fpvalid = ((data & mask) != 0); |
1230 | } |
1231 | else |
1232 | { |
1233 | if (lseek (corechan, uaddr, 0) < 0) |
1234 | perror ("seek on core file"); |
1235 | if (myread (corechan, &fpvalid, 1) < 0) |
1236 | perror ("read on core file"); |
1237 | |
1238 | } |
1239 | |
1240 | if (fpvalid == 0) |
1241 | { |
1242 | printf ("no floating point status saved\n"); |
1243 | return; |
1244 | } |
1245 | |
4187119d |
1246 | uaddr = (char *)&U_FPSTATE(u) - (char *)&u; |
e91b87a3 |
1247 | if (have_inferior_p ()) |
1248 | { |
1249 | int *ip; |
1250 | |
1251 | rounded_addr = uaddr & -sizeof (int); |
1252 | rounded_size = (((uaddr + sizeof (struct fpstate)) - uaddr) + |
1253 | sizeof (int) - 1) / sizeof (int); |
1254 | skip = uaddr - rounded_addr; |
1255 | |
1256 | ip = (int *)buf; |
1257 | for (i = 0; i < rounded_size; i++) |
1258 | { |
1259 | *ip++ = ptrace (3, inferior_pid, rounded_addr, 0); |
1260 | rounded_addr += sizeof (int); |
1261 | } |
1262 | } |
1263 | else |
1264 | { |
1265 | if (lseek (corechan, uaddr, 0) < 0) |
1266 | perror_with_name ("seek on core file"); |
1267 | if (myread (corechan, buf, sizeof (struct fpstate)) < 0) |
1268 | perror_with_name ("read from core file"); |
1269 | skip = 0; |
1270 | } |
1271 | |
1272 | fpstatep = (struct fpstate *)(buf + skip); |
1273 | print_387_status (fpstatep->status, (struct env387 *)fpstatep->state); |
1274 | } |
1275 | |