- gdb-ppc64le.patch: add support for powerpc64le-linux OBS-URL: https://build.opensuse.org/request/show/210007 OBS-URL: https://build.opensuse.org/package/show/devel:gcc/gdb?expand=0&rev=88
1773 lines
66 KiB
Diff
1773 lines
66 KiB
Diff
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) <optional> */
|
||
+ { -1, insn_ds (62, 2, 1, 40, 0), 1 },
|
||
+
|
||
+ /* addis r11, r2, <any> */
|
||
+ { insn_d (-1, -1, -1, 0), insn_d (15, 11, 2, 0), 0 },
|
||
+
|
||
+ /* ld r12, <any>(r11) */
|
||
+ { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 12, 11, 0, 0), 0 },
|
||
+
|
||
+ /* addi r11, r11, <any> <optional> */
|
||
+ { 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 <optional> */
|
||
+ { -1, 0x7d826278, 1 },
|
||
+
|
||
+ /* add r11, r11, r2 <optional> */
|
||
+ { -1, 0x7d6b1214, 1 },
|
||
+
|
||
+ /* ld r2, <any>(r11) */
|
||
+ { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 2, 11, 0, 0), 0 },
|
||
+
|
||
+ /* ld r11, <any>(r11) <optional> */
|
||
+ { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 11, 11, 0, 0), 1 },
|
||
+
|
||
+ /* bctr <optional> */
|
||
+ { -1, 0x4e800420, 1 },
|
||
+
|
||
+ /* cmpldi r2, 0 <optional> */
|
||
+ { -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) <optional> */
|
||
+ { -1, insn_ds (62, 2, 1, 40, 0), 1 },
|
||
+
|
||
+ /* ld r12, <any>(r2) */
|
||
+ { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 12, 2, 0, 0), 0 },
|
||
+
|
||
+ /* addi r2, r2, <any> <optional> */
|
||
+ { 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 <optional> */
|
||
+ { -1, 0x7d8b6278, 1 },
|
||
+
|
||
+ /* add r2, r2, r11 <optional> */
|
||
+ { -1, 0x7c425a14, 1 },
|
||
+
|
||
+ /* ld r11, <any>(r2) <optional> */
|
||
+ { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 11, 2, 0, 0), 1 },
|
||
+
|
||
+ /* ld r2, <any>(r2) */
|
||
+ { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 2, 2, 0, 0), 0 },
|
||
+
|
||
+ /* bctr <optional> */
|
||
+ { -1, 0x4e800420, 1 },
|
||
+
|
||
+ /* cmpldi r2, 0 <optional> */
|
||
+ { -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) <optional> */
|
||
+ { -1, insn_ds (62, 2, 1, 24, 0), 1 },
|
||
+
|
||
+ /* addis r11, r2, <any> */
|
||
+ { insn_d (-1, -1, -1, 0), insn_d (15, 11, 2, 0), 0 },
|
||
+
|
||
+ /* ld r12, <any>(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) <optional> */
|
||
+ { -1, insn_ds (62, 2, 1, 24, 0), 1 },
|
||
+
|
||
+ /* ld r12, <any>(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
|
||
<http://gcc.gnu.org/gcc-3.4/powerpc-abi.html>. */
|
||
- 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
|
||
|