This is the mail archive of the
libc-ports@sources.redhat.com
mailing list for the libc-ports project.
[PATCH] tile: support very large shared objects
- From: Chris Metcalf <cmetcalf at tilera dot com>
- To: <libc-alpha at sourceware dot org>, <libc-ports at sourceware dot org>
- Date: Fri, 2 Nov 2012 22:21:45 -0400
- Subject: [PATCH] tile: support very large shared objects
Changelog:
2012-11-02 Chris Metcalf <cmetcalf@tilera.com>
* config.make.in (config-cflags-mcmodel-large): Define.
* configure.in: Add libc_cv_cc_mcmodel_large.
* configure: Regenerate.
* elf/elf.h (R_TILEGX_IMM16_X[01]_HW[012]_(|LAST_)PLT_PCREL): Add.
ports/Changelog.tile:
2012-11-02 Chris Metcalf <cmetcalf@tilera.com>
* sysdeps/tile/Makefile [$(config-cflags-mcmodel-large) = yes]:
Build elf-init.c with -mcmodel=large.
* sysdeps/tile/crti.S: Support large memory model.
* sysdeps/tile/start.S: Likewise.
* sysdeps/tile/tilegx/tilegx64/configure.in: Test -mcmodel=large.
* sysdeps/tile/tilegx/tilegx64/configure: Regenerate.
With gcc 4.8 tilegx has support for -mcmodel=large, to tolerate very
large shared objects. This option changes the compiler output to
not include direct jump instructions, which have a range of only
2^30, i.e +/- 512MB. Instead the compiler marshalls the target PCs
into registers and then uses jump- or call-to-register instructions.
For glibc, the upshot is that we need to add some additional
relocations (pc-relative PLT) and we need to arrange for a few
functions to tolerate the possibility of a large range between the
PC and the target. In particular, the crti.S and start.S code needs
to be able to reach from .init to the PLT, and the elf-init code
similarly needs to be built with -mcmodel=large. Note that libc.so
et al don't need any changes; the only changes are for code that
is statically linked into user code built with -mcmodel=large.
For the assembly code, I just rewrote it so that it unconditionally
uses the large model. To be able to pass -mcmodel=large to
csu/elf-init.c, I need to check to see if the compiler supports
that flag, since gcc 4.7 doesn't; I added the support pretty
mechanically in the same way as libc_cv_cc_nofma, etc., are supported.
---
config.make.in | 1 +
configure | 2 ++
configure.in | 1 +
elf/elf.h | 17 +++++++++++++---
ports/sysdeps/tile/Makefile | 8 ++++++++
ports/sysdeps/tile/crti.S | 24 ++++++++++++++++++-----
ports/sysdeps/tile/start.S | 23 +++++++++++++++-------
ports/sysdeps/tile/tilegx/tilegx64/configure | 21 ++++++++++++++++++++
ports/sysdeps/tile/tilegx/tilegx64/configure.in | 7 +++++++
11 files changed, 103 insertions(+), 15 deletions(-)
create mode 100644 ports/sysdeps/tile/tilegx/tilegx64/configure
create mode 100644 ports/sysdeps/tile/tilegx/tilegx64/configure.in
diff --git a/config.make.in b/config.make.in
index c22acf4..3b28f33 100644
--- a/config.make.in
+++ b/config.make.in
@@ -41,6 +41,7 @@ config-cflags-avx = @libc_cv_cc_avx@
config-cflags-sse2avx = @libc_cv_cc_sse2avx@
config-cflags-novzeroupper = @libc_cv_cc_novzeroupper@
config-cflags-nofma = @libc_cv_cc_nofma@
+config-cflags-mcmodel-large = @libc_cv_cc_mcmodel_large@
config-asflags-i686 = @libc_cv_as_i686@
defines = @DEFINES@
diff --git a/configure b/configure
index 35b06c1..457173a 100755
--- a/configure
+++ b/configure
@@ -583,6 +583,7 @@ ldd_rewrite_script
use_ldconfig
libc_cv_sparc_as_vis3
libc_cv_as_i686
+libc_cv_cc_mcmodel_large
libc_cv_cc_nofma
libc_cv_cc_fma4
libc_cv_cc_novzeroupper
@@ -7510,6 +7511,7 @@ fi
+
if test x$use_ldconfig = xyes; then
$as_echo "#define USE_LDCONFIG 1" >>confdefs.h
diff --git a/configure.in b/configure.in
index 928b7b6..ca56686 100644
--- a/configure.in
+++ b/configure.in
@@ -2169,6 +2169,7 @@ AC_SUBST(libc_cv_cc_sse2avx)
AC_SUBST(libc_cv_cc_novzeroupper)
AC_SUBST(libc_cv_cc_fma4)
AC_SUBST(libc_cv_cc_nofma)
+AC_SUBST(libc_cv_cc_mcmodel_large)
AC_SUBST(libc_cv_as_i686)
AC_SUBST(libc_cv_sparc_as_vis3)
diff --git a/elf/elf.h b/elf/elf.h
index 41fc3bd..2524924 100644
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -2986,12 +2986,18 @@ typedef Elf32_Addr Elf32_Conflict;
#define R_TILEGX_IMM16_X1_HW2_LAST_PCREL 63 /* X1 pipe PC-rel last hword 2 */
#define R_TILEGX_IMM16_X0_HW0_GOT 64 /* X0 pipe hword 0 GOT offset */
#define R_TILEGX_IMM16_X1_HW0_GOT 65 /* X1 pipe hword 0 GOT offset */
-/* Relocs 66-71 are currently not defined. */
+#define R_TILEGX_IMM16_X0_HW0_PLT_PCREL 66 /* X0 pipe PC-rel PLT hword 0 */
+#define R_TILEGX_IMM16_X1_HW0_PLT_PCREL 67 /* X1 pipe PC-rel PLT hword 0 */
+#define R_TILEGX_IMM16_X0_HW1_PLT_PCREL 68 /* X0 pipe PC-rel PLT hword 1 */
+#define R_TILEGX_IMM16_X1_HW1_PLT_PCREL 69 /* X1 pipe PC-rel PLT hword 1 */
+#define R_TILEGX_IMM16_X0_HW2_PLT_PCREL 70 /* X0 pipe PC-rel PLT hword 2 */
+#define R_TILEGX_IMM16_X1_HW2_PLT_PCREL 71 /* X1 pipe PC-rel PLT hword 2 */
#define R_TILEGX_IMM16_X0_HW0_LAST_GOT 72 /* X0 pipe last hword 0 GOT offset */
#define R_TILEGX_IMM16_X1_HW0_LAST_GOT 73 /* X1 pipe last hword 0 GOT offset */
#define R_TILEGX_IMM16_X0_HW1_LAST_GOT 74 /* X0 pipe last hword 1 GOT offset */
#define R_TILEGX_IMM16_X1_HW1_LAST_GOT 75 /* X1 pipe last hword 1 GOT offset */
-/* Relocs 76-77 are currently not defined. */
+#define R_TILEGX_IMM16_X0_HW3_PLT_PCREL 76 /* X0 pipe PC-rel PLT hword 3 */
+#define R_TILEGX_IMM16_X1_HW3_PLT_PCREL 77 /* X1 pipe PC-rel PLT hword 3 */
#define R_TILEGX_IMM16_X0_HW0_TLS_GD 78 /* X0 pipe hword 0 TLS GD offset */
#define R_TILEGX_IMM16_X1_HW0_TLS_GD 79 /* X1 pipe hword 0 TLS GD offset */
#define R_TILEGX_IMM16_X0_HW0_TLS_LE 80 /* X0 pipe hword 0 TLS LE offset */
@@ -3007,7 +3013,12 @@ typedef Elf32_Addr Elf32_Conflict;
/* Relocs 90-91 are currently not defined. */
#define R_TILEGX_IMM16_X0_HW0_TLS_IE 92 /* X0 pipe hword 0 TLS IE offset */
#define R_TILEGX_IMM16_X1_HW0_TLS_IE 93 /* X1 pipe hword 0 TLS IE offset */
-/* Relocs 94-99 are currently not defined. */
+#define R_TILEGX_IMM16_X0_HW0_LAST_PLT_PCREL 94 /* X0 pipe PC-rel PLT last hword 0 */
+#define R_TILEGX_IMM16_X1_HW0_LAST_PLT_PCREL 95 /* X1 pipe PC-rel PLT last hword 0 */
+#define R_TILEGX_IMM16_X0_HW1_LAST_PLT_PCREL 96 /* X0 pipe PC-rel PLT last hword 1 */
+#define R_TILEGX_IMM16_X1_HW1_LAST_PLT_PCREL 97 /* X1 pipe PC-rel PLT last hword 1 */
+#define R_TILEGX_IMM16_X0_HW2_LAST_PLT_PCREL 98 /* X0 pipe PC-rel PLT last hword 2 */
+#define R_TILEGX_IMM16_X1_HW2_LAST_PLT_PCREL 99 /* X1 pipe PC-rel PLT last hword 2 */
#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE 100 /* X0 pipe last hword 0 IE off */
#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE 101 /* X1 pipe last hword 0 IE off */
#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE 102 /* X0 pipe last hword 1 IE off */
diff --git a/ports/sysdeps/tile/Makefile b/ports/sysdeps/tile/Makefile
index 3cd4d1e..eb04627 100644
--- a/ports/sysdeps/tile/Makefile
+++ b/ports/sysdeps/tile/Makefile
@@ -11,3 +11,11 @@ ifeq ($(subdir),elf)
# Extra shared linker files to link only into dl-allobjs.so.
sysdep-rtld-routines += dl-start __tls_get_addr
endif
+
+ifeq ($(subdir),csu)
+ifeq (yes,$(config-cflags-mcmodel-large))
+# Support largest code model since the init code at the start of the
+# linked shared object has to reach the .plt at the end of the object.
+CFLAGS-elf-init.c += -mcmodel=large
+endif
+endif
diff --git a/ports/sysdeps/tile/crti.S b/ports/sysdeps/tile/crti.S
index ccb4464..de87f4c 100644
--- a/ports/sysdeps/tile/crti.S
+++ b/ports/sysdeps/tile/crti.S
@@ -40,6 +40,7 @@
#include <libc-symbols.h>
#include <sysdep.h>
+#include <bits/wordsize.h>
#ifndef PREINIT_FUNCTION
# define PREINIT_FUNCTION __gmon_start__
@@ -70,16 +71,17 @@ _init:
#if PREINIT_FUNCTION_WEAK
lnk r2
0:
-#ifdef __tilegx__
+# ifdef __tilegx__
+ moveli r1, hw2_last(_GLOBAL_OFFSET_TABLE_ - 0b)
{
- moveli r1, hw1_last(_GLOBAL_OFFSET_TABLE_ - 0b)
+ shl16insli r1, r1, hw1(_GLOBAL_OFFSET_TABLE_ - 0b)
moveli r0, hw1_last_got(PREINIT_FUNCTION)
}
{
shl16insli r1, r1, hw0(_GLOBAL_OFFSET_TABLE_ - 0b)
shl16insli r0, r0, hw0_got(PREINIT_FUNCTION)
}
-#else
+# else
{
moveli r1, lo16(_GLOBAL_OFFSET_TABLE_ - 0b)
moveli r0, got_lo16(PREINIT_FUNCTION)
@@ -88,13 +90,25 @@ _init:
auli r1, r1, ha16(_GLOBAL_OFFSET_TABLE_ - 0b)
auli r0, r0, got_ha16(PREINIT_FUNCTION)
}
-#endif
+# endif
ADD_PTR r0, r0, r1
ADD_PTR r0, r0, r2
LD_PTR r0, r0
BEQZ r0, .Lno_weak_fn
-#endif
+ jalr r0
+#elif __WORDSIZE == 64
+ /* Since we are calling from the start of the object to the PLT,
+ use the -mcmodel=large call model. */
+ lnk r2
+0:
+ moveli r0, hw2_last_plt(PREINIT_FUNCTION - 0b)
+ shl16insli r0, r0, hw1_plt(PREINIT_FUNCTION - 0b)
+ shl16insli r0, r0, hw0_plt(PREINIT_FUNCTION - 0b)
+ add r0, r0, r2
+ jalr r0
+#else
jal plt(PREINIT_FUNCTION)
+#endif
.Lno_weak_fn:
.section .fini,"ax",@progbits
diff --git a/ports/sysdeps/tile/start.S b/ports/sysdeps/tile/start.S
index 999bb53..54f015f 100644
--- a/ports/sysdeps/tile/start.S
+++ b/ports/sysdeps/tile/start.S
@@ -126,27 +126,37 @@ _start:
moveli r0, hw2_last(main - .Lmy_pc)
}
{
- moveli r3, hw2_last(__libc_csu_init - .Lmy_pc)
shl16insli r0, r0, hw1(main - .Lmy_pc)
+ moveli r3, hw2_last(__libc_csu_init - .Lmy_pc)
}
{
- shl16insli r3, r3, hw1(__libc_csu_init - .Lmy_pc)
shl16insli r0, r0, hw0(main - .Lmy_pc)
+ shl16insli r3, r3, hw1(__libc_csu_init - .Lmy_pc)
}
{
+ ADD_PTR r0, r0, r13
shl16insli r3, r3, hw0(__libc_csu_init - .Lmy_pc)
+ }
+ {
+ moveli r12, hw2_last_plt(__libc_start_main - .Lmy_pc)
+ ADD_PTR r3, r3, r13
+ }
+ {
+ shl16insli r12, r12, hw1_plt(__libc_start_main - .Lmy_pc)
moveli r4, hw2_last(__libc_csu_fini - .Lmy_pc)
}
{
- ADD_PTR r0, r0, r13
+ shl16insli r12, r12, hw0_plt(__libc_start_main - .Lmy_pc)
shl16insli r4, r4, hw1(__libc_csu_fini - .Lmy_pc)
}
{
- ADD_PTR r3, r3, r13
+ ADD_PTR r12, r12, r13
shl16insli r4, r4, hw0(__libc_csu_fini - .Lmy_pc)
}
{
ADD_PTR r4, r4, r13
+ jalr r12
+ }
#else
addli r0, r13, lo16(main - .Lmy_pc)
}
@@ -160,13 +170,12 @@ _start:
}
{
auli r4, r4, ha16(__libc_csu_fini - .Lmy_pc)
-
-#endif
-
/* Call the user's main function, and exit with its value.
But let the libc call main. */
j plt(__libc_start_main)
}
+#endif
+
{
/* Tell backtracer to give up (_start has no caller). */
info INFO_OP_CANNOT_BACKTRACE
diff --git a/ports/sysdeps/tile/tilegx/tilegx64/configure b/ports/sysdeps/tile/tilegx/tilegx64/configure
new file mode 100644
index 0000000..dbe0a87
--- /dev/null
+++ b/ports/sysdeps/tile/tilegx/tilegx64/configure
@@ -0,0 +1,21 @@
+# This file is generated from configure.in by Autoconf. DO NOT EDIT!
+ # Local configure fragment for sysdeps/tile/tilegx/tilegx64.
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for large memory model support" >&5
+$as_echo_n "checking for large memory model support... " >&6; }
+if ${libc_cv_cc_mcmodel_large+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if { ac_try='${CC-cc} -mcmodel=large -xc /dev/null -S -o /dev/null'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then :
+ libc_cv_cc_mcmodel_large=yes
+else
+ libc_cv_cc_mcmodel_large=no
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_cc_mcmodel_large" >&5
+$as_echo "$libc_cv_cc_mcmodel_large" >&6; }
diff --git a/ports/sysdeps/tile/tilegx/tilegx64/configure.in b/ports/sysdeps/tile/tilegx/tilegx64/configure.in
new file mode 100644
index 0000000..5a7e912
--- /dev/null
+++ b/ports/sysdeps/tile/tilegx/tilegx64/configure.in
@@ -0,0 +1,7 @@
+GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
+# Local configure fragment for sysdeps/tile/tilegx/tilegx64.
+
+dnl Check if -mcmodel=large exists (gcc 4.8 and later).
+AC_CACHE_CHECK(for large memory model support, libc_cv_cc_mcmodel_large, [dnl
+LIBC_TRY_CC_OPTION([-mcmodel=large], [libc_cv_cc_mcmodel_large=yes], dnl
+[libc_cv_cc_mcmodel_large=no])])
--
1.7.10.3