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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [gdb/] [i386-linux-tdep.c] - Blame information for rev 157

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

Line No. Rev Author Line
1 24 jeremybenn
/* Target-dependent code for GNU/Linux i386.
2
 
3
   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
4
   Free Software Foundation, Inc.
5
 
6
   This file is part of GDB.
7
 
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
 
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
 
21
#include "defs.h"
22
#include "gdbcore.h"
23
#include "frame.h"
24
#include "value.h"
25
#include "regcache.h"
26
#include "inferior.h"
27
#include "osabi.h"
28
#include "reggroups.h"
29
#include "dwarf2-frame.h"
30
#include "gdb_string.h"
31
 
32
#include "i386-tdep.h"
33
#include "i386-linux-tdep.h"
34
#include "glibc-tdep.h"
35
#include "solib-svr4.h"
36
#include "symtab.h"
37
 
38
/* Return the name of register REG.  */
39
 
40
static const char *
41
i386_linux_register_name (struct gdbarch *gdbarch, int reg)
42
{
43
  /* Deal with the extra "orig_eax" pseudo register.  */
44
  if (reg == I386_LINUX_ORIG_EAX_REGNUM)
45
    return "orig_eax";
46
 
47
  return i386_register_name (gdbarch, reg);
48
}
49
 
50
/* Return non-zero, when the register is in the corresponding register
51
   group.  Put the LINUX_ORIG_EAX register in the system group.  */
52
static int
53
i386_linux_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
54
                                struct reggroup *group)
55
{
56
  if (regnum == I386_LINUX_ORIG_EAX_REGNUM)
57
    return (group == system_reggroup
58
            || group == save_reggroup
59
            || group == restore_reggroup);
60
  return i386_register_reggroup_p (gdbarch, regnum, group);
61
}
62
 
63
 
64
/* Recognizing signal handler frames.  */
65
 
66
/* GNU/Linux has two flavors of signals.  Normal signal handlers, and
67
   "realtime" (RT) signals.  The RT signals can provide additional
68
   information to the signal handler if the SA_SIGINFO flag is set
69
   when establishing a signal handler using `sigaction'.  It is not
70
   unlikely that future versions of GNU/Linux will support SA_SIGINFO
71
   for normal signals too.  */
72
 
73
/* When the i386 Linux kernel calls a signal handler and the
74
   SA_RESTORER flag isn't set, the return address points to a bit of
75
   code on the stack.  This function returns whether the PC appears to
76
   be within this bit of code.
77
 
78
   The instruction sequence for normal signals is
79
       pop    %eax
80
       mov    $0x77, %eax
81
       int    $0x80
82
   or 0x58 0xb8 0x77 0x00 0x00 0x00 0xcd 0x80.
83
 
84
   Checking for the code sequence should be somewhat reliable, because
85
   the effect is to call the system call sigreturn.  This is unlikely
86
   to occur anywhere other than in a signal trampoline.
87
 
88
   It kind of sucks that we have to read memory from the process in
89
   order to identify a signal trampoline, but there doesn't seem to be
90
   any other way.  Therefore we only do the memory reads if no
91
   function name could be identified, which should be the case since
92
   the code is on the stack.
93
 
94
   Detection of signal trampolines for handlers that set the
95
   SA_RESTORER flag is in general not possible.  Unfortunately this is
96
   what the GNU C Library has been doing for quite some time now.
97
   However, as of version 2.1.2, the GNU C Library uses signal
98
   trampolines (named __restore and __restore_rt) that are identical
99
   to the ones used by the kernel.  Therefore, these trampolines are
100
   supported too.  */
101
 
102
#define LINUX_SIGTRAMP_INSN0    0x58    /* pop %eax */
103
#define LINUX_SIGTRAMP_OFFSET0  0
104
#define LINUX_SIGTRAMP_INSN1    0xb8    /* mov $NNNN, %eax */
105
#define LINUX_SIGTRAMP_OFFSET1  1
106
#define LINUX_SIGTRAMP_INSN2    0xcd    /* int */
107
#define LINUX_SIGTRAMP_OFFSET2  6
108
 
109
static const gdb_byte linux_sigtramp_code[] =
110
{
111
  LINUX_SIGTRAMP_INSN0,                                 /* pop %eax */
112
  LINUX_SIGTRAMP_INSN1, 0x77, 0x00, 0x00, 0x00,         /* mov $0x77, %eax */
113
  LINUX_SIGTRAMP_INSN2, 0x80                            /* int $0x80 */
114
};
115
 
116
#define LINUX_SIGTRAMP_LEN (sizeof linux_sigtramp_code)
117
 
118
/* If NEXT_FRAME unwinds into a sigtramp routine, return the address
119
   of the start of the routine.  Otherwise, return 0.  */
120
 
121
static CORE_ADDR
122
i386_linux_sigtramp_start (struct frame_info *next_frame)
123
{
124
  CORE_ADDR pc = frame_pc_unwind (next_frame);
125
  gdb_byte buf[LINUX_SIGTRAMP_LEN];
126
 
127
  /* We only recognize a signal trampoline if PC is at the start of
128
     one of the three instructions.  We optimize for finding the PC at
129
     the start, as will be the case when the trampoline is not the
130
     first frame on the stack.  We assume that in the case where the
131
     PC is not at the start of the instruction sequence, there will be
132
     a few trailing readable bytes on the stack.  */
133
 
134
  if (!safe_frame_unwind_memory (next_frame, pc, buf, LINUX_SIGTRAMP_LEN))
135
    return 0;
136
 
137
  if (buf[0] != LINUX_SIGTRAMP_INSN0)
138
    {
139
      int adjust;
140
 
141
      switch (buf[0])
142
        {
143
        case LINUX_SIGTRAMP_INSN1:
144
          adjust = LINUX_SIGTRAMP_OFFSET1;
145
          break;
146
        case LINUX_SIGTRAMP_INSN2:
147
          adjust = LINUX_SIGTRAMP_OFFSET2;
148
          break;
149
        default:
150
          return 0;
151
        }
152
 
153
      pc -= adjust;
154
 
155
      if (!safe_frame_unwind_memory (next_frame, pc, buf, LINUX_SIGTRAMP_LEN))
156
        return 0;
157
    }
158
 
159
  if (memcmp (buf, linux_sigtramp_code, LINUX_SIGTRAMP_LEN) != 0)
160
    return 0;
161
 
162
  return pc;
163
}
164
 
165
/* This function does the same for RT signals.  Here the instruction
166
   sequence is
167
       mov    $0xad, %eax
168
       int    $0x80
169
   or 0xb8 0xad 0x00 0x00 0x00 0xcd 0x80.
170
 
171
   The effect is to call the system call rt_sigreturn.  */
172
 
173
#define LINUX_RT_SIGTRAMP_INSN0         0xb8 /* mov $NNNN, %eax */
174
#define LINUX_RT_SIGTRAMP_OFFSET0       0
175
#define LINUX_RT_SIGTRAMP_INSN1         0xcd /* int */
176
#define LINUX_RT_SIGTRAMP_OFFSET1       5
177
 
178
static const gdb_byte linux_rt_sigtramp_code[] =
179
{
180
  LINUX_RT_SIGTRAMP_INSN0, 0xad, 0x00, 0x00, 0x00,      /* mov $0xad, %eax */
181
  LINUX_RT_SIGTRAMP_INSN1, 0x80                         /* int $0x80 */
182
};
183
 
184
#define LINUX_RT_SIGTRAMP_LEN (sizeof linux_rt_sigtramp_code)
185
 
186
/* If NEXT_FRAME unwinds into an RT sigtramp routine, return the
187
   address of the start of the routine.  Otherwise, return 0.  */
188
 
189
static CORE_ADDR
190
i386_linux_rt_sigtramp_start (struct frame_info *next_frame)
191
{
192
  CORE_ADDR pc = frame_pc_unwind (next_frame);
193
  gdb_byte buf[LINUX_RT_SIGTRAMP_LEN];
194
 
195
  /* We only recognize a signal trampoline if PC is at the start of
196
     one of the two instructions.  We optimize for finding the PC at
197
     the start, as will be the case when the trampoline is not the
198
     first frame on the stack.  We assume that in the case where the
199
     PC is not at the start of the instruction sequence, there will be
200
     a few trailing readable bytes on the stack.  */
201
 
202
  if (!safe_frame_unwind_memory (next_frame, pc, buf, LINUX_RT_SIGTRAMP_LEN))
203
    return 0;
204
 
205
  if (buf[0] != LINUX_RT_SIGTRAMP_INSN0)
206
    {
207
      if (buf[0] != LINUX_RT_SIGTRAMP_INSN1)
208
        return 0;
209
 
210
      pc -= LINUX_RT_SIGTRAMP_OFFSET1;
211
 
212
      if (!safe_frame_unwind_memory (next_frame, pc, buf,
213
                                     LINUX_RT_SIGTRAMP_LEN))
214
        return 0;
215
    }
216
 
217
  if (memcmp (buf, linux_rt_sigtramp_code, LINUX_RT_SIGTRAMP_LEN) != 0)
218
    return 0;
219
 
220
  return pc;
221
}
222
 
223
/* Return whether the frame preceding NEXT_FRAME corresponds to a
224
   GNU/Linux sigtramp routine.  */
225
 
226
static int
227
i386_linux_sigtramp_p (struct frame_info *next_frame)
228
{
229
  CORE_ADDR pc = frame_pc_unwind (next_frame);
230
  char *name;
231
 
232
  find_pc_partial_function (pc, &name, NULL, NULL);
233
 
234
  /* If we have NAME, we can optimize the search.  The trampolines are
235
     named __restore and __restore_rt.  However, they aren't dynamically
236
     exported from the shared C library, so the trampoline may appear to
237
     be part of the preceding function.  This should always be sigaction,
238
     __sigaction, or __libc_sigaction (all aliases to the same function).  */
239
  if (name == NULL || strstr (name, "sigaction") != NULL)
240
    return (i386_linux_sigtramp_start (next_frame) != 0
241
            || i386_linux_rt_sigtramp_start (next_frame) != 0);
242
 
243
  return (strcmp ("__restore", name) == 0
244
          || strcmp ("__restore_rt", name) == 0);
245
}
246
 
247
/* Return one if the unwound PC from NEXT_FRAME is in a signal trampoline
248
   which may have DWARF-2 CFI.  */
249
 
250
static int
251
i386_linux_dwarf_signal_frame_p (struct gdbarch *gdbarch,
252
                                 struct frame_info *next_frame)
253
{
254
  CORE_ADDR pc = frame_pc_unwind (next_frame);
255
  char *name;
256
 
257
  find_pc_partial_function (pc, &name, NULL, NULL);
258
 
259
  /* If a vsyscall DSO is in use, the signal trampolines may have these
260
     names.  */
261
  if (name && (strcmp (name, "__kernel_sigreturn") == 0
262
               || strcmp (name, "__kernel_rt_sigreturn") == 0))
263
    return 1;
264
 
265
  return 0;
266
}
267
 
268
/* Offset to struct sigcontext in ucontext, from <asm/ucontext.h>.  */
269
#define I386_LINUX_UCONTEXT_SIGCONTEXT_OFFSET 20
270
 
271
/* Assuming NEXT_FRAME is a frame following a GNU/Linux sigtramp
272
   routine, return the address of the associated sigcontext structure.  */
273
 
274
static CORE_ADDR
275
i386_linux_sigcontext_addr (struct frame_info *next_frame)
276
{
277
  CORE_ADDR pc;
278
  CORE_ADDR sp;
279
  gdb_byte buf[4];
280
 
281
  frame_unwind_register (next_frame, I386_ESP_REGNUM, buf);
282
  sp = extract_unsigned_integer (buf, 4);
283
 
284
  pc = i386_linux_sigtramp_start (next_frame);
285
  if (pc)
286
    {
287
      /* The sigcontext structure lives on the stack, right after
288
         the signum argument.  We determine the address of the
289
         sigcontext structure by looking at the frame's stack
290
         pointer.  Keep in mind that the first instruction of the
291
         sigtramp code is "pop %eax".  If the PC is after this
292
         instruction, adjust the returned value accordingly.  */
293
      if (pc == frame_pc_unwind (next_frame))
294
        return sp + 4;
295
      return sp;
296
    }
297
 
298
  pc = i386_linux_rt_sigtramp_start (next_frame);
299
  if (pc)
300
    {
301
      CORE_ADDR ucontext_addr;
302
 
303
      /* The sigcontext structure is part of the user context.  A
304
         pointer to the user context is passed as the third argument
305
         to the signal handler.  */
306
      read_memory (sp + 8, buf, 4);
307
      ucontext_addr = extract_unsigned_integer (buf, 4);
308
      return ucontext_addr + I386_LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
309
    }
310
 
311
  error (_("Couldn't recognize signal trampoline."));
312
  return 0;
313
}
314
 
315
/* Set the program counter for process PTID to PC.  */
316
 
317
static void
318
i386_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
319
{
320
  regcache_cooked_write_unsigned (regcache, I386_EIP_REGNUM, pc);
321
 
322
  /* We must be careful with modifying the program counter.  If we
323
     just interrupted a system call, the kernel might try to restart
324
     it when we resume the inferior.  On restarting the system call,
325
     the kernel will try backing up the program counter even though it
326
     no longer points at the system call.  This typically results in a
327
     SIGSEGV or SIGILL.  We can prevent this by writing `-1' in the
328
     "orig_eax" pseudo-register.
329
 
330
     Note that "orig_eax" is saved when setting up a dummy call frame.
331
     This means that it is properly restored when that frame is
332
     popped, and that the interrupted system call will be restarted
333
     when we resume the inferior on return from a function call from
334
     within GDB.  In all other cases the system call will not be
335
     restarted.  */
336
  regcache_cooked_write_unsigned (regcache, I386_LINUX_ORIG_EAX_REGNUM, -1);
337
}
338
 
339
 
340
/* The register sets used in GNU/Linux ELF core-dumps are identical to
341
   the register sets in `struct user' that are used for a.out
342
   core-dumps.  These are also used by ptrace(2).  The corresponding
343
   types are `elf_gregset_t' for the general-purpose registers (with
344
   `elf_greg_t' the type of a single GP register) and `elf_fpregset_t'
345
   for the floating-point registers.
346
 
347
   Those types used to be available under the names `gregset_t' and
348
   `fpregset_t' too, and GDB used those names in the past.  But those
349
   names are now used for the register sets used in the `mcontext_t'
350
   type, which have a different size and layout.  */
351
 
352
/* Mapping between the general-purpose registers in `struct user'
353
   format and GDB's register cache layout.  */
354
 
355
/* From <sys/reg.h>.  */
356
static int i386_linux_gregset_reg_offset[] =
357
{
358
  6 * 4,                        /* %eax */
359
  1 * 4,                        /* %ecx */
360
  2 * 4,                        /* %edx */
361
 
362
  15 * 4,                       /* %esp */
363
  5 * 4,                        /* %ebp */
364
  3 * 4,                        /* %esi */
365
  4 * 4,                        /* %edi */
366
  12 * 4,                       /* %eip */
367
  14 * 4,                       /* %eflags */
368
  13 * 4,                       /* %cs */
369
  16 * 4,                       /* %ss */
370
  7 * 4,                        /* %ds */
371
  8 * 4,                        /* %es */
372
  9 * 4,                        /* %fs */
373
  10 * 4,                       /* %gs */
374
  -1, -1, -1, -1, -1, -1, -1, -1,
375
  -1, -1, -1, -1, -1, -1, -1, -1,
376
  -1, -1, -1, -1, -1, -1, -1, -1,
377
  -1,
378
  11 * 4                        /* "orig_eax" */
379
};
380
 
381
/* Mapping between the general-purpose registers in `struct
382
   sigcontext' format and GDB's register cache layout.  */
383
 
384
/* From <asm/sigcontext.h>.  */
385
static int i386_linux_sc_reg_offset[] =
386
{
387
  11 * 4,                       /* %eax */
388
  10 * 4,                       /* %ecx */
389
  9 * 4,                        /* %edx */
390
  8 * 4,                        /* %ebx */
391
  7 * 4,                        /* %esp */
392
  6 * 4,                        /* %ebp */
393
  5 * 4,                        /* %esi */
394
  4 * 4,                        /* %edi */
395
  14 * 4,                       /* %eip */
396
  16 * 4,                       /* %eflags */
397
  15 * 4,                       /* %cs */
398
  18 * 4,                       /* %ss */
399
  3 * 4,                        /* %ds */
400
  2 * 4,                        /* %es */
401
  1 * 4,                        /* %fs */
402
 
403
};
404
 
405
static void
406
i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
407
{
408
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
409
 
410
  /* GNU/Linux uses ELF.  */
411
  i386_elf_init_abi (info, gdbarch);
412
 
413
  /* Since we have the extra "orig_eax" register on GNU/Linux, we have
414
     to adjust a few things.  */
415
 
416
  set_gdbarch_write_pc (gdbarch, i386_linux_write_pc);
417
  set_gdbarch_num_regs (gdbarch, I386_LINUX_NUM_REGS);
418
  set_gdbarch_register_name (gdbarch, i386_linux_register_name);
419
  set_gdbarch_register_reggroup_p (gdbarch, i386_linux_register_reggroup_p);
420
 
421
  tdep->gregset_reg_offset = i386_linux_gregset_reg_offset;
422
  tdep->gregset_num_regs = ARRAY_SIZE (i386_linux_gregset_reg_offset);
423
  tdep->sizeof_gregset = 17 * 4;
424
 
425
  tdep->jb_pc_offset = 20;      /* From <bits/setjmp.h>.  */
426
 
427
  tdep->sigtramp_p = i386_linux_sigtramp_p;
428
  tdep->sigcontext_addr = i386_linux_sigcontext_addr;
429
  tdep->sc_reg_offset = i386_linux_sc_reg_offset;
430
  tdep->sc_num_regs = ARRAY_SIZE (i386_linux_sc_reg_offset);
431
 
432
  /* N_FUN symbols in shared libaries have 0 for their values and need
433
     to be relocated. */
434
  set_gdbarch_sofun_address_maybe_missing (gdbarch, 1);
435
 
436
  /* GNU/Linux uses SVR4-style shared libraries.  */
437
  set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
438
  set_solib_svr4_fetch_link_map_offsets
439
    (gdbarch, svr4_ilp32_fetch_link_map_offsets);
440
 
441
  /* GNU/Linux uses the dynamic linker included in the GNU C Library.  */
442
  set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
443
 
444
  dwarf2_frame_set_signal_frame_p (gdbarch, i386_linux_dwarf_signal_frame_p);
445
 
446
  /* Enable TLS support.  */
447
  set_gdbarch_fetch_tls_load_module_address (gdbarch,
448
                                             svr4_fetch_objfile_link_map);
449
}
450
 
451
/* Provide a prototype to silence -Wmissing-prototypes.  */
452
extern void _initialize_i386_linux_tdep (void);
453
 
454
void
455
_initialize_i386_linux_tdep (void)
456
{
457
  gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_LINUX,
458
                          i386_linux_init_abi);
459
}

powered by: WebSVN 2.1.0

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