aboutsummaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
authorNathan Whitehorn <nwhitehorn@FreeBSD.org>2010-07-10 02:29:22 +0000
committerNathan Whitehorn <nwhitehorn@FreeBSD.org>2010-07-10 02:29:22 +0000
commit2cf64c8006d7b7c6b122b7a492086a8cefe0f4d4 (patch)
tree9f6c3a9c7f6dc298b58f5ddb2655b080c986678d /contrib
parentb543e91ba5678e60f8a6b612d473365c8fa83648 (diff)
downloadsrc-2cf64c8006d7b7c6b122b7a492086a8cefe0f4d4.tar.gz
src-2cf64c8006d7b7c6b122b7a492086a8cefe0f4d4.zip
Teach our toolchain how to generate 64-bit PowerPC binaries. This fixes
a variety of bugs in binutils related to handling of 64-bit PPC ELF, provides a GCC configuration for 64-bit PowerPC on FreeBSD, and associated build systems tweaks. Obtained from: projects/ppc64
Notes
Notes: svn path=/head/; revision=209867
Diffstat (limited to 'contrib')
-rw-r--r--contrib/binutils/bfd/elf64-ppc.c14
-rw-r--r--contrib/binutils/ld/lexsup.c3
-rw-r--r--contrib/gcc/config/rs6000/freebsd.h182
-rw-r--r--contrib/gdb/gdb/ppcfbsd-tdep.c19
-rw-r--r--contrib/gdb/gdb/solib-svr4.c1
5 files changed, 202 insertions, 17 deletions
diff --git a/contrib/binutils/bfd/elf64-ppc.c b/contrib/binutils/bfd/elf64-ppc.c
index a0d81d0550ee..bc9e0a765dc3 100644
--- a/contrib/binutils/bfd/elf64-ppc.c
+++ b/contrib/binutils/bfd/elf64-ppc.c
@@ -3268,13 +3268,13 @@ create_got_section (bfd *abfd, struct bfd_link_info *info)
flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
| SEC_LINKER_CREATED);
- got = bfd_make_section (abfd, ".got");
+ got = bfd_make_section_anyway (abfd, ".got");
if (!got
|| !bfd_set_section_flags (abfd, got, flags)
|| !bfd_set_section_alignment (abfd, got, 3))
return FALSE;
- relgot = bfd_make_section (abfd, ".rela.got");
+ relgot = bfd_make_section_anyway (abfd, ".rela.got");
if (!relgot
|| ! bfd_set_section_flags (abfd, relgot, flags | SEC_READONLY)
|| ! bfd_set_section_alignment (abfd, relgot, 3))
@@ -6033,6 +6033,10 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
{
+ /* Skip this BFD if it is not ELF */
+ if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
+ continue;
+
s = ppc64_elf_tdata (ibfd)->got;
if (s != NULL && s != htab->got)
{
@@ -7206,7 +7210,7 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms,
stub_sec->_cooked_size = 0;
}
- if (htab->plt != NULL)
+ if (htab->glink != NULL && htab->glink->contents != NULL)
{
unsigned int indx;
bfd_vma plt0;
@@ -9000,6 +9004,10 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
while ((dynobj = dynobj->link_next) != NULL)
{
asection *s;
+
+ if (bfd_get_flavour (dynobj) != bfd_target_elf_flavour)
+ continue;
+
s = ppc64_elf_tdata (dynobj)->got;
if (s != NULL
&& s->_raw_size != 0
diff --git a/contrib/binutils/ld/lexsup.c b/contrib/binutils/ld/lexsup.c
index b377bd4c7c27..ea3a558362b4 100644
--- a/contrib/binutils/ld/lexsup.c
+++ b/contrib/binutils/ld/lexsup.c
@@ -1145,8 +1145,11 @@ parse_args (unsigned argc, char **argv)
whole_archive = TRUE;
break;
case OPTION_AS_NEEDED:
+/* XXX: --as-needed is broken on powerpc64 */
+#ifndef __powerpc64__
as_needed = TRUE;
break;
+#endif
case OPTION_NO_AS_NEEDED:
as_needed = FALSE;
break;
diff --git a/contrib/gcc/config/rs6000/freebsd.h b/contrib/gcc/config/rs6000/freebsd.h
index 1fb4b25b5ed7..2ce115df4ebe 100644
--- a/contrib/gcc/config/rs6000/freebsd.h
+++ b/contrib/gcc/config/rs6000/freebsd.h
@@ -21,13 +21,86 @@
/* Override the defaults, which exist to force the proper definition. */
-#undef CPP_OS_DEFAULT_SPEC
-#define CPP_OS_DEFAULT_SPEC "%(cpp_os_freebsd)"
+#ifdef IN_LIBGCC2
+#undef TARGET_64BIT
+#ifdef __powerpc64__
+#define TARGET_64BIT 1
+#else
+#define TARGET_64BIT 0
+#endif
+#endif
+
+/* On 64-bit systems, use the AIX ABI like Linux and NetBSD */
+
+#undef DEFAULT_ABI
+#define DEFAULT_ABI (TARGET_64BIT ? ABI_AIX : ABI_V4)
+#undef TARGET_AIX
+#define TARGET_AIX TARGET_64BIT
+
+#undef FBSD_TARGET_CPU_CPP_BUILTINS
+#define FBSD_TARGET_CPU_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__PPC__"); \
+ builtin_define ("__ppc__"); \
+ builtin_define ("__PowerPC__"); \
+ builtin_define ("__powerpc__"); \
+ if (TARGET_64BIT) \
+ { \
+ builtin_define ("__LP64__"); \
+ builtin_define ("__ppc64__"); \
+ builtin_define ("__powerpc64__"); \
+ builtin_define ("__arch64__"); \
+ builtin_assert ("cpu=powerpc64"); \
+ builtin_assert ("machine=powerpc64"); \
+ } else { \
+ builtin_assert ("cpu=powerpc"); \
+ builtin_assert ("machine=powerpc"); \
+ } \
+ } \
+ while (0)
+
+#define INVALID_64BIT "-m%s not supported in this configuration"
+#define INVALID_32BIT INVALID_64BIT
+
+#undef SUBSUBTARGET_OVERRIDE_OPTIONS
+#define SUBSUBTARGET_OVERRIDE_OPTIONS \
+ do \
+ { \
+ if (!rs6000_explicit_options.alignment) \
+ rs6000_alignment_flags = MASK_ALIGN_NATURAL; \
+ if (TARGET_64BIT) \
+ { \
+ if (DEFAULT_ABI != ABI_AIX) \
+ { \
+ rs6000_current_abi = ABI_AIX; \
+ error (INVALID_64BIT, "call"); \
+ } \
+ dot_symbols = !strcmp (rs6000_abi_name, "aixdesc"); \
+ if (target_flags & MASK_RELOCATABLE) \
+ { \
+ target_flags &= ~MASK_RELOCATABLE; \
+ error (INVALID_64BIT, "relocatable"); \
+ } \
+ if (target_flags & MASK_EABI) \
+ { \
+ target_flags &= ~MASK_EABI; \
+ error (INVALID_64BIT, "eabi"); \
+ } \
+ if (target_flags & MASK_PROTOTYPE) \
+ { \
+ target_flags &= ~MASK_PROTOTYPE; \
+ error (INVALID_64BIT, "prototype"); \
+ } \
+ if ((target_flags & MASK_POWERPC64) == 0) \
+ { \
+ target_flags |= MASK_POWERPC64; \
+ error ("64 bit CPU required"); \
+ } \
+ } \
+ } \
+ while (0)
-#undef CPP_OS_FREEBSD_SPEC
-#define CPP_OS_FREEBSD_SPEC "\
- -D__PPC__ -D__ppc__ -D__PowerPC__ -D__powerpc__ \
- -Acpu=powerpc -Amachine=powerpc "
#undef STARTFILE_DEFAULT_SPEC
#define STARTFILE_DEFAULT_SPEC "%(startfile_freebsd)"
@@ -57,7 +130,10 @@
c-common.c, and config/<arch>/<arch>.h. */
#undef SIZE_TYPE
-#define SIZE_TYPE "unsigned int"
+#define SIZE_TYPE (TARGET_64BIT ? "long unsigned int" : "unsigned int")
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE (TARGET_64BIT ? "long int" : "int")
/* rs6000.h gets this wrong for FreeBSD. We use the GCC defaults instead. */
#undef WCHAR_TYPE
@@ -75,3 +151,95 @@
/* Override rs6000.h definition. */
#undef ASM_APP_OFF
#define ASM_APP_OFF "#NO_APP\n"
+
+/* Tell the assembler we want 32/64-bit binaries if -m32 or -m64 is passed */
+#if (TARGET_DEFAULT & MASK_64BIT)
+#define SVR4_ASM_SPEC "%(asm_cpu) \
+%{.s: %{mregnames} %{mno-regnames}} %{.S: %{mregnames} %{mno-regnames}} \
+%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \
+%{mrelocatable} %{mrelocatable-lib} %{fpic|fpie|fPIC|fPIE:-K PIC} \
+%{memb|msdata|msdata=eabi: -memb} \
+%{mlittle|mlittle-endian:-mlittle; \
+ mbig|mbig-endian :-mbig; \
+ mcall-aixdesc | \
+ mcall-freebsd | \
+ mcall-netbsd | \
+ mcall-openbsd | \
+ mcall-linux | \
+ mcall-gnu :-mbig; \
+ mcall-i960-old :-mlittle}"
+#define LINK_OS_FREEBSD_SPEC_DEF "\
+ %{p:%nconsider using `-pg' instead of `-p' with gprof(1)} \
+ %{v:-V} \
+ %{assert*} %{R*} %{rpath*} %{defsym*} \
+ %{shared:-Bshareable %{h*} %{soname*}} \
+ %{!shared: \
+ %{!static: \
+ %{rdynamic: -export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker %(fbsd_dynamic_linker) }} \
+ %{static:-Bstatic}} \
+ %{symbolic:-Bsymbolic}"
+
+
+#undef ASM_DEFAULT_SPEC
+#undef ASM_SPEC
+#undef LINK_OS_FREEBSD_SPEC
+#define ASM_DEFAULT_SPEC "-mppc%{!m32:64}"
+#define ASM_SPEC "%{m32:-a32}%{!m32:-a64} " SVR4_ASM_SPEC
+#define LINK_OS_FREEBSD_SPEC "%{m32:-melf32ppc}%{!m32:-melf64ppc} " LINK_OS_FREEBSD_SPEC_DEF
+#endif
+
+/* _init and _fini functions are built from bits spread across many
+ object files, each potentially with a different TOC pointer. For
+ that reason, place a nop after the call so that the linker can
+ restore the TOC pointer if a TOC adjusting call stub is needed. */
+#ifdef __powerpc64__
+#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
+ asm (SECTION_OP "\n" \
+" bl ." #FUNC "\n" \
+" nop\n" \
+" .previous");
+#endif
+
+/* __throw will restore its own return address to be the same as the
+ return address of the function that the throw is being made to.
+ This is unfortunate, because we want to check the original
+ return address to see if we need to restore the TOC.
+ So we have to squirrel it away with this. */
+#define SETUP_FRAME_ADDRESSES() \
+ do { if (TARGET_64BIT) rs6000_aix_emit_builtin_unwind_init (); } while (0)
+
+/* Select a format to encode pointers in exception handling data. CODE
+ is 0 for data, 1 for code labels, 2 for function pointers. GLOBAL is
+ true if the symbol may be affected by dynamic relocations. */
+#undef ASM_PREFERRED_EH_DATA_FORMAT
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) \
+ ((TARGET_64BIT || flag_pic || TARGET_RELOCATABLE) \
+ ? (((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel \
+ | (TARGET_64BIT ? DW_EH_PE_udata8 : DW_EH_PE_sdata4)) \
+ : DW_EH_PE_absptr)
+
+#define MD_FROB_UPDATE_CONTEXT(CTX, FS) \
+ if (TARGET_64BIT) { \
+ if ((FS)->regs.reg[2].how == REG_UNSAVED) \
+ { \
+ unsigned int *insn \
+ = (unsigned int *) \
+ _Unwind_GetGR ((CTX), LINK_REGISTER_REGNUM); \
+ if (*insn == 0xE8410028) \
+ _Unwind_SetGRPtr ((CTX), 2, (CTX)->cfa + 40); \
+ } \
+ }
+
+/* FreeBSD doesn't support saving and restoring 64-bit regs with a 32-bit
+ kernel. This is supported when running on a 64-bit kernel with
+ COMPAT_FREEBSD32, but tell GCC it isn't so that our 32-bit binaries
+ are compatible. */
+#define OS_MISSING_POWERPC64 !TARGET_64BIT
+
+/* Function profiling bits */
+#undef RS6000_MCOUNT
+#define RS6000_MCOUNT ((TARGET_64BIT) ? "._mcount" : "_mcount")
+#define PROFILE_HOOK(LABEL) \
+ do { if (TARGET_64BIT) output_profile_hook (LABEL); } while (0)
+
diff --git a/contrib/gdb/gdb/ppcfbsd-tdep.c b/contrib/gdb/gdb/ppcfbsd-tdep.c
index 296be18e5912..3828e7f72b45 100644
--- a/contrib/gdb/gdb/ppcfbsd-tdep.c
+++ b/contrib/gdb/gdb/ppcfbsd-tdep.c
@@ -35,13 +35,13 @@
#include "gdb_assert.h"
#include "solib-svr4.h"
-#define REG_FIXREG_OFFSET(x) ((x) * 4)
-#define REG_LR_OFFSET (32 * 4)
-#define REG_CR_OFFSET (33 * 4)
-#define REG_XER_OFFSET (34 * 4)
-#define REG_CTR_OFFSET (35 * 4)
-#define REG_PC_OFFSET (36 * 4)
-#define SIZEOF_STRUCT_REG (37 * 4)
+#define REG_FIXREG_OFFSET(x) ((x) * sizeof(register_t))
+#define REG_LR_OFFSET (32 * sizeof(register_t))
+#define REG_CR_OFFSET (33 * sizeof(register_t))
+#define REG_XER_OFFSET (34 * sizeof(register_t))
+#define REG_CTR_OFFSET (35 * sizeof(register_t))
+#define REG_PC_OFFSET (36 * sizeof(register_t))
+#define SIZEOF_STRUCT_REG (37 * sizeof(register_t))
#define FPREG_FPR_OFFSET(x) ((x) * 8)
#define FPREG_FPSCR_OFFSET (32 * 8)
@@ -274,8 +274,13 @@ ppcfbsd_init_abi (struct gdbarch_info info,
/* For NetBSD, this is an on again, off again thing. Some systems
do use the broken struct convention, and some don't. */
set_gdbarch_return_value (gdbarch, ppcfbsd_return_value);
+#ifdef __powerpc64__
+ set_solib_svr4_fetch_link_map_offsets (gdbarch,
+ svr4_lp64_fetch_link_map_offsets);
+#else
set_solib_svr4_fetch_link_map_offsets (gdbarch,
svr4_ilp32_fetch_link_map_offsets);
+#endif
}
void
diff --git a/contrib/gdb/gdb/solib-svr4.c b/contrib/gdb/gdb/solib-svr4.c
index 4f4664cc017b..afea156403e2 100644
--- a/contrib/gdb/gdb/solib-svr4.c
+++ b/contrib/gdb/gdb/solib-svr4.c
@@ -94,6 +94,7 @@ static char *solib_break_names[] =
into the data section (thus skipping the descriptor's symbol),
and eventually try this one, giving us the real entry point
address. */
+ ".r_debug_state",
"._dl_debug_state",
NULL