(sect_constraint): Handle SPECIAL.
* ldlang.c (lang_output_section_find_1): Don't match SPECIAL.
(map_input_to_output_sections): Likewise.
* ldlex.l (SPECIAL): Define.
* emulparams/elf32ppc.sh (DATA_GOT, SDATA_GOT, SEPARATE_GOTPLT,
GOT, PLT, GOTPLT): Define.
* emultempl/ppc32elf.em (old_plt, old_got): New static vars.
(ppc_after_open): New function.
(PARSE_AND_LIST_PROLOGUE): Define OPTION_OLD_LPT and OPTION_OLD_GOT.
(PARSE_AND_LIST_LONGOPTS): Add "bss-plt" and "sdata-got".
(PARSE_AND_LIST_OPTIONS): Document them.
(PARSE_AND_LIST_ARGS_CASES): Handle them.
(LDEMUL_AFTER_OPEN): Define.
* scripttempl/elf.sc (PLT): Don't override existing define.
(DATA_GOT, SDATA_GOT): Define and use to enable alternate got
placement rather than using NO_SMALL_DATA. Emit GOTPLT for RELRO_NOW.
+2005-05-11 Alan Modra <amodra@bigpond.net.au>
+
+ * ldgram.y: Add SPECIAL token.
+ (sect_constraint): Handle SPECIAL.
+ * ldlang.c (lang_output_section_find_1): Don't match SPECIAL.
+ (map_input_to_output_sections): Likewise.
+ * ldlex.l (SPECIAL): Define.
+ * emulparams/elf32ppc.sh (DATA_GOT, SDATA_GOT, SEPARATE_GOTPLT,
+ GOT, PLT, GOTPLT): Define.
+ * emultempl/ppc32elf.em (old_plt, old_got): New static vars.
+ (ppc_after_open): New function.
+ (PARSE_AND_LIST_PROLOGUE): Define OPTION_OLD_LPT and OPTION_OLD_GOT.
+ (PARSE_AND_LIST_LONGOPTS): Add "bss-plt" and "sdata-got".
+ (PARSE_AND_LIST_OPTIONS): Document them.
+ (PARSE_AND_LIST_ARGS_CASES): Handle them.
+ (LDEMUL_AFTER_OPEN): Define.
+ * scripttempl/elf.sc (PLT): Don't override existing define.
+ (DATA_GOT, SDATA_GOT): Define and use to enable alternate got
+ placement rather than using NO_SMALL_DATA. Emit GOTPLT for RELRO_NOW.
+
2005-05-10 Alan Modra <amodra@bigpond.net.au>
* scripttempl/elf.sc (DATA_SEGMENT_RELRO_GOTPLT_END): Delete.
2005-04-07 Nick Clifton <nickc@redhat.com>
* emultempl/m68kcoff.em: Include ldexp.h and ldlang.h so that
- ldfile.h can use the lang_input_statement type.
+ ldfile.h can use the lang_input_statement type.
2005-04-06 Jakub Jelinek <jakub@redhat.com>
COMMONPAGESIZE=0x1000
ARCH=powerpc:common
MACHINE=
+# Yes, we want duplicate .got and .plt sections. The linker chooses the
+# appropriate one magically in ppc_after_open
+DATA_GOT=
+SDATA_GOT=
+SEPARATE_GOTPLT=0
BSS_PLT=
+GOT=".got ${RELOCATING-0} : SPECIAL { *(.got) }"
+PLT=".plt ${RELOCATING-0} : SPECIAL { *(.plt) }"
+GOTPLT="${PLT}"
+OTHER_TEXT_SECTIONS="*(.glink)"
EXECUTABLE_SYMBOLS='PROVIDE (__stack = 0); PROVIDE (___stack = 0);'
OTHER_BSS_END_SYMBOLS='__end = .;'
OTHER_RELRO_SECTIONS="
/* Whether to run tls optimization. */
static int notlsopt = 0;
+/* Chooses the correct place for .plt and .got. */
+static int old_plt = 0;
+static int old_got = 0;
+
+static void
+ppc_after_open (void)
+{
+ if (link_info.hash->creator == &bfd_elf32_powerpc_vec
+ || link_info.hash->creator == &bfd_elf32_powerpcle_vec)
+ {
+ int new_plt;
+ int keep_new;
+ unsigned int num_plt;
+ unsigned int num_got;
+ lang_output_section_statement_type *os;
+ lang_output_section_statement_type *plt_os[2];
+ lang_output_section_statement_type *got_os[2];
+
+ new_plt = ppc_elf_select_plt_layout (output_bfd, &link_info, old_plt);
+ if (new_plt < 0)
+ einfo ("%X%P: select_plt_layout problem %E\n");
+
+ num_got = 0;
+ num_plt = 0;
+ for (os = &lang_output_section_statement.head->output_section_statement;
+ os != NULL;
+ os = os->next)
+ {
+ if (os->constraint == SPECIAL && strcmp (os->name, ".plt") == 0)
+ {
+ if (num_plt < 2)
+ plt_os[num_plt] = os;
+ ++num_plt;
+ }
+ if (os->constraint == SPECIAL && strcmp (os->name, ".got") == 0)
+ {
+ if (num_got < 2)
+ got_os[num_got] = os;
+ ++num_got;
+ }
+ }
+
+ keep_new = new_plt == 1 ? 0 : -1;
+ if (num_plt == 2)
+ {
+ plt_os[0]->constraint = keep_new;
+ plt_os[1]->constraint = ~keep_new;
+ }
+ if (num_got == 2)
+ {
+ if (old_got)
+ keep_new = -1;
+ got_os[0]->constraint = keep_new;
+ got_os[1]->constraint = ~keep_new;
+ }
+ }
+
+ gld${EMULATION_NAME}_after_open ();
+}
+
static void
ppc_before_allocation (void)
{
#
PARSE_AND_LIST_PROLOGUE='
#define OPTION_NO_TLS_OPT 301
+#define OPTION_OLD_PLT 302
+#define OPTION_OLD_GOT 303
'
PARSE_AND_LIST_LONGOPTS='
{ "no-tls-optimize", no_argument, NULL, OPTION_NO_TLS_OPT },
+ { "bss-plt", no_argument, NULL, OPTION_OLD_PLT },
+ { "sdata-got", no_argument, NULL, OPTION_OLD_GOT },
'
PARSE_AND_LIST_OPTIONS='
fprintf (file, _("\
- --no-tls-optimize Don'\''t try to optimize TLS accesses.\n"
+ --no-tls-optimize Don'\''t try to optimize TLS accesses.\n\
+ --bss-plt Force old-style BSS PLT.\n\
+ --sdata-got Force GOT location just before .sdata.\n"
));
'
case OPTION_NO_TLS_OPT:
notlsopt = 1;
break;
+
+ case OPTION_OLD_PLT:
+ old_plt = 1;
+ break;
+
+ case OPTION_OLD_GOT:
+ old_got = 1;
+ break;
'
# Put these extra ppc32elf routines in ld_${EMULATION_NAME}_emulation
#
+LDEMUL_AFTER_OPEN=ppc_after_open
LDEMUL_BEFORE_ALLOCATION=ppc_before_allocation
LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
%token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START
%token <name> VERS_TAG VERS_IDENTIFIER
%token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT
-%token KEEP ONLY_IF_RO ONLY_IF_RW
+%token KEEP ONLY_IF_RO ONLY_IF_RW SPECIAL
%token EXCLUDE_FILE
%type <versyms> vers_defns
%type <versnode> vers_tag
sect_constraint:
ONLY_IF_RO { $$ = ONLY_IF_RO; }
| ONLY_IF_RW { $$ = ONLY_IF_RW; }
+ | SPECIAL { $$ = SPECIAL; }
| { $$ = 0; }
;
{
if (strcmp (name, lookup->name) == 0
&& lookup->constraint != -1
- && (constraint == 0 || constraint == lookup->constraint))
+ && (constraint == 0
+ || (constraint == lookup->constraint
+ && constraint != SPECIAL)))
return lookup;
}
return NULL;
case lang_output_section_statement_enum:
if (s->output_section_statement.constraint)
{
- if (s->output_section_statement.constraint == -1)
+ if (s->output_section_statement.constraint != ONLY_IF_RW
+ && s->output_section_statement.constraint != ONLY_IF_RO)
break;
s->output_section_statement.all_input_readonly = TRUE;
check_input_sections (s->output_section_statement.children.head,
<EXPRESSION,BOTH,SCRIPT>"OVERLAY" { RTOKEN(OVERLAY);}
<EXPRESSION,BOTH,SCRIPT>"ONLY_IF_RO" { RTOKEN(ONLY_IF_RO); }
<EXPRESSION,BOTH,SCRIPT>"ONLY_IF_RW" { RTOKEN(ONLY_IF_RW); }
+<EXPRESSION,BOTH,SCRIPT>"SPECIAL" { RTOKEN(SPECIAL); }
<BOTH,SCRIPT>"o" { RTOKEN(ORIGIN);}
<BOTH,SCRIPT>"org" { RTOKEN(ORIGIN);}
<BOTH,SCRIPT>"l" { RTOKEN( LENGTH);}
DATA_SEGMENT_RELRO_END=". = DATA_SEGMENT_RELRO_END (${SEPARATE_GOTPLT-0}, .);"
fi
INTERP=".interp ${RELOCATING-0} : { *(.interp) }"
-PLT=".plt ${RELOCATING-0} : { *(.plt) }"
+if test -z "$PLT"; then
+ PLT=".plt ${RELOCATING-0} : { *(.plt) }"
+fi
if test -z "$GOT"; then
if test -z "$SEPARATE_GOTPLT"; then
GOT=".got ${RELOCATING-0} : { *(.got.plt) *(.got) }"
else
NO_SMALL_DATA=" "
fi
+if test -z "${DATA_GOT}"; then
+ if test -n "${NO_SMALL_DATA}"; then
+ DATA_GOT=" "
+ fi
+fi
+if test -z "${SDATA_GOT}"; then
+ if test -z "${NO_SMALL_DATA}"; then
+ SDATA_GOT=" "
+ fi
+fi
test -n "$SEPARATE_GOTPLT" && SEPARATE_GOTPLT=" "
CTOR=".ctors ${CONSTRUCTING-0} :
{
${RELOCATING+${DATARELRO}}
${OTHER_RELRO_SECTIONS}
${TEXT_DYNAMIC-${DYNAMIC}}
- ${NO_SMALL_DATA+${RELRO_NOW+${GOT}}}
- ${NO_SMALL_DATA+${RELRO_NOW-${SEPARATE_GOTPLT+${GOT}}}}
+ ${DATA_GOT+${RELRO_NOW+${GOT}}}
+ ${DATA_GOT+${RELRO_NOW+${GOTPLT}}}
+ ${DATA_GOT+${RELRO_NOW-${SEPARATE_GOTPLT+${GOT}}}}
${RELOCATING+${DATA_SEGMENT_RELRO_END}}
- ${NO_SMALL_DATA+${RELRO_NOW-${SEPARATE_GOTPLT+${GOTPLT}}}}
- ${NO_SMALL_DATA+${RELRO_NOW-${SEPARATE_GOTPLT-${GOT}}}}
+ ${DATA_GOT+${RELRO_NOW-${SEPARATE_GOTPLT-${GOT}}}}
+ ${DATA_GOT+${RELRO_NOW-${GOTPLT}}}
${DATA_PLT+${PLT_BEFORE_GOT-${PLT}}}
${SMALL_DATA_CTOR+${RELOCATING+${CTOR}}}
${SMALL_DATA_DTOR+${RELOCATING+${DTOR}}}
${DATA_PLT+${PLT_BEFORE_GOT+${PLT}}}
- ${RELOCATING+${OTHER_GOT_SYMBOLS}}
- ${NO_SMALL_DATA-${GOT}}
- ${OTHER_GOT_SECTIONS}
+ ${SDATA_GOT+${RELOCATING+${OTHER_GOT_SYMBOLS}}}
+ ${SDATA_GOT+${GOT}}
+ ${SDATA_GOT+${OTHER_GOT_SECTIONS}}
${SDATA}
${OTHER_SDATA_SECTIONS}
${RELOCATING+${DATA_END_SYMBOLS-_edata = .; PROVIDE (edata = .);}}