This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
PATCH: Add double-quoted version strings
- From: Mark Mitchell <mark at codesourcery dot com>
- To: binutils at sources dot redhat dot com
- Date: Wed, 12 Oct 2005 18:07:01 -0700
- Subject: PATCH: Add double-quoted version strings
- Reply-to: mark at codesourcery dot com
GNU ld supports the extern "C++" syntax in version files so that you
can specify un-mangled names for C++ identifiers. However, at present
its difficult to use that facility in all cases. For example, you
cannot specify a space in such a name, and a "*" will be interpreted
as a wildcard character, not as the literal "*" in a demangled name
like "f(int *)".
This patch permits double-quoted strings to be used in the version
script, with the semantics that double-quoted strings are interpreted
literally, not as glob patterns.
OK?
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2005-10-12 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-12 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 00:59:36 -0000
*************** VERS_1.2 @{
*** 4287,4296 ****
--- 4292,4305 ----
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 ****
--- 4307,4318 ----
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}.
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 00:59:36 -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 00:59:37 -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 00:59:37 -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 00:59:38 -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 00:59:38 -0000
***************
*** 0 ****
--- 1,6 ----
+ /* int f<int, char>(int, char) */
+ void _Z1fIicET_S0_T0_() {}
+
+ /* double f<double, long>(double, long) */
+ void _Z1fIdlET_S0_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 00:59:38 -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 _Z1fIicET_S0_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 00:59:38 -0000
***************
*** 0 ****
--- 1,5 ----
+ VERS_31.0 {
+ extern "C++" {
+ "int f<int, char>(int, 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 00:59:38 -0000
***************
*** 0 ****
--- 1,3 ----
+ Version definitions:
+ 1 0x01 0x0966595f vers31.so
+ 2 0x00 0x07923ab0 VERS_31.0