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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.2/] [gdb/] [amd64-linux-nat.c] - Blame information for rev 330

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 330 jeremybenn
/* Native-dependent code for GNU/Linux x86-64.
2
 
3
   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4
   Free Software Foundation, Inc.
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 3 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, see <http://www.gnu.org/licenses/>.  */
21
 
22
#include "defs.h"
23
#include "inferior.h"
24
#include "gdbcore.h"
25
#include "regcache.h"
26
#include "regset.h"
27
#include "linux-nat.h"
28
#include "amd64-linux-tdep.h"
29
 
30
#include "gdb_assert.h"
31
#include "gdb_string.h"
32
#include "elf/common.h"
33
#include <sys/uio.h>
34
#include <sys/ptrace.h>
35
#include <sys/debugreg.h>
36
#include <sys/syscall.h>
37
#include <sys/procfs.h>
38
#include <asm/prctl.h>
39
/* FIXME ezannoni-2003-07-09: we need <sys/reg.h> to be included after
40
   <asm/ptrace.h> because the latter redefines FS and GS for no apparent
41
   reason, and those definitions don't match the ones that libpthread_db
42
   uses, which come from <sys/reg.h>.  */
43
/* ezannoni-2003-07-09: I think this is fixed. The extraneous defs have
44
   been removed from ptrace.h in the kernel.  However, better safe than
45
   sorry.  */
46
#include <asm/ptrace.h>
47
#include <sys/reg.h>
48
#include "gdb_proc_service.h"
49
 
50
/* Prototypes for supply_gregset etc.  */
51
#include "gregset.h"
52
 
53
#include "amd64-tdep.h"
54
#include "i386-linux-tdep.h"
55
#include "amd64-nat.h"
56
#include "i386-nat.h"
57
#include "i386-xstate.h"
58
 
59
#ifndef PTRACE_GETREGSET
60
#define PTRACE_GETREGSET        0x4204
61
#endif
62
 
63
#ifndef PTRACE_SETREGSET
64
#define PTRACE_SETREGSET        0x4205
65
#endif
66
 
67
/* Does the current host support PTRACE_GETREGSET?  */
68
static int have_ptrace_getregset = -1;
69
 
70
/* Mapping between the general-purpose registers in GNU/Linux x86-64
71
   `struct user' format and GDB's register cache layout for GNU/Linux
72
   i386.
73
 
74
   Note that most GNU/Linux x86-64 registers are 64-bit, while the
75
   GNU/Linux i386 registers are all 32-bit, but since we're
76
   little-endian we get away with that.  */
77
 
78
/* From <sys/reg.h> on GNU/Linux i386.  */
79
static int amd64_linux_gregset32_reg_offset[] =
80
{
81
  RAX * 8, RCX * 8,             /* %eax, %ecx */
82
  RDX * 8, RBX * 8,             /* %edx, %ebx */
83
  RSP * 8, RBP * 8,             /* %esp, %ebp */
84
  RSI * 8, RDI * 8,             /* %esi, %edi */
85
  RIP * 8, EFLAGS * 8,          /* %eip, %eflags */
86
  CS * 8, SS * 8,               /* %cs, %ss */
87
  DS * 8, ES * 8,               /* %ds, %es */
88
  FS * 8, GS * 8,               /* %fs, %gs */
89
  -1, -1, -1, -1, -1, -1, -1, -1,
90
  -1, -1, -1, -1, -1, -1, -1, -1,
91
  -1, -1, -1, -1, -1, -1, -1, -1, -1,
92
  -1, -1, -1, -1, -1, -1, -1, -1,
93
  ORIG_RAX * 8                  /* "orig_eax" */
94
};
95
 
96
 
97
/* Transfering the general-purpose registers between GDB, inferiors
98
   and core files.  */
99
 
100
/* Fill GDB's register cache with the general-purpose register values
101
   in *GREGSETP.  */
102
 
103
void
104
supply_gregset (struct regcache *regcache, const elf_gregset_t *gregsetp)
105
{
106
  amd64_supply_native_gregset (regcache, gregsetp, -1);
107
}
108
 
109
/* Fill register REGNUM (if it is a general-purpose register) in
110
   *GREGSETP with the value in GDB's register cache.  If REGNUM is -1,
111
   do this for all registers.  */
112
 
113
void
114
fill_gregset (const struct regcache *regcache,
115
              elf_gregset_t *gregsetp, int regnum)
116
{
117
  amd64_collect_native_gregset (regcache, gregsetp, regnum);
118
}
119
 
120
/* Transfering floating-point registers between GDB, inferiors and cores.  */
121
 
122
/* Fill GDB's register cache with the floating-point and SSE register
123
   values in *FPREGSETP.  */
124
 
125
void
126
supply_fpregset (struct regcache *regcache, const elf_fpregset_t *fpregsetp)
127
{
128
  amd64_supply_fxsave (regcache, -1, fpregsetp);
129
}
130
 
131
/* Fill register REGNUM (if it is a floating-point or SSE register) in
132
   *FPREGSETP with the value in GDB's register cache.  If REGNUM is
133
   -1, do this for all registers.  */
134
 
135
void
136
fill_fpregset (const struct regcache *regcache,
137
               elf_fpregset_t *fpregsetp, int regnum)
138
{
139
  amd64_collect_fxsave (regcache, regnum, fpregsetp);
140
}
141
 
142
 
143
/* Transferring arbitrary registers between GDB and inferior.  */
144
 
145
/* Fetch register REGNUM from the child process.  If REGNUM is -1, do
146
   this for all registers (including the floating point and SSE
147
   registers).  */
148
 
149
static void
150
amd64_linux_fetch_inferior_registers (struct target_ops *ops,
151
                                      struct regcache *regcache, int regnum)
152
{
153
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
154
  int tid;
155
 
156
  /* GNU/Linux LWP ID's are process ID's.  */
157
  tid = TIDGET (inferior_ptid);
158
  if (tid == 0)
159
    tid = PIDGET (inferior_ptid); /* Not a threaded program.  */
160
 
161
  if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum))
162
    {
163
      elf_gregset_t regs;
164
 
165
      if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
166
        perror_with_name (_("Couldn't get registers"));
167
 
168
      amd64_supply_native_gregset (regcache, &regs, -1);
169
      if (regnum != -1)
170
        return;
171
    }
172
 
173
  if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum))
174
    {
175
      elf_fpregset_t fpregs;
176
 
177
      if (have_ptrace_getregset)
178
        {
179
          char xstateregs[I386_XSTATE_MAX_SIZE];
180
          struct iovec iov;
181
 
182
          iov.iov_base = xstateregs;
183
          iov.iov_len = sizeof (xstateregs);
184
          if (ptrace (PTRACE_GETREGSET, tid,
185
                      (unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
186
            perror_with_name (_("Couldn't get extended state status"));
187
 
188
          amd64_supply_xsave (regcache, -1, xstateregs);
189
        }
190
      else
191
        {
192
          if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
193
            perror_with_name (_("Couldn't get floating point status"));
194
 
195
          amd64_supply_fxsave (regcache, -1, &fpregs);
196
        }
197
    }
198
}
199
 
200
/* Store register REGNUM back into the child process.  If REGNUM is
201
   -1, do this for all registers (including the floating-point and SSE
202
   registers).  */
203
 
204
static void
205
amd64_linux_store_inferior_registers (struct target_ops *ops,
206
                                      struct regcache *regcache, int regnum)
207
{
208
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
209
  int tid;
210
 
211
  /* GNU/Linux LWP ID's are process ID's.  */
212
  tid = TIDGET (inferior_ptid);
213
  if (tid == 0)
214
    tid = PIDGET (inferior_ptid); /* Not a threaded program.  */
215
 
216
  if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum))
217
    {
218
      elf_gregset_t regs;
219
 
220
      if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
221
        perror_with_name (_("Couldn't get registers"));
222
 
223
      amd64_collect_native_gregset (regcache, &regs, regnum);
224
 
225
      if (ptrace (PTRACE_SETREGS, tid, 0, (long) &regs) < 0)
226
        perror_with_name (_("Couldn't write registers"));
227
 
228
      if (regnum != -1)
229
        return;
230
    }
231
 
232
  if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum))
233
    {
234
      elf_fpregset_t fpregs;
235
 
236
      if (have_ptrace_getregset)
237
        {
238
          char xstateregs[I386_XSTATE_MAX_SIZE];
239
          struct iovec iov;
240
 
241
          iov.iov_base = xstateregs;
242
          iov.iov_len = sizeof (xstateregs);
243
          if (ptrace (PTRACE_GETREGSET, tid,
244
                      (unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
245
            perror_with_name (_("Couldn't get extended state status"));
246
 
247
          amd64_collect_xsave (regcache, regnum, xstateregs, 0);
248
 
249
          if (ptrace (PTRACE_SETREGSET, tid,
250
                      (unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
251
            perror_with_name (_("Couldn't write extended state status"));
252
        }
253
      else
254
        {
255
          if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
256
            perror_with_name (_("Couldn't get floating point status"));
257
 
258
          amd64_collect_fxsave (regcache, regnum, &fpregs);
259
 
260
          if (ptrace (PTRACE_SETFPREGS, tid, 0, (long) &fpregs) < 0)
261
            perror_with_name (_("Couldn't write floating point status"));
262
        }
263
    }
264
}
265
 
266
/* Support for debug registers.  */
267
 
268
static unsigned long amd64_linux_dr[DR_CONTROL + 1];
269
 
270
static unsigned long
271
amd64_linux_dr_get (ptid_t ptid, int regnum)
272
{
273
  int tid;
274
  unsigned long value;
275
 
276
  tid = TIDGET (ptid);
277
  if (tid == 0)
278
    tid = PIDGET (ptid);
279
 
280
  /* FIXME: kettenis/2001-03-27: Calling perror_with_name if the
281
     ptrace call fails breaks debugging remote targets.  The correct
282
     way to fix this is to add the hardware breakpoint and watchpoint
283
     stuff to the target vector.  For now, just return zero if the
284
     ptrace call fails.  */
285
  errno = 0;
286
  value = ptrace (PTRACE_PEEKUSER, tid,
287
                  offsetof (struct user, u_debugreg[regnum]), 0);
288
  if (errno != 0)
289
#if 0
290
    perror_with_name (_("Couldn't read debug register"));
291
#else
292
    return 0;
293
#endif
294
 
295
  return value;
296
}
297
 
298
/* Set debug register REGNUM to VALUE in only the one LWP of PTID.  */
299
 
300
static void
301
amd64_linux_dr_set (ptid_t ptid, int regnum, unsigned long value)
302
{
303
  int tid;
304
 
305
  tid = TIDGET (ptid);
306
  if (tid == 0)
307
    tid = PIDGET (ptid);
308
 
309
  errno = 0;
310
  ptrace (PTRACE_POKEUSER, tid,
311
          offsetof (struct user, u_debugreg[regnum]), value);
312
  if (errno != 0)
313
    perror_with_name (_("Couldn't write debug register"));
314
}
315
 
316
/* Set DR_CONTROL to ADDR in all LWPs of LWP_LIST.  */
317
 
318
static void
319
amd64_linux_dr_set_control (unsigned long control)
320
{
321
  struct lwp_info *lp;
322
  ptid_t ptid;
323
 
324
  amd64_linux_dr[DR_CONTROL] = control;
325
  ALL_LWPS (lp, ptid)
326
    amd64_linux_dr_set (ptid, DR_CONTROL, control);
327
}
328
 
329
/* Set address REGNUM (zero based) to ADDR in all LWPs of LWP_LIST.  */
330
 
331
static void
332
amd64_linux_dr_set_addr (int regnum, CORE_ADDR addr)
333
{
334
  struct lwp_info *lp;
335
  ptid_t ptid;
336
 
337
  gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
338
 
339
  amd64_linux_dr[DR_FIRSTADDR + regnum] = addr;
340
  ALL_LWPS (lp, ptid)
341
    amd64_linux_dr_set (ptid, DR_FIRSTADDR + regnum, addr);
342
}
343
 
344
/* Set address REGNUM (zero based) to zero in all LWPs of LWP_LIST.  */
345
 
346
static void
347
amd64_linux_dr_reset_addr (int regnum)
348
{
349
  amd64_linux_dr_set_addr (regnum, 0);
350
}
351
 
352
/* Get DR_STATUS from only the one LWP of INFERIOR_PTID.  */
353
 
354
static unsigned long
355
amd64_linux_dr_get_status (void)
356
{
357
  return amd64_linux_dr_get (inferior_ptid, DR_STATUS);
358
}
359
 
360
/* Unset MASK bits in DR_STATUS in all LWPs of LWP_LIST.  */
361
 
362
static void
363
amd64_linux_dr_unset_status (unsigned long mask)
364
{
365
  struct lwp_info *lp;
366
  ptid_t ptid;
367
 
368
  ALL_LWPS (lp, ptid)
369
    {
370
      unsigned long value;
371
 
372
      value = amd64_linux_dr_get (ptid, DR_STATUS);
373
      value &= ~mask;
374
      amd64_linux_dr_set (ptid, DR_STATUS, value);
375
    }
376
}
377
 
378
 
379
static void
380
amd64_linux_new_thread (ptid_t ptid)
381
{
382
  int i;
383
 
384
  for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
385
    amd64_linux_dr_set (ptid, i, amd64_linux_dr[i]);
386
 
387
  amd64_linux_dr_set (ptid, DR_CONTROL, amd64_linux_dr[DR_CONTROL]);
388
}
389
 
390
 
391
/* This function is called by libthread_db as part of its handling of
392
   a request for a thread's local storage address.  */
393
 
394
ps_err_e
395
ps_get_thread_area (const struct ps_prochandle *ph,
396
                    lwpid_t lwpid, int idx, void **base)
397
{
398
  if (gdbarch_ptr_bit (target_gdbarch) == 32)
399
    {
400
      /* The full structure is found in <asm-i386/ldt.h>.  The second
401
         integer is the LDT's base_address and that is used to locate
402
         the thread's local storage.  See i386-linux-nat.c more
403
         info.  */
404
      unsigned int desc[4];
405
 
406
      /* This code assumes that "int" is 32 bits and that
407
         GET_THREAD_AREA returns no more than 4 int values.  */
408
      gdb_assert (sizeof (int) == 4);
409
#ifndef PTRACE_GET_THREAD_AREA
410
#define PTRACE_GET_THREAD_AREA 25
411
#endif
412
      if  (ptrace (PTRACE_GET_THREAD_AREA,
413
                   lwpid, (void *) (long) idx, (unsigned long) &desc) < 0)
414
        return PS_ERR;
415
 
416
      /* Extend the value to 64 bits.  Here it's assumed that a "long"
417
         and a "void *" are the same.  */
418
      (*base) = (void *) (long) desc[1];
419
      return PS_OK;
420
    }
421
  else
422
    {
423
      /* This definition comes from prctl.h, but some kernels may not
424
         have it.  */
425
#ifndef PTRACE_ARCH_PRCTL
426
#define PTRACE_ARCH_PRCTL      30
427
#endif
428
      /* FIXME: ezannoni-2003-07-09 see comment above about include
429
         file order.  We could be getting bogus values for these two.  */
430
      gdb_assert (FS < ELF_NGREG);
431
      gdb_assert (GS < ELF_NGREG);
432
      switch (idx)
433
        {
434
        case FS:
435
          if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_FS) == 0)
436
            return PS_OK;
437
          break;
438
        case GS:
439
          if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_GS) == 0)
440
            return PS_OK;
441
          break;
442
        default:                   /* Should not happen.  */
443
          return PS_BADADDR;
444
        }
445
    }
446
  return PS_ERR;               /* ptrace failed.  */
447
}
448
 
449
 
450
static void (*super_post_startup_inferior) (ptid_t ptid);
451
 
452
static void
453
amd64_linux_child_post_startup_inferior (ptid_t ptid)
454
{
455
  i386_cleanup_dregs ();
456
  super_post_startup_inferior (ptid);
457
}
458
 
459
 
460
/* When GDB is built as a 64-bit application on linux, the
461
   PTRACE_GETSIGINFO data is always presented in 64-bit layout.  Since
462
   debugging a 32-bit inferior with a 64-bit GDB should look the same
463
   as debugging it with a 32-bit GDB, we do the 32-bit <-> 64-bit
464
   conversion in-place ourselves.  */
465
 
466
/* These types below (compat_*) define a siginfo type that is layout
467
   compatible with the siginfo type exported by the 32-bit userspace
468
   support.  */
469
 
470
typedef int compat_int_t;
471
typedef unsigned int compat_uptr_t;
472
 
473
typedef int compat_time_t;
474
typedef int compat_timer_t;
475
typedef int compat_clock_t;
476
 
477
struct compat_timeval
478
{
479
  compat_time_t tv_sec;
480
  int tv_usec;
481
};
482
 
483
typedef union compat_sigval
484
{
485
  compat_int_t sival_int;
486
  compat_uptr_t sival_ptr;
487
} compat_sigval_t;
488
 
489
typedef struct compat_siginfo
490
{
491
  int si_signo;
492
  int si_errno;
493
  int si_code;
494
 
495
  union
496
  {
497
    int _pad[((128 / sizeof (int)) - 3)];
498
 
499
    /* kill() */
500
    struct
501
    {
502
      unsigned int _pid;
503
      unsigned int _uid;
504
    } _kill;
505
 
506
    /* POSIX.1b timers */
507
    struct
508
    {
509
      compat_timer_t _tid;
510
      int _overrun;
511
      compat_sigval_t _sigval;
512
    } _timer;
513
 
514
    /* POSIX.1b signals */
515
    struct
516
    {
517
      unsigned int _pid;
518
      unsigned int _uid;
519
      compat_sigval_t _sigval;
520
    } _rt;
521
 
522
    /* SIGCHLD */
523
    struct
524
    {
525
      unsigned int _pid;
526
      unsigned int _uid;
527
      int _status;
528
      compat_clock_t _utime;
529
      compat_clock_t _stime;
530
    } _sigchld;
531
 
532
    /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
533
    struct
534
    {
535
      unsigned int _addr;
536
    } _sigfault;
537
 
538
    /* SIGPOLL */
539
    struct
540
    {
541
      int _band;
542
      int _fd;
543
    } _sigpoll;
544
  } _sifields;
545
} compat_siginfo_t;
546
 
547
#define cpt_si_pid _sifields._kill._pid
548
#define cpt_si_uid _sifields._kill._uid
549
#define cpt_si_timerid _sifields._timer._tid
550
#define cpt_si_overrun _sifields._timer._overrun
551
#define cpt_si_status _sifields._sigchld._status
552
#define cpt_si_utime _sifields._sigchld._utime
553
#define cpt_si_stime _sifields._sigchld._stime
554
#define cpt_si_ptr _sifields._rt._sigval.sival_ptr
555
#define cpt_si_addr _sifields._sigfault._addr
556
#define cpt_si_band _sifields._sigpoll._band
557
#define cpt_si_fd _sifields._sigpoll._fd
558
 
559
/* glibc at least up to 2.3.2 doesn't have si_timerid, si_overrun.
560
   In their place is si_timer1,si_timer2.  */
561
#ifndef si_timerid
562
#define si_timerid si_timer1
563
#endif
564
#ifndef si_overrun
565
#define si_overrun si_timer2
566
#endif
567
 
568
static void
569
compat_siginfo_from_siginfo (compat_siginfo_t *to, siginfo_t *from)
570
{
571
  memset (to, 0, sizeof (*to));
572
 
573
  to->si_signo = from->si_signo;
574
  to->si_errno = from->si_errno;
575
  to->si_code = from->si_code;
576
 
577
  if (to->si_code < 0)
578
    {
579
      to->cpt_si_ptr = (intptr_t) from->si_ptr;
580
    }
581
  else if (to->si_code == SI_USER)
582
    {
583
      to->cpt_si_pid = from->si_pid;
584
      to->cpt_si_uid = from->si_uid;
585
    }
586
  else if (to->si_code == SI_TIMER)
587
    {
588
      to->cpt_si_timerid = from->si_timerid;
589
      to->cpt_si_overrun = from->si_overrun;
590
      to->cpt_si_ptr = (intptr_t) from->si_ptr;
591
    }
592
  else
593
    {
594
      switch (to->si_signo)
595
        {
596
        case SIGCHLD:
597
          to->cpt_si_pid = from->si_pid;
598
          to->cpt_si_uid = from->si_uid;
599
          to->cpt_si_status = from->si_status;
600
          to->cpt_si_utime = from->si_utime;
601
          to->cpt_si_stime = from->si_stime;
602
          break;
603
        case SIGILL:
604
        case SIGFPE:
605
        case SIGSEGV:
606
        case SIGBUS:
607
          to->cpt_si_addr = (intptr_t) from->si_addr;
608
          break;
609
        case SIGPOLL:
610
          to->cpt_si_band = from->si_band;
611
          to->cpt_si_fd = from->si_fd;
612
          break;
613
        default:
614
          to->cpt_si_pid = from->si_pid;
615
          to->cpt_si_uid = from->si_uid;
616
          to->cpt_si_ptr = (intptr_t) from->si_ptr;
617
          break;
618
        }
619
    }
620
}
621
 
622
static void
623
siginfo_from_compat_siginfo (siginfo_t *to, compat_siginfo_t *from)
624
{
625
  memset (to, 0, sizeof (*to));
626
 
627
  to->si_signo = from->si_signo;
628
  to->si_errno = from->si_errno;
629
  to->si_code = from->si_code;
630
 
631
  if (to->si_code < 0)
632
    {
633
      to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
634
    }
635
  else if (to->si_code == SI_USER)
636
    {
637
      to->si_pid = from->cpt_si_pid;
638
      to->si_uid = from->cpt_si_uid;
639
    }
640
  else if (to->si_code == SI_TIMER)
641
    {
642
      to->si_timerid = from->cpt_si_timerid;
643
      to->si_overrun = from->cpt_si_overrun;
644
      to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
645
    }
646
  else
647
    {
648
      switch (to->si_signo)
649
        {
650
        case SIGCHLD:
651
          to->si_pid = from->cpt_si_pid;
652
          to->si_uid = from->cpt_si_uid;
653
          to->si_status = from->cpt_si_status;
654
          to->si_utime = from->cpt_si_utime;
655
          to->si_stime = from->cpt_si_stime;
656
          break;
657
        case SIGILL:
658
        case SIGFPE:
659
        case SIGSEGV:
660
        case SIGBUS:
661
          to->si_addr = (void *) (intptr_t) from->cpt_si_addr;
662
          break;
663
        case SIGPOLL:
664
          to->si_band = from->cpt_si_band;
665
          to->si_fd = from->cpt_si_fd;
666
          break;
667
        default:
668
          to->si_pid = from->cpt_si_pid;
669
          to->si_uid = from->cpt_si_uid;
670
          to->si_ptr = (void* ) (intptr_t) from->cpt_si_ptr;
671
          break;
672
        }
673
    }
674
}
675
 
676
/* Convert a native/host siginfo object, into/from the siginfo in the
677
   layout of the inferiors' architecture.  Returns true if any
678
   conversion was done; false otherwise.  If DIRECTION is 1, then copy
679
   from INF to NATIVE.  If DIRECTION is 0, copy from NATIVE to
680
   INF.  */
681
 
682
static int
683
amd64_linux_siginfo_fixup (struct siginfo *native, gdb_byte *inf, int direction)
684
{
685
  /* Is the inferior 32-bit?  If so, then do fixup the siginfo
686
     object.  */
687
  if (gdbarch_addr_bit (get_frame_arch (get_current_frame ())) == 32)
688
    {
689
      gdb_assert (sizeof (struct siginfo) == sizeof (compat_siginfo_t));
690
 
691
      if (direction == 0)
692
        compat_siginfo_from_siginfo ((struct compat_siginfo *) inf, native);
693
      else
694
        siginfo_from_compat_siginfo (native, (struct compat_siginfo *) inf);
695
 
696
      return 1;
697
    }
698
  else
699
    return 0;
700
}
701
 
702
/* Get Linux/x86 target description from running target.
703
 
704
   Value of CS segment register:
705
     1. 64bit process: 0x33.
706
     2. 32bit process: 0x23.
707
 */
708
 
709
#define AMD64_LINUX_USER64_CS   0x33
710
 
711
static const struct target_desc *
712
amd64_linux_read_description (struct target_ops *ops)
713
{
714
  unsigned long cs;
715
  int tid;
716
  int is_64bit;
717
  static uint64_t xcr0;
718
 
719
  /* GNU/Linux LWP ID's are process ID's.  */
720
  tid = TIDGET (inferior_ptid);
721
  if (tid == 0)
722
    tid = PIDGET (inferior_ptid); /* Not a threaded program.  */
723
 
724
  /* Get CS register.  */
725
  errno = 0;
726
  cs = ptrace (PTRACE_PEEKUSER, tid,
727
               offsetof (struct user_regs_struct, cs), 0);
728
  if (errno != 0)
729
    perror_with_name (_("Couldn't get CS register"));
730
 
731
  is_64bit = cs == AMD64_LINUX_USER64_CS;
732
 
733
  if (have_ptrace_getregset == -1)
734
    {
735
      uint64_t xstateregs[(I386_XSTATE_SSE_SIZE / sizeof (uint64_t))];
736
      struct iovec iov;
737
 
738
      iov.iov_base = xstateregs;
739
      iov.iov_len = sizeof (xstateregs);
740
 
741
      /* Check if PTRACE_GETREGSET works.  */
742
      if (ptrace (PTRACE_GETREGSET, tid,
743
                  (unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
744
        have_ptrace_getregset = 0;
745
      else
746
        {
747
          have_ptrace_getregset = 1;
748
 
749
          /* Get XCR0 from XSAVE extended state.  */
750
          xcr0 = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET
751
                             / sizeof (uint64_t))];
752
        }
753
    }
754
 
755
  /* Check the native XCR0 only if PTRACE_GETREGSET is available.  */
756
  if (have_ptrace_getregset
757
      && (xcr0 & I386_XSTATE_AVX_MASK) == I386_XSTATE_AVX_MASK)
758
    {
759
      if (is_64bit)
760
        return tdesc_amd64_avx_linux;
761
      else
762
        return tdesc_i386_avx_linux;
763
    }
764
  else
765
    {
766
      if (is_64bit)
767
        return tdesc_amd64_linux;
768
      else
769
        return tdesc_i386_linux;
770
    }
771
}
772
 
773
/* Provide a prototype to silence -Wmissing-prototypes.  */
774
void _initialize_amd64_linux_nat (void);
775
 
776
void
777
_initialize_amd64_linux_nat (void)
778
{
779
  struct target_ops *t;
780
 
781
  amd64_native_gregset32_reg_offset = amd64_linux_gregset32_reg_offset;
782
  amd64_native_gregset32_num_regs = I386_LINUX_NUM_REGS;
783
  amd64_native_gregset64_reg_offset = amd64_linux_gregset_reg_offset;
784
  amd64_native_gregset64_num_regs = AMD64_LINUX_NUM_REGS;
785
 
786
  gdb_assert (ARRAY_SIZE (amd64_linux_gregset32_reg_offset)
787
              == amd64_native_gregset32_num_regs);
788
 
789
  /* Fill in the generic GNU/Linux methods.  */
790
  t = linux_target ();
791
 
792
  i386_use_watchpoints (t);
793
 
794
  i386_dr_low.set_control = amd64_linux_dr_set_control;
795
  i386_dr_low.set_addr = amd64_linux_dr_set_addr;
796
  i386_dr_low.reset_addr = amd64_linux_dr_reset_addr;
797
  i386_dr_low.get_status = amd64_linux_dr_get_status;
798
  i386_dr_low.unset_status = amd64_linux_dr_unset_status;
799
  i386_set_debug_register_length (8);
800
 
801
  /* Override the GNU/Linux inferior startup hook.  */
802
  super_post_startup_inferior = t->to_post_startup_inferior;
803
  t->to_post_startup_inferior = amd64_linux_child_post_startup_inferior;
804
 
805
  /* Add our register access methods.  */
806
  t->to_fetch_registers = amd64_linux_fetch_inferior_registers;
807
  t->to_store_registers = amd64_linux_store_inferior_registers;
808
 
809
  t->to_read_description = amd64_linux_read_description;
810
 
811
  /* Register the target.  */
812
  linux_nat_add_target (t);
813
  linux_nat_set_new_thread (t, amd64_linux_new_thread);
814
  linux_nat_set_siginfo_fixup (t, amd64_linux_siginfo_fixup);
815
}

powered by: WebSVN 2.1.0

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