This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: PATCH: Add double-quoted version strings
Nick Clifton wrote:
> Hi Mark,
>
>> OK?
> The patch is OK, but I agree with Daniel that we ought to have a
> cautionary note in the linker documentation about matching demangler
> output.
Here is the patch, as checked in, incorporating your suggestions.
Thanks,
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
(916) 791-8304
2005-10-13 Mark Mitchell <mark@codesourcery.com>
* ld.texino: Describe double-quoted string syntax for version
nodes.
* ldlang.h (lang_new_vers_pattern): Add literal_p parameter.
* ldgram.y (vers_defns): Allow NAME as well as VERS_IDENTIFIER.
Adjust calls to lang_new_vers_pattern to pass literal_p argument.
* ldlang.c (lang_vers_match): Fix indentation. Do not glob-match
version nodes without a pattern.
(lang_new_vers_pattern): Add literal_p parameter.
(lang_do_version_exports_section): Pass it.
2005-10-13 Mark Mitchell <mark@codesourcery.com>
* ld-elfvers/vers.exp: Add vers31.
* ld-elfvers/vers31.c: New file.
* ld-elfvers/vers31.dsym: Likewise.
* ld-elfvers/vers31.map: Likewise.
* ld-elfvers/vers31.ver: Likewise.
Index: ld.texinfo
===================================================================
RCS file: /cvs/src/src/ld/ld.texinfo,v
retrieving revision 1.148
diff -c -5 -p -r1.148 ld.texinfo
*** ld.texinfo 28 Sep 2005 00:34:21 -0000 1.148
--- ld.texinfo 13 Oct 2005 17:26:14 -0000
*************** VERS_1.2 @{
*** 4287,4296 ****
--- 4287,4300 ----
foo2;
@} VERS_1.1;
VERS_2.0 @{
bar1; bar2;
+ extern "C++" @{
+ ns::*;
+ "int f(int, double)";
+ @}
@} VERS_1.2;
@end smallexample
This example version script defines three version nodes. The first
version node defined is @samp{VERS_1.1}; it has no other dependencies.
*************** The script binds the symbol @samp{foo1}
*** 4298,4307 ****
--- 4302,4313 ----
a number of symbols to local scope so that they are not visible outside
of the shared library; this is done using wildcard patterns, so that any
symbol whose name begins with @samp{old}, @samp{original}, or @samp{new}
is matched. The wildcard patterns available are the same as those used
in the shell when matching filenames (also known as ``globbing'').
+ However, if you specify the symbol name inside double quotes, then the
+ name is treated as literal, rather than as a glob pattern.
Next, the version script defines node @samp{VERS_1.2}. This node
depends upon @samp{VERS_1.1}. The script binds the symbol @samp{foo2}
to the version node @samp{VERS_1.2}.
*************** VERSION extern "lang" @{ version-script-
*** 4407,4416 ****
--- 4413,4432 ----
The supported @samp{lang}s are @samp{C}, @samp{C++}, and @samp{Java}.
The linker will iterate over the list of symbols at the link time and
demangle them according to @samp{lang} before matching them to the
patterns specified in @samp{version-script-commands}.
+ Demangled names may contains spaces and other special characters. As
+ described above, you can use a glob pattern to match demangled names,
+ or you can use a double-quoted string to match the string exactly. In
+ the latter case, be aware that minor differences (such as differing
+ whitespace) between the version script and the demangler output will
+ cause a mismatch. As the exact string generated by the demangler
+ might change in the future, even if the mangled name does not, you
+ should check that all of your version directives are behaving as you
+ expect when you upgrade.
+
@node Expressions
@section Expressions in Linker Scripts
@cindex expressions
@cindex arithmetic
The syntax for expressions in the linker script language is identical to
Index: ldgram.y
===================================================================
RCS file: /cvs/src/src/ld/ldgram.y,v
retrieving revision 1.47
diff -c -5 -p -r1.47 ldgram.y
*** ldgram.y 28 Sep 2005 00:34:21 -0000 1.47
--- ldgram.y 13 Oct 2005 17:26:14 -0000
*************** vers_tag:
*** 1217,1231 ****
;
vers_defns:
VERS_IDENTIFIER
{
! $$ = lang_new_vers_pattern (NULL, $1, ldgram_vers_current_lang);
}
| vers_defns ';' VERS_IDENTIFIER
{
! $$ = lang_new_vers_pattern ($1, $3, ldgram_vers_current_lang);
}
| vers_defns ';' EXTERN NAME '{'
{
$<name>$ = ldgram_vers_current_lang;
ldgram_vers_current_lang = $4;
--- 1217,1239 ----
;
vers_defns:
VERS_IDENTIFIER
{
! $$ = lang_new_vers_pattern (NULL, $1, ldgram_vers_current_lang, FALSE);
! }
! | NAME
! {
! $$ = lang_new_vers_pattern (NULL, $1, ldgram_vers_current_lang, TRUE);
}
| vers_defns ';' VERS_IDENTIFIER
{
! $$ = lang_new_vers_pattern ($1, $3, ldgram_vers_current_lang, FALSE);
! }
! | vers_defns ';' NAME
! {
! $$ = lang_new_vers_pattern ($1, $3, ldgram_vers_current_lang, TRUE);
}
| vers_defns ';' EXTERN NAME '{'
{
$<name>$ = ldgram_vers_current_lang;
ldgram_vers_current_lang = $4;
*************** vers_defns:
*** 1248,1278 ****
$$ = $5;
ldgram_vers_current_lang = $<name>4;
}
| GLOBAL
{
! $$ = lang_new_vers_pattern (NULL, "global", ldgram_vers_current_lang);
}
| vers_defns ';' GLOBAL
{
! $$ = lang_new_vers_pattern ($1, "global", ldgram_vers_current_lang);
}
| LOCAL
{
! $$ = lang_new_vers_pattern (NULL, "local", ldgram_vers_current_lang);
}
| vers_defns ';' LOCAL
{
! $$ = lang_new_vers_pattern ($1, "local", ldgram_vers_current_lang);
}
| EXTERN
{
! $$ = lang_new_vers_pattern (NULL, "extern", ldgram_vers_current_lang);
}
| vers_defns ';' EXTERN
{
! $$ = lang_new_vers_pattern ($1, "extern", ldgram_vers_current_lang);
}
;
opt_semicolon:
/* empty */
--- 1256,1286 ----
$$ = $5;
ldgram_vers_current_lang = $<name>4;
}
| GLOBAL
{
! $$ = lang_new_vers_pattern (NULL, "global", ldgram_vers_current_lang, FALSE);
}
| vers_defns ';' GLOBAL
{
! $$ = lang_new_vers_pattern ($1, "global", ldgram_vers_current_lang, FALSE);
}
| LOCAL
{
! $$ = lang_new_vers_pattern (NULL, "local", ldgram_vers_current_lang, FALSE);
}
| vers_defns ';' LOCAL
{
! $$ = lang_new_vers_pattern ($1, "local", ldgram_vers_current_lang, FALSE);
}
| EXTERN
{
! $$ = lang_new_vers_pattern (NULL, "extern", ldgram_vers_current_lang, FALSE);
}
| vers_defns ';' EXTERN
{
! $$ = lang_new_vers_pattern ($1, "extern", ldgram_vers_current_lang, FALSE);
}
;
opt_semicolon:
/* empty */
Index: ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.199
diff -c -5 -p -r1.199 ldlang.c
*** ldlang.c 30 Sep 2005 22:10:54 -0000 1.199
--- ldlang.c 13 Oct 2005 17:26:16 -0000
*************** lang_vers_match (struct bfd_elf_version_
*** 6220,6255 ****
e.symbol = sym;
expr = htab_find (head->htab, &e);
while (expr && strcmp (expr->symbol, sym) == 0)
if (expr->mask == BFD_ELF_VERSION_C_TYPE)
goto out_ret;
! else
! expr = expr->next;
}
/* Fallthrough */
case BFD_ELF_VERSION_C_TYPE:
if (head->mask & BFD_ELF_VERSION_CXX_TYPE)
{
e.symbol = cxx_sym;
expr = htab_find (head->htab, &e);
while (expr && strcmp (expr->symbol, cxx_sym) == 0)
if (expr->mask == BFD_ELF_VERSION_CXX_TYPE)
goto out_ret;
! else
! expr = expr->next;
}
/* Fallthrough */
case BFD_ELF_VERSION_CXX_TYPE:
if (head->mask & BFD_ELF_VERSION_JAVA_TYPE)
{
e.symbol = java_sym;
expr = htab_find (head->htab, &e);
while (expr && strcmp (expr->symbol, java_sym) == 0)
if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE)
goto out_ret;
! else
! expr = expr->next;
}
/* Fallthrough */
default:
break;
}
--- 6220,6255 ----
e.symbol = sym;
expr = htab_find (head->htab, &e);
while (expr && strcmp (expr->symbol, sym) == 0)
if (expr->mask == BFD_ELF_VERSION_C_TYPE)
goto out_ret;
! else
! expr = expr->next;
}
/* Fallthrough */
case BFD_ELF_VERSION_C_TYPE:
if (head->mask & BFD_ELF_VERSION_CXX_TYPE)
{
e.symbol = cxx_sym;
expr = htab_find (head->htab, &e);
while (expr && strcmp (expr->symbol, cxx_sym) == 0)
if (expr->mask == BFD_ELF_VERSION_CXX_TYPE)
goto out_ret;
! else
! expr = expr->next;
}
/* Fallthrough */
case BFD_ELF_VERSION_CXX_TYPE:
if (head->mask & BFD_ELF_VERSION_JAVA_TYPE)
{
e.symbol = java_sym;
expr = htab_find (head->htab, &e);
while (expr && strcmp (expr->symbol, java_sym) == 0)
if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE)
goto out_ret;
! else
! expr = expr->next;
}
/* Fallthrough */
default:
break;
}
*************** lang_vers_match (struct bfd_elf_version_
*** 6258,6271 ****
/* Finally, try the wildcards. */
if (prev == NULL || prev->symbol)
expr = head->remaining;
else
expr = prev->next;
! while (expr)
{
const char *s;
if (expr->pattern[0] == '*' && expr->pattern[1] == '\0')
break;
if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE)
s = java_sym;
--- 6258,6274 ----
/* Finally, try the wildcards. */
if (prev == NULL || prev->symbol)
expr = head->remaining;
else
expr = prev->next;
! for (; expr; expr = expr->next)
{
const char *s;
+ if (!expr->pattern)
+ continue;
+
if (expr->pattern[0] == '*' && expr->pattern[1] == '\0')
break;
if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE)
s = java_sym;
*************** lang_vers_match (struct bfd_elf_version_
*** 6273,6283 ****
s = cxx_sym;
else
s = sym;
if (fnmatch (expr->pattern, s, 0) == 0)
break;
- expr = expr->next;
}
out_ret:
if (cxx_sym != sym)
free ((char *) cxx_sym);
--- 6276,6285 ----
*************** realsymbol (const char *pattern)
*** 6328,6352 ****
free (symbol);
return pattern;
}
}
! /* This is called for each variable name or match expression. */
struct bfd_elf_version_expr *
lang_new_vers_pattern (struct bfd_elf_version_expr *orig,
const char *new,
! const char *lang)
{
struct bfd_elf_version_expr *ret;
ret = xmalloc (sizeof *ret);
ret->next = orig;
! ret->pattern = new;
ret->symver = 0;
ret->script = 0;
! ret->symbol = realsymbol (new);
if (lang == NULL || strcasecmp (lang, "C") == 0)
ret->mask = BFD_ELF_VERSION_C_TYPE;
else if (strcasecmp (lang, "C++") == 0)
ret->mask = BFD_ELF_VERSION_CXX_TYPE;
--- 6330,6357 ----
free (symbol);
return pattern;
}
}
! /* This is called for each variable name or match expression. NEW is
! the name of the symbol to match, or, if LITERAL_P is FALSE, a glob
! pattern to be matched against symbol names. */
struct bfd_elf_version_expr *
lang_new_vers_pattern (struct bfd_elf_version_expr *orig,
const char *new,
! const char *lang,
! bfd_boolean literal_p)
{
struct bfd_elf_version_expr *ret;
ret = xmalloc (sizeof *ret);
ret->next = orig;
! ret->pattern = literal_p ? NULL : new;
ret->symver = 0;
ret->script = 0;
! ret->symbol = literal_p ? new : realsymbol (new);
if (lang == NULL || strcasecmp (lang, "C") == 0)
ret->mask = BFD_ELF_VERSION_C_TYPE;
else if (strcasecmp (lang, "C++") == 0)
ret->mask = BFD_ELF_VERSION_CXX_TYPE;
*************** lang_do_version_exports_section (void)
*** 6626,6646 ****
einfo (_("%X%P: unable to read .exports section contents\n"), sec);
p = contents;
while (p < contents + len)
{
! greg = lang_new_vers_pattern (greg, p, NULL);
p = strchr (p, '\0') + 1;
}
/* Do not free the contents, as we used them creating the regex. */
/* Do not include this section in the link. */
sec->flags |= SEC_EXCLUDE;
}
! lreg = lang_new_vers_pattern (NULL, "*", NULL);
lang_register_vers_node (command_line.version_exports_section,
lang_new_vers_node (greg, lreg), NULL);
}
void
--- 6631,6651 ----
einfo (_("%X%P: unable to read .exports section contents\n"), sec);
p = contents;
while (p < contents + len)
{
! greg = lang_new_vers_pattern (greg, p, NULL, FALSE);
p = strchr (p, '\0') + 1;
}
/* Do not free the contents, as we used them creating the regex. */
/* Do not include this section in the link. */
sec->flags |= SEC_EXCLUDE;
}
! lreg = lang_new_vers_pattern (NULL, "*", NULL, FALSE);
lang_register_vers_node (command_line.version_exports_section,
lang_new_vers_node (greg, lreg), NULL);
}
void
Index: ldlang.h
===================================================================
RCS file: /cvs/src/src/ld/ldlang.h,v
retrieving revision 1.53
diff -c -5 -p -r1.53 ldlang.h
*** ldlang.h 30 Sep 2005 17:45:46 -0000 1.53
--- ldlang.h 13 Oct 2005 17:26:16 -0000
*************** extern void lang_leave_overlay
*** 584,594 ****
lang_output_section_phdr_list *, const char *);
extern struct bfd_elf_version_tree *lang_elf_version_info;
extern struct bfd_elf_version_expr *lang_new_vers_pattern
! (struct bfd_elf_version_expr *, const char *, const char *);
extern struct bfd_elf_version_tree *lang_new_vers_node
(struct bfd_elf_version_expr *, struct bfd_elf_version_expr *);
extern struct bfd_elf_version_deps *lang_add_vers_depend
(struct bfd_elf_version_deps *, const char *);
extern void lang_register_vers_node
--- 584,594 ----
lang_output_section_phdr_list *, const char *);
extern struct bfd_elf_version_tree *lang_elf_version_info;
extern struct bfd_elf_version_expr *lang_new_vers_pattern
! (struct bfd_elf_version_expr *, const char *, const char *, bfd_boolean);
extern struct bfd_elf_version_tree *lang_new_vers_node
(struct bfd_elf_version_expr *, struct bfd_elf_version_expr *);
extern struct bfd_elf_version_deps *lang_add_vers_depend
(struct bfd_elf_version_deps *, const char *);
extern void lang_register_vers_node
Index: testsuite/ld-elfvers/vers.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-elfvers/vers.exp,v
retrieving revision 1.38
diff -c -5 -p -r1.38 vers.exp
*** testsuite/ld-elfvers/vers.exp 17 Aug 2005 10:08:30 -0000 1.38
--- testsuite/ld-elfvers/vers.exp 13 Oct 2005 17:26:17 -0000
*************** build_vers_lib_pic "vers28c" vers28c.c v
*** 962,966 ****
--- 962,969 ----
build_vers_lib_pic_flags "vers29" vers29.c vers29 "" "" vers29.ver vers29.dsym "" "--default-symver"
# Test #30 - test handling of symbol names global, local and extern in the
# version script.
build_vers_lib_pic "vers30" vers30.c vers30 "" vers30.map vers30.ver vers30.dsym ""
+
+ # Test #31 -- quoted strings in version sections.
+ build_vers_lib_pic "vers31" vers31.c vers31 "" vers31.map vers31.ver vers31.dsym ""
Index: testsuite/ld-elfvers/vers31.c
===================================================================
RCS file: testsuite/ld-elfvers/vers31.c
diff -N testsuite/ld-elfvers/vers31.c
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/ld-elfvers/vers31.c 13 Oct 2005 17:26:17 -0000
***************
*** 0 ****
--- 1,6 ----
+ /* void f<int [3], char>(int (*) [3], char) */
+ void _Z1fIA3_icEvPT_T0_() {}
+
+ /* void f<double [3], long>(double (*) [3], long) */
+ void _Z1fIA3_dlEvPT_T0_() {}
+
Index: testsuite/ld-elfvers/vers31.dsym
===================================================================
RCS file: testsuite/ld-elfvers/vers31.dsym
diff -N testsuite/ld-elfvers/vers31.dsym
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/ld-elfvers/vers31.dsym 13 Oct 2005 17:26:17 -0000
***************
*** 0 ****
--- 1,2 ----
+ [0]* g DO \*ABS\* [0]* VERS_31.0 VERS_31.0
+ [0-9a-f]* g DF (.text|\*ABS\*) [0-9a-f]* VERS_31.0 _Z1fIA3_icEvPT_T0
Index: testsuite/ld-elfvers/vers31.map
===================================================================
RCS file: testsuite/ld-elfvers/vers31.map
diff -N testsuite/ld-elfvers/vers31.map
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/ld-elfvers/vers31.map 13 Oct 2005 17:26:17 -0000
***************
*** 0 ****
--- 1,5 ----
+ VERS_31.0 {
+ extern "C++" {
+ "void f<int [3], char>(int (*) [3], char)";
+ };
+ };
Index: testsuite/ld-elfvers/vers31.ver
===================================================================
RCS file: testsuite/ld-elfvers/vers31.ver
diff -N testsuite/ld-elfvers/vers31.ver
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/ld-elfvers/vers31.ver 13 Oct 2005 17:26:17 -0000
***************
*** 0 ****
--- 1,3 ----
+ Version definitions:
+ 1 0x01 0x0966595f vers31.so
+ 2 0x00 0x07923ab0 VERS_31.0