+++ /dev/null
-2004-06-22 Andrew Cagney <cagney@gnu.org>
-
- * rs6000-tdep.c (struct rs6000_framedata): Add field "func_start".
- (skip_prologue): Delete local variable "orig_pc", use
- "func_start". Add local variable "num_skip_linux_syscall_insn",
- use to skip over first half of a GNU/Linux syscall and update
- "func_start".
-
-Index: gdb-7.2.50.20110117/gdb/rs6000-tdep.c
-===================================================================
---- gdb-7.2.50.20110117.orig/gdb/rs6000-tdep.c 2011-01-11 20:23:02.000000000 +0100
-+++ gdb-7.2.50.20110117/gdb/rs6000-tdep.c 2011-01-17 15:48:19.000000000 +0100
-@@ -126,6 +126,7 @@ static const char *powerpc_vector_abi_st
-
- struct rs6000_framedata
- {
-+ CORE_ADDR func_start; /* True function start. */
- int offset; /* total size of frame --- the distance
- by which we decrement sp to allocate
- the frame */
-@@ -1496,7 +1497,6 @@ static CORE_ADDR
- skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
- struct rs6000_framedata *fdata)
- {
-- CORE_ADDR orig_pc = pc;
- CORE_ADDR last_prologue_pc = pc;
- CORE_ADDR li_found_pc = 0;
- gdb_byte buf[4];
-@@ -1514,12 +1514,14 @@ skip_prologue (struct gdbarch *gdbarch,
- int minimal_toc_loaded = 0;
- int prev_insn_was_prologue_insn = 1;
- int num_skip_non_prologue_insns = 0;
-+ int num_skip_ppc64_gnu_linux_syscall_insn = 0;
- int r0_contains_arg = 0;
- const struct bfd_arch_info *arch_info = gdbarch_bfd_arch_info (gdbarch);
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-
- memset (fdata, 0, sizeof (struct rs6000_framedata));
-+ fdata->func_start = pc;
- fdata->saved_gpr = -1;
- fdata->saved_fpr = -1;
- fdata->saved_vr = -1;
-@@ -1553,6 +1555,55 @@ skip_prologue (struct gdbarch *gdbarch,
- break;
- op = extract_unsigned_integer (buf, 4, byte_order);
-
-+ /* A PPC64 GNU/Linux system call function is split into two
-+ sub-functions: a non-threaded fast-path (__NAME_nocancel)
-+ which does not use a frame; and a threaded slow-path
-+ (Lpseudo_cancel) that does create a frame. Ref:
-+ nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h
-+
-+ *INDENT-OFF*
-+ NAME:
-+ SINGLE_THREAD_P
-+ bne- .Lpseudo_cancel
-+ __NAME_nocancel:
-+ li r0,162
-+ sc
-+ bnslr+
-+ b 0x7fe014ef64 <.__syscall_error>
-+ Lpseudo_cancel:
-+ stdu r1,-128(r1)
-+ ...
-+ *INDENT-ON*
-+
-+ Unfortunatly, because the latter case uses a local label (not
-+ in the symbol table) a PC in "Lpseudo_cancel" appears to be
-+ in "__NAME_nocancel". The following code recognizes this,
-+ adjusting FUNC_START to point to where "Lpseudo_cancel"
-+ should be, and parsing the prologue sequence as if
-+ "Lpseudo_cancel" was the entry point. */
-+
-+ if (((op & 0xffff0000) == 0x38000000 /* li r0,N */
-+ && pc == fdata->func_start + 0
-+ && num_skip_ppc64_gnu_linux_syscall_insn == 0)
-+ || (op == 0x44000002 /* sc */
-+ && pc == fdata->func_start + 4
-+ && num_skip_ppc64_gnu_linux_syscall_insn == 1)
-+ || (op == 0x4ca30020 /* bnslr+ */
-+ && pc == fdata->func_start + 8
-+ && num_skip_ppc64_gnu_linux_syscall_insn == 2))
-+ {
-+ num_skip_ppc64_gnu_linux_syscall_insn++;
-+ continue;
-+ }
-+ else if ((op & 0xfc000003) == 0x48000000 /* b __syscall_error */
-+ && pc == fdata->func_start + 12
-+ && num_skip_ppc64_gnu_linux_syscall_insn == 3)
-+ {
-+ num_skip_ppc64_gnu_linux_syscall_insn = -1;
-+ fdata->func_start = pc;
-+ continue;
-+ }
-+
- if ((op & 0xfc1fffff) == 0x7c0802a6)
- { /* mflr Rx */
- /* Since shared library / PIC code, which needs to get its
-@@ -1734,9 +1785,9 @@ skip_prologue (struct gdbarch *gdbarch,
- we have no line table information or the line info tells
- us that the subroutine call is not part of the line
- associated with the prologue. */
-- if ((pc - orig_pc) > 8)
-+ if ((pc - fdata->func_start) > 8)
- {
-- struct symtab_and_line prologue_sal = find_pc_line (orig_pc, 0);
-+ struct symtab_and_line prologue_sal = find_pc_line (fdata->func_start, 0);
- struct symtab_and_line this_sal = find_pc_line (pc, 0);
-
- if ((prologue_sal.line == 0)