Bug 1077366 - Remove most symbol wrapping from Android builds. r=nfroyd
authorMike Hommey <mh+mozilla@glandium.org>
Tue, 14 Oct 2014 07:17:13 +0900
changeset 210256 b1deaba82ee2a152841cf9e1fbca2ae8584f5452
parent 210255 a3ea5b08baba6e217386d0b452366d12093bfab9
child 210257 03f12339a48514c7c600212976291568a71df029
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersnfroyd
bugs1077366
milestone35.0a1
Bug 1077366 - Remove most symbol wrapping from Android builds. r=nfroyd Since essentially everything is linked to libmozglue and libmozglue takes precedence in symbol resolution in our dynamic linker, there is no need to wrap most symbols. PR_GetEnv/PR_SetEnv still needs wrapping because there's no other way to actually wrap the calls from NSPR itself and NSS, as well as the symbols wrapped because our dynamic linker can't find them in system libraries on some devices because they're weak.
config/config.mk
configure.in
memory/build/mozmemory_wrap.h
memory/mozalloc/VolatileBufferAshmem.cpp
mozglue/build/BionicGlue.cpp
mozglue/build/Makefile.in
other-licenses/android/getaddrinfo.c
--- a/config/config.mk
+++ b/config/config.mk
@@ -670,20 +670,29 @@ ifneq ($(OS_ARCH),Darwin)
 CHECK_STDCXX = @$(TOOLCHAIN_PREFIX)objdump -p $(1) | grep -v -e 'GLIBCXX_3\.4\.\(9\|[1-9][0-9]\)' > /dev/null || ( echo 'TEST-UNEXPECTED-FAIL | check_stdcxx | We do not want these libstdc++ symbols to be used:' && $(TOOLCHAIN_PREFIX)objdump -T $(1) | grep -e 'GLIBCXX_3\.4\.\(9\|[1-9][0-9]\)' && false)
 endif
 endif
 
 ifeq (,$(filter $(OS_TARGET),WINNT Darwin))
 CHECK_TEXTREL = @$(TOOLCHAIN_PREFIX)readelf -d $(1) | grep TEXTREL > /dev/null && echo 'TEST-UNEXPECTED-FAIL | check_textrel | We do not want text relocations in libraries and programs' || true
 endif
 
+ifeq ($(MOZ_WIDGET_TOOLKIT),android)
+# While this is very unlikely (libc being added by the compiler at the end
+# of the linker command line), if libmozglue.so ends up after libc.so, all
+# hell breaks loose, so better safe than sorry, and check it's actually the
+# case.
+CHECK_MOZGLUE_ORDER = @$(TOOLCHAIN_PREFIX)readelf -d $(1) | grep NEEDED | awk '{ libs[$$NF] = ++n } END { if (libs["[libmozglue.so]"] && libs["[libc.so]"] < libs["[libmozglue.so]"]) { print "libmozglue.so must be linked before libc.so"; exit 1 } }'
+endif
+
 define CHECK_BINARY
 $(call CHECK_STDCXX,$(1))
 $(call CHECK_TEXTREL,$(1))
 $(call LOCAL_CHECKS,$(1))
+$(call CHECK_MOZGLUE_ORDER,$(1))
 endef
 
 # autoconf.mk sets OBJ_SUFFIX to an error to avoid use before including
 # this file
 OBJ_SUFFIX := $(_OBJ_SUFFIX)
 
 # PGO builds with GCC build objects with instrumentation in a first pass,
 # then objects optimized, without instrumentation, in a second pass. If
--- a/configure.in
+++ b/configure.in
@@ -7187,19 +7187,17 @@ else
     AC_DEFINE(MOZ_MEMORY_DARWIN)
     ;;
   *-*freebsd*)
     AC_DEFINE(MOZ_MEMORY_BSD)
     ;;
   *-android*|*-linuxandroid*)
     AC_DEFINE(MOZ_MEMORY_LINUX)
     AC_DEFINE(MOZ_MEMORY_ANDROID)
-    if test -z "$gonkdir"; then
-      _WRAP_MALLOC=1
-    else
+    if test -n "$gonkdir"; then
       AC_DEFINE(MOZ_MEMORY_GONK)
     fi
     MOZ_GLUE_LDFLAGS=
     ;;
   *-*linux*)
     AC_DEFINE(MOZ_MEMORY_LINUX)
     ;;
   *-netbsd*)
@@ -7238,21 +7236,17 @@ AC_SUBST_LIST(WIN32_CRT_LIBS)
 dnl Need to set this for make because NSS doesn't have configure
 AC_SUBST(DLLFLAGS)
 
 dnl We need to wrap dlopen and related functions on Android because we use
 dnl our own linker.
 if test "$OS_TARGET" = Android; then
     WRAP_LDFLAGS="${WRAP_LDFLAGS} -L$_objdir/dist/lib -lmozglue"
     WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=PR_GetEnv,--wrap=PR_SetEnv"
-    if test "$MOZ_WIDGET_TOOLKIT" = android; then
-        WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=getaddrinfo,--wrap=freeaddrinfo,--wrap=gai_strerror"
-    fi
     if test -z "$gonkdir"; then
-        WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=fork,--wrap=pthread_atfork,--wrap=raise"
         WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=memccpy,--wrap=memchr,--wrap=memrchr,--wrap=memcmp,--wrap=memcpy,--wrap=memmove,--wrap=memset,--wrap=memmem,--wrap=index,--wrap=strchr,--wrap=strrchr,--wrap=strlen,--wrap=strcmp,--wrap=strcpy,--wrap=strcat,--wrap=strcasecmp,--wrap=strncasecmp,--wrap=strstr,--wrap=strcasestr,--wrap=strtok,--wrap=strtok_r,--wrap=strerror,--wrap=strerror_r,--wrap=strnlen,--wrap=strncat,--wrap=strncmp,--wrap=strncpy,--wrap=strlcat,--wrap=strlcpy,--wrap=strcspn,--wrap=strpbrk,--wrap=strsep,--wrap=strspn,--wrap=strcoll,--wrap=strxfrm"
     fi
     if test "$MOZ_WIDGET_TOOLKIT" = gonk -a -n "$MOZ_NUWA_PROCESS"; then
         WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=pthread_create,--wrap=epoll_wait,--wrap=poll,--wrap=pthread_cond_timedwait,--wrap=__pthread_cond_timedwait,--wrap=pthread_cond_wait,--wrap=epoll_create,--wrap=epoll_ctl,--wrap=close,--wrap=pthread_key_create,--wrap=pthread_key_delete,--wrap=socketpair,--wrap=pthread_self,--wrap=pthread_mutex_lock,--wrap=pthread_join,--wrap=pipe,--wrap=pipe2,--wrap=tgkill"
     fi
 fi
 
 dnl ========================================================
--- a/memory/build/mozmemory_wrap.h
+++ b/memory/build/mozmemory_wrap.h
@@ -54,39 +54,36 @@
  * - On MacOSX, the system libc has a zone allocator, which allows us to
  *   hook custom malloc implementation functions without exporting them.
  *   The malloc implementation functions are all prefixed with "je_" and used
  *   this way from the custom zone allocator. They are not exported.
  *   Duplication functions are not included, since they will call the custom
  *   zone allocator anyways. Jemalloc-specific functions are also left
  *   unprefixed.
  *
- * - On Android, both malloc implementation and duplication functions are
- *   prefixed with "__wrap_". Additionally, C++ allocation functions
- *   (operator new/delete) are also exported and prefixed with "__wrap_".
- *   Jemalloc specific functions are left unprefixed.
- *
- * - On Gonk, all functions are left unprefixed. Additionally, C++ allocation
- *   functions (operator new/delete) are also exported and unprefixed.
+ * - On Android and Gonk, all functions are left unprefixed. Additionally,
+ *   C++ allocation functions (operator new/delete) are also exported and
+ *   unprefixed.
  *
  * - On other systems (mostly Linux), all functions are left unprefixed.
  *
  * Only Android and Gonk add C++ allocation functions.
  *
  * Proper exporting of the various functions is done with the MOZ_MEMORY_API
  * and MOZ_JEMALLOC_API macros. MOZ_MEMORY_API is meant to be used for malloc
  * implementation and duplication functions, while MOZ_JEMALLOC_API is
  * dedicated to jemalloc specific functions.
  *
  *
  * All these functions are meant to be called with no prefix from Gecko code.
  * In most cases, this is because that's how they are available at runtime.
- * However, on Android, "__wrap_" prefixing is left to the build-time linker
- * (with -Wl,--wrap), or to the mozmemory.h header for malloc_good_size and
- * jemalloc specific functions.
+ * However, on Android, this relies on faulty.lib (the custom dynamic linker)
+ * resolving mozglue symbols before libc symbols, which is guaranteed by the
+ * way faulty.lib works (it respects the DT_NEEDED order, and libc always
+ * appears after mozglue ; which we double check when building anyways)
  *
  *
  * Within libmozglue (when MOZ_MEMORY_IMPL is defined), all the functions
  * should be suffixed with "_impl" both for declarations and use.
  * That is, the implementation declaration for e.g. strdup would look like:
  *   char* strdup_impl(const char *)
  * That implementation would call malloc by using "malloc_impl".
  *
@@ -152,23 +149,16 @@
 #        endif
 #      endif
 #    endif
 #    ifdef XP_WIN
 #      define mozmem_dup_impl(a)      wrap_ ## a
 #    endif
 #  endif
 
-#  if defined(MOZ_WIDGET_ANDROID)
-#    ifndef mozmem_malloc_impl
-#      define mozmem_malloc_impl(a)   __wrap_ ## a
-#    endif
-#    define mozmem_dup_impl(a)      __wrap_ ## a
-#  endif
-
 /* All other jemalloc3 functions are prefixed with "je_", except when
  * building against an unprefixed system jemalloc library */
 #  define je_(a) je_ ## a
 #else /* defined(MOZ_NATIVE_JEMALLOC) */
 #  define je_(a) a
 #endif
 
 #if !defined(MOZ_MEMORY_IMPL) || defined(MOZ_NATIVE_JEMALLOC)
--- a/memory/mozalloc/VolatileBufferAshmem.cpp
+++ b/memory/mozalloc/VolatileBufferAshmem.cpp
@@ -10,22 +10,18 @@
 #include <fcntl.h>
 #include <linux/ashmem.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
 
 #ifdef MOZ_MEMORY
-#ifdef MOZ_WIDGET_ANDROID
-extern "C" int __wrap_posix_memalign(void** memptr, size_t alignment, size_t size);
-#else
 extern "C" int posix_memalign(void** memptr, size_t alignment, size_t size);
 #endif
-#endif
 
 #define MIN_VOLATILE_ALLOC_SIZE 8192
 
 namespace mozilla {
 
 VolatileBuffer::VolatileBuffer()
   : mBuf(nullptr)
   , mSize(0)
@@ -63,21 +59,17 @@ VolatileBuffer::Init(size_t aSize, size_
 heap_alloc:
   mBuf = nullptr;
   if (mFd >= 0) {
     close(mFd);
     mFd = -1;
   }
 
 #ifdef MOZ_MEMORY
-#ifdef MOZ_WIDGET_ANDROID
-  __wrap_posix_memalign(&mBuf, aAlignment, aSize);
-#else
   posix_memalign(&mBuf, aAlignment, aSize);
-#endif
 #else
   mBuf = memalign(aAlignment, aSize);
 #endif
   return !!mBuf;
 }
 
 VolatileBuffer::~VolatileBuffer()
 {
--- a/mozglue/build/BionicGlue.cpp
+++ b/mozglue/build/BionicGlue.cpp
@@ -61,51 +61,49 @@ private:
   bool bufUsed;
 };
 
 static std::vector<AtForkFuncs, SpecialAllocator<AtForkFuncs> > atfork;
 #endif
 
 #ifdef MOZ_WIDGET_GONK
 #include "cpuacct.h"
-#define WRAP(x) x
 
 #if ANDROID_VERSION < 17 || defined(MOZ_WIDGET_ANDROID)
 extern "C" NS_EXPORT int
 timer_create(clockid_t, struct sigevent*, timer_t*)
 {
   __android_log_print(ANDROID_LOG_ERROR, "BionicGlue", "timer_create not supported!");
   abort();
   return -1;
 }
 #endif
 
 #else
 #define cpuacct_add(x)
-#define WRAP(x) __wrap_##x
 #endif
 
 #if ANDROID_VERSION < 17 || defined(MOZ_WIDGET_ANDROID)
 extern "C" NS_EXPORT int
-WRAP(pthread_atfork)(void (*prepare)(void), void (*parent)(void), void (*child)(void))
+pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void))
 {
   AtForkFuncs funcs;
   funcs.prepare = prepare;
   funcs.parent = parent;
   funcs.child = child;
   if (!atfork.capacity())
     atfork.reserve(1);
   atfork.push_back(funcs);
   return 0;
 }
 
 extern "C" NS_EXPORT pid_t __fork(void);
 
 extern "C" NS_EXPORT pid_t
-WRAP(fork)(void)
+fork(void)
 {
   pid_t pid;
   for (auto it = atfork.rbegin();
        it < atfork.rend(); ++it)
     if (it->prepare)
       it->prepare();
 
   switch ((pid = syscall(__NR_clone, SIGCHLD, NULL, NULL, NULL, NULL))) {
@@ -122,17 +120,17 @@ WRAP(fork)(void)
       if (it->parent)
         it->parent();
   }
   return pid;
 }
 #endif
 
 extern "C" NS_EXPORT int
-WRAP(raise)(int sig)
+raise(int sig)
 {
   // Bug 741272: Bionic incorrectly uses kill(), which signals the
   // process, and thus could signal another thread (and let this one
   // return "successfully" from raising a fatal signal).
   //
   // Bug 943170: POSIX specifies pthread_kill(pthread_self(), sig) as
   // equivalent to raise(sig), but Bionic also has a bug with these
   // functions, where a forked child will kill its parent instead.
--- a/mozglue/build/Makefile.in
+++ b/mozglue/build/Makefile.in
@@ -44,21 +44,16 @@ OS_LDFLAGS += \
 ifneq ($(MOZ_REPLACE_MALLOC_LINKAGE),compiler support)
 OS_LDFLAGS += -flat_namespace
 endif
 ifeq ($(MOZ_REPLACE_MALLOC_LINKAGE),dummy library)
 OS_LDFLAGS += -Wl,-weak_library,$(DEPTH)/memory/replace/dummy/$(DLL_PREFIX)replace_malloc$(DLL_SUFFIX)
 endif
 endif
 
-ifeq (android, $(MOZ_WIDGET_TOOLKIT))
-# To properly wrap jemalloc's pthread_atfork call.
-OS_LDFLAGS += -Wl,--wrap=pthread_atfork
-endif
-
 ifdef MOZ_LINKER
 ifeq (arm, $(TARGET_CPU))
 OS_LDFLAGS += -Wl,-version-script,$(srcdir)/arm-eabi-filter
 endif
 
 endif
 
 ifeq (Android, $(OS_TARGET))
--- a/other-licenses/android/getaddrinfo.c
+++ b/other-licenses/android/getaddrinfo.c
@@ -402,21 +402,21 @@ do { 								\
 	((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || 	\
 	    (y) == PF_UNSPEC)))
 #define MATCH(x, y, w) 							\
 	((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
 
 #pragma GCC visibility push(default)
 
 extern const char *
-__wrap_gai_strerror(int ecode);
+gai_strerror(int ecode);
 extern void
-__wrap_freeaddrinfo(struct addrinfo *ai);
+freeaddrinfo(struct addrinfo *ai);
 extern int
-__wrap_getaddrinfo(const char *hostname, const char *servname,
+getaddrinfo(const char *hostname, const char *servname,
     const struct addrinfo *hints, struct addrinfo **res);
 
 int android_sdk_version;
 
 #pragma GCC visibility pop
 
 int android_sdk_version = -1;
 
@@ -426,27 +426,27 @@ static int honeycomb_or_later()
 	__android_log_print(ANDROID_LOG_INFO, "getaddrinfo",
 		"I am%s Honeycomb\n",
 		(android_sdk_version >= 11) ? "" : " not");
 #endif
 	return android_sdk_version >= 11;
 }
 
 const char *
-__wrap_gai_strerror(int ecode)
+gai_strerror(int ecode)
 {
 	if (honeycomb_or_later())
 		return gai_strerror(ecode);
 	if (ecode < 0 || ecode > EAI_MAX)
 		ecode = EAI_MAX;
 	return ai_errlist[ecode];
 }
 
 void
-__wrap_freeaddrinfo(struct addrinfo *ai)
+freeaddrinfo(struct addrinfo *ai)
 {
 	struct addrinfo *next;
 
 	if (honeycomb_or_later()) {
 		freeaddrinfo(ai);
 		return;
 	}
 
@@ -528,17 +528,17 @@ static int
 		.sin_family = AF_INET,
 		.sin_addr.s_addr = __constant_htonl(0x08080808L)  // 8.8.8.8
 	};
         sockaddr_union addr = { .in = sin_test };
         return _test_connect(PF_INET, &addr.generic, sizeof(addr.in));
 }
 
 int
-__wrap_getaddrinfo(const char *hostname, const char *servname,
+getaddrinfo(const char *hostname, const char *servname,
     const struct addrinfo *hints, struct addrinfo **res)
 {
 	struct addrinfo sentinel;
 	struct addrinfo *cur;
 	int error = 0;
 	struct addrinfo ai;
 	struct addrinfo ai0;
 	struct addrinfo *pai;
@@ -726,17 +726,17 @@ int
 			*res = sentinel.ai_next;
 			return SUCCESS;
 		} else
 			error = EAI_FAIL;
 	}
  free:
  bad:
 	if (sentinel.ai_next)
-		__wrap_freeaddrinfo(sentinel.ai_next);
+		freeaddrinfo(sentinel.ai_next);
 	*res = NULL;
 	return error;
 }
 
 /*
  * FQDN hostname, DNS lookup
  */
 static int
@@ -787,17 +787,17 @@ explore_fqdn(const struct addrinfo *pai,
 	}
 
 	*res = result;
 
 	return 0;
 
 free:
 	if (result)
-		__wrap_freeaddrinfo(result);
+		freeaddrinfo(result);
 	return error;
 }
 
 /*
  * hostname == NULL.
  * passive socket -> anyaddr (0.0.0.0 or ::)
  * non-passive socket -> localhost (127.0.0.1 or ::1)
  */
@@ -855,17 +855,17 @@ explore_null(const struct addrinfo *pai,
 	}
 	cur = cur->ai_next;
 
 	*res = sentinel.ai_next;
 	return 0;
 
 free:
 	if (sentinel.ai_next)
-		__wrap_freeaddrinfo(sentinel.ai_next);
+		freeaddrinfo(sentinel.ai_next);
 	return error;
 }
 
 /*
  * numeric hostname
  */
 static int
 explore_numeric(const struct addrinfo *pai, const char *hostname,
@@ -942,17 +942,17 @@ explore_numeric(const struct addrinfo *p
 	}
 
 	*res = sentinel.ai_next;
 	return 0;
 
 free:
 bad:
 	if (sentinel.ai_next)
-		__wrap_freeaddrinfo(sentinel.ai_next);
+		freeaddrinfo(sentinel.ai_next);
 	return error;
 }
 
 /*
  * numeric hostname with scope
  */
 static int
 explore_numeric_scope(const struct addrinfo *pai, const char *hostname,
@@ -2000,26 +2000,26 @@ static struct addrinfo *
 		if (strcasecmp(name, tname) == 0)
 			goto found;
 	}
 	goto again;
 
 found:
 	hints = *pai;
 	hints.ai_flags = AI_NUMERICHOST;
-	error = __wrap_getaddrinfo(addr, NULL, &hints, &res0);
+	error = getaddrinfo(addr, NULL, &hints, &res0);
 	if (error)
 		goto again;
 	for (res = res0; res; res = res->ai_next) {
 		/* cover it up */
 		res->ai_flags = pai->ai_flags;
 
 		if (pai->ai_flags & AI_CANONNAME) {
 			if (get_canonname(pai, res, cname) != 0) {
-				__wrap_freeaddrinfo(res0);
+				freeaddrinfo(res0);
 				goto again;
 			}
 		}
 	}
 	return res0;
 }
 
 /*ARGSUSED*/