Merge "change argument type in madvise"
diff --git a/build/run-on-host.mk b/build/run-on-host.mk
index f016361..dc7e5d5 100644
--- a/build/run-on-host.mk
+++ b/build/run-on-host.mk
@@ -14,6 +14,10 @@
 # limitations under the License.
 #
 
+# Include once
+ifneq ($(bionic_run_on_host_mk_included),true)
+bionic_run_on_host_mk_included:=true
+
 ifneq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),arm mips x86))
 LINKER = linker64
 else
@@ -37,3 +41,4 @@
 	  ln -fs `realpath $(TARGET_OUT)/lib64` /system/; \
 	fi
 endif
+endif
diff --git a/libc/arch-arm64/include/machine/endian.h b/libc/arch-arm64/include/machine/endian.h
index 4743733..b9544af 100644
--- a/libc/arch-arm64/include/machine/endian.h
+++ b/libc/arch-arm64/include/machine/endian.h
@@ -31,13 +31,8 @@
 
 #ifdef __GNUC__
 
-#define __swap16md(x) ({                                        \
-    register u_int16_t _x = (x);                                \
-    __asm volatile ("rev16 %0, %0" : "+r" (_x));                \
-    _x;                                                         \
-})
-
 /* Use GCC builtins */
+#define __swap16md(x) __builtin_bswap16(x)
 #define __swap32md(x) __builtin_bswap32(x)
 #define __swap64md(x) __builtin_bswap64(x)
 
diff --git a/libc/arch-x86/include/machine/endian.h b/libc/arch-x86/include/machine/endian.h
index e1506b1..5feebd8 100644
--- a/libc/arch-x86/include/machine/endian.h
+++ b/libc/arch-x86/include/machine/endian.h
@@ -27,33 +27,14 @@
 #ifndef _MACHINE_ENDIAN_H_
 #define _MACHINE_ENDIAN_H_
 
-#ifdef __GNUC__
-
-#define	__swap32md(x) __statement({					\
-	uint32_t __swap32md_x = (x);					\
-									\
-	__asm ("bswap %0" : "+r" (__swap32md_x));			\
-	__swap32md_x;							\
-})
-
-#define	__swap64md(x) __statement({					\
-	uint64_t __swap64md_x = (x);					\
-									\
-	(uint64_t)__swap32md(__swap64md_x >> 32) |			\
-	    (uint64_t)__swap32md(__swap64md_x & 0xffffffff) << 32;	\
-})
-#define	__swap16md(x) __statement({					\
-	uint16_t __swap16md_x = (x);					\
-									\
-	__asm ("rorw $8, %w0" : "+r" (__swap16md_x));			\
-	__swap16md_x;							\
-})
+/* Use GCC builtins */
+#define __swap16md(x) __builtin_bswap16(x)
+#define __swap32md(x) __builtin_bswap32(x)
+#define __swap64md(x) __builtin_bswap64(x)
 
 /* Tell sys/endian.h we have MD variants of the swap macros.  */
 #define MD_SWAP
 
-#endif	/* __GNUC__ */
-
 #define _BYTE_ORDER _LITTLE_ENDIAN
 #include <sys/types.h>
 #include <sys/endian.h>
diff --git a/libc/arch-x86_64/include/machine/endian.h b/libc/arch-x86_64/include/machine/endian.h
index 8a3b0c5..2c493b2 100644
--- a/libc/arch-x86_64/include/machine/endian.h
+++ b/libc/arch-x86_64/include/machine/endian.h
@@ -27,34 +27,14 @@
 #ifndef _MACHINE_ENDIAN_H_
 #define _MACHINE_ENDIAN_H_
 
-#ifdef __GNUC__
-
-#define	__swap32md(x) __statement({					\
-	u_int32_t __swap32md_x = (x);					\
-									\
-	__asm ("bswap %0" : "+r" (__swap32md_x));			\
-	__swap32md_x;							\
-})
-
-#define	__swap64md(x) __statement({					\
-	u_int64_t __swap64md_x = (x);					\
-									\
-	__asm ("bswapq %0" : "+r" (__swap64md_x));			\
-	__swap64md_x;							\
-})
-
-#define	__swap16md(x) __statement({					\
-	u_int16_t __swap16md_x = (x);					\
-									\
-	__asm ("rorw $8, %w0" : "+r" (__swap16md_x));			\
-	__swap16md_x;							\
-})
+/* Use GCC builtins */
+#define __swap16md(x) __builtin_bswap16(x)
+#define __swap32md(x) __builtin_bswap32(x)
+#define __swap64md(x) __builtin_bswap64(x)
 
 /* Tell sys/endian.h we have MD variants of the swap macros.  */
 #define MD_SWAP
 
-#endif	/* __GNUC__ */
-
 #define _BYTE_ORDER _LITTLE_ENDIAN
 #include <sys/types.h>
 #include <sys/endian.h>
diff --git a/linker/linker.cpp b/linker/linker.cpp
index b2e7464..3409931 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -320,7 +320,7 @@
 
   if (trav == nullptr) {
     // si was not in solist
-    DL_ERR("name \"%s\" is not in solist!", si->name);
+    DL_ERR("name \"%s\"@%p is not in solist!", si->name, si);
     return;
   }
 
@@ -1150,20 +1150,29 @@
     soinfo* si = nullptr;
 
     while ((si = depth_first_list.pop_front()) != nullptr) {
+      if (local_unload_list.contains(si)) {
+        continue;
+      }
+
       local_unload_list.push_back(si);
+
       if (si->has_min_version(0)) {
         soinfo* child = nullptr;
         while ((child = si->get_children().pop_front()) != nullptr) {
-          TRACE("%s needs to unload %s", si->name, child->name);
+          TRACE("%s@%p needs to unload %s@%p", si->name, si, child->name, child);
           if (local_unload_list.contains(child)) {
             continue;
-          } else if (child->get_local_group_root() != root) {
+          } else if (child->is_linked() && child->get_local_group_root() != root) {
             external_unload_list.push_back(child);
           } else {
             depth_first_list.push_front(child);
           }
         }
       } else {
+#ifdef __LP64__
+        __libc_fatal("soinfo for \"%s\"@%p has no version", si->name, si);
+#else
+        PRINT("warning: soinfo for \"%s\"@%p has no version", si->name, si);
         for_each_dt_needed(si, [&] (const char* library_name) {
           TRACE("deprecated (old format of soinfo): %s needs to unload %s", si->name, library_name);
           soinfo* needed = find_library(library_name, RTLD_NOLOAD, nullptr);
@@ -1175,7 +1184,7 @@
           } else if (local_unload_list.contains(needed)) {
             // already visited
             return;
-          } else if (needed->get_local_group_root() != root) {
+          } else if (needed->is_linked() && needed->get_local_group_root() != root) {
             // external group
             external_unload_list.push_back(needed);
           } else {
@@ -1183,6 +1192,7 @@
             depth_first_list.push_front(needed);
           }
         });
+#endif
       }
     }