OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [gdb/] [x86-64-linux-nat.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1181 sfurman
/* Native-dependent code for GNU/Linux x86-64.
2
 
3
   Copyright 2001, 2002 Free Software Foundation, Inc.
4
 
5
   Contributed by Jiri Smid, SuSE Labs.
6
 
7
   This file is part of GDB.
8
 
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 2 of the License, or
12
   (at your option) any later version.
13
 
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
 
19
   You should have received a copy of the GNU General Public License
20
   along with this program; if not, write to the Free Software
21
   Foundation, Inc., 59 Temple Place - Suite 330,
22
   Boston, MA 02111-1307, USA.  */
23
 
24
#include "defs.h"
25
#include "inferior.h"
26
#include "gdbcore.h"
27
#include "regcache.h"
28
#include "gdb_assert.h"
29
#include "gdb_string.h"
30
#include "x86-64-tdep.h"
31
 
32
#include <sys/ptrace.h>
33
#include <sys/debugreg.h>
34
#include <sys/syscall.h>
35
#include <sys/procfs.h>
36
#include <sys/reg.h>
37
 
38
/* Mapping between the general-purpose registers in `struct user'
39
   format and GDB's register array layout.  */
40
 
41
static int x86_64_regmap[] = {
42
  RAX, RBX, RCX, RDX,
43
  RSI, RDI, RBP, RSP,
44
  R8, R9, R10, R11,
45
  R12, R13, R14, R15,
46
  RIP, EFLAGS, CS, SS,
47
  DS, ES, FS, GS
48
};
49
 
50
static unsigned long
51
x86_64_linux_dr_get (int regnum)
52
{
53
  int tid;
54
  unsigned long value;
55
 
56
  /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
57
     multi-threaded processes here.  For now, pretend there is just
58
     one thread.  */
59
  tid = PIDGET (inferior_ptid);
60
 
61
  /* FIXME: kettenis/2001-03-27: Calling perror_with_name if the
62
     ptrace call fails breaks debugging remote targets.  The correct
63
     way to fix this is to add the hardware breakpoint and watchpoint
64
     stuff to the target vectore.  For now, just return zero if the
65
     ptrace call fails.  */
66
  errno = 0;
67
  value = ptrace (PT_READ_U, tid,
68
                  offsetof (struct user, u_debugreg[regnum]), 0);
69
  if (errno != 0)
70
#if 0
71
    perror_with_name ("Couldn't read debug register");
72
#else
73
    return 0;
74
#endif
75
 
76
  return value;
77
}
78
 
79
static void
80
x86_64_linux_dr_set (int regnum, unsigned long value)
81
{
82
  int tid;
83
 
84
  /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
85
     multi-threaded processes here.  For now, pretend there is just
86
     one thread.  */
87
  tid = PIDGET (inferior_ptid);
88
 
89
  errno = 0;
90
  ptrace (PT_WRITE_U, tid, offsetof (struct user, u_debugreg[regnum]), value);
91
  if (errno != 0)
92
    perror_with_name ("Couldn't write debug register");
93
}
94
 
95
void
96
x86_64_linux_dr_set_control (unsigned long control)
97
{
98
  x86_64_linux_dr_set (DR_CONTROL, control);
99
}
100
 
101
void
102
x86_64_linux_dr_set_addr (int regnum, CORE_ADDR addr)
103
{
104
  gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
105
 
106
  x86_64_linux_dr_set (DR_FIRSTADDR + regnum, addr);
107
}
108
 
109
void
110
x86_64_linux_dr_reset_addr (int regnum)
111
{
112
  gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
113
 
114
  x86_64_linux_dr_set (DR_FIRSTADDR + regnum, 0L);
115
}
116
 
117
unsigned long
118
x86_64_linux_dr_get_status (void)
119
{
120
  return x86_64_linux_dr_get (DR_STATUS);
121
}
122
 
123
 
124
/* The register sets used in GNU/Linux ELF core-dumps are identical to
125
   the register sets used by `ptrace'.  */
126
 
127
#define GETREGS_SUPPLIES(regno) \
128
  (0 <= (regno) && (regno) < x86_64_num_gregs)
129
#define GETFPREGS_SUPPLIES(regno) \
130
  (FP0_REGNUM <= (regno) && (regno) <= MXCSR_REGNUM)
131
 
132
 
133
/* Transfering the general-purpose registers between GDB, inferiors
134
   and core files.  */
135
 
136
/* Fill GDB's register array with the general-purpose register values
137
   in *GREGSETP.  */
138
 
139
void
140
supply_gregset (elf_gregset_t * gregsetp)
141
{
142
  elf_greg_t *regp = (elf_greg_t *) gregsetp;
143
  int i;
144
 
145
  for (i = 0; i < x86_64_num_gregs; i++)
146
    supply_register (i, (char *) (regp + x86_64_regmap[i]));
147
}
148
 
149
/* Fill register REGNO (if it is a general-purpose register) in
150
   *GREGSETPS with the value in GDB's register array.  If REGNO is -1,
151
   do this for all registers.  */
152
 
153
void
154
fill_gregset (elf_gregset_t * gregsetp, int regno)
155
{
156
  elf_greg_t *regp = (elf_greg_t *) gregsetp;
157
  int i;
158
 
159
  for (i = 0; i < x86_64_num_gregs; i++)
160
    if ((regno == -1 || regno == i))
161
      read_register_gen (i, (char *) (regp + x86_64_regmap[i]));
162
}
163
 
164
/* Fetch all general-purpose registers from process/thread TID and
165
   store their values in GDB's register array.  */
166
 
167
static void
168
fetch_regs (int tid)
169
{
170
  elf_gregset_t regs;
171
 
172
  if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
173
    perror_with_name ("Couldn't get registers");
174
 
175
  supply_gregset (&regs);
176
}
177
 
178
/* Store all valid general-purpose registers in GDB's register array
179
   into the process/thread specified by TID.  */
180
 
181
static void
182
store_regs (int tid, int regno)
183
{
184
  elf_gregset_t regs;
185
 
186
  if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
187
    perror_with_name ("Couldn't get registers");
188
 
189
  fill_gregset (&regs, regno);
190
 
191
  if (ptrace (PTRACE_SETREGS, tid, 0, (long) &regs) < 0)
192
    perror_with_name ("Couldn't write registers");
193
}
194
 
195
 
196
/* Transfering floating-point registers between GDB, inferiors and cores.  */
197
 
198
static void *
199
x86_64_fxsave_offset (elf_fpregset_t * fxsave, int regnum)
200
{
201
  const char *reg_name;
202
  int reg_index;
203
 
204
  gdb_assert (x86_64_num_gregs - 1 < regnum && regnum < x86_64_num_regs);
205
 
206
  reg_name = x86_64_register_name (regnum);
207
 
208
  if (reg_name[0] == 's' && reg_name[1] == 't')
209
    {
210
      reg_index = reg_name[2] - '0';
211
      return &fxsave->st_space[reg_index * 2];
212
    }
213
 
214
  if (reg_name[0] == 'x' && reg_name[1] == 'm' && reg_name[2] == 'm')
215
    {
216
      reg_index = reg_name[3] - '0';
217
      return &fxsave->xmm_space[reg_index * 4];
218
    }
219
 
220
  if (strcmp (reg_name, "mxcsr") == 0)
221
    return &fxsave->mxcsr;
222
 
223
  return NULL;
224
}
225
 
226
/* Fill GDB's register array with the floating-point and SSE register
227
   values in *FXSAVE.  This function masks off any of the reserved
228
   bits in *FXSAVE.  */
229
 
230
void
231
supply_fpregset (elf_fpregset_t * fxsave)
232
{
233
  int i, reg_st0, reg_mxcsr;
234
 
235
  reg_st0 = x86_64_register_number ("st0");
236
  reg_mxcsr = x86_64_register_number ("mxcsr");
237
 
238
  gdb_assert (reg_st0 > 0 && reg_mxcsr > reg_st0);
239
 
240
  for (i = reg_st0; i <= reg_mxcsr; i++)
241
    supply_register (i, x86_64_fxsave_offset (fxsave, i));
242
}
243
 
244
/* Fill register REGNUM (if it is a floating-point or SSE register) in
245
   *FXSAVE with the value in GDB's register array.  If REGNUM is -1, do
246
   this for all registers.  This function doesn't touch any of the
247
   reserved bits in *FXSAVE.  */
248
 
249
void
250
fill_fpregset (elf_fpregset_t * fxsave, int regnum)
251
{
252
  int i, last_regnum = MXCSR_REGNUM;
253
  void *ptr;
254
 
255
  if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
256
    last_regnum = FOP_REGNUM;
257
 
258
  for (i = FP0_REGNUM; i <= last_regnum; i++)
259
    if (regnum == -1 || regnum == i)
260
      {
261
        ptr = x86_64_fxsave_offset (fxsave, i);
262
        if (ptr)
263
          regcache_collect (i, ptr);
264
      }
265
}
266
 
267
/* Fetch all floating-point registers from process/thread TID and store
268
   thier values in GDB's register array.  */
269
 
270
static void
271
fetch_fpregs (int tid)
272
{
273
  elf_fpregset_t fpregs;
274
 
275
  if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
276
    perror_with_name ("Couldn't get floating point status");
277
 
278
  supply_fpregset (&fpregs);
279
}
280
 
281
/* Store all valid floating-point registers in GDB's register array
282
   into the process/thread specified by TID.  */
283
 
284
static void
285
store_fpregs (int tid, int regno)
286
{
287
  elf_fpregset_t fpregs;
288
 
289
  if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
290
    perror_with_name ("Couldn't get floating point status");
291
 
292
  fill_fpregset (&fpregs, regno);
293
 
294
  if (ptrace (PTRACE_SETFPREGS, tid, 0, (long) &fpregs) < 0)
295
    perror_with_name ("Couldn't write floating point status");
296
}
297
 
298
 
299
/* Transferring arbitrary registers between GDB and inferior.  */
300
 
301
/* Fetch register REGNO from the child process.  If REGNO is -1, do
302
   this for all registers (including the floating point and SSE
303
   registers).  */
304
 
305
void
306
fetch_inferior_registers (int regno)
307
{
308
  int tid;
309
 
310
  /* GNU/Linux LWP ID's are process ID's.  */
311
  if ((tid = TIDGET (inferior_ptid)) == 0)
312
    tid = PIDGET (inferior_ptid);       /* Not a threaded program.  */
313
 
314
  if (regno == -1)
315
    {
316
      fetch_regs (tid);
317
      fetch_fpregs (tid);
318
      return;
319
    }
320
 
321
  if (GETREGS_SUPPLIES (regno))
322
    {
323
      fetch_regs (tid);
324
      return;
325
    }
326
 
327
  if (GETFPREGS_SUPPLIES (regno))
328
    {
329
      fetch_fpregs (tid);
330
      return;
331
    }
332
 
333
  internal_error (__FILE__, __LINE__,
334
                  "Got request for bad register number %d.", regno);
335
}
336
 
337
/* Store register REGNO back into the child process.  If REGNO is -1,
338
   do this for all registers (including the floating point and SSE
339
   registers).  */
340
void
341
store_inferior_registers (int regno)
342
{
343
  int tid;
344
 
345
  /* GNU/Linux LWP ID's are process ID's.  */
346
  if ((tid = TIDGET (inferior_ptid)) == 0)
347
    tid = PIDGET (inferior_ptid);       /* Not a threaded program.  */
348
 
349
  if (regno == -1)
350
    {
351
      store_regs (tid, regno);
352
      store_fpregs (tid, regno);
353
      return;
354
    }
355
 
356
  if (GETREGS_SUPPLIES (regno))
357
    {
358
      store_regs (tid, regno);
359
      return;
360
    }
361
 
362
  if (GETFPREGS_SUPPLIES (regno))
363
    {
364
      store_fpregs (tid, regno);
365
      return;
366
    }
367
 
368
  internal_error (__FILE__, __LINE__,
369
                  "Got request to store bad register number %d.", regno);
370
}
371
 
372
 
373
static const unsigned char linux_syscall[] = { 0x0f, 0x05 };
374
 
375
#define LINUX_SYSCALL_LEN (sizeof linux_syscall)
376
 
377
/* The system call number is stored in the %rax register.  */
378
#define LINUX_SYSCALL_REGNUM 0  /* %rax */
379
 
380
/* We are specifically interested in the sigreturn and rt_sigreturn
381
   system calls.  */
382
 
383
#ifndef SYS_sigreturn
384
#define SYS_sigreturn           __NR_sigreturn
385
#endif
386
#ifndef SYS_rt_sigreturn
387
#define SYS_rt_sigreturn        __NR_rt_sigreturn
388
#endif
389
 
390
/* Offset to saved processor flags, from <asm/sigcontext.h>.  */
391
#define LINUX_SIGCONTEXT_EFLAGS_OFFSET (152)
392
/* Offset to saved processor registers from <asm/ucontext.h> */
393
#define LINUX_UCONTEXT_SIGCONTEXT_OFFSET (36)
394
 
395
/* Interpreting register set info found in core files.  */
396
/* Provide registers to GDB from a core file.
397
 
398
   CORE_REG_SECT points to an array of bytes, which are the contents
399
   of a `note' from a core file which BFD thinks might contain
400
   register contents.  CORE_REG_SIZE is its size.
401
 
402
   WHICH says which register set corelow suspects this is:
403
 
404
     2 --- the floating-point register set, in elf_fpregset_t format
405
 
406
   REG_ADDR isn't used on GNU/Linux.  */
407
 
408
static void
409
fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
410
                      int which, CORE_ADDR reg_addr)
411
{
412
  elf_gregset_t gregset;
413
  elf_fpregset_t fpregset;
414
  switch (which)
415
    {
416
    case 0:
417
      if (core_reg_size != sizeof (gregset))
418
        warning ("Wrong size gregset in core file.");
419
      else
420
        {
421
          memcpy (&gregset, core_reg_sect, sizeof (gregset));
422
          supply_gregset (&gregset);
423
        }
424
      break;
425
 
426
    case 2:
427
      if (core_reg_size != sizeof (fpregset))
428
        warning ("Wrong size fpregset in core file.");
429
      else
430
        {
431
          memcpy (&fpregset, core_reg_sect, sizeof (fpregset));
432
          supply_fpregset (&fpregset);
433
        }
434
      break;
435
 
436
    default:
437
      /* We've covered all the kinds of registers we know about here,
438
         so this must be something we wouldn't know what to do with
439
         anyway.  Just ignore it.  */
440
      break;
441
    }
442
}
443
 
444
/* Register that we are able to handle GNU/Linux ELF core file formats.  */
445
 
446
static struct core_fns linux_elf_core_fns = {
447
  bfd_target_elf_flavour,       /* core_flavour */
448
  default_check_format,         /* check_format */
449
  default_core_sniffer,         /* core_sniffer */
450
  fetch_core_registers,         /* core_read_registers */
451
  NULL                          /* next */
452
};
453
 
454
 
455
#if !defined (offsetof)
456
#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
457
#endif
458
 
459
/* Return the address of register REGNUM.  BLOCKEND is the value of
460
   u.u_ar0, which should point to the registers.  */
461
CORE_ADDR
462
x86_64_register_u_addr (CORE_ADDR blockend, int regnum)
463
{
464
  struct user u;
465
  CORE_ADDR fpstate;
466
  CORE_ADDR ubase;
467
  ubase = blockend;
468
  if (IS_FP_REGNUM (regnum))
469
    {
470
      fpstate = ubase + ((char *) &u.i387.st_space - (char *) &u);
471
      return (fpstate + 16 * (regnum - FP0_REGNUM));
472
    }
473
  else if (IS_SSE_REGNUM (regnum))
474
    {
475
      fpstate = ubase + ((char *) &u.i387.xmm_space - (char *) &u);
476
      return (fpstate + 16 * (regnum - XMM0_REGNUM));
477
    }
478
  else
479
    return (ubase + 8 * x86_64_regmap[regnum]);
480
}
481
 
482
void
483
_initialize_x86_64_linux_nat (void)
484
{
485
  add_core_fns (&linux_elf_core_fns);
486
}
487
 
488
int
489
kernel_u_size (void)
490
{
491
  return (sizeof (struct user));
492
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.