1999-11-01 Steve Chamberlain <sac@pobox.com>
[deliverable/binutils-gdb.git] / gdb / i386-linux-nat.c
CommitLineData
d4f3574e
SS
1/* Native-dependent code for Linux running on i386's, for GDB.
2
3This file is part of GDB.
4
5This program is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation; either version 2 of the License, or
8(at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18
19#include "defs.h"
20#include "inferior.h"
21#include "gdbcore.h"
22
23/* For i386_linux_skip_solib_resolver */
24#include "symtab.h"
25#include "frame.h"
26#include "symfile.h"
27#include "objfiles.h"
28
29#include <sys/ptrace.h>
30#include <sys/user.h>
31#include <sys/procfs.h>
32
33#ifdef HAVE_SYS_REG_H
34#include <sys/reg.h>
35#endif
36
37/* This is a duplicate of the table in i386-xdep.c. */
38
39static int regmap[] =
40{
41 EAX, ECX, EDX, EBX,
42 UESP, EBP, ESI, EDI,
43 EIP, EFL, CS, SS,
44 DS, ES, FS, GS,
45};
46
47
917317f4
JM
48/* Given a pointer to a general register set in struct user format
49 (gregset_t *), unpack the register contents and supply them as
50 gdb's idea of the current register values. */
d4f3574e
SS
51void
52supply_gregset (gregsetp)
53 gregset_t *gregsetp;
54{
55 register int regi;
56 register greg_t *regp = (greg_t *) gregsetp;
57
917317f4 58 for (regi = 0; regi < NUM_GREGS; regi++)
d4f3574e
SS
59 {
60 supply_register (regi, (char *) (regp + regmap[regi]));
61 }
62}
63
917317f4
JM
64/* Fill in a gregset_t object with selected data from a gdb-format
65 register file.
66 - GREGSETP points to the gregset_t object to be filled.
67 - GDB_REGS points to the GDB-style register file providing the data.
68 - VALID is an array indicating which registers in GDB_REGS are
69 valid; the parts of *GREGSETP that would hold registers marked
70 invalid in GDB_REGS are left unchanged. If VALID is zero, all
71 registers are assumed to be valid. */
d4f3574e 72void
917317f4
JM
73convert_to_gregset (gregset_t *gregsetp,
74 char *gdb_regs,
75 signed char *valid)
d4f3574e
SS
76{
77 int regi;
78 register greg_t *regp = (greg_t *) gregsetp;
79
917317f4
JM
80 for (regi = 0; regi < NUM_GREGS; regi++)
81 if (! valid || valid[regi])
82 *(regp + regmap[regi]) = * (int *) &registers[REGISTER_BYTE (regi)];
83}
84
85void
86fill_gregset (gregset_t *gregsetp,
87 int regno)
88{
89 if (regno == -1)
90 convert_to_gregset (gregsetp, registers, 0);
91 else
d4f3574e 92 {
917317f4
JM
93 signed char valid[NUM_GREGS];
94 memset (valid, 0, sizeof (valid));
95 valid[regno] = 1;
96 convert_to_gregset (gregsetp, valid, valid);
d4f3574e
SS
97 }
98}
99
100
917317f4
JM
101/* Where does st(N) start in the fpregset_t structure F? */
102#define FPREGSET_T_FPREG_OFFSET(f, n) \
103 ((char *) &(f)->st_space + (n) * 10)
d4f3574e 104
917317f4
JM
105/* Fill GDB's register file with the floating-point register values in
106 *FPREGSETP. */
d4f3574e 107void
917317f4 108supply_fpregset (fpregset_t *fpregsetp)
d4f3574e 109{
917317f4
JM
110 int i;
111
112 /* Supply the floating-point registers. */
113 for (i = 0; i < 8; i++)
114 supply_register (FP0_REGNUM + i, FPREGSET_T_FPREG_OFFSET (fpregsetp, i));
115
116 supply_register (FCTRL_REGNUM, (char *) &fpregsetp->cwd);
117 supply_register (FSTAT_REGNUM, (char *) &fpregsetp->swd);
118 supply_register (FTAG_REGNUM, (char *) &fpregsetp->twd);
119 supply_register (FCOFF_REGNUM, (char *) &fpregsetp->fip);
120 supply_register (FDS_REGNUM, (char *) &fpregsetp->fos);
121 supply_register (FDOFF_REGNUM, (char *) &fpregsetp->foo);
122
123 /* Extract the code segment and opcode from the "fcs" member. */
124 {
125 long l;
126
127 l = fpregsetp->fcs & 0xffff;
128 supply_register (FCS_REGNUM, (char *) &l);
129
130 l = (fpregsetp->fcs >> 16) & ((1 << 11) - 1);
131 supply_register (FOP_REGNUM, (char *) &l);
132 }
d4f3574e
SS
133}
134
d4f3574e 135
917317f4
JM
136/* Fill in an fpregset_t structure with selected data from a
137 gdb-format register file.
138 - FPREGSETP points to the structure to be filled.
139 - GDB_REGS points to the GDB-style register file providing the data.
140 - VALID is an array indicating which registers in GDB_REGS are
141 valid; the parts of *FPREGSETP that would hold registers marked
142 invalid in GDB_REGS are left unchanged. If VALID is zero, all
143 registers are assumed to be valid. */
d4f3574e 144void
917317f4
JM
145convert_to_fpregset (fpregset_t *fpregsetp,
146 char *gdb_regs,
147 signed char *valid)
d4f3574e 148{
917317f4
JM
149 int i;
150
151 /* Fill in the floating-point registers. */
152 for (i = 0; i < 8; i++)
153 if (!valid || valid[i])
154 memcpy (FPREGSET_T_FPREG_OFFSET (fpregsetp, i),
155 &registers[REGISTER_BYTE (FP0_REGNUM + i)],
156 REGISTER_RAW_SIZE(FP0_REGNUM + i));
157
158#define fill(MEMBER, REGNO) \
159 if (! valid || valid[(REGNO)]) \
160 memcpy (&fpregsetp->MEMBER, &registers[REGISTER_BYTE (REGNO)], \
161 sizeof (fpregsetp->MEMBER))
162
163 fill (cwd, FCTRL_REGNUM);
164 fill (swd, FSTAT_REGNUM);
165 fill (twd, FTAG_REGNUM);
166 fill (fip, FCOFF_REGNUM);
167 fill (foo, FDOFF_REGNUM);
168 fill (fos, FDS_REGNUM);
169
170#undef fill
171
172 if (! valid || valid[FCS_REGNUM])
173 fpregsetp->fcs
174 = ((fpregsetp->fcs & ~0xffff)
175 | (* (int *) &registers[REGISTER_BYTE (FCS_REGNUM)] & 0xffff));
176
177 if (! valid || valid[FOP_REGNUM])
178 fpregsetp->fcs
179 = ((fpregsetp->fcs & 0xffff)
180 | ((*(int *) &registers[REGISTER_BYTE (FOP_REGNUM)] & ((1 << 11) - 1))
181 << 16));
182}
d4f3574e 183
917317f4
JM
184
185/* Given a pointer to a floating point register set in (fpregset_t *)
186 format, update all of the registers from gdb's idea of the current
187 floating point register set. */
188
189void
190fill_fpregset (fpregset_t *fpregsetp,
191 int regno)
192{
193 convert_to_fpregset (fpregsetp, registers, 0);
d4f3574e
SS
194}
195
917317f4
JM
196
197/* Get the whole floating point state of the process and store the
198 floating point stack into registers[]. */
d4f3574e 199static void
917317f4 200fetch_fpregs ()
d4f3574e
SS
201{
202 int ret, regno;
917317f4 203 fpregset_t buf;
d4f3574e 204
917317f4
JM
205 ret = ptrace (PTRACE_GETFPREGS, inferior_pid, 0, (int) &buf);
206 if (ret < 0)
d4f3574e
SS
207 {
208 warning ("Couldn't get floating point status");
209 return;
210 }
211
917317f4
JM
212 /* ptrace fills an fpregset_t, so we can use the same function we do
213 for core files. */
214 supply_fpregset (&buf);
d4f3574e
SS
215}
216
217
917317f4
JM
218/* Set the inferior's floating-point registers to the values in
219 registers[] --- but only those registers marked valid. */
d4f3574e 220static void
917317f4 221store_fpregs ()
d4f3574e 222{
917317f4
JM
223 int ret;
224 fpregset_t buf;
d4f3574e 225
917317f4
JM
226 ret = ptrace (PTRACE_GETFPREGS, inferior_pid, 0, (int) &buf);
227 if (ret < 0)
d4f3574e
SS
228 {
229 warning ("Couldn't get floating point status");
230 return;
231 }
232
917317f4 233 convert_to_fpregset (&buf, registers, register_valid);
d4f3574e 234
917317f4
JM
235 ret = ptrace (PTRACE_SETFPREGS, inferior_pid, 0, (int) &buf);
236 if (ret < 0)
d4f3574e
SS
237 {
238 warning ("Couldn't write floating point status");
239 return;
240 }
d4f3574e
SS
241}
242
243
917317f4
JM
244/* Read the general registers from the process, and store them
245 in registers[]. */
d4f3574e 246static void
917317f4 247fetch_regs ()
d4f3574e
SS
248{
249 int ret, regno;
917317f4 250 gregset_t buf;
d4f3574e 251
917317f4
JM
252 ret = ptrace (PTRACE_GETREGS, inferior_pid, 0, (int) &buf);
253 if (ret < 0)
d4f3574e
SS
254 {
255 warning ("Couldn't get registers");
256 return;
257 }
258
917317f4 259 supply_gregset (&buf);
d4f3574e
SS
260}
261
262
917317f4
JM
263/* Set the inferior's general registers to the values in registers[]
264 --- but only those registers marked as valid. */
d4f3574e 265static void
917317f4 266store_regs ()
d4f3574e
SS
267{
268 int ret, regno;
917317f4 269 gregset_t buf;
d4f3574e 270
917317f4
JM
271 ret = ptrace (PTRACE_GETREGS, inferior_pid, 0, (int) &buf);
272 if (ret < 0)
d4f3574e
SS
273 {
274 warning ("Couldn't get registers");
275 return;
276 }
277
917317f4 278 convert_to_gregset (&buf, registers, register_valid);
d4f3574e
SS
279
280 ret = ptrace (PTRACE_SETREGS, inferior_pid, 0, (int)buf);
917317f4 281 if (ret < 0)
d4f3574e 282 {
917317f4 283 warning ("Couldn't write registers");
d4f3574e
SS
284 return;
285 }
d4f3574e
SS
286}
287
288
289/* Fetch registers from the child process.
290 Fetch all if regno == -1, otherwise fetch all ordinary
291 registers or all floating point registers depending
292 upon the value of regno. */
293
294void
917317f4 295fetch_inferior_registers (int regno)
d4f3574e 296{
917317f4
JM
297 if (regno < NUM_GREGS || regno == -1)
298 fetch_regs ();
d4f3574e 299
917317f4
JM
300 if (regno >= NUM_GREGS || regno == -1)
301 fetch_fpregs ();
d4f3574e
SS
302}
303
304
305/* Store our register values back into the inferior.
306 If REGNO is -1, do this for all registers.
307 Otherwise, REGNO specifies which register, which
308 then determines whether we store all ordinary
309 registers or all of the floating point registers. */
310
311void
312store_inferior_registers (regno)
313 int regno;
314{
917317f4
JM
315 if (regno < NUM_GREGS || regno == -1)
316 store_regs ();
d4f3574e 317
917317f4
JM
318 if (regno >= NUM_GREGS || regno == -1)
319 store_fpregs ();
d4f3574e
SS
320}
321
322
323/* Find the minimal symbol named NAME, and return both the minsym
324 struct and its objfile. This probably ought to be in minsym.c, but
325 everything there is trying to deal with things like C++ and
326 SOFUN_ADDRESS_MAYBE_TURQUOISE, ... Since this is so simple, it may
327 be considered too special-purpose for general consumption. */
328
329static struct minimal_symbol *
330find_minsym_and_objfile (char *name, struct objfile **objfile_p)
331{
332 struct objfile *objfile;
333
334 ALL_OBJFILES (objfile)
335 {
336 struct minimal_symbol *msym;
337
338 ALL_OBJFILE_MSYMBOLS (objfile, msym)
339 {
340 if (SYMBOL_NAME (msym)
341 && STREQ (SYMBOL_NAME (msym), name))
342 {
343 *objfile_p = objfile;
344 return msym;
345 }
346 }
347 }
348
349 return 0;
350}
351
352
353static CORE_ADDR
354skip_hurd_resolver (CORE_ADDR pc)
355{
356 /* The HURD dynamic linker is part of the GNU C library, so many
357 GNU/Linux distributions use it. (All ELF versions, as far as I
358 know.) An unresolved PLT entry points to "_dl_runtime_resolve",
359 which calls "fixup" to patch the PLT, and then passes control to
360 the function.
361
362 We look for the symbol `_dl_runtime_resolve', and find `fixup' in
363 the same objfile. If we are at the entry point of `fixup', then
364 we set a breakpoint at the return address (at the top of the
365 stack), and continue.
366
367 It's kind of gross to do all these checks every time we're
368 called, since they don't change once the executable has gotten
369 started. But this is only a temporary hack --- upcoming versions
370 of Linux will provide a portable, efficient interface for
371 debugging programs that use shared libraries. */
372
373 struct objfile *objfile;
374 struct minimal_symbol *resolver
375 = find_minsym_and_objfile ("_dl_runtime_resolve", &objfile);
376
377 if (resolver)
378 {
379 struct minimal_symbol *fixup
380 = lookup_minimal_symbol ("fixup", 0, objfile);
381
382 if (fixup && SYMBOL_VALUE_ADDRESS (fixup) == pc)
383 return (SAVED_PC_AFTER_CALL (get_current_frame ()));
384 }
385
386 return 0;
387}
388
389
390/* See the comments for SKIP_SOLIB_RESOLVER at the top of infrun.c.
391 This function:
392 1) decides whether a PLT has sent us into the linker to resolve
393 a function reference, and
394 2) if so, tells us where to set a temporary breakpoint that will
395 trigger when the dynamic linker is done. */
396
397CORE_ADDR
398i386_linux_skip_solib_resolver (CORE_ADDR pc)
399{
400 CORE_ADDR result;
401
402 /* Plug in functions for other kinds of resolvers here. */
403 result = skip_hurd_resolver (pc);
404 if (result)
405 return result;
406
407 return 0;
408}
This page took 0.060419 seconds and 4 git commands to generate.