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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [gdb/] [amd64-linux-nat.c] - Blame information for rev 825

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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