diff --git a/gdb-ppc64le.patch b/gdb-ppc64le.patch new file mode 100644 index 0000000..f55763a --- /dev/null +++ b/gdb-ppc64le.patch @@ -0,0 +1,1772 @@ +Index: gdb-7.6.50.20130731-cvs/gdb/auxv.c +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/gdb/auxv.c ++++ gdb-7.6.50.20130731-cvs/gdb/auxv.c +@@ -442,6 +442,7 @@ fprint_target_auxv (struct ui_file *file + TAG (AT_IGNOREPPC, _("Entry should be ignored"), dec); + TAG (AT_BASE_PLATFORM, _("String identifying base platform"), str); + TAG (AT_RANDOM, _("Address of 16 random bytes"), hex); ++ TAG (AT_HWCAP2, _("Extension of AT_HWCAP"), hex); + TAG (AT_EXECFN, _("File name of executable"), str); + TAG (AT_SECURE, _("Boolean, was exec setuid-like?"), dec); + TAG (AT_SYSINFO, _("Special system info/entry points"), hex); +Index: gdb-7.6.50.20130731-cvs/gdb/configure.host +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/gdb/configure.host ++++ gdb-7.6.50.20130731-cvs/gdb/configure.host +@@ -129,18 +129,18 @@ mips64*-*-openbsd*) gdb_host=obsd64 ;; + powerpc-*-aix* | rs6000-*-*) + gdb_host=aix ;; + powerpc*-*-freebsd*) gdb_host=fbsd ;; +-powerpc-*-linux*) gdb_host=linux ;; + powerpc-*-netbsd* | powerpc-*-knetbsd*-gnu) + gdb_host=nbsd ;; + powerpc-*-openbsd*) gdb_host=obsd ;; + +-powerpc64-*-linux*) gdb_host=ppc64-linux ++powerpc64*-*-linux*) gdb_host=ppc64-linux + # Support 'pseudo-native' debugging on the Cell BE + if test "${target_cpu}" = "spu"; then + gdb_host=spu-linux + gdb_native=yes + fi + ;; ++powerpc*-*-linux*) gdb_host=linux ;; + + s390*-*-*) gdb_host=s390 ;; + +Index: gdb-7.6.50.20130731-cvs/gdb/configure.tgt +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/gdb/configure.tgt ++++ gdb-7.6.50.20130731-cvs/gdb/configure.tgt +@@ -438,7 +438,7 @@ powerpc-*-aix* | rs6000-*-*) + ppc-sysv-tdep.o solib-aix.o \ + ravenscar-thread.o ppc-ravenscar-thread.o" + ;; +-powerpc-*-linux* | powerpc64-*-linux*) ++powerpc*-*-linux*) + # Target: PowerPC running Linux + gdb_target_obs="rs6000-tdep.o ppc-linux-tdep.o ppc-sysv-tdep.o \ + ppc64-tdep.o solib-svr4.o solib-spu.o \ +Index: gdb-7.6.50.20130731-cvs/gdb/doublest.c +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/gdb/doublest.c ++++ gdb-7.6.50.20130731-cvs/gdb/doublest.c +@@ -190,7 +190,8 @@ convert_floatformat_to_doublest (const s + { + double dto; + +- floatformat_to_double (fmt, from, &dto); ++ floatformat_to_double (fmt->split_half ? fmt->split_half : fmt, ++ from, &dto); + *to = (DOUBLEST) dto; + return; + } +@@ -514,6 +515,11 @@ floatformat_is_negative (const struct fl + gdb_assert (fmt->totalsize + <= FLOATFORMAT_LARGEST_BYTES * FLOATFORMAT_CHAR_BIT); + ++ /* An IBM long double (a two element array of double) always takes the ++ sign of the first double. */ ++ if (fmt->split_half) ++ fmt = fmt->split_half; ++ + order = floatformat_normalize_byteorder (fmt, uval, newfrom); + + if (order != fmt->byteorder) +@@ -540,6 +546,13 @@ floatformat_classify (const struct float + gdb_assert (fmt->totalsize + <= FLOATFORMAT_LARGEST_BYTES * FLOATFORMAT_CHAR_BIT); + ++ /* An IBM long double (a two element array of double) can be classified ++ by looking at the first double. inf and nan are specified as ++ ignoring the second double. zero and subnormal will always have ++ the second double 0.0 if the long double is correctly rounded. */ ++ if (fmt->split_half) ++ fmt = fmt->split_half; ++ + order = floatformat_normalize_byteorder (fmt, uval, newfrom); + + if (order != fmt->byteorder) +@@ -622,6 +635,16 @@ floatformat_mantissa (const struct float + gdb_assert (fmt->totalsize + <= FLOATFORMAT_LARGEST_BYTES * FLOATFORMAT_CHAR_BIT); + ++ /* For IBM long double (a two element array of double), return the ++ mantissa of the first double. The problem with returning the ++ actual mantissa from both doubles is that there can be an ++ arbitrary number of implied 0's or 1's between the mantissas ++ of the first and second double. In any case, this function ++ is only used for dumping out nans, and a nan is specified to ++ ignore the value in the second double. */ ++ if (fmt->split_half) ++ fmt = fmt->split_half; ++ + order = floatformat_normalize_byteorder (fmt, uval, newfrom); + + if (order != fmt->byteorder) +@@ -879,27 +902,3 @@ convert_typed_floating (const void *from + floatformat_from_doublest (to_fmt, &d, to); + } + } +- +-const struct floatformat *floatformat_ieee_single[BFD_ENDIAN_UNKNOWN]; +-const struct floatformat *floatformat_ieee_double[BFD_ENDIAN_UNKNOWN]; +-const struct floatformat *floatformat_ieee_quad[BFD_ENDIAN_UNKNOWN]; +-const struct floatformat *floatformat_arm_ext[BFD_ENDIAN_UNKNOWN]; +-const struct floatformat *floatformat_ia64_spill[BFD_ENDIAN_UNKNOWN]; +- +-extern void _initialize_doublest (void); +- +-extern void +-_initialize_doublest (void) +-{ +- floatformat_ieee_single[BFD_ENDIAN_LITTLE] = &floatformat_ieee_single_little; +- floatformat_ieee_single[BFD_ENDIAN_BIG] = &floatformat_ieee_single_big; +- floatformat_ieee_double[BFD_ENDIAN_LITTLE] = &floatformat_ieee_double_little; +- floatformat_ieee_double[BFD_ENDIAN_BIG] = &floatformat_ieee_double_big; +- floatformat_arm_ext[BFD_ENDIAN_LITTLE] +- = &floatformat_arm_ext_littlebyte_bigword; +- floatformat_arm_ext[BFD_ENDIAN_BIG] = &floatformat_arm_ext_big; +- floatformat_ia64_spill[BFD_ENDIAN_LITTLE] = &floatformat_ia64_spill_little; +- floatformat_ia64_spill[BFD_ENDIAN_BIG] = &floatformat_ia64_spill_big; +- floatformat_ieee_quad[BFD_ENDIAN_LITTLE] = &floatformat_ia64_quad_little; +- floatformat_ieee_quad[BFD_ENDIAN_BIG] = &floatformat_ia64_quad_big; +-} +Index: gdb-7.6.50.20130731-cvs/gdb/gdbarch.c +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/gdb/gdbarch.c ++++ gdb-7.6.50.20130731-cvs/gdb/gdbarch.c +@@ -200,6 +200,7 @@ struct gdbarch + gdbarch_return_in_first_hidden_param_p_ftype *return_in_first_hidden_param_p; + gdbarch_skip_prologue_ftype *skip_prologue; + gdbarch_skip_main_prologue_ftype *skip_main_prologue; ++ gdbarch_skip_entrypoint_ftype *skip_entrypoint; + gdbarch_inner_than_ftype *inner_than; + gdbarch_breakpoint_from_pc_ftype *breakpoint_from_pc; + gdbarch_remote_breakpoint_from_pc_ftype *remote_breakpoint_from_pc; +@@ -372,6 +373,7 @@ struct gdbarch startup_gdbarch = + default_return_in_first_hidden_param_p, /* return_in_first_hidden_param_p */ + 0, /* skip_prologue */ + 0, /* skip_main_prologue */ ++ 0, /* skip_entrypoint */ + 0, /* inner_than */ + 0, /* breakpoint_from_pc */ + default_remote_breakpoint_from_pc, /* remote_breakpoint_from_pc */ +@@ -674,6 +676,7 @@ verify_gdbarch (struct gdbarch *gdbarch) + if (gdbarch->skip_prologue == 0) + fprintf_unfiltered (log, "\n\tskip_prologue"); + /* Skip verify of skip_main_prologue, has predicate. */ ++ /* Skip verify of skip_entrypoint, has predicate. */ + if (gdbarch->inner_than == 0) + fprintf_unfiltered (log, "\n\tinner_than"); + if (gdbarch->breakpoint_from_pc == 0) +@@ -1294,6 +1297,12 @@ gdbarch_dump (struct gdbarch *gdbarch, s + "gdbarch_dump: single_step_through_delay = <%s>\n", + host_address_to_string (gdbarch->single_step_through_delay)); + fprintf_unfiltered (file, ++ "gdbarch_dump: gdbarch_skip_entrypoint_p() = %d\n", ++ gdbarch_skip_entrypoint_p (gdbarch)); ++ fprintf_unfiltered (file, ++ "gdbarch_dump: skip_entrypoint = <%s>\n", ++ host_address_to_string (gdbarch->skip_entrypoint)); ++ fprintf_unfiltered (file, + "gdbarch_dump: gdbarch_skip_main_prologue_p() = %d\n", + gdbarch_skip_main_prologue_p (gdbarch)); + fprintf_unfiltered (file, +@@ -2644,6 +2653,30 @@ set_gdbarch_skip_main_prologue (struct g + } + + int ++gdbarch_skip_entrypoint_p (struct gdbarch *gdbarch) ++{ ++ gdb_assert (gdbarch != NULL); ++ return gdbarch->skip_entrypoint != NULL; ++} ++ ++CORE_ADDR ++gdbarch_skip_entrypoint (struct gdbarch *gdbarch, CORE_ADDR ip) ++{ ++ gdb_assert (gdbarch != NULL); ++ gdb_assert (gdbarch->skip_entrypoint != NULL); ++ if (gdbarch_debug >= 2) ++ fprintf_unfiltered (gdb_stdlog, "gdbarch_skip_entrypoint called\n"); ++ return gdbarch->skip_entrypoint (gdbarch, ip); ++} ++ ++void ++set_gdbarch_skip_entrypoint (struct gdbarch *gdbarch, ++ gdbarch_skip_entrypoint_ftype skip_entrypoint) ++{ ++ gdbarch->skip_entrypoint = skip_entrypoint; ++} ++ ++int + gdbarch_inner_than (struct gdbarch *gdbarch, CORE_ADDR lhs, CORE_ADDR rhs) + { + gdb_assert (gdbarch != NULL); +Index: gdb-7.6.50.20130731-cvs/gdb/gdbarch.h +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/gdb/gdbarch.h ++++ gdb-7.6.50.20130731-cvs/gdb/gdbarch.h +@@ -487,6 +487,12 @@ typedef CORE_ADDR (gdbarch_skip_main_pro + extern CORE_ADDR gdbarch_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR ip); + extern void set_gdbarch_skip_main_prologue (struct gdbarch *gdbarch, gdbarch_skip_main_prologue_ftype *skip_main_prologue); + ++extern int gdbarch_skip_entrypoint_p (struct gdbarch *gdbarch); ++ ++typedef CORE_ADDR (gdbarch_skip_entrypoint_ftype) (struct gdbarch *gdbarch, CORE_ADDR ip); ++extern CORE_ADDR gdbarch_skip_entrypoint (struct gdbarch *gdbarch, CORE_ADDR ip); ++extern void set_gdbarch_skip_entrypoint (struct gdbarch *gdbarch, gdbarch_skip_entrypoint_ftype *skip_entrypoint); ++ + typedef int (gdbarch_inner_than_ftype) (CORE_ADDR lhs, CORE_ADDR rhs); + extern int gdbarch_inner_than (struct gdbarch *gdbarch, CORE_ADDR lhs, CORE_ADDR rhs); + extern void set_gdbarch_inner_than (struct gdbarch *gdbarch, gdbarch_inner_than_ftype *inner_than); +Index: gdb-7.6.50.20130731-cvs/gdb/gdbarch.sh +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/gdb/gdbarch.sh ++++ gdb-7.6.50.20130731-cvs/gdb/gdbarch.sh +@@ -527,6 +527,7 @@ m:int:return_in_first_hidden_param_p:str + + m:CORE_ADDR:skip_prologue:CORE_ADDR ip:ip:0:0 + M:CORE_ADDR:skip_main_prologue:CORE_ADDR ip:ip ++M:CORE_ADDR:skip_entrypoint:CORE_ADDR ip:ip + f:int:inner_than:CORE_ADDR lhs, CORE_ADDR rhs:lhs, rhs:0:0 + m:const gdb_byte *:breakpoint_from_pc:CORE_ADDR *pcptr, int *lenptr:pcptr, lenptr::0: + # Return the adjusted address and kind to use for Z0/Z1 packets. +Index: gdb-7.6.50.20130731-cvs/gdb/gdbtypes.c +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/gdb/gdbtypes.c ++++ gdb-7.6.50.20130731-cvs/gdb/gdbtypes.c +@@ -111,8 +111,8 @@ const struct floatformat *floatformats_v + &floatformat_vax_d + }; + const struct floatformat *floatformats_ibm_long_double[BFD_ENDIAN_UNKNOWN] = { +- &floatformat_ibm_long_double, +- &floatformat_ibm_long_double ++ &floatformat_ibm_long_double_big, ++ &floatformat_ibm_long_double_little + }; + + /* Should opaque types be resolved? */ +Index: gdb-7.6.50.20130731-cvs/gdb/infrun.c +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/gdb/infrun.c ++++ gdb-7.6.50.20130731-cvs/gdb/infrun.c +@@ -3151,6 +3151,10 @@ fill_in_stop_func (struct gdbarch *gdbar + ecs->stop_func_start + += gdbarch_deprecated_function_start_offset (gdbarch); + ++ if (gdbarch_skip_entrypoint_p (gdbarch)) ++ ecs->stop_func_start = gdbarch_skip_entrypoint (gdbarch, ++ ecs->stop_func_start); ++ + ecs->stop_func_filled_in = 1; + } + } +Index: gdb-7.6.50.20130731-cvs/gdb/ppc64-tdep.c +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/gdb/ppc64-tdep.c ++++ gdb-7.6.50.20130731-cvs/gdb/ppc64-tdep.c +@@ -48,21 +48,21 @@ + | (((spr) & 0x3e0) << 6) \ + | (((xo) & 0x3ff) << 1)) + +-/* If DESC is the address of a 64-bit PowerPC FreeBSD function +- descriptor, return the descriptor's entry point. */ ++/* If PLT is the address of a 64-bit PowerPC PLT entry, ++ return the function's entry point. */ + + static CORE_ADDR +-ppc64_desc_entry_point (struct gdbarch *gdbarch, CORE_ADDR desc) ++ppc64_plt_entry_point (struct gdbarch *gdbarch, CORE_ADDR plt) + { + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); +- /* The first word of the descriptor is the entry point. */ +- return (CORE_ADDR) read_memory_unsigned_integer (desc, 8, byte_order); ++ /* The first word of the PLT entry is the function entry point. */ ++ return (CORE_ADDR) read_memory_unsigned_integer (plt, 8, byte_order); + } + + /* Patterns for the standard linkage functions. These are built by + build_plt_stub in bfd/elf64-ppc.c. */ + +-/* Old PLT call stub. */ ++/* Old ELFv1 PLT call stub. */ + + static struct ppc_insn_pattern ppc64_standard_linkage1[] = + { +@@ -96,7 +96,7 @@ static struct ppc_insn_pattern ppc64_sta + { 0, 0, 0 } + }; + +-/* Current PLT call stub to access PLT entries more than +/- 32k from r2. ++/* ELFv1 PLT call stub to access PLT entries more than +/- 32k from r2. + Also supports older stub with different placement of std 2,40(1), + a stub that omits the std 2,40(1), and both versions of power7 + thread safety read barriers. Note that there are actually two more +@@ -144,7 +144,7 @@ static struct ppc_insn_pattern ppc64_sta + { 0, 0, 0 } + }; + +-/* Current PLT call stub to access PLT entries within +/- 32k of r2. */ ++/* ELFv1 PLT call stub to access PLT entries within +/- 32k of r2. */ + + static struct ppc_insn_pattern ppc64_standard_linkage3[] = + { +@@ -181,6 +181,128 @@ static struct ppc_insn_pattern ppc64_sta + { 0, 0, 0 } + }; + ++/* ELFv1 PLT call stub to access PLT entries more than +/- 32k from r2. ++ A more modern variant of ppc64_standard_linkage2 differing in ++ register usage. */ ++ ++static struct ppc_insn_pattern ppc64_standard_linkage4[] = ++ { ++ /* std r2, 40(r1) */ ++ { -1, insn_ds (62, 2, 1, 40, 0), 1 }, ++ ++ /* addis r11, r2, */ ++ { insn_d (-1, -1, -1, 0), insn_d (15, 11, 2, 0), 0 }, ++ ++ /* ld r12, (r11) */ ++ { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 12, 11, 0, 0), 0 }, ++ ++ /* addi r11, r11, */ ++ { insn_d (-1, -1, -1, 0), insn_d (14, 11, 11, 0), 1 }, ++ ++ /* mtctr r12 */ ++ { insn_xfx (-1, -1, -1, -1), insn_xfx (31, 12, 9, 467), 0 }, ++ ++ /* xor r2, r12, r12 */ ++ { -1, 0x7d826278, 1 }, ++ ++ /* add r11, r11, r2 */ ++ { -1, 0x7d6b1214, 1 }, ++ ++ /* ld r2, (r11) */ ++ { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 2, 11, 0, 0), 0 }, ++ ++ /* ld r11, (r11) */ ++ { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 11, 11, 0, 0), 1 }, ++ ++ /* bctr */ ++ { -1, 0x4e800420, 1 }, ++ ++ /* cmpldi r2, 0 */ ++ { -1, 0x28220000, 1 }, ++ ++ { 0, 0, 0 } ++ }; ++ ++/* ELFv1 PLT call stub to access PLT entries within +/- 32k of r2. ++ A more modern variant of ppc64_standard_linkage3 differing in ++ register usage. */ ++ ++static struct ppc_insn_pattern ppc64_standard_linkage5[] = ++ { ++ /* std r2, 40(r1) */ ++ { -1, insn_ds (62, 2, 1, 40, 0), 1 }, ++ ++ /* ld r12, (r2) */ ++ { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 12, 2, 0, 0), 0 }, ++ ++ /* addi r2, r2, */ ++ { insn_d (-1, -1, -1, 0), insn_d (14, 2, 2, 0), 1 }, ++ ++ /* mtctr r12 */ ++ { insn_xfx (-1, -1, -1, -1), insn_xfx (31, 12, 9, 467), 0 }, ++ ++ /* xor r11, r12, r12 */ ++ { -1, 0x7d8b6278, 1 }, ++ ++ /* add r2, r2, r11 */ ++ { -1, 0x7c425a14, 1 }, ++ ++ /* ld r11, (r2) */ ++ { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 11, 2, 0, 0), 1 }, ++ ++ /* ld r2, (r2) */ ++ { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 2, 2, 0, 0), 0 }, ++ ++ /* bctr */ ++ { -1, 0x4e800420, 1 }, ++ ++ /* cmpldi r2, 0 */ ++ { -1, 0x28220000, 1 }, ++ ++ { 0, 0, 0 } ++ }; ++ ++/* ELFv2 PLT call stub to access PLT entries more than +/- 32k from r2. */ ++ ++static struct ppc_insn_pattern ppc64_standard_linkage6[] = ++ { ++ /* std r2, 24(r1) */ ++ { -1, insn_ds (62, 2, 1, 24, 0), 1 }, ++ ++ /* addis r11, r2, */ ++ { insn_d (-1, -1, -1, 0), insn_d (15, 11, 2, 0), 0 }, ++ ++ /* ld r12, (r11) */ ++ { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 12, 11, 0, 0), 0 }, ++ ++ /* mtctr r12 */ ++ { insn_xfx (-1, -1, -1, -1), insn_xfx (31, 12, 9, 467), 0 }, ++ ++ /* bctr */ ++ { -1, 0x4e800420, 0 }, ++ ++ { 0, 0, 0 } ++ }; ++ ++/* ELFv2 PLT call stub to access PLT entries within +/- 32k of r2. */ ++ ++static struct ppc_insn_pattern ppc64_standard_linkage7[] = ++ { ++ /* std r2, 24(r1) */ ++ { -1, insn_ds (62, 2, 1, 24, 0), 1 }, ++ ++ /* ld r12, (r2) */ ++ { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 12, 2, 0, 0), 0 }, ++ ++ /* mtctr r12 */ ++ { insn_xfx (-1, -1, -1, -1), insn_xfx (31, 12, 9, 467), 0 }, ++ ++ /* bctr */ ++ { -1, 0x4e800420, 0 }, ++ ++ { 0, 0, 0 } ++ }; ++ + /* When the dynamic linker is doing lazy symbol resolution, the first + call to a function in another object will go like this: + +@@ -243,16 +365,14 @@ ppc64_standard_linkage1_target (struct f + struct gdbarch *gdbarch = get_frame_arch (frame); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + +- /* The address of the function descriptor this linkage function +- references. */ +- CORE_ADDR desc ++ /* The address of the PLT entry this linkage function references. */ ++ CORE_ADDR plt + = ((CORE_ADDR) get_frame_register_unsigned (frame, + tdep->ppc_gp0_regnum + 2) + + (ppc_insn_d_field (insn[0]) << 16) + + ppc_insn_ds_field (insn[2])); + +- /* The first word of the descriptor is the entry point. Return that. */ +- return ppc64_desc_entry_point (gdbarch, desc); ++ return ppc64_plt_entry_point (gdbarch, plt); + } + + static CORE_ADDR +@@ -262,16 +382,14 @@ ppc64_standard_linkage2_target (struct f + struct gdbarch *gdbarch = get_frame_arch (frame); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + +- /* The address of the function descriptor this linkage function +- references. */ +- CORE_ADDR desc ++ /* The address of the PLT entry this linkage function references. */ ++ CORE_ADDR plt + = ((CORE_ADDR) get_frame_register_unsigned (frame, + tdep->ppc_gp0_regnum + 2) + + (ppc_insn_d_field (insn[1]) << 16) + + ppc_insn_ds_field (insn[3])); + +- /* The first word of the descriptor is the entry point. Return that. */ +- return ppc64_desc_entry_point (gdbarch, desc); ++ return ppc64_plt_entry_point (gdbarch, plt); + } + + static CORE_ADDR +@@ -281,15 +399,28 @@ ppc64_standard_linkage3_target (struct f + struct gdbarch *gdbarch = get_frame_arch (frame); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + +- /* The address of the function descriptor this linkage function +- references. */ +- CORE_ADDR desc ++ /* The address of the PLT entry this linkage function references. */ ++ CORE_ADDR plt + = ((CORE_ADDR) get_frame_register_unsigned (frame, + tdep->ppc_gp0_regnum + 2) + + ppc_insn_ds_field (insn[1])); + +- /* The first word of the descriptor is the entry point. Return that. */ +- return ppc64_desc_entry_point (gdbarch, desc); ++ return ppc64_plt_entry_point (gdbarch, plt); ++} ++ ++static CORE_ADDR ++ppc64_standard_linkage4_target (struct frame_info *frame, ++ CORE_ADDR pc, unsigned int *insn) ++{ ++ struct gdbarch *gdbarch = get_frame_arch (frame); ++ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ++ ++ CORE_ADDR plt ++ = ((CORE_ADDR) get_frame_register_unsigned (frame, tdep->ppc_gp0_regnum + 2) ++ + (ppc_insn_d_field (insn[1]) << 16) ++ + ppc_insn_ds_field (insn[2])); ++ ++ return ppc64_plt_entry_point (gdbarch, plt); + } + + +@@ -300,13 +431,27 @@ CORE_ADDR + ppc64_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc) + { + #define MAX(a,b) ((a) > (b) ? (a) : (b)) +- unsigned int insns[MAX (MAX (ARRAY_SIZE (ppc64_standard_linkage1), +- ARRAY_SIZE (ppc64_standard_linkage2)), +- ARRAY_SIZE (ppc64_standard_linkage3)) - 1]; ++ unsigned int insns[MAX (MAX (MAX (ARRAY_SIZE (ppc64_standard_linkage1), ++ ARRAY_SIZE (ppc64_standard_linkage2)), ++ MAX (ARRAY_SIZE (ppc64_standard_linkage3), ++ ARRAY_SIZE (ppc64_standard_linkage4))), ++ MAX (MAX (ARRAY_SIZE (ppc64_standard_linkage5), ++ ARRAY_SIZE (ppc64_standard_linkage6)), ++ ARRAY_SIZE (ppc64_standard_linkage7))) - 1]; + CORE_ADDR target; + +- if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage3, insns) +- && (insns[8] != 0 || insns[9] != 0)) ++ 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)) +Index: gdb-7.6.50.20130731-cvs/gdb/ppc-linux-tdep.c +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/gdb/ppc-linux-tdep.c ++++ gdb-7.6.50.20130731-cvs/gdb/ppc-linux-tdep.c +@@ -44,6 +44,7 @@ + #include "observer.h" + #include "auxv.h" + #include "elf/common.h" ++#include "elf/ppc64.h" + #include "exceptions.h" + #include "arch-utils.h" + #include "spu-tdep.h" +@@ -876,6 +877,43 @@ ppc_linux_core_read_description (struct + } + } + ++/* If the ELF symbol has a local entry point, use it as SYMBOL_VALUE_ADDRESS ++ for the msymbol. This matches the DWARF function start if present. */ ++ ++static void ++ppc_elfv2_elf_make_msymbol_special (asymbol *sym, struct minimal_symbol *msym) ++{ ++ elf_symbol_type *elf_sym = (elf_symbol_type *)sym; ++ switch (PPC64_LOCAL_ENTRY_OFFSET (elf_sym->internal_elf_sym.st_other)) ++ { ++ default: ++ break; ++ case 8: ++ MSYMBOL_TARGET_FLAG_1 (msym) = 1; ++ break; ++ } ++} ++ ++static CORE_ADDR ++ppc_elfv2_skip_entrypoint (struct gdbarch *gdbarch, CORE_ADDR pc) ++{ ++ struct bound_minimal_symbol fun; ++ int local_entry_offset = 0; ++ ++ fun = lookup_minimal_symbol_by_pc (pc); ++ if (fun.minsym == NULL) ++ return pc; ++ ++ if (MSYMBOL_TARGET_FLAG_1 (fun.minsym)) ++ local_entry_offset = 8; ++ ++ if (SYMBOL_VALUE_ADDRESS (fun.minsym) <= pc ++ && pc < SYMBOL_VALUE_ADDRESS (fun.minsym) + local_entry_offset) ++ return SYMBOL_VALUE_ADDRESS (fun.minsym) + local_entry_offset; ++ ++ return pc; ++} ++ + /* Implementation of `gdbarch_stap_is_single_operand', as defined in + gdbarch.h. */ + +@@ -1332,13 +1370,23 @@ ppc_linux_init_abi (struct gdbarch_info + + if (tdep->wordsize == 8) + { +- /* Handle PPC GNU/Linux 64-bit function pointers (which are really +- function descriptors). */ +- set_gdbarch_convert_from_func_ptr_addr +- (gdbarch, ppc64_convert_from_func_ptr_addr); ++ if (tdep->elf_abi == POWERPC_ELF_V1) ++ { ++ /* Handle PPC GNU/Linux 64-bit function pointers (which are really ++ function descriptors). */ ++ set_gdbarch_convert_from_func_ptr_addr ++ (gdbarch, ppc64_convert_from_func_ptr_addr); + +- set_gdbarch_elf_make_msymbol_special (gdbarch, +- ppc64_elf_make_msymbol_special); ++ set_gdbarch_elf_make_msymbol_special ++ (gdbarch, ppc64_elf_make_msymbol_special); ++ } ++ else ++ { ++ set_gdbarch_elf_make_msymbol_special ++ (gdbarch, ppc_elfv2_elf_make_msymbol_special); ++ ++ set_gdbarch_skip_entrypoint (gdbarch, ppc_elfv2_skip_entrypoint); ++ } + + /* Shared library handling. */ + set_gdbarch_skip_trampoline_code (gdbarch, ppc64_skip_trampoline_code); +Index: gdb-7.6.50.20130731-cvs/gdb/ppc-sysv-tdep.c +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/gdb/ppc-sysv-tdep.c ++++ gdb-7.6.50.20130731-cvs/gdb/ppc-sysv-tdep.c +@@ -610,42 +610,48 @@ ppc_sysv_abi_push_dummy_call (struct gdb + } + + /* Handle the return-value conventions for Decimal Floating Point values +- in both ppc32 and ppc64, which are the same. */ +-static int ++ in both ppc32 and ppc64, which are the same. INDEX specifies which ++ part of a multi-part return value is to be handled. */ ++static void + get_decimal_float_return_value (struct gdbarch *gdbarch, struct type *valtype, + struct regcache *regcache, gdb_byte *readbuf, +- const gdb_byte *writebuf) ++ const gdb_byte *writebuf, int index) + { + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ++ int offset = index * TYPE_LENGTH (valtype); + + gdb_assert (TYPE_CODE (valtype) == TYPE_CODE_DECFLOAT); + + /* 32-bit and 64-bit decimal floats in f1. */ + if (TYPE_LENGTH (valtype) <= 8) + { ++ int regnum = tdep->ppc_fp0_regnum + 1 + index; ++ + if (writebuf != NULL) + { + gdb_byte regval[MAX_REGISTER_SIZE]; + const gdb_byte *p; + + /* 32-bit decimal float is right aligned in the doubleword. */ +- if (TYPE_LENGTH (valtype) == 4) ++ if (TYPE_LENGTH (valtype) == 4 ++ && gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) + { +- memcpy (regval + 4, writebuf, 4); ++ memcpy (regval + 4, writebuf + offset, 4); + p = regval; + } + else +- p = writebuf; ++ p = writebuf + offset; + +- regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1, p); ++ regcache_cooked_write (regcache, regnum, p); + } + if (readbuf != NULL) + { +- regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1, readbuf); ++ regcache_cooked_read (regcache, regnum, readbuf); + + /* Left align 32-bit decimal float. */ +- if (TYPE_LENGTH (valtype) == 4) +- memcpy (readbuf, readbuf + 4, 4); ++ if (TYPE_LENGTH (valtype) == 4 ++ && gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) ++ memcpy (readbuf + offset, readbuf + offset + 4, 4); + } + } + /* 128-bit decimal floats in f2,f3. */ +@@ -653,24 +659,27 @@ get_decimal_float_return_value (struct g + { + if (writebuf != NULL || readbuf != NULL) + { +- int i; ++ int i, regnum; + + for (i = 0; i < 2; i++) + { ++ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) ++ regnum = tdep->ppc_fp0_regnum + 2 + i + 2 * index; ++ else ++ regnum = tdep->ppc_fp0_regnum + 3 - i + 2 * index; ++ + if (writebuf != NULL) +- regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 2 + i, +- writebuf + i * 8); ++ regcache_cooked_write (regcache, regnum, ++ writebuf + offset + i * 8); + if (readbuf != NULL) +- regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 2 + i, +- readbuf + i * 8); ++ regcache_cooked_read (regcache, regnum, ++ readbuf + offset + i * 8); + } + } + } + else + /* Can't happen. */ + internal_error (__FILE__, __LINE__, _("Unknown decimal float size.")); +- +- return RETURN_VALUE_REGISTER_CONVENTION; + } + + /* Handle the return-value conventions specified by the SysV 32-bit +@@ -802,8 +811,11 @@ do_ppc_sysv_return_value (struct gdbarch + return RETURN_VALUE_REGISTER_CONVENTION; + } + if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT && !tdep->soft_float) +- return get_decimal_float_return_value (gdbarch, type, regcache, readbuf, +- writebuf); ++ { ++ get_decimal_float_return_value (gdbarch, type, regcache, ++ readbuf, writebuf, 0); ++ return RETURN_VALUE_REGISTER_CONVENTION; ++ } + else if ((TYPE_CODE (type) == TYPE_CODE_INT + || TYPE_CODE (type) == TYPE_CODE_CHAR + || TYPE_CODE (type) == TYPE_CODE_BOOL +@@ -1102,6 +1114,156 @@ convert_code_addr_to_desc_addr (CORE_ADD + return 1; + } + ++/* Walk down the type tree of TYPE counting consecutive base elements. ++ If *FIELD_TYPE is NULL, then set it to the first valid floating point ++ or vector type. If a non-floating point or vector type is found, or ++ if a floating point or vector type that doesn't match a non-NULL ++ *FIELD_TYPE is found, then return -1, otherwise return the count in the ++ sub-tree. */ ++ ++static LONGEST ++ppc64_aggregate_candidate (struct type *type, ++ struct type **field_type) ++{ ++ type = check_typedef (type); ++ ++ switch (TYPE_CODE (type)) ++ { ++ case TYPE_CODE_FLT: ++ case TYPE_CODE_DECFLOAT: ++ if (!*field_type) ++ *field_type = type; ++ if (TYPE_CODE (*field_type) == TYPE_CODE (type) ++ && TYPE_LENGTH (*field_type) == TYPE_LENGTH (type)) ++ return 1; ++ break; ++ ++ case TYPE_CODE_COMPLEX: ++ type = TYPE_TARGET_TYPE (type); ++ if (TYPE_CODE (type) == TYPE_CODE_FLT ++ || TYPE_CODE (type) == TYPE_CODE_DECFLOAT) ++ { ++ if (!*field_type) ++ *field_type = type; ++ if (TYPE_CODE (*field_type) == TYPE_CODE (type) ++ && TYPE_LENGTH (*field_type) == TYPE_LENGTH (type)) ++ return 2; ++ } ++ break; ++ ++ case TYPE_CODE_ARRAY: ++ if (TYPE_VECTOR (type)) ++ { ++ if (!*field_type) ++ *field_type = type; ++ if (TYPE_CODE (*field_type) == TYPE_CODE (type) ++ && TYPE_LENGTH (*field_type) == TYPE_LENGTH (type)) ++ return 1; ++ } ++ else ++ { ++ LONGEST count, low_bound, high_bound; ++ ++ count = ppc64_aggregate_candidate ++ (TYPE_TARGET_TYPE (type), field_type); ++ if (count == -1) ++ return -1; ++ ++ if (!get_array_bounds (type, &low_bound, &high_bound)) ++ return -1; ++ count *= high_bound - low_bound; ++ ++ /* There must be no padding. */ ++ if (count == 0) ++ return TYPE_LENGTH (type) == 0 ? 0 : -1; ++ else if (TYPE_LENGTH (type) != count * TYPE_LENGTH (*field_type)) ++ return -1; ++ ++ return count; ++ } ++ break; ++ ++ case TYPE_CODE_STRUCT: ++ case TYPE_CODE_UNION: ++ { ++ LONGEST count = 0; ++ int i; ++ ++ for (i = 0; i < TYPE_NFIELDS (type); i++) ++ { ++ LONGEST sub_count; ++ ++ if (field_is_static (&TYPE_FIELD (type, i))) ++ continue; ++ ++ sub_count = ppc64_aggregate_candidate ++ (TYPE_FIELD_TYPE (type, i), field_type); ++ if (sub_count == -1) ++ return -1; ++ ++ if (TYPE_CODE (type) == TYPE_CODE_STRUCT) ++ count += sub_count; ++ else ++ count = max (count, sub_count); ++ } ++ ++ /* There must be no padding. */ ++ if (count == 0) ++ return TYPE_LENGTH (type) == 0 ? 0 : -1; ++ else if (TYPE_LENGTH (type) != count * TYPE_LENGTH (*field_type)) ++ return -1; ++ ++ return count; ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ return -1; ++} ++ ++/* If an argument of type TYPE is a homogeneous float or vector aggregate ++ that shall be passed in FP/vector registers according to the ELFv2 ABI, ++ return the homogeneous element type in *ELT_TYPE and the number of ++ elements in *N_ELTS, and return non-zero. Otherwise, return zero. */ ++ ++static int ++ppc64_elfv2_abi_homogeneous_aggregate (struct type *type, ++ struct type **elt_type, int *n_elts) ++{ ++ /* Complex types at the top level are treated separately. However, ++ complex types can be elements of homogeneous aggregates. */ ++ if (TYPE_CODE (type) == TYPE_CODE_STRUCT ++ || TYPE_CODE (type) == TYPE_CODE_UNION ++ || (TYPE_CODE (type) == TYPE_CODE_ARRAY && !TYPE_VECTOR (type))) ++ { ++ struct type *field_type = NULL; ++ LONGEST field_count = ppc64_aggregate_candidate (type, &field_type); ++ ++ if (field_count > 0) ++ { ++ int n_regs = ((TYPE_CODE (field_type) == TYPE_CODE_FLT ++ || TYPE_CODE (field_type) == TYPE_CODE_DECFLOAT)? ++ (TYPE_LENGTH (field_type) + 7) >> 3 : 1); ++ ++ /* The ELFv2 ABI allows homogeneous aggregates to occupy ++ up to 8 registers. */ ++ if (field_count * n_regs <= 8) ++ { ++ if (elt_type) ++ *elt_type = field_type; ++ if (n_elts) ++ *n_elts = (int) field_count; ++ return 1; ++ } ++ } ++ } ++ ++ return 0; ++} ++ + /* Push a float in either registers, or in the stack. Using the ppc 64 bit + SysV ABI. + +@@ -1143,6 +1305,8 @@ ppc64_sysv_abi_push_float (struct gdbarc + + /* Write value in the stack's parameter save area. */ + write_memory (gparam, p, 8); ++ if (greg <= 10) ++ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + greg, p); + + /* Floats and Doubles go in f1 .. f13. They also consume a left aligned + GREG, and can end up in memory. */ +@@ -1154,8 +1318,6 @@ ppc64_sysv_abi_push_float (struct gdbarc + convert_typed_floating (val, type, regval, regtype); + regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + freg, regval); + } +- if (greg <= 10) +- regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + greg, regval); + } + else + { +@@ -1268,9 +1430,13 @@ ppc64_sysv_abi_push_dummy_call (struct g + to their corresponding regions. */ + refparam = align_down (sp - refparam_size, 16); + gparam = align_down (refparam - gparam_size, 16); +- /* Add in space for the TOC, link editor double word, +- compiler double word, LR save area, CR save area. */ +- sp = align_down (gparam - 48, 16); ++ /* Add in space for the TOC, link editor double word (v1 only), ++ compiler double word (v1 only), LR save area, CR save area, ++ and backchain. */ ++ if (tdep->elf_abi == POWERPC_ELF_V1) ++ sp = align_down (gparam - 48, 16); ++ else ++ sp = align_down (gparam - 32, 16); + } + + /* If the function is returning a `struct', then there is an +@@ -1375,7 +1541,8 @@ ppc64_sysv_abi_push_dummy_call (struct g + + /* 32-bit decimal floats are right aligned in the + doubleword. */ +- if (TYPE_LENGTH (type) == 4) ++ if (TYPE_LENGTH (type) == 4 ++ && byte_order == BFD_ENDIAN_BIG) + { + memcpy (regval + 4, val, 4); + p = regval; +@@ -1407,10 +1574,21 @@ ppc64_sysv_abi_push_dummy_call (struct g + { + /* Make sure freg is even. */ + freg += freg & 1; +- regcache_cooked_write (regcache, +- tdep->ppc_fp0_regnum + freg, val); +- regcache_cooked_write (regcache, +- tdep->ppc_fp0_regnum + freg + 1, val + 8); ++ ++ if (byte_order == BFD_ENDIAN_BIG) ++ { ++ regcache_cooked_write (regcache, ++ tdep->ppc_fp0_regnum + freg, val); ++ regcache_cooked_write (regcache, ++ tdep->ppc_fp0_regnum + freg + 1, val + 8); ++ } ++ else ++ { ++ regcache_cooked_write (regcache, ++ tdep->ppc_fp0_regnum + freg + 1, val); ++ regcache_cooked_write (regcache, ++ tdep->ppc_fp0_regnum + freg, val + 8); ++ } + } + + write_memory (gparam, val, TYPE_LENGTH (type)); +@@ -1587,8 +1765,9 @@ ppc64_sysv_abi_push_dummy_call (struct g + ULONGEST word = unpack_long (type, val); + /* Convert any function code addresses into + descriptors. */ +- if (TYPE_CODE (type) == TYPE_CODE_PTR +- || TYPE_CODE (type) == TYPE_CODE_REF) ++ if (tdep->elf_abi == POWERPC_ELF_V1 ++ && (TYPE_CODE (type) == TYPE_CODE_PTR ++ || TYPE_CODE (type) == TYPE_CODE_REF)) + { + struct type *target_type; + target_type = check_typedef (TYPE_TARGET_TYPE (type)); +@@ -1613,6 +1792,9 @@ ppc64_sysv_abi_push_dummy_call (struct g + } + else + { ++ struct type *elt_type; ++ int n_elts; ++ + ssize_t byte; + for (byte = 0; byte < TYPE_LENGTH (type); + byte += tdep->wordsize) +@@ -1630,7 +1812,7 @@ ppc64_sysv_abi_push_dummy_call (struct g + versions before 3.4 implemented this + incorrectly; see + . */ +- if (byte == 0) ++ if (byte_order == BFD_ENDIAN_BIG && byte == 0) + memcpy (regval + tdep->wordsize - len, + val + byte, len); + else +@@ -1649,7 +1831,7 @@ ppc64_sysv_abi_push_dummy_call (struct g + value to memory. Fortunately, doing this + simplifies the code. */ + ssize_t len = TYPE_LENGTH (type); +- if (len < tdep->wordsize) ++ if (byte_order == BFD_ENDIAN_BIG && len < tdep->wordsize) + write_memory (gparam + tdep->wordsize - len, val, len); + else + write_memory (gparam, val, len); +@@ -1705,6 +1887,132 @@ ppc64_sysv_abi_push_dummy_call (struct g + } + } + } ++ /* In the ELFv2 ABI, homogeneous floating-point or vector ++ aggregates are passed in registers. */ ++ if (tdep->elf_abi == POWERPC_ELF_V2 ++ && ppc64_elfv2_abi_homogeneous_aggregate (type, ++ &elt_type, &n_elts)) ++ { ++ int i; ++ for (i = 0; i < n_elts; i++) ++ { ++ const gdb_byte *elt_val ++ = val + i * TYPE_LENGTH (elt_type); ++ ++ switch (TYPE_CODE (elt_type)) ++ { ++ case TYPE_CODE_FLT: ++ if (TYPE_LENGTH (elt_type) <= 8) ++ { ++ if (write_pass && freg <= 13) ++ { ++ int fregnum = tdep->ppc_fp0_regnum + freg; ++ gdb_byte regval[MAX_REGISTER_SIZE]; ++ struct type *regtype ++ = register_type (gdbarch, fregnum); ++ convert_typed_floating (elt_val, elt_type, ++ regval, regtype); ++ regcache_cooked_write (regcache, ++ fregnum, regval); ++ } ++ freg++; ++ } ++ else if (TYPE_LENGTH (elt_type) == 16 ++ && (gdbarch_long_double_format (gdbarch) ++ == floatformats_ibm_long_double)) ++ { ++ if (write_pass && freg <= 13) ++ { ++ int fregnum = tdep->ppc_fp0_regnum + freg; ++ regcache_cooked_write (regcache, ++ fregnum, elt_val); ++ if (freg <= 12) ++ regcache_cooked_write (regcache, ++ fregnum + 1, ++ elt_val + 8); ++ } ++ freg += 2; ++ } ++ break; ++ ++ case TYPE_CODE_DECFLOAT: ++ if (TYPE_LENGTH (elt_type) <= 8) ++ { ++ if (write_pass && freg <= 13) ++ { ++ int fregnum = tdep->ppc_fp0_regnum + freg; ++ gdb_byte regval[MAX_REGISTER_SIZE]; ++ const gdb_byte *p; ++ ++ /* 32-bit decimal floats are right aligned ++ in the doubleword. */ ++ if (TYPE_LENGTH (elt_type) == 4 ++ && byte_order == BFD_ENDIAN_BIG) ++ { ++ memcpy (regval + 4, elt_val, 4); ++ p = regval; ++ } ++ else ++ p = elt_val; ++ ++ regcache_cooked_write (regcache, fregnum, p); ++ } ++ freg++; ++ } ++ else if (TYPE_LENGTH (elt_type) == 16) ++ { ++ /* Make sure freg is even. */ ++ freg += freg & 1; ++ ++ if (write_pass && freg <= 12) ++ { ++ int fregnum = tdep->ppc_fp0_regnum + freg; ++ if (byte_order == BFD_ENDIAN_BIG) ++ { ++ regcache_cooked_write (regcache, ++ fregnum, ++ elt_val); ++ regcache_cooked_write (regcache, ++ fregnum + 1, ++ elt_val + 8); ++ } ++ else ++ { ++ regcache_cooked_write (regcache, ++ fregnum + 1, ++ elt_val); ++ regcache_cooked_write (regcache, ++ fregnum, ++ elt_val + 8); ++ } ++ } ++ freg += 2; ++ } ++ break; ++ ++ case TYPE_CODE_ARRAY: ++ gdb_assert (TYPE_VECTOR (type)); ++ ++ if (tdep->vector_abi == POWERPC_VEC_ALTIVEC ++ && TYPE_LENGTH (elt_type) == 16) ++ { ++ if (write_pass && vreg <= 13) ++ { ++ int vregnum = tdep->ppc_vr0_regnum + vreg; ++ regcache_cooked_write (regcache, ++ vregnum, elt_val); ++ } ++ vreg++; ++ } ++ break; ++ ++ default: ++ internal_error (__FILE__, __LINE__, ++ _("Unknown element type.")); ++ break; ++ } ++ } ++ } + /* Always consume parameter stack space. */ + gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize); + } +@@ -1733,24 +2041,31 @@ ppc64_sysv_abi_push_dummy_call (struct g + breakpoint. */ + regcache_cooked_write_signed (regcache, tdep->ppc_lr_regnum, bp_addr); + +- /* Use the func_addr to find the descriptor, and use that to find +- the TOC. If we're calling via a function pointer, the pointer +- itself identifies the descriptor. */ +- { +- struct type *ftype = check_typedef (value_type (function)); +- CORE_ADDR desc_addr = value_as_address (function); +- +- if (TYPE_CODE (ftype) == TYPE_CODE_PTR +- || convert_code_addr_to_desc_addr (func_addr, &desc_addr)) +- { +- /* The TOC is the second double word in the descriptor. */ +- CORE_ADDR toc = +- read_memory_unsigned_integer (desc_addr + tdep->wordsize, +- tdep->wordsize, byte_order); +- regcache_cooked_write_unsigned (regcache, +- tdep->ppc_gp0_regnum + 2, toc); +- } +- } ++ /* In the ELFv1 ABI, use the func_addr to find the descriptor, and use ++ that to find the TOC. If we're calling via a function pointer, ++ the pointer itself identifies the descriptor. */ ++ if (tdep->elf_abi == POWERPC_ELF_V1) ++ { ++ struct type *ftype = check_typedef (value_type (function)); ++ CORE_ADDR desc_addr = value_as_address (function); ++ ++ if (TYPE_CODE (ftype) == TYPE_CODE_PTR ++ || convert_code_addr_to_desc_addr (func_addr, &desc_addr)) ++ { ++ /* The TOC is the second double word in the descriptor. */ ++ CORE_ADDR toc = ++ read_memory_unsigned_integer (desc_addr + tdep->wordsize, ++ tdep->wordsize, byte_order); ++ regcache_cooked_write_unsigned (regcache, ++ tdep->ppc_gp0_regnum + 2, toc); ++ } ++ } ++ ++ /* In the ELFv2 ABI, we need to pass the target address in r12 since ++ we may be calling a global entry point. */ ++ if (tdep->elf_abi == POWERPC_ELF_V2) ++ regcache_cooked_write_unsigned (regcache, ++ tdep->ppc_gp0_regnum + 12, func_addr); + + return sp; + } +@@ -1775,6 +2090,8 @@ ppc64_sysv_abi_return_value (struct gdba + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + struct type *func_type = function ? value_type (function) : NULL; + int opencl_abi = func_type? ppc_sysv_use_opencl_abi (func_type) : 0; ++ struct type *elt_type; ++ int n_elts; + + /* This function exists to support a calling convention that + requires floating-point registers. It shouldn't be used on +@@ -1799,8 +2116,11 @@ ppc64_sysv_abi_return_value (struct gdba + return RETURN_VALUE_REGISTER_CONVENTION; + } + if (TYPE_CODE (valtype) == TYPE_CODE_DECFLOAT) +- return get_decimal_float_return_value (gdbarch, valtype, regcache, readbuf, +- writebuf); ++ { ++ get_decimal_float_return_value (gdbarch, valtype, regcache, ++ readbuf, writebuf, 0); ++ return RETURN_VALUE_REGISTER_CONVENTION; ++ } + /* Integers in r3. */ + if ((TYPE_CODE (valtype) == TYPE_CODE_INT + || TYPE_CODE (valtype) == TYPE_CODE_ENUM +@@ -2019,6 +2339,114 @@ ppc64_sysv_abi_return_value (struct gdba + } + } + return RETURN_VALUE_REGISTER_CONVENTION; ++ } ++ /* In the ELFv2 ABI, homogeneous floating-point or vector ++ aggregates are returned in registers. */ ++ if (tdep->elf_abi == POWERPC_ELF_V2 ++ && ppc64_elfv2_abi_homogeneous_aggregate (valtype, &elt_type, &n_elts)) ++ { ++ int i; ++ for (i = 0; i < n_elts; i++) ++ { ++ int offset = i * TYPE_LENGTH (elt_type); ++ ++ switch (TYPE_CODE (elt_type)) ++ { ++ case TYPE_CODE_FLT: ++ if (TYPE_LENGTH (elt_type) <= 8) ++ { ++ int regnum = tdep->ppc_fp0_regnum + 1 + i; ++ gdb_byte regval[MAX_REGISTER_SIZE]; ++ struct type *regtype = register_type (gdbarch, regnum); ++ if (writebuf != NULL) ++ { ++ convert_typed_floating (writebuf + offset, elt_type, ++ regval, regtype); ++ regcache_cooked_write (regcache, regnum, regval); ++ } ++ if (readbuf != NULL) ++ { ++ regcache_cooked_read (regcache, regnum, regval); ++ convert_typed_floating (regval, regtype, ++ readbuf + offset, elt_type); ++ } ++ } ++ else ++ { ++ int j, nregs = (TYPE_LENGTH (elt_type) + 7) / 8; ++ for (j = 0; j < nregs; j++) ++ { ++ int regnum = tdep->ppc_fp0_regnum + 1 + nregs * i + j; ++ ++ if (writebuf != NULL) ++ regcache_cooked_write (regcache, regnum, ++ writebuf + offset + j * 8); ++ if (readbuf != NULL) ++ regcache_cooked_read (regcache, regnum, ++ readbuf + offset + j * 8); ++ } ++ } ++ break; ++ ++ case TYPE_CODE_DECFLOAT: ++ get_decimal_float_return_value (gdbarch, elt_type, regcache, ++ readbuf, writebuf, i); ++ break; ++ ++ case TYPE_CODE_ARRAY: ++ { ++ int regnum = tdep->ppc_vr0_regnum + 2 + i; ++ gdb_assert (TYPE_VECTOR (elt_type)); ++ ++ if (writebuf != NULL) ++ regcache_cooked_write (regcache, regnum, writebuf + offset); ++ if (readbuf != NULL) ++ regcache_cooked_read (regcache, regnum, readbuf + offset); ++ } ++ break; ++ } ++ } ++ return RETURN_VALUE_REGISTER_CONVENTION; ++ } ++ /* In the ELFv2 ABI, aggregate types of up to 16 bytes are ++ returned in registers r3:r4. */ ++ if (tdep->elf_abi == POWERPC_ELF_V2 ++ && TYPE_LENGTH (valtype) <= 16 ++ && (TYPE_CODE (valtype) == TYPE_CODE_STRUCT ++ || TYPE_CODE (valtype) == TYPE_CODE_UNION ++ || (TYPE_CODE (valtype) == TYPE_CODE_ARRAY && !TYPE_VECTOR (valtype)))) ++ { ++ int n_regs = (TYPE_LENGTH (valtype) + tdep->wordsize - 1) / tdep->wordsize; ++ int i; ++ ++ for (i = 0; i < n_regs; i++) ++ { ++ gdb_byte regval[MAX_REGISTER_SIZE]; ++ int regnum = tdep->ppc_gp0_regnum + 3 + i; ++ int offset = i * tdep->wordsize; ++ int len = TYPE_LENGTH (valtype) - offset; ++ if (len > tdep->wordsize) ++ len = tdep->wordsize; ++ ++ if (writebuf != NULL) ++ { ++ memset (regval, 0, sizeof regval); ++ if (byte_order == BFD_ENDIAN_BIG && offset == 0) ++ memcpy (regval + tdep->wordsize - len, writebuf, len); ++ else ++ memcpy (regval, writebuf + offset, len); ++ regcache_cooked_write (regcache, regnum, regval); ++ } ++ if (readbuf != NULL) ++ { ++ regcache_cooked_read (regcache, regnum, regval); ++ if (byte_order == BFD_ENDIAN_BIG && offset == 0) ++ memcpy (readbuf, regval + tdep->wordsize - len, len); ++ else ++ memcpy (readbuf + offset, regval, len); ++ } ++ } ++ return RETURN_VALUE_REGISTER_CONVENTION; + } + return RETURN_VALUE_STRUCT_CONVENTION; + } +Index: gdb-7.6.50.20130731-cvs/gdb/ppc-tdep.h +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/gdb/ppc-tdep.h ++++ gdb-7.6.50.20130731-cvs/gdb/ppc-tdep.h +@@ -182,6 +182,15 @@ extern void ppc_collect_vsxregset (const + + /* Private data that this module attaches to struct gdbarch. */ + ++/* ELF ABI version used by the inferior. */ ++enum powerpc_elf_abi ++{ ++ POWERPC_ELF_AUTO, ++ POWERPC_ELF_V1, ++ POWERPC_ELF_V2, ++ POWERPC_ELF_LAST ++}; ++ + /* Vector ABI used by the inferior. */ + enum powerpc_vector_abi + { +@@ -197,6 +206,8 @@ struct gdbarch_tdep + int wordsize; /* Size in bytes of fixed-point word. */ + int soft_float; /* Avoid FP registers for arguments? */ + ++ enum powerpc_elf_abi elf_abi; /* ELF ABI version. */ ++ + /* How to pass vector arguments. Never set to AUTO or LAST. */ + enum powerpc_vector_abi vector_abi; + +Index: gdb-7.6.50.20130731-cvs/gdb/rs6000-tdep.c +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/gdb/rs6000-tdep.c ++++ gdb-7.6.50.20130731-cvs/gdb/rs6000-tdep.c +@@ -48,6 +48,7 @@ + + #include "elf-bfd.h" + #include "elf/ppc.h" ++#include "elf/ppc64.h" + + #include "solib-svr4.h" + #include "ppc-tdep.h" +@@ -1667,7 +1668,19 @@ skip_prologue (struct gdbarch *gdbarch, + continue; + + } +- else if ((op & 0xffff0000) == 0x60000000) ++ else if ((op & 0xffff0000) == 0x3c4c0000 ++ || (op & 0xffff0000) == 0x3c400000 ++ || (op & 0xffff0000) == 0x38420000) ++ { ++ /* . 0: addis 2,12,.TOC.-0b@ha ++ . addi 2,2,.TOC.-0b@l ++ or ++ . lis 2,.TOC.@ha ++ . addi 2,2,.TOC.@l ++ used by ELFv2 global entry points to set up r2. */ ++ continue; ++ } ++ else if (op == 0x60000000) + { + /* nop */ + /* Allow nops in the prologue, but do not consider them to +@@ -1678,8 +1691,7 @@ skip_prologue (struct gdbarch *gdbarch, + + } + else if ((op & 0xffff0000) == 0x3c000000) +- { /* addis 0,0,NUM, used +- for >= 32k frames */ ++ { /* addis 0,0,NUM, used for >= 32k frames */ + fdata->offset = (op & 0x0000ffff) << 16; + fdata->frameless = 0; + r0_contains_arg = 0; +@@ -1687,8 +1699,7 @@ skip_prologue (struct gdbarch *gdbarch, + + } + else if ((op & 0xffff0000) == 0x60000000) +- { /* ori 0,0,NUM, 2nd ha +- lf of >= 32k frames */ ++ { /* ori 0,0,NUM, 2nd half of >= 32k frames */ + fdata->offset |= (op & 0x0000ffff); + fdata->frameless = 0; + r0_contains_arg = 0; +@@ -2713,10 +2724,10 @@ dfp_pseudo_register_read (struct gdbarch + else + { + status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum + +- 2 * reg_index + 1, buffer + 8); ++ 2 * reg_index + 1, buffer); + if (status == REG_VALID) + status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum + +- 2 * reg_index, buffer); ++ 2 * reg_index, buffer + 8); + } + + return status; +@@ -2742,9 +2753,9 @@ dfp_pseudo_register_write (struct gdbarc + else + { + regcache_raw_write (regcache, tdep->ppc_fp0_regnum + +- 2 * reg_index + 1, buffer + 8); ++ 2 * reg_index + 1, buffer); + regcache_raw_write (regcache, tdep->ppc_fp0_regnum + +- 2 * reg_index, buffer); ++ 2 * reg_index, buffer + 8); + } + } + +@@ -2822,7 +2833,8 @@ efpr_pseudo_register_read (struct gdbarc + int reg_index = reg_nr - tdep->ppc_efpr0_regnum; + + /* Read the portion that overlaps the VMX register. */ +- return regcache_raw_read_part (regcache, tdep->ppc_vr0_regnum + reg_index, 0, ++ int offset = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 0 : 8; ++ return regcache_raw_read_part (regcache, tdep->ppc_vr0_regnum + reg_index, offset, + register_size (gdbarch, reg_nr), buffer); + } + +@@ -2835,7 +2847,8 @@ efpr_pseudo_register_write (struct gdbar + int reg_index = reg_nr - tdep->ppc_efpr0_regnum; + + /* Write the portion that overlaps the VMX register. */ +- regcache_raw_write_part (regcache, tdep->ppc_vr0_regnum + reg_index, 0, ++ int offset = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 0 : 8; ++ regcache_raw_write_part (regcache, tdep->ppc_vr0_regnum + reg_index, offset, + register_size (gdbarch, reg_nr), buffer); + } + +@@ -3591,6 +3604,7 @@ rs6000_gdbarch_init (struct gdbarch_info + enum auto_boolean soft_float_flag = powerpc_soft_float_global; + int soft_float; + enum powerpc_vector_abi vector_abi = powerpc_vector_abi_global; ++ enum powerpc_elf_abi elf_abi = POWERPC_ELF_AUTO; + int have_fpu = 1, have_spe = 0, have_mq = 0, have_altivec = 0, have_dfp = 0, + have_vsx = 0; + int tdesc_wordsize = -1; +@@ -3897,6 +3911,21 @@ rs6000_gdbarch_init (struct gdbarch_info + } + + #ifdef HAVE_ELF ++ if (from_elf_exec) ++ { ++ switch (elf_elfheader (info.abfd)->e_flags & EF_PPC64_ABI) ++ { ++ case 1: ++ elf_abi = POWERPC_ELF_V1; ++ break; ++ case 2: ++ elf_abi = POWERPC_ELF_V2; ++ break; ++ default: ++ break; ++ } ++ } ++ + if (soft_float_flag == AUTO_BOOLEAN_AUTO && from_elf_exec) + { + switch (bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU, +@@ -3933,6 +3962,15 @@ rs6000_gdbarch_init (struct gdbarch_info + } + #endif + ++ /* Default to ELFv2 ABI on 64-bit little-endian, and ELFv1 otherwise. */ ++ if (elf_abi == POWERPC_ELF_AUTO) ++ { ++ if (wordsize == 8 && info.byte_order == BFD_ENDIAN_LITTLE) ++ elf_abi = POWERPC_ELF_V2; ++ else ++ elf_abi = POWERPC_ELF_V1; ++ } ++ + if (soft_float_flag == AUTO_BOOLEAN_TRUE) + soft_float = 1; + else if (soft_float_flag == AUTO_BOOLEAN_FALSE) +@@ -3975,6 +4013,8 @@ rs6000_gdbarch_init (struct gdbarch_info + meaningful, because 64-bit CPUs can run in 32-bit mode. So, perform + separate word size check. */ + tdep = gdbarch_tdep (arches->gdbarch); ++ if (tdep && tdep->elf_abi != elf_abi) ++ continue; + if (tdep && tdep->soft_float != soft_float) + continue; + if (tdep && tdep->vector_abi != vector_abi) +@@ -3997,6 +4037,7 @@ rs6000_gdbarch_init (struct gdbarch_info + + tdep = XCALLOC (1, struct gdbarch_tdep); + tdep->wordsize = wordsize; ++ tdep->elf_abi = elf_abi; + tdep->soft_float = soft_float; + tdep->vector_abi = vector_abi; + +Index: gdb-7.6.50.20130731-cvs/gdb/symtab.c +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/gdb/symtab.c ++++ gdb-7.6.50.20130731-cvs/gdb/symtab.c +@@ -2882,6 +2882,8 @@ skip_prologue_sal (struct symtab_and_lin + + /* Skip "first line" of function (which is actually its prologue). */ + pc += gdbarch_deprecated_function_start_offset (gdbarch); ++ if (gdbarch_skip_entrypoint_p (gdbarch)) ++ pc = gdbarch_skip_entrypoint (gdbarch, pc); + if (skip) + pc = gdbarch_skip_prologue (gdbarch, pc); + +Index: gdb-7.6.50.20130731-cvs/gdb/testsuite/gdb.arch/altivec-regs.exp +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/gdb/testsuite/gdb.arch/altivec-regs.exp ++++ gdb-7.6.50.20130731-cvs/gdb/testsuite/gdb.arch/altivec-regs.exp +@@ -118,7 +118,7 @@ gdb_test "info reg vscr" "vscr.*0x1\t1" + if {$endianness == "big"} { + set decimal_vector ".uint128 = 0x00000001000000010000000100000001, v4_float = .1.*e-45, 1.*e-45, 1.*e-45, 1.*e-45., v4_int32 = .1, 1, 1, 1., v8_int16 = .0, 1, 0, 1, 0, 1, 0, 1., v16_int8 = .0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1.." + } else { +- set decimal_vector ".uint128 = 0x00000001000000010000000100000001, v4_float = .1.*e-45, 1.*e-45, 1.*e-45, 1.*e-45., v4_int32 = .1, 1, 1, 1., v8_int16 = .1, 0, 1, 0, 1, 0, 1, 0., v16_int8 = .1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.." ++ set decimal_vector ".uint128 = 0x00000001000000010000000100000001, v4_float = .1.*e-45, 1.*e-45, 1.*e-45, 1.*e-45., v4_int32 = .1, 1, 1, 1., v8_int16 = .1, 0, 1, 0, 1, 0, 1, 0., v16_int8 = .1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.." + } + + for {set i 0} {$i < 32} {incr i 1} { +Index: gdb-7.6.50.20130731-cvs/gdb/testsuite/gdb.arch/powerpc-d128-regs.exp +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/gdb/testsuite/gdb.arch/powerpc-d128-regs.exp ++++ gdb-7.6.50.20130731-cvs/gdb/testsuite/gdb.arch/powerpc-d128-regs.exp +@@ -20,7 +20,7 @@ + + # Testcase for ppc decimal128 pseudo-registers. + +-if ![istarget "powerpc64-*"] then { ++if ![istarget "powerpc64*-*"] then { + verbose "Skipping powerpc Decimal128 pseudo-registers testcase." + return + } +Index: gdb-7.6.50.20130731-cvs/gdb/testsuite/gdb.arch/vsx-regs.exp +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/gdb/testsuite/gdb.arch/vsx-regs.exp ++++ gdb-7.6.50.20130731-cvs/gdb/testsuite/gdb.arch/vsx-regs.exp +@@ -58,19 +58,46 @@ if ![runto_main] then { + gdb_suppress_tests + } + ++send_gdb "show endian\n" ++set endianness "" ++gdb_expect { ++ -re "(The target endianness is set automatically .currently )(big|little)( endian.*)$gdb_prompt $" { ++ pass "endianness" ++ set endianness $expect_out(2,string) ++ } ++ -re ".*$gdb_prompt $" { ++ fail "couldn't get endianness" ++ } ++ timeout { fail "(timeout) endianness" } ++} ++ + # Data sets used throughout the test + +-set vector_register1 ".uint128 = 0x3ff4cccccccccccc0000000000000000, v2_double = .0x1, 0x0., v4_float = .0x1, 0xf99999a0, 0x0, 0x0., v4_int32 = .0x3ff4cccc, 0xcccccccc, 0x0, 0x0., v8_int16 = .0x3ff4, 0xcccc, 0xcccc, 0xcccc, 0x0, 0x0, 0x0, 0x0., v16_int8 = .0x3f, 0xf4, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0.." ++if {$endianness == "big"} { ++ set vector_register1 ".uint128 = 0x3ff4cccccccccccc0000000000000000, v2_double = .0x1, 0x0., v4_float = .0x1, 0xf99999a0, 0x0, 0x0., v4_int32 = .0x3ff4cccc, 0xcccccccc, 0x0, 0x0., v8_int16 = .0x3ff4, 0xcccc, 0xcccc, 0xcccc, 0x0, 0x0, 0x0, 0x0., v16_int8 = .0x3f, 0xf4, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0.." ++ ++ set vector_register1_vr ".uint128 = 0x3ff4cccccccccccc0000000100000001, v4_float = .0x1, 0xf99999a0, 0x0, 0x0., v4_int32 = .0x3ff4cccc, 0xcccccccc, 0x1, 0x1., v8_int16 = .0x3ff4, 0xcccc, 0xcccc, 0xcccc, 0x0, 0x1, 0x0, 0x1., v16_int8 = .0x3f, 0xf4, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1.." ++ ++ set vector_register2 "uint128 = 0xdeadbeefdeadbeefdeadbeefdeadbeef, v2_double = .0x1, 0x1., v4_float = .0x0, 0x0, 0x0, 0x0., v4_int32 = .0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef., v8_int16 = .0xdead, 0xbeef, 0xdead, 0xbeef, 0xdead, 0xbeef, 0xdead, 0xbeef., v16_int8 = .0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef.." + +-set vector_register1_vr ".uint128 = 0x3ff4cccccccccccc0000000100000001, v4_float = .0x1, 0xf99999a0, 0x0, 0x0., v4_int32 = .0x3ff4cccc, 0xcccccccc, 0x1, 0x1., v8_int16 = .0x3ff4, 0xcccc, 0xcccc, 0xcccc, 0x0, 0x1, 0x0, 0x1., v16_int8 = .0x3f, 0xf4, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1.." ++ set vector_register2_vr "uint128 = 0xdeadbeefdeadbeefdeadbeefdeadbeef, v4_float = .0x0, 0x0, 0x0, 0x0., v4_int32 = .0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef., v8_int16 = .0xdead, 0xbeef, 0xdead, 0xbeef, 0xdead, 0xbeef, 0xdead, 0xbeef., v16_int8 = .0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef.." + +-set vector_register2 "uint128 = 0xdeadbeefdeadbeefdeadbeefdeadbeef, v2_double = .0x1, 0x1., v4_float = .0x0, 0x0, 0x0, 0x0., v4_int32 = .0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef., v8_int16 = .0xdead, 0xbeef, 0xdead, 0xbeef, 0xdead, 0xbeef, 0xdead, 0xbeef., v16_int8 = .0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef.." ++ set vector_register3 ".uint128 = 0x00000001000000010000000100000001, v2_double = .0x0, 0x0., v4_float = .0x0, 0x0, 0x0, 0x0., v4_int32 = .0x1, 0x1, 0x1, 0x1., v8_int16 = .0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1., v16_int8 = .0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1.." + +-set vector_register2_vr "uint128 = 0xdeadbeefdeadbeefdeadbeefdeadbeef, v4_float = .0x0, 0x0, 0x0, 0x0., v4_int32 = .0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef., v8_int16 = .0xdead, 0xbeef, 0xdead, 0xbeef, 0xdead, 0xbeef, 0xdead, 0xbeef., v16_int8 = .0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef.." ++ set vector_register3_vr ".uint128 = 0x00000001000000010000000100000001, v4_float = .0x0, 0x0, 0x0, 0x0., v4_int32 = .0x1, 0x1, 0x1, 0x1., v8_int16 = .0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1., v16_int8 = .0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1.." ++} else { ++ set vector_register1 ".uint128 = 0x3ff4cccccccccccc0000000000000000, v2_double = .0x0, 0x1., v4_float = .0x0, 0x0, 0xf99999a0, 0x1., v4_int32 = .0x0, 0x0, 0xcccccccc, 0x3ff4cccc., v8_int16 = .0x0, 0x0, 0x0, 0x0, 0xcccc, 0xcccc, 0xcccc, 0x3ff4., v16_int8 = .0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xf4, 0x3f.." + +-set vector_register3 ".uint128 = 0x00000001000000010000000100000001, v2_double = .0x0, 0x0., v4_float = .0x0, 0x0, 0x0, 0x0., v4_int32 = .0x1, 0x1, 0x1, 0x1., v8_int16 = .0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1., v16_int8 = .0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1.." ++ set vector_register1_vr ".uint128 = 0x3ff4cccccccccccc0000000100000001, v4_float = .0x0, 0x0, 0xf99999a0, 0x1., v4_int32 = .0x1, 0x1, 0xcccccccc, 0x3ff4cccc., v8_int16 = .0x1, 0x0, 0x1, 0x0, 0xcccc, 0xcccc, 0xcccc, 0x3ff4., v16_int8 = .0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xf4, 0x3f.." + +-set vector_register3_vr ".uint128 = 0x00000001000000010000000100000001, v4_float = .0x0, 0x0, 0x0, 0x0., v4_int32 = .0x1, 0x1, 0x1, 0x1., v8_int16 = .0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1., v16_int8 = .0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1.." ++ set vector_register2 "uint128 = 0xdeadbeefdeadbeefdeadbeefdeadbeef, v2_double = .0x1, 0x1., v4_float = .0x0, 0x0, 0x0, 0x0., v4_int32 = .0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef., v8_int16 = .0xbeef, 0xdead, 0xbeef, 0xdead, 0xbeef, 0xdead, 0xbeef, 0xdead., v16_int8 = .0xef, 0xbe, 0xad, 0xde, 0xef, 0xbe, 0xad, 0xde, 0xef, 0xbe, 0xad, 0xde, 0xef, 0xbe, 0xad, 0xde.." ++ ++ set vector_register2_vr "uint128 = 0xdeadbeefdeadbeefdeadbeefdeadbeef, v4_float = .0x0, 0x0, 0x0, 0x0., v4_int32 = .0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef., v8_int16 = .0xbeef, 0xdead, 0xbeef, 0xdead, 0xbeef, 0xdead, 0xbeef, 0xdead., v16_int8 = .0xef, 0xbe, 0xad, 0xde, 0xef, 0xbe, 0xad, 0xde, 0xef, 0xbe, 0xad, 0xde, 0xef, 0xbe, 0xad, 0xde.." ++ ++ set vector_register3 ".uint128 = 0x00000001000000010000000100000001, v2_double = .0x0, 0x0., v4_float = .0x0, 0x0, 0x0, 0x0., v4_int32 = .0x1, 0x1, 0x1, 0x1., v8_int16 = .0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0., v16_int8 = .0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0.." ++ ++ set vector_register3_vr ".uint128 = 0x00000001000000010000000100000001, v4_float = .0x0, 0x0, 0x0, 0x0., v4_int32 = .0x1, 0x1, 0x1, 0x1., v8_int16 = .0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0., v16_int8 = .0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0.." ++} + + set float_register ".raw 0xdeadbeefdeadbeef." + +Index: gdb-7.6.50.20130731-cvs/gdb/testsuite/gdb.base/sigbpt.exp +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/gdb/testsuite/gdb.base/sigbpt.exp ++++ gdb-7.6.50.20130731-cvs/gdb/testsuite/gdb.base/sigbpt.exp +@@ -76,7 +76,7 @@ gdb_test "break keeper" + set bowler_addrs bowler + set segv_addr none + gdb_test {display/i $pc} +-gdb_test "advance *bowler" "bowler.*" "advance to the bowler" ++gdb_test "advance bowler" "bowler.*" "advance to the bowler" + set test "stepping to fault" + set signame "SIGSEGV" + gdb_test_multiple "stepi" "$test" { +Index: gdb-7.6.50.20130731-cvs/gdb/testsuite/gdb.base/step-bt.exp +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/gdb/testsuite/gdb.base/step-bt.exp ++++ gdb-7.6.50.20130731-cvs/gdb/testsuite/gdb.base/step-bt.exp +@@ -24,7 +24,7 @@ if {[prepare_for_testing $testfile.exp $ + return -1 + } + +-gdb_test "break *hello" \ ++gdb_test "break hello" \ + "Breakpoint.*at.* file .*$srcfile, line .*" \ + "breakpoint at first instruction of hello()" + +Index: gdb-7.6.50.20130731-cvs/include/elf/common.h +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/include/elf/common.h ++++ gdb-7.6.50.20130731-cvs/include/elf/common.h +@@ -959,6 +959,7 @@ + #define AT_BASE_PLATFORM 24 /* String identifying real platform, + may differ from AT_PLATFORM. */ + #define AT_RANDOM 25 /* Address of 16 random bytes. */ ++#define AT_HWCAP2 26 /* Extension of AT_HWCAP. */ + #define AT_EXECFN 31 /* Filename of executable. */ + /* Pointer to the global system page used for system calls and other + nice things. */ +Index: gdb-7.6.50.20130731-cvs/include/floatformat.h +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/include/floatformat.h ++++ gdb-7.6.50.20130731-cvs/include/floatformat.h +@@ -128,7 +128,8 @@ extern const struct floatformat floatfor + extern const struct floatformat floatformat_ia64_quad_big; + extern const struct floatformat floatformat_ia64_quad_little; + /* IBM long double (double+double). */ +-extern const struct floatformat floatformat_ibm_long_double; ++extern const struct floatformat floatformat_ibm_long_double_big; ++extern const struct floatformat floatformat_ibm_long_double_little; + + /* Convert from FMT to a double. + FROM is the address of the extended float. +Index: gdb-7.6.50.20130731-cvs/libiberty/floatformat.c +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/libiberty/floatformat.c ++++ gdb-7.6.50.20130731-cvs/libiberty/floatformat.c +@@ -371,14 +371,23 @@ floatformat_ibm_long_double_is_valid (co + } + } + +-const struct floatformat floatformat_ibm_long_double = ++const struct floatformat floatformat_ibm_long_double_big = + { + floatformat_big, 128, 0, 1, 11, 1023, 2047, 12, 52, + floatformat_intbit_no, +- "floatformat_ibm_long_double", ++ "floatformat_ibm_long_double_big", + floatformat_ibm_long_double_is_valid, + &floatformat_ieee_double_big + }; ++ ++const struct floatformat floatformat_ibm_long_double_little = ++{ ++ floatformat_little, 128, 0, 1, 11, 1023, 2047, 12, 52, ++ floatformat_intbit_no, ++ "floatformat_ibm_long_double_little", ++ floatformat_ibm_long_double_is_valid, ++ &floatformat_ieee_double_little ++}; + + + #ifndef min +Index: gdb-7.6.50.20130731-cvs/include/elf/ppc64.h +=================================================================== +--- gdb-7.6.50.20130731-cvs.orig/include/elf/ppc64.h ++++ gdb-7.6.50.20130731-cvs/include/elf/ppc64.h +@@ -164,6 +164,60 @@ END_RELOC_NUMBERS (R_PPC64_max) + #define IS_PPC64_TLS_RELOC(R) \ + ((R) >= R_PPC64_TLS && (R) <= R_PPC64_DTPREL16_HIGHESTA) + ++ ++/* e_flags bits specifying ABI. ++ 1 for original function descriptor using ABI, ++ 2 for revised ABI without function descriptors, ++ 0 for unspecified or not using any features affected by the differences. */ ++#define EF_PPC64_ABI 3 ++ ++/* The ELFv2 ABI uses three bits in the symbol st_other field of a ++ function definition to specify the number of instructions between a ++ function's global entry point and local entry point. ++ The global entry point is used when it is necessary to set up the ++ toc pointer (r2) for the function. Callers must enter the global ++ entry point with r12 set to the global entry point address. On ++ return from the function, r2 may have a different value to that ++ which it had on entry. ++ The local entry point is used when r2 is known to already be valid ++ for the function. There is no requirement on r12 when using the ++ local entry point, and on return r2 will contain the same value as ++ at entry. ++ A value of zero in these bits means that the function has a single ++ entry point with no requirement on r12 or r2, and that on return r2 ++ will contain the same value as at entry. ++ Values of one and seven are reserved. */ ++#define STO_PPC64_LOCAL_BIT 5 ++#define STO_PPC64_LOCAL_MASK (7 << STO_PPC64_LOCAL_BIT) ++ ++// 3 bit other field to bytes. ++static inline unsigned int ++ppc64_decode_local_entry(unsigned int other) ++{ ++ return ((1 << other) >> 2) << 2; ++} ++ ++// bytes to field value. ++static inline unsigned int ++ppc64_encode_local_entry(unsigned int val) ++{ ++ return (val >= 4 * 4 ++ ? (val >= 8 * 4 ++ ? (val >= 16 * 4 ? 6 : 5) ++ : 4) ++ : (val >= 2 * 4 ++ ? 3 ++ : (val >= 1 * 4 ? 2 : 0))); ++} ++ ++/* st_other to number of bytes. */ ++#define PPC64_LOCAL_ENTRY_OFFSET(other) \ ++ ppc64_decode_local_entry (((other) & STO_PPC64_LOCAL_MASK) \ ++ >> STO_PPC64_LOCAL_BIT) ++/* number of bytes to st_other. */ ++#define PPC64_SET_LOCAL_ENTRY_OFFSET(val) \ ++ ppc64_encode_local_entry (val) << STO_PPC64_LOCAL_BIT ++ + /* Specify the start of the .glink section. */ + #define DT_PPC64_GLINK DT_LOPROC + diff --git a/gdb.changes b/gdb.changes index 5b4820e..a32bb59 100644 --- a/gdb.changes +++ b/gdb.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Mon Dec 9 14:16:53 UTC 2013 - uweigand@de.ibm.com + +- gdb-ppc64le.patch: add support for powerpc64le-linux + ------------------------------------------------------------------- Fri Nov 15 12:08:19 UTC 2013 - rguenther@suse.com diff --git a/gdb.spec b/gdb.spec index 17a0d7a..27968f6 100644 --- a/gdb.spec +++ b/gdb.spec @@ -191,6 +191,7 @@ Patch104: gdb-rhel5-compat.patch Patch1002: gdb-6.6-buildid-locate-rpm-suse.patch Patch1004: gdb-ia64-tdep.patch Patch1005: gdb-aarch64-hw-break.patch +Patch1006: gdb-ppc64le.patch BuildRequires: ncurses-devel texinfo gettext flex bison glibc-devel zlib-devel %if %{suse_version} < 1020 @@ -423,6 +424,7 @@ find -name "*.info*"|xargs rm -f %patch1002 -p1 %patch1004 -p1 %patch1005 -p0 +%patch1006 -p1 find -name "*.orig" | xargs rm -f ! find -name "*.rej" # Should not happen. @@ -461,12 +463,12 @@ fi if test -f /usr/%{_lib}/librpm.so.3; then export LIBRPM=librpm.so.3 fi -%ifarch %ix86 ia64 ppc ppc64 s390 s390x x86_64 +%ifarch %ix86 ia64 ppc ppc64 ppc64le s390 s390x x86_64 %define build_multitarget 1 %else %define build_multitarget 0 %endif -%define target_list i686 ia64 powerpc powerpc64 s390 s390x x86_64 arm aarch64 m68k +%define target_list i686 ia64 powerpc powerpc64 powerpc64le s390 s390x x86_64 arm aarch64 m68k %define DIST %(echo '%distribution' | sed 's, /.*,,') %if %build_multitarget EXTRA_TARGETS="%(printf ,%%s-suse-linux %target_list)" @@ -486,7 +488,7 @@ EXTRA_TARGETS= --with-system-gdbinit=%{_sysconfdir}/gdbinit \ --with-gdb-datadir=%{_datadir}/gdb \ --enable-gdb-build-warnings=,-Wno-unused \ -%ifnarch %{ix86} alpha ia64 ppc s390 s390x x86_64 ppc64 sparc sparcv9 sparc64 +%ifnarch %{ix86} alpha ia64 ppc s390 s390x x86_64 ppc64 ppc64le sparc sparcv9 sparc64 --disable-werror \ %else %if %{suse_version} < 1110 @@ -784,6 +786,9 @@ cp -p %{SOURCE3} $RPM_BUILD_ROOT%{_mandir}/man1/gstack.1 %ifnarch ppc ppc64 rm -f ppc{,64}-linux.xml %endif +%ifnarch ppc64le + rm -f ppc64le-linux.xml +%endif ) # It would break RHEL-5 by leaving excessive files for the doc subpackage.