diff mbox

locale: Make _nl_C_locobj_ptr usable outside of libc

Message ID 0c665fea-79ba-88df-af1f-4494ffd06b12@redhat.com
State New
Headers show

Commit Message

Florian Weimer Sept. 16, 2016, 11:53 a.m. UTC
I need something like this to fix incorrect locale dependence in 
libresolv (bug 19687).

I tested this with the fixes, including one for nscd, which uses
__libc_C_locobj@GLIBC_PRIVATE.  libresolv uses _nl_C_locobj@GLIBC_PRIVATE.

I'm not entirely sure if we should use the function approach everywhere 
instead.  But as far as I can tell, this patch does not lead to the 
allocation of space for a _nl_C_locobj copy in libresolv (which we would 
not want because it is wasteful).

An alternative would add of functions such as those in <ctype.h> and 
strcasecmp/strncasecmp which are always tied to the C locale.  This 
would be more efficient because access to the locale object is easier, 
or the variants can even be optimized inline (such as isblank).

Thanks,
Florian
diff mbox

Patch

locale: Make _nl_C_locobj_ptr usable outside of libc

To avoid a copy relocation if the access happens from the main program,
the __libc_C_locobj function returns a pointer to the hidden locale
object in libc.

2016-09-16  Florian Weimer  <fweimer@redhat.com>

	* include/locale.h (__libc_C_locobj): Declare.
	[IS_IN (libc) || SHARED] (_nl_C_locobj): Export and add hidden
	alias.
	[!IS_IN (libc) && !SHARED] (_nl_C_locobj_ptr): Call
	__libc_C_locobj.
	* locale/xlocale.c (_nl_C_locobj): Export and add hidden alias.
	* locale/Makefile (routines): Add C_locobj.
	(shared-only-routines): Likewise.
	* locale/C_locobj.c: New file.
	* locale/Versions (GLIBC_PRIVATE): Add _nl_C_locobj and
	__libc_C_locobj.

diff --git a/include/locale.h b/include/locale.h
index 8091e1d..68425f9 100644
--- a/include/locale.h
+++ b/include/locale.h
@@ -13,8 +13,15 @@  libc_hidden_proto (__uselocale)
 extern struct loaded_l10nfile *_nl_locale_file_list[] attribute_hidden;
 
 /* Locale object for C locale.  */
-extern const struct __locale_struct _nl_C_locobj attribute_hidden;
-#define _nl_C_locobj_ptr ((struct __locale_struct *) &_nl_C_locobj)
+struct __locale_struct *__libc_C_locobj (void)
+     __attribute__ ((const)) internal_function;
+# if IS_IN (libc) || defined SHARED
+extern const struct __locale_struct _nl_C_locobj;
+libc_hidden_proto (_nl_C_locobj)
+#  define _nl_C_locobj_ptr ((struct __locale_struct *) &_nl_C_locobj)
+# else
+#  define _nl_C_locobj_ptr __libc_C_locobj ()
+# endif
 
 /* Now define the internal interfaces.  */
 extern struct lconv *__localeconv (void);
diff --git a/locale/C_locobj.c b/locale/C_locobj.c
new file mode 100644
index 0000000..ae80abf
--- /dev/null
+++ b/locale/C_locobj.c
@@ -0,0 +1,26 @@ 
+/* Access to the C locale object outside of libc.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <locale.h>
+
+__attribute__ ((const)) internal_function
+struct __locale_struct *
+__libc_C_locobj (void)
+{
+  return _nl_C_locobj_ptr;
+}
diff --git a/locale/Makefile b/locale/Makefile
index c5379e6..784a2c6 100644
--- a/locale/Makefile
+++ b/locale/Makefile
@@ -25,7 +25,8 @@  include ../Makeconfig
 headers		= locale.h bits/locale.h langinfo.h xlocale.h
 routines	= setlocale findlocale loadlocale loadarchive \
 		  localeconv nl_langinfo nl_langinfo_l mb_cur_max \
-		  newlocale duplocale freelocale uselocale
+		  newlocale duplocale freelocale uselocale C_locobj
+shared-only-routines = C_locobj
 tests		= tst-C-locale tst-locname tst-duplocale
 categories	= ctype messages monetary numeric time paper name \
 		  address telephone measurement identification collate
diff --git a/locale/Versions b/locale/Versions
index 7211934..d2a3d37 100644
--- a/locale/Versions
+++ b/locale/Versions
@@ -70,5 +70,8 @@  libc {
     # global variables
     __collate_element_hash; __collate_element_strings;
     __collate_symbol_classes; __collate_symbol_hash; __collate_symbol_strings;
+
+    # Access to the C locale objects for other parts of glibc.
+    _nl_C_locobj; __libc_C_locobj;
   }
 }
diff --git a/locale/xlocale.c b/locale/xlocale.c
index 18faaf1..10f760a 100644
--- a/locale/xlocale.c
+++ b/locale/xlocale.c
@@ -31,7 +31,7 @@  extern const char _nl_C_LC_CTYPE_toupper[] attribute_hidden;
 extern const char _nl_C_LC_CTYPE_tolower[] attribute_hidden;
 
 
-const struct __locale_struct _nl_C_locobj attribute_hidden =
+const struct __locale_struct _nl_C_locobj =
   {
     .__locales =
     {
@@ -52,3 +52,5 @@  const struct __locale_struct _nl_C_locobj attribute_hidden =
     .__ctype_tolower = (const int *) _nl_C_LC_CTYPE_tolower + 128,
     .__ctype_toupper = (const int *) _nl_C_LC_CTYPE_toupper + 128
   };
+
+libc_hidden_data_def (_nl_C_locobj)