X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=gdb%2Fppc-linux-tdep.c;h=6d3a64c4f0dfb15181b7dc9a78b476c439781824;hb=f6ac5f3d63e03a81c4ff3749aba234961cc9090e;hp=5f313f85b94d764bc01056a40a9b3e14551d69c8;hpb=9ac86b52da268147b2565e4920357432bb7a34c3;p=thirdparty%2Fbinutils-gdb.git diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index 5f313f85b94..6d3a64c4f0d 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -1,6 +1,6 @@ /* Target-dependent code for GDB, the GNU debugger. - Copyright (C) 1986-2017 Free Software Foundation, Inc. + Copyright (C) 1986-2018 Free Software Foundation, Inc. This file is part of GDB. @@ -41,7 +41,7 @@ #include "trad-frame.h" #include "frame-unwind.h" #include "tramp-frame.h" -#include "observer.h" +#include "observable.h" #include "auxv.h" #include "elf/common.h" #include "elf/ppc64.h" @@ -60,7 +60,7 @@ #include "parser-defs.h" #include "user-regs.h" #include -#include "elf-bfd.h" /* for elfcore_write_* */ +#include "elf-bfd.h" #include "features/rs6000/powerpc-32l.c" #include "features/rs6000/powerpc-altivec32l.c" @@ -256,8 +256,8 @@ ppc_linux_return_value (struct gdbarch *gdbarch, struct value *function, readbuf, writebuf); } -/* PLT stub in executable. */ -static struct ppc_insn_pattern powerpc32_plt_stub[] = +/* PLT stub in an executable. */ +static const struct ppc_insn_pattern powerpc32_plt_stub[] = { { 0xffff0000, 0x3d600000, 0 }, /* lis r11, xxxx */ { 0xffff0000, 0x816b0000, 0 }, /* lwz r11, xxxx(r11) */ @@ -266,16 +266,30 @@ static struct ppc_insn_pattern powerpc32_plt_stub[] = { 0, 0, 0 } }; -/* PLT stub in shared library. */ -static struct ppc_insn_pattern powerpc32_plt_stub_so[] = +/* PLT stubs in a shared library or PIE. + The first variant is used when the PLT entry is within +/-32k of + the GOT pointer (r30). */ +static const struct ppc_insn_pattern powerpc32_plt_stub_so_1[] = { { 0xffff0000, 0x817e0000, 0 }, /* lwz r11, xxxx(r30) */ { 0xffffffff, 0x7d6903a6, 0 }, /* mtctr r11 */ { 0xffffffff, 0x4e800420, 0 }, /* bctr */ - { 0xffffffff, 0x60000000, 0 }, /* nop */ { 0, 0, 0 } }; -#define POWERPC32_PLT_STUB_LEN ARRAY_SIZE (powerpc32_plt_stub) + +/* The second variant is used when the PLT entry is more than +/-32k + from the GOT pointer (r30). */ +static const struct ppc_insn_pattern powerpc32_plt_stub_so_2[] = + { + { 0xffff0000, 0x3d7e0000, 0 }, /* addis r11, r30, xxxx */ + { 0xffff0000, 0x816b0000, 0 }, /* lwz r11, xxxx(r11) */ + { 0xffffffff, 0x7d6903a6, 0 }, /* mtctr r11 */ + { 0xffffffff, 0x4e800420, 0 }, /* bctr */ + { 0, 0, 0 } + }; + +/* The max number of insns we check using ppc_insns_match_pattern. */ +#define POWERPC32_PLT_CHECK_LEN (ARRAY_SIZE (powerpc32_plt_stub) - 1) /* Check if PC is in PLT stub. For non-secure PLT, stub is in .plt section. For secure PLT, stub is in .text and we need to check @@ -306,13 +320,13 @@ powerpc_linux_in_dynsym_resolve_code (CORE_ADDR pc) When the execution direction is EXEC_REVERSE, scan backward to check whether we are in the middle of a PLT stub. Currently, - we only look-behind at most 4 instructions (the max length of PLT + we only look-behind at most 4 instructions (the max length of a PLT stub sequence. */ static CORE_ADDR ppc_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc) { - unsigned int insnbuf[POWERPC32_PLT_STUB_LEN]; + unsigned int insnbuf[POWERPC32_PLT_CHECK_LEN]; struct gdbarch *gdbarch = get_frame_arch (frame); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); @@ -323,40 +337,47 @@ ppc_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc) /* When reverse-debugging, scan backward to check whether we are in the middle of trampoline code. */ if (execution_direction == EXEC_REVERSE) - scan_limit = 4; /* At more 4 instructions. */ + scan_limit = 4; /* At most 4 instructions. */ for (i = 0; i < scan_limit; i++) { if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub, insnbuf)) { - /* Insn pattern is + /* Calculate PLT entry address from lis r11, xxxx - lwz r11, xxxx(r11) - Branch target is in r11. */ - - target = (ppc_insn_d_field (insnbuf[0]) << 16) - | ppc_insn_d_field (insnbuf[1]); - target = read_memory_unsigned_integer (target, 4, byte_order); + lwz r11, xxxx(r11). */ + target = ((ppc_insn_d_field (insnbuf[0]) << 16) + + ppc_insn_d_field (insnbuf[1])); + } + else if (i < ARRAY_SIZE (powerpc32_plt_stub_so_1) - 1 + && ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub_so_1, + insnbuf)) + { + /* Calculate PLT entry address from + lwz r11, xxxx(r30). */ + target = (ppc_insn_d_field (insnbuf[0]) + + get_frame_register_unsigned (frame, + tdep->ppc_gp0_regnum + 30)); } - else if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub_so, + else if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub_so_2, insnbuf)) { - /* Insn pattern is - lwz r11, xxxx(r30) - Branch target is in r11. */ - - target = get_frame_register_unsigned (frame, - tdep->ppc_gp0_regnum + 30) - + ppc_insn_d_field (insnbuf[0]); - target = read_memory_unsigned_integer (target, 4, byte_order); + /* Calculate PLT entry address from + addis r11, r30, xxxx + lwz r11, xxxx(r11). */ + target = ((ppc_insn_d_field (insnbuf[0]) << 16) + + ppc_insn_d_field (insnbuf[1]) + + get_frame_register_unsigned (frame, + tdep->ppc_gp0_regnum + 30)); } else { - /* Scan backward one more instructions if doesn't match. */ + /* Scan backward one more instruction if it doesn't match. */ pc -= 4; continue; } + target = read_memory_unsigned_integer (target, 4, byte_order); return target; } @@ -375,7 +396,7 @@ ppc_linux_supply_gregset (const struct regset *regset, ppc_supply_gregset (regset, regcache, regnum, gregs, len); - if (ppc_linux_trap_reg_p (get_regcache_arch (regcache))) + if (ppc_linux_trap_reg_p (regcache->arch ())) { /* "orig_r3" is stored 2 slots after "pc". */ if (regnum == -1 || regnum == PPC_ORIG_R3_REGNUM) @@ -405,7 +426,7 @@ ppc_linux_collect_gregset (const struct regset *regset, ppc_collect_gregset (regset, regcache, regnum, gregs, len); - if (ppc_linux_trap_reg_p (get_regcache_arch (regcache))) + if (ppc_linux_trap_reg_p (regcache->arch ())) { /* "orig_r3" is stored 2 slots after "pc". */ if (regnum == -1 || regnum == PPC_ORIG_R3_REGNUM) @@ -725,28 +746,19 @@ ppc_linux_get_syscall_number (struct gdbarch *gdbarch, struct regcache *regcache = get_thread_regcache (ptid); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct cleanup *cleanbuf; - /* The content of a register */ - gdb_byte *buf; - /* The result */ - LONGEST ret; /* Make sure we're in a 32- or 64-bit machine */ gdb_assert (tdep->wordsize == 4 || tdep->wordsize == 8); - buf = (gdb_byte *) xmalloc (tdep->wordsize * sizeof (gdb_byte)); - - cleanbuf = make_cleanup (xfree, buf); + /* The content of a register */ + gdb::byte_vector buf (tdep->wordsize); /* Getting the system call number from the register. When dealing with PowerPC architecture, this information is stored at 0th register. */ - regcache_cooked_read (regcache, tdep->ppc_gp0_regnum, buf); - - ret = extract_signed_integer (buf, tdep->wordsize, byte_order); - do_cleanups (cleanbuf); + regcache_cooked_read (regcache, tdep->ppc_gp0_regnum, buf.data ()); - return ret; + return extract_signed_integer (buf.data (), tdep->wordsize, byte_order); } /* PPC process record-replay */ @@ -798,7 +810,7 @@ ppc_canonicalize_syscall (int syscall) static int ppc_linux_syscall_record (struct regcache *regcache) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ULONGEST scnum; enum gdb_syscall syscall_gdb; @@ -927,7 +939,7 @@ ppc_linux_record_signal (struct gdbarch *gdbarch, struct regcache *regcache, static void ppc_linux_write_pc (struct regcache *regcache, CORE_ADDR pc) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); regcache_cooked_write_unsigned (regcache, gdbarch_pc_regnum (gdbarch), pc); @@ -1191,7 +1203,7 @@ ppc_linux_spe_context (int wordsize, enum bfd_endian byte_order, /* Look up cached address of thread-local variable. */ if (!ptid_equal (spe_context_cache_ptid, inferior_ptid)) { - struct target_ops *target = ¤t_target; + struct target_ops *target = target_stack; TRY { @@ -1202,9 +1214,9 @@ ppc_linux_spe_context (int wordsize, enum bfd_endian byte_order, Instead, we have cached the lm_addr value, and use that to directly call the target's to_get_thread_local_address. */ spe_context_cache_address - = target->to_get_thread_local_address (target, inferior_ptid, - spe_context_lm_addr, - spe_context_offset); + = target->get_thread_local_address (inferior_ptid, + spe_context_lm_addr, + spe_context_offset); spe_context_cache_ptid = inferior_ptid; } @@ -1250,14 +1262,14 @@ ppc_linux_spe_context (int wordsize, enum bfd_endian byte_order, struct ppu2spu_cache { struct frame_id frame_id; - struct regcache *regcache; + readonly_detached_regcache *regcache; }; static struct gdbarch * ppu2spu_prev_arch (struct frame_info *this_frame, void **this_cache) { struct ppu2spu_cache *cache = (struct ppu2spu_cache *) *this_cache; - return get_regcache_arch (cache->regcache); + return cache->regcache->arch (); } static void @@ -1273,16 +1285,12 @@ ppu2spu_prev_register (struct frame_info *this_frame, void **this_cache, int regnum) { struct ppu2spu_cache *cache = (struct ppu2spu_cache *) *this_cache; - struct gdbarch *gdbarch = get_regcache_arch (cache->regcache); + struct gdbarch *gdbarch = cache->regcache->arch (); gdb_byte *buf; buf = (gdb_byte *) alloca (register_size (gdbarch, regnum)); - if (regnum < gdbarch_num_regs (gdbarch)) - regcache_raw_read (cache->regcache, regnum, buf); - else - gdbarch_pseudo_register_read (gdbarch, cache->regcache, regnum, buf); - + cache->regcache->cooked_read (regnum, buf); return frame_unwind_got_bytes (this_frame, regnum, buf); } @@ -1355,17 +1363,16 @@ ppu2spu_sniffer (const struct frame_unwind *self, return 0; xsnprintf (annex, sizeof annex, "%d/regs", data.id); - if (target_read (¤t_target, TARGET_OBJECT_SPU, annex, + if (target_read (target_stack, TARGET_OBJECT_SPU, annex, data.gprs, 0, sizeof data.gprs) == sizeof data.gprs) { struct ppu2spu_cache *cache = FRAME_OBSTACK_CALLOC (1, struct ppu2spu_cache); - - struct address_space *aspace = get_frame_address_space (this_frame); - std::unique_ptr regcache - (new struct regcache (data.gdbarch, aspace)); - regcache_save (regcache.get (), ppu2spu_unwind_register, &data); + std::unique_ptr regcache + (new readonly_detached_regcache (data.gdbarch, + ppu2spu_unwind_register, + &data)); cache->frame_id = frame_id_build (base, func); cache->regcache = regcache.release (); @@ -1633,12 +1640,17 @@ ppc_floatformat_for_type (struct gdbarch *gdbarch, const char *name, int len) { if (len == 128 && name) - if (strcmp (name, "__float128") == 0 - || strcmp (name, "_Float128") == 0 - || strcmp (name, "_Float64x") == 0 - || strcmp (name, "complex _Float128") == 0 - || strcmp (name, "complex _Float64x") == 0) - return floatformats_ia64_quad; + { + if (strcmp (name, "__float128") == 0 + || strcmp (name, "_Float128") == 0 + || strcmp (name, "_Float64x") == 0 + || strcmp (name, "complex _Float128") == 0 + || strcmp (name, "complex _Float64x") == 0) + return floatformats_ia64_quad; + + if (strcmp (name, "__ibm128") == 0) + return floatformats_ibm_long_double; + } return default_floatformat_for_type (gdbarch, name, len); } @@ -1658,12 +1670,15 @@ ppc_linux_init_abi (struct gdbarch_info info, linux_init_abi (info, gdbarch); /* PPC GNU/Linux uses either 64-bit or 128-bit long doubles; where - 128-bit, they are IBM long double, not IEEE quad long double as - in the System V ABI PowerPC Processor Supplement. We can safely - let them default to 128-bit, since the debug info will give the - size of type actually used in each case. */ + 128-bit, they can be either IBM long double or IEEE quad long double. + The 64-bit long double case will be detected automatically using + the size specified in debug info. We use a .gnu.attribute flag + to distinguish between the IBM long double and IEEE quad cases. */ set_gdbarch_long_double_bit (gdbarch, 16 * TARGET_CHAR_BIT); - set_gdbarch_long_double_format (gdbarch, floatformats_ibm_long_double); + if (tdep->long_double_abi == POWERPC_LONG_DOUBLE_IEEE128) + set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad); + else + set_gdbarch_long_double_format (gdbarch, floatformats_ibm_long_double); /* Support for floating-point data type variants. */ set_gdbarch_floatformat_for_type (gdbarch, ppc_floatformat_for_type); @@ -1772,12 +1787,6 @@ ppc_linux_init_abi (struct gdbarch_info info, set_gdbarch_gcore_bfd_target (gdbarch, "elf64-powerpc"); } - /* PPC32 uses a different prpsinfo32 compared to most other Linux - archs. */ - if (tdep->wordsize == 4) - set_gdbarch_elfcore_write_linux_prpsinfo (gdbarch, - elfcore_write_ppc_linux_prpsinfo32); - set_gdbarch_core_read_description (gdbarch, ppc_linux_core_read_description); set_gdbarch_iterate_over_regset_sections (gdbarch, ppc_linux_iterate_over_regset_sections); @@ -1817,6 +1826,10 @@ ppc_linux_init_abi (struct gdbarch_info info, /* Cell/B.E. cross-architecture unwinder support. */ frame_unwind_prepend_unwinder (gdbarch, &ppu2spu_unwind); + + /* We need to support more than "addr_bit" significant address bits + in order to support SPUADDR_ADDR encoded values. */ + set_gdbarch_significant_addr_bit (gdbarch, 64); } set_gdbarch_displaced_step_location (gdbarch, @@ -1844,9 +1857,9 @@ _initialize_ppc_linux_tdep (void) ppc_linux_init_abi); /* Attach to observers to track __spe_current_active_context. */ - observer_attach_inferior_created (ppc_linux_spe_context_inferior_created); - observer_attach_solib_loaded (ppc_linux_spe_context_solib_loaded); - observer_attach_solib_unloaded (ppc_linux_spe_context_solib_unloaded); + gdb::observers::inferior_created.attach (ppc_linux_spe_context_inferior_created); + gdb::observers::solib_loaded.attach (ppc_linux_spe_context_solib_loaded); + gdb::observers::solib_unloaded.attach (ppc_linux_spe_context_solib_unloaded); /* Initialize the Linux target descriptions. */ initialize_tdesc_powerpc_32l ();