]>
Commit | Line | Data |
---|---|---|
3a58abaf AM |
1 | 2004-06-22 Andrew Cagney <cagney@gnu.org> |
2 | ||
3 | * rs6000-tdep.c (struct rs6000_framedata): Add field "func_start". | |
4 | (skip_prologue): Delete local variable "orig_pc", use | |
5 | "func_start". Add local variable "num_skip_linux_syscall_insn", | |
6 | use to skip over first half of a GNU/Linux syscall and update | |
7 | "func_start". | |
8 | ||
6ed6bacf | 9 | Index: gdb-7.2.50.20110117/gdb/rs6000-tdep.c |
3a58abaf | 10 | =================================================================== |
6ed6bacf AM |
11 | --- gdb-7.2.50.20110117.orig/gdb/rs6000-tdep.c 2011-01-11 20:23:02.000000000 +0100 |
12 | +++ gdb-7.2.50.20110117/gdb/rs6000-tdep.c 2011-01-17 15:48:19.000000000 +0100 | |
7566401a | 13 | @@ -126,6 +126,7 @@ static const char *powerpc_vector_abi_st |
3a58abaf AM |
14 | |
15 | struct rs6000_framedata | |
16 | { | |
17 | + CORE_ADDR func_start; /* True function start. */ | |
18 | int offset; /* total size of frame --- the distance | |
19 | by which we decrement sp to allocate | |
20 | the frame */ | |
6ed6bacf | 21 | @@ -1496,7 +1497,6 @@ static CORE_ADDR |
3a58abaf AM |
22 | skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc, |
23 | struct rs6000_framedata *fdata) | |
24 | { | |
25 | - CORE_ADDR orig_pc = pc; | |
26 | CORE_ADDR last_prologue_pc = pc; | |
27 | CORE_ADDR li_found_pc = 0; | |
28 | gdb_byte buf[4]; | |
6ed6bacf | 29 | @@ -1514,12 +1514,14 @@ skip_prologue (struct gdbarch *gdbarch, |
3a58abaf AM |
30 | int minimal_toc_loaded = 0; |
31 | int prev_insn_was_prologue_insn = 1; | |
32 | int num_skip_non_prologue_insns = 0; | |
33 | + int num_skip_ppc64_gnu_linux_syscall_insn = 0; | |
34 | int r0_contains_arg = 0; | |
35 | const struct bfd_arch_info *arch_info = gdbarch_bfd_arch_info (gdbarch); | |
36 | struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); | |
7566401a | 37 | enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); |
3a58abaf AM |
38 | |
39 | memset (fdata, 0, sizeof (struct rs6000_framedata)); | |
40 | + fdata->func_start = pc; | |
41 | fdata->saved_gpr = -1; | |
42 | fdata->saved_fpr = -1; | |
43 | fdata->saved_vr = -1; | |
6ed6bacf | 44 | @@ -1553,6 +1555,55 @@ skip_prologue (struct gdbarch *gdbarch, |
3a58abaf | 45 | break; |
7566401a | 46 | op = extract_unsigned_integer (buf, 4, byte_order); |
3a58abaf AM |
47 | |
48 | + /* A PPC64 GNU/Linux system call function is split into two | |
49 | + sub-functions: a non-threaded fast-path (__NAME_nocancel) | |
50 | + which does not use a frame; and a threaded slow-path | |
51 | + (Lpseudo_cancel) that does create a frame. Ref: | |
52 | + nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h | |
53 | + | |
54 | + *INDENT-OFF* | |
55 | + NAME: | |
56 | + SINGLE_THREAD_P | |
57 | + bne- .Lpseudo_cancel | |
58 | + __NAME_nocancel: | |
59 | + li r0,162 | |
60 | + sc | |
61 | + bnslr+ | |
62 | + b 0x7fe014ef64 <.__syscall_error> | |
63 | + Lpseudo_cancel: | |
64 | + stdu r1,-128(r1) | |
65 | + ... | |
66 | + *INDENT-ON* | |
67 | + | |
68 | + Unfortunatly, because the latter case uses a local label (not | |
69 | + in the symbol table) a PC in "Lpseudo_cancel" appears to be | |
70 | + in "__NAME_nocancel". The following code recognizes this, | |
71 | + adjusting FUNC_START to point to where "Lpseudo_cancel" | |
72 | + should be, and parsing the prologue sequence as if | |
73 | + "Lpseudo_cancel" was the entry point. */ | |
74 | + | |
75 | + if (((op & 0xffff0000) == 0x38000000 /* li r0,N */ | |
76 | + && pc == fdata->func_start + 0 | |
77 | + && num_skip_ppc64_gnu_linux_syscall_insn == 0) | |
78 | + || (op == 0x44000002 /* sc */ | |
79 | + && pc == fdata->func_start + 4 | |
80 | + && num_skip_ppc64_gnu_linux_syscall_insn == 1) | |
81 | + || (op == 0x4ca30020 /* bnslr+ */ | |
82 | + && pc == fdata->func_start + 8 | |
83 | + && num_skip_ppc64_gnu_linux_syscall_insn == 2)) | |
84 | + { | |
85 | + num_skip_ppc64_gnu_linux_syscall_insn++; | |
86 | + continue; | |
87 | + } | |
88 | + else if ((op & 0xfc000003) == 0x48000000 /* b __syscall_error */ | |
89 | + && pc == fdata->func_start + 12 | |
90 | + && num_skip_ppc64_gnu_linux_syscall_insn == 3) | |
91 | + { | |
92 | + num_skip_ppc64_gnu_linux_syscall_insn = -1; | |
93 | + fdata->func_start = pc; | |
94 | + continue; | |
95 | + } | |
96 | + | |
97 | if ((op & 0xfc1fffff) == 0x7c0802a6) | |
98 | { /* mflr Rx */ | |
99 | /* Since shared library / PIC code, which needs to get its | |
6ed6bacf | 100 | @@ -1734,9 +1785,9 @@ skip_prologue (struct gdbarch *gdbarch, |
3a58abaf AM |
101 | we have no line table information or the line info tells |
102 | us that the subroutine call is not part of the line | |
103 | associated with the prologue. */ | |
104 | - if ((pc - orig_pc) > 8) | |
105 | + if ((pc - fdata->func_start) > 8) | |
106 | { | |
107 | - struct symtab_and_line prologue_sal = find_pc_line (orig_pc, 0); | |
108 | + struct symtab_and_line prologue_sal = find_pc_line (fdata->func_start, 0); | |
109 | struct symtab_and_line this_sal = find_pc_line (pc, 0); | |
110 | ||
6ed6bacf | 111 | if ((prologue_sal.line == 0) |