diff options
-rw-r--r-- | gdb/ppc-linux-tdep.c | 48 |
1 files changed, 39 insertions, 9 deletions
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index 5f6bb604a3c..78c90fdb155 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -685,11 +685,10 @@ struct insn_pattern When the match is successful, fill INSN[i] with what PATTERN[i] matched. If PATTERN[i] is optional, and the instruction wasn't - present, set INSN[i] to 0 (an invalid instruction on the PPC). - INSN should have as many elements as PATTERN. Note that, if - PATTERN contains optional instructions which aren't present in - memory, then INSN will have holes, so INSN[i] isn't necessarily the - i'th instruction in memory. */ + present, set INSN[i] to -1. INSN should have as many elements as + PATTERN. Note that, if PATTERN contains optional instructions + which aren't present in memory, then INSN will have holes, so + INSN[i] isn't necessarily the i'th instruction in memory. */ static int insns_match_pattern (CORE_ADDR pc, struct insn_pattern *pattern, @@ -731,6 +730,16 @@ insn_ds_field (unsigned int insn) } +/* If DESC is the address of a 64-bit PowerPC Linux function + descriptor, return the descriptor's entry point. */ +static CORE_ADDR +ppc64_desc_entry_point (CORE_ADDR desc) +{ + /* The first word of the descriptor is the entry point. */ + return (CORE_ADDR) read_memory_unsigned_integer (desc, 8); +} + + /* Pattern for the standard linkage function. These are built by build_plt_stub in elf64-ppc.c, whose GLINK argument is always zero. */ @@ -865,7 +874,7 @@ ppc64_standard_linkage_target (CORE_ADDR pc, unsigned int *insn) + insn_ds_field (insn[2])); /* The first word of the descriptor is the entry point. Return that. */ - return (CORE_ADDR) read_memory_unsigned_integer (desc, 8); + return ppc64_desc_entry_point (desc); } @@ -884,6 +893,18 @@ ppc64_skip_trampoline_code (CORE_ADDR pc) } +/* On 64-bit PowerPC Linux, the ELF header's e_entry field is the + address of a function descriptor for the entry point function, not + the actual entry point itself. So to find the actual address at + which execution should begin, we need to fetch the function's entry + point from that descriptor. */ +static CORE_ADDR +ppc64_call_dummy_address (void) +{ + return ppc64_desc_entry_point (entry_point_address ()); +} + + enum { ELF_NGREG = 48, ELF_NFPREG = 33, @@ -995,13 +1016,22 @@ ppc_linux_init_abi (struct gdbarch_info info, set_gdbarch_memory_remove_breakpoint (gdbarch, ppc_linux_memory_remove_breakpoint); + /* Shared library handling. */ + set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section); + set_gdbarch_skip_trampoline_code (gdbarch, + ppc_linux_skip_trampoline_code); set_solib_svr4_fetch_link_map_offsets (gdbarch, ppc_linux_svr4_fetch_link_map_offsets); } + + if (tdep->wordsize == 8) + { + set_gdbarch_call_dummy_address (gdbarch, ppc64_call_dummy_address); - /* Shared library handling. */ - set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section); - set_gdbarch_skip_trampoline_code (gdbarch, ppc_linux_skip_trampoline_code); + set_gdbarch_in_solib_call_trampoline + (gdbarch, ppc64_in_solib_call_trampoline); + set_gdbarch_skip_trampoline_code (gdbarch, ppc64_skip_trampoline_code); + } } void |