This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]