/* Common target-dependent code for ppc64 GDB, the GNU debugger.
- Copyright (C) 1986-2014 Free Software Foundation, Inc.
+ Copyright (C) 1986-2016 Free Software Foundation, Inc.
This file is part of GDB.
#include "defs.h"
#include "frame.h"
#include "gdbcore.h"
+#include "infrun.h"
#include "ppc-tdep.h"
#include "ppc64-tdep.h"
#include "elf-bfd.h"
/* Given that we've begun executing a call trampoline at PC, return
- the entry point of the function the trampoline will go to. */
+ the entry point of the function the trampoline will go to.
-CORE_ADDR
-ppc64_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
+ When the execution direction is EXEC_REVERSE, scan backward to
+ check whether we are in the middle of a PLT stub. */
+
+static CORE_ADDR
+ppc64_skip_trampoline_code_1 (struct frame_info *frame, CORE_ADDR pc)
{
#define MAX(a,b) ((a) > (b) ? (a) : (b))
unsigned int insns[MAX (MAX (MAX (ARRAY_SIZE (ppc64_standard_linkage1),
ARRAY_SIZE (ppc64_standard_linkage8))))
- 1];
CORE_ADDR target;
+ int scan_limit, i;
+
+ scan_limit = 1;
+ /* When reverse-debugging, scan backward to check whether we are
+ in the middle of trampoline code. */
+ if (execution_direction == EXEC_REVERSE)
+ scan_limit = ARRAY_SIZE (insns) - 1;
+
+ for (i = 0; i < scan_limit; i++)
+ {
+ if (i < ARRAY_SIZE (ppc64_standard_linkage8) - 1
+ && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage8, insns))
+ pc = ppc64_standard_linkage4_target (frame, pc, insns);
+ else if (i < ARRAY_SIZE (ppc64_standard_linkage7) - 1
+ && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage7,
+ insns))
+ pc = ppc64_standard_linkage3_target (frame, pc, insns);
+ else if (i < ARRAY_SIZE (ppc64_standard_linkage6) - 1
+ && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage6,
+ insns))
+ pc = ppc64_standard_linkage4_target (frame, pc, insns);
+ else if (i < ARRAY_SIZE (ppc64_standard_linkage5) - 1
+ && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage5,
+ insns)
+ && (insns[8] != 0 || insns[9] != 0))
+ pc = ppc64_standard_linkage3_target (frame, pc, insns);
+ else if (i < ARRAY_SIZE (ppc64_standard_linkage4) - 1
+ && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage4,
+ insns)
+ && (insns[9] != 0 || insns[10] != 0))
+ pc = ppc64_standard_linkage4_target (frame, pc, insns);
+ else if (i < ARRAY_SIZE (ppc64_standard_linkage3) - 1
+ && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage3,
+ insns)
+ && (insns[8] != 0 || insns[9] != 0))
+ pc = ppc64_standard_linkage3_target (frame, pc, insns);
+ else if (i < ARRAY_SIZE (ppc64_standard_linkage2) - 1
+ && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage2,
+ insns)
+ && (insns[10] != 0 || insns[11] != 0))
+ pc = ppc64_standard_linkage2_target (frame, pc, insns);
+ else if (i < ARRAY_SIZE (ppc64_standard_linkage1) - 1
+ && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage1,
+ insns))
+ pc = ppc64_standard_linkage1_target (frame, pc, insns);
+ else
+ {
+ /* Scan backward one more instructions if doesn't match. */
+ pc -= 4;
+ continue;
+ }
+
+ /* The PLT descriptor will either point to the already resolved target
+ address, or else to a glink stub. As the latter carry synthetic @plt
+ symbols, find_solib_trampoline_target should be able to resolve them. */
+ target = find_solib_trampoline_target (frame, pc);
+ return target ? target : pc;
+ }
+
+ return 0;
+}
+
+/* Wrapper of ppc64_skip_trampoline_code_1 checking also
+ ppc_elfv2_skip_entrypoint. */
+
+CORE_ADDR
+ppc64_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
+{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
- if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage8, insns))
- pc = ppc64_standard_linkage4_target (frame, pc, insns);
- else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage7, insns))
- pc = ppc64_standard_linkage3_target (frame, pc, insns);
- else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage6, insns))
- pc = ppc64_standard_linkage4_target (frame, pc, insns);
- else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage5, insns)
- && (insns[8] != 0 || insns[9] != 0))
- pc = ppc64_standard_linkage3_target (frame, pc, insns);
- else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage4, insns)
- && (insns[9] != 0 || insns[10] != 0))
- pc = ppc64_standard_linkage4_target (frame, pc, insns);
- else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage3, insns)
- && (insns[8] != 0 || insns[9] != 0))
- pc = ppc64_standard_linkage3_target (frame, pc, insns);
- else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage2, insns)
- && (insns[10] != 0 || insns[11] != 0))
- pc = ppc64_standard_linkage2_target (frame, pc, insns);
- else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage1, insns))
- pc = ppc64_standard_linkage1_target (frame, pc, insns);
- else
- return 0;
-
- /* The PLT descriptor will either point to the already resolved target
- address, or else to a glink stub. As the latter carry synthetic @plt
- symbols, find_solib_trampoline_target should be able to resolve them. */
- target = find_solib_trampoline_target (frame, pc);
- return target ? target : pc;
+ pc = ppc64_skip_trampoline_code_1 (frame, pc);
+ if (pc != 0 && gdbarch_skip_entrypoint_p (gdbarch))
+ pc = gdbarch_skip_entrypoint (gdbarch, pc);
+ return pc;
}
/* Support for convert_from_func_ptr_addr (ARCH, ADDR, TARG) on PPC64