]>
Commit | Line | Data |
---|---|---|
7a7adcdf JB |
1 | /* Native-dependent code for Interix running on i386's, for GDB. |
2 | Copyright 2002 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |
19 | ||
20 | #include "defs.h" | |
21 | ||
22 | #include <sys/procfs.h> | |
23 | #include <inferior.h> | |
24 | #include <fcntl.h> | |
25 | ||
26 | #include <i386-tdep.h> | |
27 | #include "gdb_string.h" | |
28 | #include "gdbcore.h" | |
29 | #include "gregset.h" | |
30 | #include "regcache.h" | |
31 | ||
32 | typedef unsigned long greg_t; | |
33 | ||
34 | /* This is a duplicate of the table in i386-linux-nat.c. */ | |
35 | ||
36 | static int regmap[] = { | |
37 | EAX, ECX, EDX, EBX, | |
38 | UESP, EBP, ESI, EDI, | |
39 | EIP, EFL, CS, SS, | |
40 | DS, ES, FS, GS, | |
41 | }; | |
42 | ||
43 | /* Forward declarations. */ | |
44 | extern void _initialize_core_interix (void); | |
45 | extern initialize_file_ftype _initialize_core_interix; | |
46 | ||
47 | /* Given a pointer to a general register set in /proc format (gregset_t *), | |
48 | unpack the register contents and supply them as gdb's idea of the current | |
49 | register values. */ | |
50 | ||
51 | void | |
52 | supply_gregset (gregset_t *gregsetp) | |
53 | { | |
54 | int regi; | |
55 | greg_t *regp = (greg_t *) & gregsetp->gregs; | |
56 | ||
57 | for (regi = 0; regi < I386_NUM_GREGS; regi++) | |
58 | { | |
59 | supply_register (regi, (char *) (regp + regmap[regi])); | |
60 | } | |
61 | } | |
62 | ||
63 | /* Store GDB's value for REGNO in *GREGSETP. If REGNO is -1, do all | |
64 | of them. */ | |
65 | ||
66 | void | |
67 | fill_gregset (gregset_t *gregsetp, int regno) | |
68 | { | |
69 | int regi; | |
70 | greg_t *regp = (greg_t *) gregsetp->gregs; | |
71 | ||
72 | for (regi = 0; regi < I386_NUM_GREGS; regi++) | |
73 | if (regno == -1 || regi == regno) | |
74 | regcache_collect (regi, (void *) (regp + regmap[regi])); | |
75 | } | |
76 | ||
77 | /* Fill GDB's register file with the floating-point register values in | |
78 | *FPREGSETP. */ | |
79 | ||
80 | void | |
81 | supply_fpregset (fpregset_t *fpregsetp) | |
82 | { | |
83 | i387_supply_fsave ((char *) fpregsetp); | |
84 | } | |
85 | ||
86 | /* Given a pointer to a floating point register set in (fpregset_t *) | |
87 | format, update all of the registers from gdb's idea of the current | |
88 | floating point register set. */ | |
89 | ||
90 | void | |
91 | fill_fpregset (fpregset_t *fpregsetp, int regno) | |
92 | { | |
93 | i387_fill_fsave ((char *) fpregsetp, regno); | |
94 | } | |
95 | ||
96 | /* Read the values of either the general register set (WHICH equals 0) | |
97 | or the floating point register set (WHICH equals 2) from the core | |
98 | file data (pointed to by CORE_REG_SECT), and update gdb's idea of | |
99 | their current values. The CORE_REG_SIZE parameter is compared to | |
100 | the size of the gregset or fpgregset structures (as appropriate) to | |
101 | validate the size of the structure from the core file. The | |
102 | REG_ADDR parameter is ignored. */ | |
103 | ||
104 | static void | |
105 | fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which, | |
106 | CORE_ADDR reg_addr) | |
107 | { | |
108 | gdb_gregset_t gregset; | |
109 | gdb_fpregset_t fpregset; | |
110 | ||
111 | if (which == 0) | |
112 | { | |
113 | if (core_reg_size != sizeof (gregset)) | |
114 | { | |
115 | warning ("wrong size gregset struct in core file"); | |
116 | } | |
117 | else | |
118 | { | |
119 | memcpy ((char *) &gregset, core_reg_sect, sizeof (gregset)); | |
120 | supply_gregset (&gregset); | |
121 | } | |
122 | } | |
123 | else if (which == 2) | |
124 | { | |
125 | if (core_reg_size != sizeof (fpregset)) | |
126 | { | |
127 | warning ("wrong size fpregset struct in core file"); | |
128 | } | |
129 | else | |
130 | { | |
131 | memcpy ((char *) &fpregset, core_reg_sect, sizeof (fpregset)); | |
132 | supply_fpregset (&fpregset); | |
133 | } | |
134 | } | |
135 | } | |
136 | ||
137 | #include <setjmp.h> | |
138 | ||
139 | static struct core_fns interix_core_fns = | |
140 | { | |
141 | bfd_target_coff_flavour, /* core_flavour (more or less) */ | |
142 | default_check_format, /* check_format */ | |
143 | default_core_sniffer, /* core_sniffer */ | |
144 | fetch_core_registers, /* core_read_registers */ | |
145 | NULL /* next */ | |
146 | }; | |
147 | ||
148 | void | |
149 | _initialize_core_interix (void) | |
150 | { | |
151 | add_core_fns (&interix_core_fns); | |
152 | } | |
153 | ||
154 | /* We don't have a /proc/pid/file or /proc/pid/exe to read a link from, | |
155 | so read it from the same place ps gets the name. */ | |
156 | ||
157 | char * | |
158 | child_pid_to_exec_file (int pid) | |
159 | { | |
160 | char *path; | |
161 | char *buf; | |
162 | int fd, c; | |
163 | char *p; | |
164 | ||
165 | xasprintf (&path, "/proc/%d/stat", pid); | |
166 | buf = xcalloc (MAXPATHLEN + 1, sizeof (char)); | |
167 | make_cleanup (xfree, path); | |
168 | make_cleanup (xfree, buf); | |
169 | ||
170 | fd = open (path, O_RDONLY); | |
171 | ||
172 | if (fd < 0) | |
173 | return NULL; | |
174 | ||
175 | /* Skip over "Argv0\t". */ | |
176 | lseek (fd, 6, SEEK_SET); | |
177 | ||
178 | c = read (fd, buf, MAXPATHLEN); | |
179 | close (fd); | |
180 | ||
181 | if (c < 0) | |
182 | return NULL; | |
183 | ||
184 | buf[c] = '\0'; /* Ensure null termination. */ | |
185 | p = strchr (buf, '\n'); | |
186 | if (p != NULL) | |
187 | *p = '\0'; | |
188 | ||
189 | return buf; | |
190 | } |