This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH 1/4] LD: Linker script hidden symbol support
- From: "Maciej W. Rozycki" <macro at codesourcery dot com>
- To: <binutils at sourceware dot org>
- Cc: Richard Sandiford <rdsandiford at googlemail dot com>
- Date: Fri, 3 Aug 2012 19:00:05 +0100
- Subject: [PATCH 1/4] LD: Linker script hidden symbol support
Hi,
A change to LD seven years ago, as recorded here:
http://sourceware.org/ml/binutils/2005-08/msg00045.html
switched the scope of symbols created in linker scripts from object to
global. A later update added support for hidden default symbols (as in
PROVIDE vs PROVIDE_HIDDEN) here:
http://sourceware.org/ml/binutils/2005-08/msg00054.html
however the lost ability to create hidden symbols unconditionally has
never been restituted.
A workaround exists, in the form of version scripts (that may also be
embedded in regular linker scripts with the use of the VERSION keyword)
that can force the scope of any global symbols back to object, however
that approach was not considered back when PROVIDE_HIDDEN was defined and
therefore I decided to follow the precedent and implement a new keyword
that will complement the three cases already handled: assignment, PROVIDE
and PROVIDE_HIDDEN.
Somewhat unimaginatively I called the new keyword HIDDEN, its syntax is
exactly like that of PROVIDE and PROVIDE_HIDDEN, and its semantics exactly
like that of a simple assignment (compound assignments are not supported;
they don't adjust the scope of an already defined symbol), except that the
newly defined symbol will have its scope set to object.
While at it I have cleaned up a hack that reached as far as BFD and that
caused this change not to be contained within LD -- for unconditional
symbol definitions current code overloads the "hidden" member of the
assignment structure used internally to mean the symbol has been defined
with the --defsym command-line option rather than in a script.
As a result unrelated code has to handle this special case in a few
places, including BFD, with a suitable comment attached to explain what is
really going on there, for a questionable saving of some structure space.
With this change I have removed the hack and there is now a separate
"defsym" member that denotes such symbols explicitly.
The original change also broke all MIPS SVR4 ABI binaries produced as
with the switch from the object to the global scope the required _gp
symbol was no longer defined such as the MIPS psABI mandated. This will
be handled with a follow-up change, building on functionality added here.
I have regression-tested it successfully against a superset of Alan's set
of targets with no problems seen. OK to apply?
2012-08-03 Maciej W. Rozycki <macro@codesourcery.com>
bfd/
* elflink.c (bfd_elf_record_link_assignment): Remove --defsym
symbols special case.
ld/
* ldexp.h (etree_union): Add defsym member to the assign member
structure.
(exp_assign): Add hidden argument to prototype.
* ldexp.c (exp_fold_tree_1): Use the defsym member to handle
--defsym symbols.
(exp_assop): Add defsym argument, initialize the defsym member
of the assign structure.
(exp_assign): Handle hidden symbols.
(exp_defsym): Update to use the defsym argument to exp_assop.
(exp_provide): Update to handle the defsym argument to exp_assop.
* ldlex.l (HIDDEN): New token.
* ldgram.y (HIDDEN): Likewise.
(assignment, section): Update calls to exp_assign.
* ldctor.c (ldctor_build_sets): Likewise.
* mri.c (mri_format): Likewise.
* ldlang.c (lang_insert_orphan, lang_leave_overlay): Likewise.
(open_input_bfds): Remove --defsym symbols special case.
* ld/emultempl/beos.em (gld_${EMULATION_NAME}_set_symbols):
Update call to exp_assign.
* ld/emultempl/pe.em (gld_${EMULATION_NAME}_set_symbols):
Likewise.
* ld/emultempl/pep.em (gld_${EMULATION_NAME}_set_symbols):
Likewise.
* ld/emultempl/spuelf.em (spu_place_special_section): Likewise.
* ld/emultempl/xtensaelf.em (ld_xtensa_insert_page_offsets):
Likewise.
* ld.texinfo (Assigning Values to Symbols): Add HIDDEN.
(HIDDEN): New subsection.
Maciej
binutils-ld-hidden.diff
Index: binutils-fsf-trunk-quilt/bfd/elflink.c
===================================================================
--- binutils-fsf-trunk-quilt.orig/bfd/elflink.c 2012-07-30 19:11:21.000000000 +0100
+++ binutils-fsf-trunk-quilt/bfd/elflink.c 2012-08-02 22:35:36.011761953 +0100
@@ -569,7 +569,7 @@ bfd_elf_record_link_assignment (bfd *out
h->def_regular = 1;
- if (provide && hidden)
+ if (hidden)
{
bed = get_elf_backend_data (output_bfd);
h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
Index: binutils-fsf-trunk-quilt/ld/ld.texinfo
===================================================================
--- binutils-fsf-trunk-quilt.orig/ld/ld.texinfo 2012-07-30 19:11:21.000000000 +0100
+++ binutils-fsf-trunk-quilt/ld/ld.texinfo 2012-08-02 22:35:36.011761953 +0100
@@ -3410,6 +3410,7 @@ the symbol and place it into the symbol
@menu
* Simple Assignments:: Simple Assignments
+* HIDDEN:: HIDDEN
* PROVIDE:: PROVIDE
* PROVIDE_HIDDEN:: PROVIDE_HIDDEN
* Source Code Reference:: How to use a linker script defined symbol in source code
@@ -3473,6 +3474,31 @@ the last @samp{.text} input section. Th
defined as the address following the @samp{.text} output section aligned
upward to a 4 byte boundary.
+@node HIDDEN
+@subsection HIDDEN
+@cindex HIDDEN
+For ELF targeted ports, define a symbol that will be hidden and won't be
+exported. The syntax is @code{HIDDEN(@var{symbol} = @var{expression})}.
+
+Here is the example from @ref{Simple Assignments}, rewritten to use
+@code{HIDDEN}:
+
+@smallexample
+HIDDEN(floating_point = 0);
+SECTIONS
+@{
+ .text :
+ @{
+ *(.text)
+ HIDDEN(_etext = .);
+ @}
+ HIDDEN(_bdata = (. + 3) & ~ 3);
+ .data : @{ *(.data) @}
+@}
+@end smallexample
+@noindent
+In this case none of the three symbols will be visible outside this module.
+
@node PROVIDE
@subsection PROVIDE
@cindex PROVIDE
Index: binutils-fsf-trunk-quilt/ld/ldctor.c
===================================================================
--- binutils-fsf-trunk-quilt.orig/ld/ldctor.c 2012-07-30 19:11:21.000000000 +0100
+++ binutils-fsf-trunk-quilt/ld/ldctor.c 2012-08-02 22:35:36.011761953 +0100
@@ -321,9 +321,11 @@ ldctor_build_sets (void)
lang_add_assignment (exp_assign (".",
exp_unop (ALIGN_K,
- exp_intop (reloc_size))));
+ exp_intop (reloc_size)),
+ FALSE));
lang_add_assignment (exp_assign (p->h->root.string,
- exp_nameop (NAME, ".")));
+ exp_nameop (NAME, "."),
+ FALSE));
lang_add_data (size, exp_intop (p->count));
for (e = p->elements; e != NULL; e = e->next)
Index: binutils-fsf-trunk-quilt/ld/ldexp.c
===================================================================
--- binutils-fsf-trunk-quilt.orig/ld/ldexp.c 2012-07-30 19:11:21.000000000 +0100
+++ binutils-fsf-trunk-quilt/ld/ldexp.c 2012-08-02 22:35:36.041394701 +0100
@@ -892,7 +892,7 @@ exp_fold_tree_1 (etree_type *tree)
if (expld.result.valid_p
|| (expld.phase <= lang_mark_phase_enum
&& tree->type.node_class == etree_assign
- && tree->assign.hidden))
+ && tree->assign.defsym))
{
if (h == NULL)
{
@@ -1054,6 +1054,7 @@ static etree_type *
exp_assop (const char *dst,
etree_type *src,
enum node_tree_enum class,
+ bfd_boolean defsym,
bfd_boolean hidden)
{
etree_type *n;
@@ -1065,20 +1066,25 @@ exp_assop (const char *dst,
n->assign.type.node_class = class;
n->assign.src = src;
n->assign.dst = dst;
+ n->assign.defsym = defsym;
n->assign.hidden = hidden;
return n;
}
+/* Handle linker script assignments and HIDDEN. */
+
etree_type *
-exp_assign (const char *dst, etree_type *src)
+exp_assign (const char *dst, etree_type *src, bfd_boolean hidden)
{
- return exp_assop (dst, src, etree_assign, FALSE);
+ return exp_assop (dst, src, etree_assign, FALSE, hidden);
}
+/* Handle --defsym command-line option. */
+
etree_type *
exp_defsym (const char *dst, etree_type *src)
{
- return exp_assop (dst, src, etree_assign, TRUE);
+ return exp_assop (dst, src, etree_assign, TRUE, FALSE);
}
/* Handle PROVIDE. */
@@ -1086,7 +1092,7 @@ exp_defsym (const char *dst, etree_type
etree_type *
exp_provide (const char *dst, etree_type *src, bfd_boolean hidden)
{
- return exp_assop (dst, src, etree_provide, hidden);
+ return exp_assop (dst, src, etree_provide, FALSE, hidden);
}
/* Handle ASSERT. */
Index: binutils-fsf-trunk-quilt/ld/ldexp.h
===================================================================
--- binutils-fsf-trunk-quilt.orig/ld/ldexp.h 2012-07-30 19:11:21.000000000 +0100
+++ binutils-fsf-trunk-quilt/ld/ldexp.h 2012-08-02 22:35:36.061761927 +0100
@@ -67,6 +67,7 @@ typedef union etree_union {
node_type type;
const char *dst;
union etree_union *src;
+ bfd_boolean defsym;
bfd_boolean hidden;
} assign;
struct {
@@ -199,7 +200,7 @@ etree_type *exp_unop
etree_type *exp_nameop
(int, const char *);
etree_type *exp_assign
- (const char *, etree_type *);
+ (const char *, etree_type *, bfd_boolean);
etree_type *exp_defsym
(const char *, etree_type *);
etree_type *exp_provide
Index: binutils-fsf-trunk-quilt/ld/ldgram.y
===================================================================
--- binutils-fsf-trunk-quilt.orig/ld/ldgram.y 2012-07-30 19:11:21.000000000 +0100
+++ binutils-fsf-trunk-quilt/ld/ldgram.y 2012-08-02 22:35:36.061761927 +0100
@@ -146,7 +146,7 @@ static int error_index;
%token STARTUP HLL SYSLIB FLOAT NOFLOAT NOCROSSREFS
%token ORIGIN FILL
%token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS
-%token ALIGNMOD AT SUBALIGN PROVIDE PROVIDE_HIDDEN AS_NEEDED
+%token ALIGNMOD AT SUBALIGN HIDDEN PROVIDE PROVIDE_HIDDEN AS_NEEDED
%type <token> assign_op atype attributes_opt sect_constraint
%type <name> filename
%token CHIP LIST SECT ABSOLUTE LOAD NEWLINE ENDWORD ORDER NAMEWORD ASSERT_K
@@ -759,7 +759,7 @@ end: ';' | ','
assignment:
NAME '=' mustbe_exp
{
- lang_add_assignment (exp_assign ($1, $3));
+ lang_add_assignment (exp_assign ($1, $3, FALSE));
}
| NAME assign_op mustbe_exp
{
@@ -767,7 +767,11 @@ end: ';' | ','
exp_binop ($2,
exp_nameop (NAME,
$1),
- $3)));
+ $3), FALSE));
+ }
+ | HIDDEN '(' NAME '=' mustbe_exp ')'
+ {
+ lang_add_assignment (exp_assign ($3, $5, TRUE));
}
| PROVIDE '(' NAME '=' mustbe_exp ')'
{
@@ -1085,7 +1089,7 @@ section: NAME { ldlex_expression(); }
opt_exp_with_type
{
ldlex_popstate ();
- lang_add_assignment (exp_assign (".", $3));
+ lang_add_assignment (exp_assign (".", $3, FALSE));
}
'{' sec_or_group_p1 '}'
| INCLUDE filename
Index: binutils-fsf-trunk-quilt/ld/ldlang.c
===================================================================
--- binutils-fsf-trunk-quilt.orig/ld/ldlang.c 2012-08-02 15:17:47.000000000 +0100
+++ binutils-fsf-trunk-quilt/ld/ldlang.c 2012-08-02 22:35:36.061761927 +0100
@@ -3286,7 +3286,7 @@ open_input_bfds (lang_statement_union_ty
#endif
break;
case lang_assignment_statement_enum:
- if (s->assignment_statement.exp->assign.hidden)
+ if (s->assignment_statement.exp->assign.defsym)
/* This is from a --defsym on the command line. */
exp_fold_tree_no_dot (s->assignment_statement.exp);
break;
@@ -7437,7 +7437,7 @@ lang_leave_overlay (etree_type *lma_expr
{
overlay_list->os->update_dot = 1;
overlay_list->os->update_dot_tree
- = exp_assign (".", exp_binop ('+', overlay_vma, overlay_max));
+ = exp_assign (".", exp_binop ('+', overlay_vma, overlay_max), FALSE);
}
l = overlay_list;
Index: binutils-fsf-trunk-quilt/ld/ldlex.l
===================================================================
--- binutils-fsf-trunk-quilt.orig/ld/ldlex.l 2012-07-30 19:11:21.000000000 +0100
+++ binutils-fsf-trunk-quilt/ld/ldlex.l 2012-08-02 22:35:36.061761927 +0100
@@ -320,6 +320,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([
<BOTH,SCRIPT>"PHDRS" { RTOKEN (PHDRS); }
<EXPRESSION,BOTH,SCRIPT>"AT" { RTOKEN(AT);}
<EXPRESSION,BOTH,SCRIPT>"SUBALIGN" { RTOKEN(SUBALIGN);}
+<EXPRESSION,BOTH,SCRIPT>"HIDDEN" { RTOKEN(HIDDEN); }
<EXPRESSION,BOTH,SCRIPT>"PROVIDE" { RTOKEN(PROVIDE); }
<EXPRESSION,BOTH,SCRIPT>"PROVIDE_HIDDEN" { RTOKEN(PROVIDE_HIDDEN); }
<EXPRESSION,BOTH,SCRIPT>"KEEP" { RTOKEN(KEEP); }
Index: binutils-fsf-trunk-quilt/ld/mri.c
===================================================================
--- binutils-fsf-trunk-quilt.orig/ld/mri.c 2012-07-30 19:11:21.000000000 +0100
+++ binutils-fsf-trunk-quilt/ld/mri.c 2012-08-02 22:35:36.061761927 +0100
@@ -297,7 +297,7 @@ mri_format (const char *name)
void
mri_public (const char *name, etree_type *exp)
{
- lang_add_assignment (exp_assign (name, exp));
+ lang_add_assignment (exp_assign (name, exp, FALSE));
}
void
Index: binutils-fsf-trunk-quilt/ld/emultempl/beos.em
===================================================================
--- binutils-fsf-trunk-quilt.orig/ld/emultempl/beos.em 2012-07-30 19:11:20.000000000 +0100
+++ binutils-fsf-trunk-quilt/ld/emultempl/beos.em 2012-08-02 22:38:10.911761895 +0100
@@ -348,7 +348,8 @@ gld_${EMULATION_NAME}_set_symbols (void)
for (j = 0; init[j].ptr; j++)
{
long val = init[j].value;
- lang_add_assignment (exp_assign (init[j].symbol, exp_intop (val)));
+ lang_add_assignment (exp_assign (init[j].symbol, exp_intop (val),
+ FALSE));
if (init[j].size == sizeof(short))
*(short *)init[j].ptr = val;
else if (init[j].size == sizeof(int))
Index: binutils-fsf-trunk-quilt/ld/emultempl/pe.em
===================================================================
--- binutils-fsf-trunk-quilt.orig/ld/emultempl/pe.em 2012-07-30 19:11:20.000000000 +0100
+++ binutils-fsf-trunk-quilt/ld/emultempl/pe.em 2012-08-02 22:38:10.911761895 +0100
@@ -944,7 +944,7 @@ gld_${EMULATION_NAME}_set_symbols (void)
lang_assignment_statement_type *rv;
rv = lang_add_assignment (exp_assign (GET_INIT_SYMBOL_NAME (j),
- exp_intop (val)));
+ exp_intop (val), FALSE));
if (init[j].size == sizeof (short))
*(short *) init[j].ptr = val;
else if (init[j].size == sizeof (int))
@@ -1721,8 +1721,9 @@ gld_${EMULATION_NAME}_unrecognized_file
= pe_def_file->base_address;
init[IMAGEBASEOFF].inited = 1;
if (image_base_statement)
- image_base_statement->exp = exp_assign ("__image_base__",
- exp_intop (pe.ImageBase));
+ image_base_statement->exp
+ = exp_assign ("__image_base__", exp_intop (pe.ImageBase),
+ FALSE);
}
if (pe_def_file->stack_reserve != -1
Index: binutils-fsf-trunk-quilt/ld/emultempl/pep.em
===================================================================
--- binutils-fsf-trunk-quilt.orig/ld/emultempl/pep.em 2012-07-30 19:11:20.000000000 +0100
+++ binutils-fsf-trunk-quilt/ld/emultempl/pep.em 2012-08-02 22:38:10.911761895 +0100
@@ -856,7 +856,7 @@ gld_${EMULATION_NAME}_set_symbols (void)
lang_assignment_statement_type *rv;
rv = lang_add_assignment (exp_assign (GET_INIT_SYMBOL_NAME (j),
- exp_intop (val)));
+ exp_intop (val), FALSE));
if (init[j].size == sizeof (short))
*(short *) init[j].ptr = (short) val;
else if (init[j].size == sizeof (int))
@@ -1522,8 +1522,9 @@ gld_${EMULATION_NAME}_unrecognized_file
= pep_def_file->base_address;
init[IMAGEBASEOFF].inited = 1;
if (image_base_statement)
- image_base_statement->exp = exp_assign ("__image_base__",
- exp_intop (pep.ImageBase));
+ image_base_statement->exp
+ = exp_assign ("__image_base__", exp_intop (pep.ImageBase),
+ FALSE);
}
if (pep_def_file->stack_reserve != -1
Index: binutils-fsf-trunk-quilt/ld/emultempl/spuelf.em
===================================================================
--- binutils-fsf-trunk-quilt.orig/ld/emultempl/spuelf.em 2012-07-30 19:11:20.000000000 +0100
+++ binutils-fsf-trunk-quilt/ld/emultempl/spuelf.em 2012-08-02 22:38:10.911761895 +0100
@@ -165,7 +165,7 @@ spu_place_special_section (asection *s,
push_stat_ptr (&os->children);
e_size = exp_intop (params.line_size - s->size);
- lang_add_assignment (exp_assign (".", e_size));
+ lang_add_assignment (exp_assign (".", e_size, FALSE));
pop_stat_ptr ();
}
lang_add_section (&os->children, s, NULL, os);
Index: binutils-fsf-trunk-quilt/ld/emultempl/xtensaelf.em
===================================================================
--- binutils-fsf-trunk-quilt.orig/ld/emultempl/xtensaelf.em 2012-07-30 19:11:20.000000000 +0100
+++ binutils-fsf-trunk-quilt/ld/emultempl/xtensaelf.em 2012-08-02 22:38:10.911761895 +0100
@@ -1887,7 +1887,7 @@ ld_xtensa_insert_page_offsets (bfd_vma d
etree_type *name_op = exp_nameop (NAME, ".");
etree_type *addend_op = exp_intop (1 << xtensa_page_power);
etree_type *add_op = exp_binop ('+', name_op, addend_op);
- etree_type *assign_op = exp_assign (".", add_op);
+ etree_type *assign_op = exp_assign (".", add_op, FALSE);
lang_assignment_statement_type *assign_stmt;
lang_statement_union_type *assign_union;