From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 16734 invoked by alias); 3 Nov 2012 03:42:55 -0000 Received: (qmail 16721 invoked by uid 22791); 3 Nov 2012 03:42:54 -0000 X-SWARE-Spam-Status: No, hits=-2.4 required=5.0 tests=AWL,BAYES_00,KHOP_SPAMHAUS_DROP,RP_MATCHES_RCVD,TW_AV,TW_EG,TW_VZ X-Spam-Check-By: sourceware.org Received: from usmamail.tilera.com (HELO USMAMAIL.TILERA.COM) (12.216.194.151) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sat, 03 Nov 2012 03:42:49 +0000 Received: from farm-0002.internal.tilera.com (10.2.0.32) by USMAEXCH2.tad.internal.tilera.com (10.3.0.33) with Microsoft SMTP Server (TLS) id 14.0.694.0; Fri, 2 Nov 2012 23:42:47 -0400 Received: (from cmetcalf@localhost) by farm-0002.internal.tilera.com (8.14.4/8.12.11/Submit) id qA33glX8011417; Fri, 2 Nov 2012 23:42:47 -0400 Message-ID: <201211030342.qA33glX8011417@farm-0002.internal.tilera.com> From: Chris Metcalf Date: Sat, 03 Nov 2012 03:42:00 -0000 Subject: [PATCH] tile: support very large shared objects To: , MIME-Version: 1.0 Content-Type: text/plain X-IsSubscribed: yes Mailing-List: contact libc-ports-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: libc-ports-owner@sourceware.org X-SW-Source: 2012-11/txt/msg00008.txt.bz2 Changelog: 2012-11-02 Chris Metcalf * 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 * 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 #include +#include #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