Make libdl.so be loaded after libc.so

Make sure that libdl is always after libc on the command line.
Simplifies the logic to always support system_shared_libs for
sdk and vndk builds.

For backwards compatibility without updating lots of Android.bp
files, allow libdl to be listed in shared_libs as long as it
is also in system_shared_libs or libc is not in system_shared_libs.

Remove all the places that libdl is added as a dependency, since
it will always be present unless explicitly removed now.

Bug: 62815515
Test: m -j checkbuild
Merged-In: I0233178ffea87a2f0b82190746022476304a68e2
Change-Id: I0233178ffea87a2f0b82190746022476304a68e2
(cherry picked from commit ef88ae2369aa9a097941bf1bff7823589ffc819f)
diff --git a/cc/linker.go b/cc/linker.go
index 5250d2d..79b80fa 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -48,8 +48,8 @@
 	No_default_compiler_flags *bool
 
 	// list of system libraries that will be dynamically linked to
-	// shared library and executable modules.  If unset, generally defaults to libc
-	// and libm.  Set to [] to prevent linking against libc and libm.
+	// shared library and executable modules.  If unset, generally defaults to libc,
+	// libm, and libdl.  Set to [] to prevent linking against the defaults.
 	System_shared_libs []string
 
 	// allow the module to contain undefined symbols.  By default,
@@ -153,34 +153,32 @@
 		}
 
 		if !ctx.static() {
-			// libdl should always appear after libc in dt_needed list - see below
-			// the only exception is when libc is not in linker.Properties.System_shared_libs
-			// such as for libc module itself
-			if inList("libc", linker.Properties.System_shared_libs) {
-				_, deps.SharedLibs = removeFromList("libdl", deps.SharedLibs)
+			systemSharedLibs := linker.Properties.System_shared_libs
+			if systemSharedLibs == nil {
+				systemSharedLibs = []string{"libc", "libm", "libdl"}
 			}
 
-			if linker.Properties.System_shared_libs != nil {
-				if !inList("libdl", linker.Properties.System_shared_libs) &&
-					inList("libc", linker.Properties.System_shared_libs) {
-					linker.Properties.System_shared_libs = append(linker.Properties.System_shared_libs,
-						"libdl")
+			if inList("libdl", deps.SharedLibs) {
+				// If system_shared_libs has libc but not libdl, make sure shared_libs does not
+				// have libdl to avoid loading libdl before libc.
+				if inList("libc", systemSharedLibs) {
+					if !inList("libdl", systemSharedLibs) {
+						ctx.PropertyErrorf("shared_libs",
+							"libdl must be in system_shared_libs, not shared_libs")
+					}
+					_, deps.SharedLibs = removeFromList("libdl", deps.SharedLibs)
 				}
-				deps.LateSharedLibs = append(deps.LateSharedLibs,
-					linker.Properties.System_shared_libs...)
-			} else if !ctx.sdk() && !ctx.vndk() {
-				deps.LateSharedLibs = append(deps.LateSharedLibs, "libc", "libm", "libdl")
 			}
-		}
 
-		if ctx.sdk() {
-			deps.SharedLibs = append(deps.SharedLibs,
-				"libc",
-				"libm",
-				"libdl",
-			)
-		}
-		if ctx.vndk() {
+			// If libc and libdl are both in system_shared_libs make sure libd comes after libc
+			// to avoid loading libdl before libc.
+			if inList("libdl", systemSharedLibs) && inList("libc", systemSharedLibs) &&
+				indexList("libdl", systemSharedLibs) < indexList("libc", systemSharedLibs) {
+				ctx.PropertyErrorf("system_shared_libs", "libdl must be after libc")
+			}
+
+			deps.LateSharedLibs = append(deps.LateSharedLibs, systemSharedLibs...)
+		} else if ctx.sdk() || ctx.vndk() {
 			deps.LateSharedLibs = append(deps.LateSharedLibs, "libc", "libm", "libdl")
 		}
 	}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 916fe71..9c3b8e5 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -264,9 +264,6 @@
 		if Bool(sanitize.Properties.Sanitize.Address) {
 			deps.StaticLibs = append(deps.StaticLibs, asanLibs...)
 		}
-		if Bool(sanitize.Properties.Sanitize.Address) || Bool(sanitize.Properties.Sanitize.Thread) {
-			deps.SharedLibs = append(deps.SharedLibs, "libdl")
-		}
 	}
 
 	return deps
diff --git a/cc/stl.go b/cc/stl.go
index 9e67145..16c377c 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -107,8 +107,6 @@
 			}
 			if ctx.staticBinary() {
 				deps.StaticLibs = append(deps.StaticLibs, "libm", "libc", "libdl")
-			} else {
-				deps.SharedLibs = append(deps.SharedLibs, "libdl")
 			}
 		}
 	case "":
@@ -118,15 +116,9 @@
 		// The system STL doesn't have a prebuilt (it uses the system's libstdc++), but it does have
 		// its own includes. The includes are handled in CCBase.Flags().
 		deps.SharedLibs = append([]string{"libstdc++"}, deps.SharedLibs...)
-	case "ndk_libc++_shared":
-		deps.SharedLibs = append(deps.SharedLibs, stl.Properties.SelectedStl,
-			"libdl")
-	case "ndk_libc++_static":
-		deps.StaticLibs = append(deps.StaticLibs, stl.Properties.SelectedStl)
-		deps.SharedLibs = append(deps.SharedLibs, "libdl")
-	case "ndk_libstlport_shared":
+	case "ndk_libc++_shared", "ndk_libstlport_shared":
 		deps.SharedLibs = append(deps.SharedLibs, stl.Properties.SelectedStl)
-	case "ndk_libstlport_static", "ndk_libgnustl_static":
+	case "ndk_libc++_static", "ndk_libstlport_static", "ndk_libgnustl_static":
 		deps.StaticLibs = append(deps.StaticLibs, stl.Properties.SelectedStl)
 	default:
 		panic(fmt.Errorf("Unknown stl: %q", stl.Properties.SelectedStl))